From 928e3e4e44156c999abca8468a11723e2104b962 Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Sun, 13 Dec 2015 10:09:52 -0500 Subject: [PATCH 1/6] mk: actually run valgrind on x86_64-apple-darwin --- mk/platform.mk | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/mk/platform.mk b/mk/platform.mk index fd8416e8a6e61..bb6957bd79075 100644 --- a/mk/platform.mk +++ b/mk/platform.mk @@ -64,14 +64,18 @@ define DEF_GOOD_VALGRIND ifeq ($(OSTYPE_$(1)),unknown-linux-gnu) GOOD_VALGRIND_$(1) = 1 endif - ifneq (,$(filter $(OSTYPE_$(1)),darwin freebsd)) - ifeq (HOST_$(1),x86_64) + ifneq (,$(filter $(OSTYPE_$(1)),apple-darwin freebsd)) + ifeq ($(HOST_$(1)),x86_64) GOOD_VALGRIND_$(1) = 1 endif endif + ifdef GOOD_VALGRIND_$(t) + $$(info cfg: have good valgrind for $(t)) + else + $$(info cfg: no good valgrind for $(t)) + endif endef $(foreach t,$(CFG_TARGET),$(eval $(call DEF_GOOD_VALGRIND,$(t)))) -$(foreach t,$(CFG_TARGET),$(info cfg: good valgrind for $(t) is $(GOOD_VALGRIND_$(t)))) ifneq ($(findstring linux,$(CFG_OSTYPE)),) ifdef CFG_PERF From a3d81c64791d794bfda34254665284b475de6598 Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Sat, 12 Dec 2015 23:53:17 -0500 Subject: [PATCH 2/6] update valgrind suppressions --- src/etc/apple-darwin.supp | 72 +++++++--------------- src/etc/x86.supp | 8 +-- src/test/run-pass-valgrind/exit-flushes.rs | 3 + 3 files changed, 28 insertions(+), 55 deletions(-) diff --git a/src/etc/apple-darwin.supp b/src/etc/apple-darwin.supp index 866578930a3d8..50e30caa2b34b 100644 --- a/src/etc/apple-darwin.supp +++ b/src/etc/apple-darwin.supp @@ -1,17 +1,11 @@ { osx-frameworks.rs-fails-otherwise-1 Memcheck:Leak - match-leak-kinds: possible + match-leak-kinds: definite,possible fun:malloc ... fun:__CFInitialize - fun:_ZN16ImageLoaderMachO11doImageInitERKN11ImageLoader11LinkContextE - fun:_ZN16ImageLoaderMachO16doInitializationERKN11ImageLoader11LinkContextE - fun:_ZN11ImageLoader23recursiveInitializationERKNS_11LinkContextEjRNS_21InitializerTimingListERNS_15UninitedUpwardsE - fun:_ZN11ImageLoader23recursiveInitializationERKNS_11LinkContextEjRNS_21InitializerTimingListERNS_15UninitedUpwardsE - fun:_ZN11ImageLoader19processInitializersERKNS_11LinkContextEjRNS_21InitializerTimingListERNS_15UninitedUpwardsE - fun:_ZN11ImageLoader15runInitializersERKNS_11LinkContextERNS_21InitializerTimingListE - fun:_ZN4dyld24initializeMainExecutableEv + ... } { @@ -22,10 +16,6 @@ ... fun:__CFInitialize fun:_ZN16ImageLoaderMachO11doImageInitERKN11ImageLoader11LinkContextE - fun:_ZN16ImageLoaderMachO16doInitializationERKN11ImageLoader11LinkContextE - fun:_ZN11ImageLoader23recursiveInitializationERKNS_11LinkContextEjRNS_21InitializerTimingListERNS_15UninitedUpwardsE - fun:_ZN11ImageLoader23recursiveInitializationERKNS_11LinkContextEjRNS_21InitializerTimingListERNS_15UninitedUpwardsE - fun:_ZN11ImageLoader19processInitializersERKNS_11LinkContextEjRNS_21InitializerTimingListERNS_15UninitedUpwardsE } { @@ -33,12 +23,10 @@ Memcheck:Leak match-leak-kinds: possible fun:realloc - fun:_ZL12realizeClassP10objc_class - fun:_ZL12realizeClassP10objc_class - fun:_ZN13list_array_ttIm15protocol_list_tE11attachListsEPKPS0_j + ... fun:_read_images fun:map_images_nolock - fun:map_2_images + ... fun:_ZN4dyldL18notifyBatchPartialE17dyld_image_statesbPFPKcS0_jPK15dyld_image_infoE fun:_ZN4dyld36registerImageStateBatchChangeHandlerE17dyld_image_statesPFPKcS0_jPK15dyld_image_infoE fun:dyld_register_image_state_change_handler @@ -49,7 +37,7 @@ { osx-frameworks.rs-fails-otherwise-4 Memcheck:Leak - match-leak-kinds: possible + match-leak-kinds: definite,possible fun:calloc ... fun:__CFInitialize @@ -61,45 +49,27 @@ { osx-frameworks.rs-fails-otherwise-5 Memcheck:Leak - match-leak-kinds: definite - fun:calloc + match-leak-kinds: definite,possible + fun:malloc_zone_malloc ... fun:__CFInitialize - fun:_ZN16ImageLoaderMachO11doImageInitERKN11ImageLoader11LinkContextE - fun:_ZN16ImageLoaderMachO16doInitializationERKN11ImageLoader11LinkContextE - fun:_ZN11ImageLoader23recursiveInitializationERKNS_11LinkContextEjRNS_21InitializerTimingListERNS_15UninitedUpwardsE -} - -{ - osx-frameworks.rs-fails-otherwise-6 - Memcheck:Leak - match-leak-kinds: definite - fun:malloc - fun:strdup - fun:_CFProcessPath - fun:__CFInitialize - fun:_ZN16ImageLoaderMachO11doImageInitERKN11ImageLoader11LinkContextE - fun:_ZN16ImageLoaderMachO16doInitializationERKN11ImageLoader11LinkContextE - fun:_ZN11ImageLoader23recursiveInitializationERKNS_11LinkContextEjRNS_21InitializerTimingListERNS_15UninitedUpwardsE - fun:_ZN11ImageLoader23recursiveInitializationERKNS_11LinkContextEjRNS_21InitializerTimingListERNS_15UninitedUpwardsE - fun:_ZN11ImageLoader19processInitializersERKNS_11LinkContextEjRNS_21InitializerTimingListERNS_15UninitedUpwardsE - fun:_ZN11ImageLoader15runInitializersERKNS_11LinkContextERNS_21InitializerTimingListE - fun:_ZN4dyld24initializeMainExecutableEv - fun:_ZN4dyld5_mainEPK12macho_headermiPPKcS5_S5_Pm + ... } { - osx-frameworks.rs-fails-otherwise-7 + fails-since-xcode-7.2 Memcheck:Leak - match-leak-kinds: definite + match-leak-kinds: possible fun:malloc_zone_malloc - ... - fun:__CFInitialize - fun:_ZN16ImageLoaderMachO11doImageInitERKN11ImageLoader11LinkContextE - fun:_ZN16ImageLoaderMachO16doInitializationERKN11ImageLoader11LinkContextE - fun:_ZN11ImageLoader23recursiveInitializationERKNS_11LinkContextEjRNS_21InitializerTimingListERNS_15UninitedUpwardsE - fun:_ZN11ImageLoader23recursiveInitializationERKNS_11LinkContextEjRNS_21InitializerTimingListERNS_15UninitedUpwardsE - fun:_ZN11ImageLoader19processInitializersERKNS_11LinkContextEjRNS_21InitializerTimingListERNS_15UninitedUpwardsE - fun:_ZN11ImageLoader15runInitializersERKNS_11LinkContextERNS_21InitializerTimingListE - fun:_ZN4dyld24initializeMainExecutableEv + fun:_objc_copyClassNamesForImage + fun:_ZL9protocolsv + fun:_Z9readClassP10objc_classbb + fun:gc_init + fun:_ZL33objc_initializeClassPair_internalP10objc_classPKcS0_S0_ + fun:layout_string_create + fun:_ZL12realizeClassP10objc_class + fun:_ZL22copySwiftV1MangledNamePKcb + fun:_ZL22copySwiftV1MangledNamePKcb + fun:_ZL22copySwiftV1MangledNamePKcb + fun:_ZL22copySwiftV1MangledNamePKcb } diff --git a/src/etc/x86.supp b/src/etc/x86.supp index e4368da90331f..6e409af79aecf 100644 --- a/src/etc/x86.supp +++ b/src/etc/x86.supp @@ -12,7 +12,7 @@ fun:tlv_finalize fun:_pthread_tsd_cleanup fun:_pthread_exit - fun:_pthread_body + ... fun:_pthread_start fun:thread_start } @@ -24,7 +24,7 @@ fun:tlv_finalize fun:_pthread_tsd_cleanup fun:_pthread_exit - fun:_pthread_body + ... fun:_pthread_start fun:thread_start } @@ -36,7 +36,7 @@ fun:tlv_finalize fun:_pthread_tsd_cleanup fun:_pthread_exit - fun:_pthread_body + ... fun:_pthread_start fun:thread_start } @@ -48,7 +48,7 @@ fun:tlv_finalize fun:_pthread_tsd_cleanup fun:_pthread_exit - fun:_pthread_body + ... fun:_pthread_start fun:thread_start } diff --git a/src/test/run-pass-valgrind/exit-flushes.rs b/src/test/run-pass-valgrind/exit-flushes.rs index 76ecbfd2f223d..632693dd728c3 100644 --- a/src/test/run-pass-valgrind/exit-flushes.rs +++ b/src/test/run-pass-valgrind/exit-flushes.rs @@ -8,6 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-macos this needs valgrind 3.11 or higher; see +// https://github.com/rust-lang/rust/pull/30365#issuecomment-165763679 + use std::env; use std::process::{exit, Command}; From fa2a7411e403ec31b426c339c9950af8a1037995 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Fri, 25 Dec 2015 13:59:02 -0500 Subject: [PATCH 3/6] Use a more efficient encoding for opaque data in RBML. --- src/librbml/leb128.rs | 162 ++++++ src/librbml/lib.rs | 33 +- src/librbml/opaque.rs | 811 +++++++++++++++++++++++++++ src/librustc/middle/cstore.rs | 52 +- src/librustc_metadata/astencode.rs | 136 ++--- src/librustc_metadata/decoder.rs | 12 +- src/librustc_metadata/encoder.rs | 102 +--- src/librustc_metadata/tls_context.rs | 31 +- src/librustc_metadata/tydecode.rs | 8 +- src/librustc_metadata/tyencode.rs | 314 ++++++----- src/librustc_trans/trans/base.rs | 5 +- src/libsyntax/codemap.rs | 11 +- 12 files changed, 1308 insertions(+), 369 deletions(-) create mode 100644 src/librbml/leb128.rs create mode 100644 src/librbml/opaque.rs diff --git a/src/librbml/leb128.rs b/src/librbml/leb128.rs new file mode 100644 index 0000000000000..a5e8522623a2e --- /dev/null +++ b/src/librbml/leb128.rs @@ -0,0 +1,162 @@ +// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[inline] +pub fn write_to_vec(vec: &mut Vec, position: &mut usize, byte: u8) +{ + if *position == vec.len() { + vec.push(byte); + } else { + vec[*position] = byte; + } + + *position += 1; +} + +pub fn write_unsigned_leb128(out: &mut Vec, + start_position: usize, + mut value: u64) + -> usize { + let mut position = start_position; + loop + { + let mut byte = (value & 0x7F) as u8; + value >>= 7; + if value != 0 { + byte |= 0x80; + } + + write_to_vec(out, &mut position, byte); + + if value == 0 { + break; + } + } + + return position - start_position; +} + +pub fn read_unsigned_leb128(data: &[u8], + start_position: usize) + -> (u64, usize) { + let mut result = 0; + let mut shift = 0; + let mut position = start_position; + loop { + let byte = data[position]; + position += 1; + result |= ((byte & 0x7F) as u64) << shift; + if (byte & 0x80) == 0 { + break; + } + shift += 7; + } + + (result, position - start_position) +} + + +pub fn write_signed_leb128(out: &mut Vec, + start_position: usize, + mut value: i64) -> usize { + let mut position = start_position; + + loop { + let mut byte = (value as u8) & 0x7f; + value >>= 7; + let more = !((((value == 0 ) && ((byte & 0x40) == 0)) || + ((value == -1) && ((byte & 0x40) != 0)))); + if more { + byte |= 0x80; // Mark this byte to show that more bytes will follow. + } + + write_to_vec(out, &mut position, byte); + + if !more { + break; + } + } + + return position - start_position; +} + +pub fn read_signed_leb128(data: &[u8], + start_position: usize) + -> (i64, usize) { + let mut result = 0; + let mut shift = 0; + let mut position = start_position; + let mut byte; + + loop { + byte = data[position]; + position += 1; + result |= ((byte & 0x7F) as i64) << shift; + shift += 7; + + if (byte & 0x80) == 0 { + break; + } + } + + if (shift < 64) && ((byte & 0x40) != 0) { + /* sign extend */ + result |= -(1i64 << shift); + } + + (result, position - start_position) +} + +#[test] +fn test_unsigned_leb128() { + let mut stream = Vec::with_capacity(10000); + + for x in 0..62 { + let pos = stream.len(); + let bytes_written = write_unsigned_leb128(&mut stream, pos, 3 << x); + assert_eq!(stream.len(), pos + bytes_written); + } + + let mut position = 0; + for x in 0..62 { + let expected = 3 << x; + let (actual, bytes_read) = read_unsigned_leb128(&stream, position); + assert_eq!(expected, actual); + position += bytes_read; + } + assert_eq!(stream.len(), position); +} + +#[test] +fn test_signed_leb128() { + let mut values = Vec::new(); + + let mut i = -500; + while i < 500 { + values.push(i * 123457i64); + i += 1; + } + + let mut stream = Vec::new(); + + for &x in &values { + let pos = stream.len(); + let bytes_written = write_signed_leb128(&mut stream, pos, x); + assert_eq!(stream.len(), pos + bytes_written); + } + + let mut pos = 0; + for &x in &values { + let (value, bytes_read) = read_signed_leb128(&mut stream, pos); + pos += bytes_read; + assert_eq!(x, value); + } + assert_eq!(pos, stream.len()); +} diff --git a/src/librbml/lib.rs b/src/librbml/lib.rs index d8d6ea93f7569..f3a1bbd7e26b8 100644 --- a/src/librbml/lib.rs +++ b/src/librbml/lib.rs @@ -128,10 +128,17 @@ #![cfg_attr(test, feature(test))] extern crate serialize; + +#[cfg(test)] +extern crate serialize as rustc_serialize; // Used by RustcEncodable + #[macro_use] extern crate log; #[cfg(test)] extern crate test; +pub mod opaque; +pub mod leb128; + pub use self::EbmlEncoderTag::*; pub use self::Error::*; @@ -241,6 +248,7 @@ pub mod reader { use serialize; + use super::opaque; use super::{ ApplicationError, EsVec, EsMap, EsEnum, EsSub8, EsSub32, EsVecElt, EsMapKey, EsU64, EsU32, EsU16, EsU8, EsI64, EsI32, EsI16, EsI8, EsBool, EsF64, EsF32, EsChar, EsStr, EsMapVal, @@ -621,18 +629,16 @@ pub mod reader { } pub fn read_opaque(&mut self, op: F) -> DecodeResult where - F: FnOnce(&mut Decoder, Doc) -> DecodeResult, + F: FnOnce(&mut opaque::Decoder, Doc) -> DecodeResult, { let doc = try!(self.next_doc(EsOpaque)); - let (old_parent, old_pos) = (self.parent, self.pos); - self.parent = doc; - self.pos = doc.start; - - let result = try!(op(self, doc)); + let result = { + let mut opaque_decoder = opaque::Decoder::new(doc.data, + doc.start); + try!(op(&mut opaque_decoder, doc)) + }; - self.parent = old_parent; - self.pos = old_pos; Ok(result) } @@ -877,6 +883,7 @@ pub mod writer { use std::io::prelude::*; use std::io::{self, SeekFrom, Cursor}; + use super::opaque; use super::{ EsVec, EsMap, EsEnum, EsSub8, EsSub32, EsVecElt, EsMapKey, EsU64, EsU32, EsU16, EsU8, EsI64, EsI32, EsI16, EsI8, EsBool, EsF64, EsF32, EsChar, EsStr, EsMapVal, @@ -1120,10 +1127,16 @@ pub mod writer { } pub fn emit_opaque(&mut self, f: F) -> EncodeResult where - F: FnOnce(&mut Encoder) -> EncodeResult, + F: FnOnce(&mut opaque::Encoder) -> EncodeResult, { try!(self.start_tag(EsOpaque as usize)); - try!(f(self)); + + { + let mut opaque_encoder = opaque::Encoder::new(self.writer); + try!(f(&mut opaque_encoder)); + } + + self.mark_stable_position(); self.end_tag() } } diff --git a/src/librbml/opaque.rs b/src/librbml/opaque.rs new file mode 100644 index 0000000000000..64756090e8b48 --- /dev/null +++ b/src/librbml/opaque.rs @@ -0,0 +1,811 @@ +// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use Error as DecodeError; +use writer::EncodeResult; +use leb128::{read_signed_leb128, read_unsigned_leb128, write_signed_leb128, + write_unsigned_leb128}; +use std::io::{self, Write}; +use serialize; + +//=----------------------------------------------------------------------------- +// Encoder +//=----------------------------------------------------------------------------- + +pub struct Encoder<'a> { + pub cursor: &'a mut io::Cursor>, +} + +impl<'a> Encoder<'a> { + pub fn new(cursor: &'a mut io::Cursor>) -> Encoder<'a> { + Encoder { + cursor: cursor + } + } +} + + +macro_rules! write_uleb128 { + ($enc:expr, $value:expr) => {{ + let pos = $enc.cursor.position() as usize; + let bytes_written = write_unsigned_leb128($enc.cursor.get_mut(), pos, $value as u64); + $enc.cursor.set_position((pos + bytes_written) as u64); + Ok(()) + }} +} + +macro_rules! write_sleb128 { + ($enc:expr, $value:expr) => {{ + let pos = $enc.cursor.position() as usize; + let bytes_written = write_signed_leb128($enc.cursor.get_mut(), pos, $value as i64); + $enc.cursor.set_position((pos + bytes_written) as u64); + Ok(()) + }} +} + +impl<'a> serialize::Encoder for Encoder<'a> { + type Error = io::Error; + + fn emit_nil(&mut self) -> EncodeResult { + Ok(()) + } + + fn emit_uint(&mut self, v: usize) -> EncodeResult { + write_uleb128!(self, v) + } + + fn emit_u64(&mut self, v: u64) -> EncodeResult { + write_uleb128!(self, v) + } + + fn emit_u32(&mut self, v: u32) -> EncodeResult { + write_uleb128!(self, v) + } + + fn emit_u16(&mut self, v: u16) -> EncodeResult { + write_uleb128!(self, v) + } + + fn emit_u8(&mut self, v: u8) -> EncodeResult { + let _ = self.cursor.write_all(&[v]); + Ok(()) + } + + fn emit_int(&mut self, v: isize) -> EncodeResult { + write_sleb128!(self, v) + } + + fn emit_i64(&mut self, v: i64) -> EncodeResult { + write_sleb128!(self, v) + } + + fn emit_i32(&mut self, v: i32) -> EncodeResult { + write_sleb128!(self, v) + } + + fn emit_i16(&mut self, v: i16) -> EncodeResult { + write_sleb128!(self, v) + } + + fn emit_i8(&mut self, v: i8) -> EncodeResult { + let as_u8: u8 = unsafe { ::std::mem::transmute(v) }; + let _ = self.cursor.write_all(&[as_u8]); + Ok(()) + } + + fn emit_bool(&mut self, v: bool) -> EncodeResult { + self.emit_u8(if v { 1 } else { 0 }) + } + + fn emit_f64(&mut self, v: f64) -> EncodeResult { + let as_u64: u64 = unsafe { ::std::mem::transmute(v) }; + self.emit_u64(as_u64) + } + + fn emit_f32(&mut self, v: f32) -> EncodeResult { + let as_u32: u32 = unsafe { ::std::mem::transmute(v) }; + self.emit_u32(as_u32) + } + + fn emit_char(&mut self, v: char) -> EncodeResult { + self.emit_u32(v as u32) + } + + fn emit_str(&mut self, v: &str) -> EncodeResult { + try!(self.emit_uint(v.len())); + let _ = self.cursor.write_all(v.as_bytes()); + Ok(()) + } + + fn emit_enum(&mut self, _name: &str, f: F) -> EncodeResult + where F: FnOnce(&mut Self) -> EncodeResult { + f(self) + } + + fn emit_enum_variant(&mut self, + _v_name: &str, + v_id: usize, + _len: usize, + f: F) -> EncodeResult + where F: FnOnce(&mut Self) -> EncodeResult + { + try!(self.emit_uint(v_id)); + f(self) + } + + fn emit_enum_variant_arg(&mut self, _: usize, f: F) -> EncodeResult where + F: FnOnce(&mut Encoder<'a>) -> EncodeResult, + { + f(self) + } + + fn emit_enum_struct_variant(&mut self, + v_name: &str, + v_id: usize, + cnt: usize, + f: F) -> EncodeResult where + F: FnOnce(&mut Encoder<'a>) -> EncodeResult, + { + self.emit_enum_variant(v_name, v_id, cnt, f) + } + + fn emit_enum_struct_variant_field(&mut self, + _: &str, + idx: usize, + f: F) -> EncodeResult where + F: FnOnce(&mut Encoder<'a>) -> EncodeResult, + { + self.emit_enum_variant_arg(idx, f) + } + + fn emit_struct(&mut self, _: &str, _len: usize, f: F) -> EncodeResult where + F: FnOnce(&mut Encoder<'a>) -> EncodeResult, + { + f(self) + } + + fn emit_struct_field(&mut self, _name: &str, _: usize, f: F) -> EncodeResult where + F: FnOnce(&mut Encoder<'a>) -> EncodeResult, + { + f(self) + } + + fn emit_tuple(&mut self, len: usize, f: F) -> EncodeResult where + F: FnOnce(&mut Encoder<'a>) -> EncodeResult, + { + self.emit_seq(len, f) + } + + fn emit_tuple_arg(&mut self, idx: usize, f: F) -> EncodeResult where + F: FnOnce(&mut Encoder<'a>) -> EncodeResult, + { + self.emit_seq_elt(idx, f) + } + + fn emit_tuple_struct(&mut self, _: &str, len: usize, f: F) -> EncodeResult where + F: FnOnce(&mut Encoder<'a>) -> EncodeResult, + { + self.emit_seq(len, f) + } + + fn emit_tuple_struct_arg(&mut self, idx: usize, f: F) -> EncodeResult where + F: FnOnce(&mut Encoder<'a>) -> EncodeResult, + { + self.emit_seq_elt(idx, f) + } + + fn emit_option(&mut self, f: F) -> EncodeResult where + F: FnOnce(&mut Encoder<'a>) -> EncodeResult, + { + self.emit_enum("Option", f) + } + + fn emit_option_none(&mut self) -> EncodeResult { + self.emit_enum_variant("None", 0, 0, |_| Ok(())) + } + + fn emit_option_some(&mut self, f: F) -> EncodeResult where + F: FnOnce(&mut Encoder<'a>) -> EncodeResult, + { + self.emit_enum_variant("Some", 1, 1, f) + } + + fn emit_seq(&mut self, len: usize, f: F) -> EncodeResult where + F: FnOnce(&mut Encoder<'a>) -> EncodeResult, + { + try!(self.emit_uint(len)); + f(self) + } + + fn emit_seq_elt(&mut self, _idx: usize, f: F) -> EncodeResult where + F: FnOnce(&mut Encoder<'a>) -> EncodeResult, + { + f(self) + } + + fn emit_map(&mut self, len: usize, f: F) -> EncodeResult where + F: FnOnce(&mut Encoder<'a>) -> EncodeResult, + { + try!(self.emit_uint(len)); + f(self) + } + + fn emit_map_elt_key(&mut self, _idx: usize, f: F) -> EncodeResult where + F: FnOnce(&mut Encoder<'a>) -> EncodeResult, + { + f(self) + } + + fn emit_map_elt_val(&mut self, _idx: usize, f: F) -> EncodeResult where + F: FnOnce(&mut Encoder<'a>) -> EncodeResult, + { + f(self) + } +} + +impl<'a> Encoder<'a> { + pub fn position(&self) -> usize { + self.cursor.position() as usize + } + + pub fn from_rbml<'b: 'c, 'c>(rbml: &'c mut ::writer::Encoder<'b>) -> Encoder<'c> { + Encoder { + cursor: rbml.writer + } + } +} + +//=----------------------------------------------------------------------------- +// Decoder +//=----------------------------------------------------------------------------- + +pub struct Decoder<'a> { + pub data: &'a [u8], + position: usize, +} + +impl<'a> Decoder<'a> { + pub fn new(data: &'a [u8], position: usize) -> Decoder<'a> { + Decoder { + data: data, + position: position + } + } + + pub fn position(&self) -> usize { + self.position + } + + pub fn advance(&mut self, bytes: usize) { + self.position += bytes; + } +} + +macro_rules! read_uleb128 { + ($dec:expr, $t:ty) => ({ + let (value, bytes_read) = read_unsigned_leb128($dec.data, $dec.position); + $dec.position += bytes_read; + Ok(value as $t) + }) +} + +macro_rules! read_sleb128 { + ($dec:expr, $t:ty) => ({ + let (value, bytes_read) = read_signed_leb128($dec.data, $dec.position); + $dec.position += bytes_read; + Ok(value as $t) + }) +} + + +impl<'a> serialize::Decoder for Decoder<'a> { + type Error = DecodeError; + + fn read_nil(&mut self) -> Result<(), Self::Error> { + Ok(()) + } + + fn read_u64(&mut self) -> Result { + read_uleb128!(self, u64) + } + + fn read_u32(&mut self) -> Result { + read_uleb128!(self, u32) + } + + fn read_u16(&mut self) -> Result { + read_uleb128!(self, u16) + } + + fn read_u8(&mut self) -> Result { + let value = self.data[self.position]; + self.position += 1; + Ok(value) + } + + fn read_uint(&mut self) -> Result { + read_uleb128!(self, usize) + } + + fn read_i64(&mut self) -> Result { + read_sleb128!(self, i64) + } + + fn read_i32(&mut self) -> Result { + read_sleb128!(self, i32) + } + + fn read_i16(&mut self) -> Result { + read_sleb128!(self, i16) + } + + fn read_i8(&mut self) -> Result { + let as_u8 = self.data[self.position]; + self.position += 1; + unsafe { + Ok(::std::mem::transmute(as_u8)) + } + } + + fn read_int(&mut self) -> Result { + read_sleb128!(self, isize) + } + + fn read_bool(&mut self) -> Result { + let value = try!(self.read_u8()); + Ok(value != 0) + } + + fn read_f64(&mut self) -> Result { + let bits = try!(self.read_u64()); + Ok(unsafe { ::std::mem::transmute(bits) }) + } + + fn read_f32(&mut self) -> Result { + let bits = try!(self.read_u32()); + Ok(unsafe { ::std::mem::transmute(bits) }) + } + + fn read_char(&mut self) -> Result { + let bits = try!(self.read_u32()); + Ok(::std::char::from_u32(bits).unwrap()) + } + + fn read_str(&mut self) -> Result { + let len = try!(self.read_uint()); + let s = ::std::str::from_utf8(&self.data[self.position .. self.position + len]).unwrap(); + self.position += len; + Ok(s.to_string()) + } + + fn read_enum(&mut self, _name: &str, f: F) -> Result where + F: FnOnce(&mut Decoder<'a>) -> Result, + { + f(self) + } + + fn read_enum_variant(&mut self, + _: &[&str], + mut f: F) + -> Result + where F: FnMut(&mut Decoder<'a>, usize) -> Result, + { + let disr = try!(self.read_uint()); + f(self, disr) + } + + fn read_enum_variant_arg(&mut self, _idx: usize, f: F) -> Result where + F: FnOnce(&mut Decoder<'a>) -> Result, + { + f(self) + } + + fn read_enum_struct_variant(&mut self, + _: &[&str], + mut f: F) -> Result + where F: FnMut(&mut Decoder<'a>, usize) -> Result, + { + let disr = try!(self.read_uint()); + f(self, disr) + } + + fn read_enum_struct_variant_field(&mut self, + _name: &str, + _idx: usize, + f: F) + -> Result where + F: FnOnce(&mut Decoder<'a>) -> Result, + { + f(self) + } + + fn read_struct(&mut self, _name: &str, _: usize, f: F) -> Result where + F: FnOnce(&mut Decoder<'a>) -> Result, + { + f(self) + } + + fn read_struct_field(&mut self, + _name: &str, + _idx: usize, f: F) + -> Result where + F: FnOnce(&mut Decoder<'a>) -> Result, + { + f(self) + } + + fn read_tuple(&mut self, tuple_len: usize, f: F) -> Result where + F: FnOnce(&mut Decoder<'a>) -> Result, + { + self.read_seq(move |d, len| { + if len == tuple_len { + f(d) + } else { + let err = format!("Invalid tuple length. Expected {}, found {}", + tuple_len, + len); + Err(DecodeError::Expected(err)) + } + }) + } + + fn read_tuple_arg(&mut self, idx: usize, f: F) -> Result where + F: FnOnce(&mut Decoder<'a>) -> Result, + { + self.read_seq_elt(idx, f) + } + + fn read_tuple_struct(&mut self, + _name: &str, + len: usize, f: F) + -> Result where + F: FnOnce(&mut Decoder<'a>) -> Result, + { + self.read_tuple(len, f) + } + + fn read_tuple_struct_arg(&mut self, + idx: usize, + f: F) + -> Result where + F: FnOnce(&mut Decoder<'a>) -> Result, + { + self.read_tuple_arg(idx, f) + } + + fn read_option(&mut self, mut f: F) -> Result where + F: FnMut(&mut Decoder<'a>, bool) -> Result, + { + self.read_enum("Option", move |this| { + this.read_enum_variant(&["None", "Some"], move |this, idx| { + match idx { + 0 => f(this, false), + 1 => f(this, true), + _ => { + let msg = format!("Invalid Option index: {}", idx); + Err(DecodeError::Expected(msg)) + } + } + }) + }) + } + + fn read_seq(&mut self, f: F) -> Result where + F: FnOnce(&mut Decoder<'a>, usize) -> Result, + { + let len = try!(self.read_uint()); + f(self, len) + } + + fn read_seq_elt(&mut self, _idx: usize, f: F) -> Result where + F: FnOnce(&mut Decoder<'a>) -> Result, + { + f(self) + } + + fn read_map(&mut self, f: F) -> Result where + F: FnOnce(&mut Decoder<'a>, usize) -> Result, + { + let len = try!(self.read_uint()); + f(self, len) + } + + fn read_map_elt_key(&mut self, _idx: usize, f: F) -> Result where + F: FnOnce(&mut Decoder<'a>) -> Result, + { + f(self) + } + + fn read_map_elt_val(&mut self, _idx: usize, f: F) -> Result where + F: FnOnce(&mut Decoder<'a>) -> Result, + { + f(self) + } + + fn error(&mut self, err: &str) -> Self::Error { + DecodeError::ApplicationError(err.to_string()) + } +} + + +#[cfg(test)] +mod tests { + use serialize::{Encodable, Decodable}; + use std::io::{Cursor}; + use std::fmt::Debug; + use super::{Encoder, Decoder}; + + #[derive(PartialEq, Clone, Debug, RustcEncodable, RustcDecodable)] + struct Struct { + a: (), + b: u8, + c: u16, + d: u32, + e: u64, + f: usize, + + g: i8, + h: i16, + i: i32, + j: i64, + k: isize, + + l: char, + m: String, + n: f32, + o: f64, + p: bool, + q: Option, + } + + + fn check_round_trip(values: Vec) { + let mut cursor = Cursor::new(Vec::new()); + + for value in &values { + let mut encoder = Encoder::new(&mut cursor); + Encodable::encode(&value, &mut encoder).unwrap(); + } + + let data = cursor.into_inner(); + let mut decoder = Decoder::new(&data[..], 0); + + for value in values { + let decoded = Decodable::decode(&mut decoder).unwrap(); + assert_eq!(value, decoded); + } + } + + #[test] + fn test_unit() { + check_round_trip(vec![(), (), (), ()]); + } + + #[test] + fn test_u8() { + let mut vec = vec![]; + for i in ::std::u8::MIN .. ::std::u8::MAX { + vec.push(i); + } + check_round_trip(vec); + } + + #[test] + fn test_u16() { + for i in ::std::u16::MIN .. ::std::u16::MAX { + check_round_trip(vec![1, 2, 3, i, i, i]); + } + } + + #[test] + fn test_u32() { + check_round_trip(vec![1, 2, 3, ::std::u32::MIN, 0, 1, ::std::u32::MAX, 2, 1]); + } + + #[test] + fn test_u64() { + check_round_trip(vec![1, 2, 3, ::std::u64::MIN, 0, 1, ::std::u64::MAX, 2, 1]); + } + + #[test] + fn test_usize() { + check_round_trip(vec![1, 2, 3, ::std::usize::MIN, 0, 1, ::std::usize::MAX, 2, 1]); + } + + #[test] + fn test_i8() { + let mut vec = vec![]; + for i in ::std::i8::MIN .. ::std::i8::MAX { + vec.push(i); + } + check_round_trip(vec); + } + + #[test] + fn test_i16() { + for i in ::std::i16::MIN .. ::std::i16::MAX { + check_round_trip(vec![-1, 2, -3, i, i, i, 2]); + } + } + + #[test] + fn test_i32() { + check_round_trip(vec![-1, 2, -3, ::std::i32::MIN, 0, 1, ::std::i32::MAX, 2, 1]); + } + + #[test] + fn test_i64() { + check_round_trip(vec![-1, 2, -3, ::std::i64::MIN, 0, 1, ::std::i64::MAX, 2, 1]); + } + + #[test] + fn test_isize() { + check_round_trip(vec![-1, 2, -3, ::std::isize::MIN, 0, 1, ::std::isize::MAX, 2, 1]); + } + + #[test] + fn test_bool() { + check_round_trip(vec![false, true, true, false, false]); + } + + #[test] + fn test_f32() { + let mut vec = vec![]; + for i in -100 .. 100 { + vec.push( (i as f32) / 3.0 ); + } + check_round_trip(vec); + } + + #[test] + fn test_f64() { + let mut vec = vec![]; + for i in -100 .. 100 { + vec.push( (i as f64) / 3.0 ); + } + check_round_trip(vec); + } + + #[test] + fn test_char() { + let vec = vec!['a', 'b', 'c', 'd', 'A', 'X', ' ', '#', 'Ö', 'Ä', 'µ', '€']; + check_round_trip(vec); + } + + #[test] + fn test_string() { + let vec = vec![ + "abcbuÖeiovÄnameÜavmpßvmea€µsbpnvapeapmaebn".to_string(), + "abcbuÖganeiovÄnameÜavmpßvmea€µsbpnvapeapmaebn".to_string(), + "abcbuÖganeiovÄnameÜavmpßvmea€µsbpapmaebn".to_string(), + "abcbuÖganeiovÄnameÜavmpßvmeabpnvapeapmaebn".to_string(), + "abcbuÖganeiÄnameÜavmpßvmea€µsbpnvapeapmaebn".to_string(), + "abcbuÖganeiovÄnameÜavmpßvmea€µsbpmaebn".to_string(), + "abcbuÖganeiovÄnameÜavmpßvmea€µnvapeapmaebn".to_string()]; + + check_round_trip(vec); + } + + #[test] + fn test_option() { + check_round_trip(vec![Some(-1i8)]); + check_round_trip(vec![Some(-2i16)]); + check_round_trip(vec![Some(-3i32)]); + check_round_trip(vec![Some(-4i64)]); + check_round_trip(vec![Some(-5isize)]); + + let none_i8: Option = None; + check_round_trip(vec![none_i8]); + + let none_i16: Option = None; + check_round_trip(vec![none_i16]); + + let none_i32: Option = None; + check_round_trip(vec![none_i32]); + + let none_i64: Option = None; + check_round_trip(vec![none_i64]); + + let none_isize: Option = None; + check_round_trip(vec![none_isize]); + } + + #[test] + fn test_struct() { + check_round_trip(vec![Struct { + a: (), + b: 10, + c: 11, + d: 12, + e: 13, + f: 14, + + g: 15, + h: 16, + i: 17, + j: 18, + k: 19, + + l: 'x', + m: "abc".to_string(), + n: 20.5, + o: 21.5, + p: false, + q: None, + }]); + + check_round_trip(vec![Struct { + a: (), + b: 101, + c: 111, + d: 121, + e: 131, + f: 141, + + g: -15, + h: -16, + i: -17, + j: -18, + k: -19, + + l: 'y', + m: "def".to_string(), + n: -20.5, + o: -21.5, + p: true, + q: Some(1234567), + }]); + } + + #[derive(PartialEq, Clone, Debug, RustcEncodable, RustcDecodable)] + enum Enum { + Variant1, + Variant2(usize, f32), + Variant3 { a: i32, b: char, c: bool } + } + + #[test] + fn test_enum() { + check_round_trip(vec![Enum::Variant1, + Enum::Variant2(1, 2.5), + Enum::Variant3 { a: 3, b: 'b', c: false }, + Enum::Variant3 { a: -4, b: 'f', c: true }]); + } + + #[test] + fn test_sequence() { + let mut vec = vec![]; + for i in -100i64 .. 100i64 { + vec.push(i*100000); + } + + check_round_trip(vec![vec]); + } + + #[test] + fn test_hash_map() { + use std::collections::HashMap; + let mut map = HashMap::new(); + for i in -100i64 .. 100i64 { + map.insert(i*100000, i*10000); + } + + check_round_trip(vec![map]); + } + + #[test] + fn test_tuples() { + check_round_trip(vec![('x', (), false, 0.5f32)]); + check_round_trip(vec![(9i8, 10u16, 1.5f64)]); + check_round_trip(vec![(-12i16, 11u8, 12usize)]); + check_round_trip(vec![(1234567isize, 100000000000000u64, 99999999999999i64)]); + check_round_trip(vec![(String::new(), "some string".to_string())]); + } +} diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index 2c3b89bf2fbb2..380f543f969f0 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -432,8 +432,8 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore { /// Note, however, that this only works for RBML-based encoding and decoding at /// the moment. pub mod tls { - use rbml::writer::Encoder as RbmlEncoder; - use rbml::reader::Decoder as RbmlDecoder; + use rbml::opaque::Encoder as OpaqueEncoder; + use rbml::opaque::Decoder as OpaqueDecoder; use serialize; use std::mem; use middle::ty::{self, Ty}; @@ -442,8 +442,8 @@ pub mod tls { pub trait EncodingContext<'tcx> { fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx>; - fn encode_ty(&self, rbml_w: &mut RbmlEncoder, t: Ty<'tcx>); - fn encode_substs(&self, rbml_w: &mut RbmlEncoder, substs: &Substs<'tcx>); + fn encode_ty(&self, encoder: &mut OpaqueEncoder, t: Ty<'tcx>); + fn encode_substs(&self, encoder: &mut OpaqueEncoder, substs: &Substs<'tcx>); } /// Marker type used for the scoped TLS slot. @@ -455,13 +455,13 @@ pub mod tls { /// Execute f after pushing the given EncodingContext onto the TLS stack. pub fn enter_encoding_context<'tcx, F, R>(ecx: &EncodingContext<'tcx>, - rbml_w: &mut RbmlEncoder, + encoder: &mut OpaqueEncoder, f: F) -> R - where F: FnOnce(&EncodingContext<'tcx>, &mut RbmlEncoder) -> R + where F: FnOnce(&EncodingContext<'tcx>, &mut OpaqueEncoder) -> R { - let tls_payload = (ecx as *const _, rbml_w as *mut _); + let tls_payload = (ecx as *const _, encoder as *mut _); let tls_ptr = &tls_payload as *const _ as *const TlsPayload; - TLS_ENCODING.set(unsafe { &*tls_ptr }, || f(ecx, rbml_w)) + TLS_ENCODING.set(unsafe { &*tls_ptr }, || f(ecx, encoder)) } /// Execute f with access to the thread-local encoding context and @@ -473,16 +473,16 @@ pub mod tls { /// possible to construct cases where the EncodingContext is exchanged /// while the same encoder is used, thus working with a wrong context. pub fn with_encoding_context<'tcx, E, F, R>(encoder: &mut E, f: F) -> R - where F: FnOnce(&EncodingContext<'tcx>, &mut RbmlEncoder) -> R, + where F: FnOnce(&EncodingContext<'tcx>, &mut OpaqueEncoder) -> R, E: serialize::Encoder { unsafe { - unsafe_with_encoding_context(|ecx, rbml_w| { - assert!(encoder as *mut _ as usize == rbml_w as *mut _ as usize); + unsafe_with_encoding_context(|ecx, tls_encoder| { + assert!(encoder as *mut _ as usize == tls_encoder as *mut _ as usize); let ecx: &EncodingContext<'tcx> = mem::transmute(ecx); - f(ecx, rbml_w) + f(ecx, tls_encoder) }) } } @@ -490,19 +490,19 @@ pub mod tls { /// Execute f with access to the thread-local encoding context and /// rbml encoder. pub unsafe fn unsafe_with_encoding_context(f: F) -> R - where F: FnOnce(&EncodingContext, &mut RbmlEncoder) -> R + where F: FnOnce(&EncodingContext, &mut OpaqueEncoder) -> R { TLS_ENCODING.with(|tls| { let tls_payload = (tls as *const TlsPayload) - as *mut (&EncodingContext, &mut RbmlEncoder); + as *mut (&EncodingContext, &mut OpaqueEncoder); f((*tls_payload).0, (*tls_payload).1) }) } pub trait DecodingContext<'tcx> { fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx>; - fn decode_ty(&self, rbml_r: &mut RbmlDecoder) -> ty::Ty<'tcx>; - fn decode_substs(&self, rbml_r: &mut RbmlDecoder) -> Substs<'tcx>; + fn decode_ty(&self, decoder: &mut OpaqueDecoder) -> ty::Ty<'tcx>; + fn decode_substs(&self, decoder: &mut OpaqueDecoder) -> Substs<'tcx>; fn translate_def_id(&self, def_id: DefId) -> DefId; } @@ -510,13 +510,13 @@ pub mod tls { /// Execute f after pushing the given DecodingContext onto the TLS stack. pub fn enter_decoding_context<'tcx, F, R>(dcx: &DecodingContext<'tcx>, - rbml_r: &mut RbmlDecoder, + decoder: &mut OpaqueDecoder, f: F) -> R - where F: FnOnce(&DecodingContext<'tcx>, &mut RbmlDecoder) -> R + where F: FnOnce(&DecodingContext<'tcx>, &mut OpaqueDecoder) -> R { - let tls_payload = (dcx as *const _, rbml_r as *mut _); + let tls_payload = (dcx as *const _, decoder as *mut _); let tls_ptr = &tls_payload as *const _ as *const TlsPayload; - TLS_DECODING.set(unsafe { &*tls_ptr }, || f(dcx, rbml_r)) + TLS_DECODING.set(unsafe { &*tls_ptr }, || f(dcx, decoder)) } /// Execute f with access to the thread-local decoding context and @@ -530,16 +530,16 @@ pub mod tls { pub fn with_decoding_context<'decoder, 'tcx, D, F, R>(d: &'decoder mut D, f: F) -> R where D: serialize::Decoder, F: FnOnce(&DecodingContext<'tcx>, - &mut RbmlDecoder) -> R, + &mut OpaqueDecoder) -> R, 'tcx: 'decoder { unsafe { - unsafe_with_decoding_context(|dcx, rbml_r| { - assert!((d as *mut _ as usize) == (rbml_r as *mut _ as usize)); + unsafe_with_decoding_context(|dcx, decoder| { + assert!((d as *mut _ as usize) == (decoder as *mut _ as usize)); let dcx: &DecodingContext<'tcx> = mem::transmute(dcx); - f(dcx, rbml_r) + f(dcx, decoder) }) } } @@ -547,11 +547,11 @@ pub mod tls { /// Execute f with access to the thread-local decoding context and /// rbml decoder. pub unsafe fn unsafe_with_decoding_context(f: F) -> R - where F: FnOnce(&DecodingContext, &mut RbmlDecoder) -> R + where F: FnOnce(&DecodingContext, &mut OpaqueDecoder) -> R { TLS_DECODING.with(|tls| { let tls_payload = (tls as *const TlsPayload) - as *mut (&DecodingContext, &mut RbmlDecoder); + as *mut (&DecodingContext, &mut OpaqueDecoder); f((*tls_payload).0, (*tls_payload).1) }) } diff --git a/src/librustc_metadata/astencode.rs b/src/librustc_metadata/astencode.rs index 8f74acd9ebdf6..8c3bd3c4f8a53 100644 --- a/src/librustc_metadata/astencode.rs +++ b/src/librustc_metadata/astencode.rs @@ -292,7 +292,7 @@ impl def_id_decoder_helpers for D fn encode_ast(rbml_w: &mut Encoder, item: &InlinedItem) { rbml_w.start_tag(c::tag_tree as usize); - item.encode(rbml_w); + rbml_w.emit_opaque(|this| item.encode(this)); rbml_w.end_tag(); } @@ -361,8 +361,8 @@ fn simplify_ast(ii: InlinedItemRef) -> InlinedItem { fn decode_ast(par_doc: rbml::Doc) -> InlinedItem { let chi_doc = par_doc.get(c::tag_tree as usize); - let mut d = reader::Decoder::new(chi_doc); - Decodable::decode(&mut d).unwrap() + let mut rbml_r = reader::Decoder::new(chi_doc); + rbml_r.read_opaque(|decoder, _| Decodable::decode(decoder)).unwrap() } // ______________________________________________________________________ @@ -509,21 +509,6 @@ pub fn encode_cast_kind(ebml_w: &mut Encoder, kind: cast::CastKind) { // ______________________________________________________________________ // Encoding and decoding the side tables -trait get_ty_str_ctxt<'tcx> { - fn ty_str_ctxt<'a>(&'a self) -> tyencode::ctxt<'a, 'tcx>; -} - -impl<'a, 'tcx> get_ty_str_ctxt<'tcx> for e::EncodeContext<'a, 'tcx> { - fn ty_str_ctxt<'b>(&'b self) -> tyencode::ctxt<'b, 'tcx> { - tyencode::ctxt { - diag: self.tcx.sess.diagnostic(), - ds: e::def_to_string, - tcx: self.tcx, - abbrevs: &self.type_abbrevs - } - } -} - trait rbml_writer_helpers<'tcx> { fn emit_region(&mut self, ecx: &e::EncodeContext, r: ty::Region); fn emit_ty<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>, ty: Ty<'tcx>); @@ -548,11 +533,15 @@ trait rbml_writer_helpers<'tcx> { impl<'a, 'tcx> rbml_writer_helpers<'tcx> for Encoder<'a> { fn emit_region(&mut self, ecx: &e::EncodeContext, r: ty::Region) { - self.emit_opaque(|this| Ok(e::write_region(ecx, this, r))); + self.emit_opaque(|this| Ok(tyencode::enc_region(&mut this.cursor, + &ecx.ty_str_ctxt(), + r))); } fn emit_ty<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>, ty: Ty<'tcx>) { - self.emit_opaque(|this| Ok(e::write_type(ecx, this, ty))); + self.emit_opaque(|this| Ok(tyencode::enc_ty(&mut this.cursor, + &ecx.ty_str_ctxt(), + ty))); } fn emit_tys<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>, tys: &[Ty<'tcx>]) { @@ -561,13 +550,15 @@ impl<'a, 'tcx> rbml_writer_helpers<'tcx> for Encoder<'a> { fn emit_trait_ref<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>, trait_ref: &ty::TraitRef<'tcx>) { - self.emit_opaque(|this| Ok(e::write_trait_ref(ecx, this, trait_ref))); + self.emit_opaque(|this| Ok(tyencode::enc_trait_ref(&mut this.cursor, + &ecx.ty_str_ctxt(), + *trait_ref))); } fn emit_predicate<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>, predicate: &ty::Predicate<'tcx>) { self.emit_opaque(|this| { - Ok(tyencode::enc_predicate(this, + Ok(tyencode::enc_predicate(&mut this.cursor, &ecx.ty_str_ctxt(), predicate)) }); @@ -575,13 +566,13 @@ impl<'a, 'tcx> rbml_writer_helpers<'tcx> for Encoder<'a> { fn emit_existential_bounds<'b>(&mut self, ecx: &e::EncodeContext<'b,'tcx>, bounds: &ty::ExistentialBounds<'tcx>) { - self.emit_opaque(|this| Ok(tyencode::enc_existential_bounds(this, + self.emit_opaque(|this| Ok(tyencode::enc_existential_bounds(&mut this.cursor, &ecx.ty_str_ctxt(), bounds))); } fn emit_builtin_bounds(&mut self, ecx: &e::EncodeContext, bounds: &ty::BuiltinBounds) { - self.emit_opaque(|this| Ok(tyencode::enc_builtin_bounds(this, + self.emit_opaque(|this| Ok(tyencode::enc_builtin_bounds(&mut this.cursor, &ecx.ty_str_ctxt(), bounds))); } @@ -608,9 +599,9 @@ impl<'a, 'tcx> rbml_writer_helpers<'tcx> for Encoder<'a> { fn emit_substs<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>, substs: &subst::Substs<'tcx>) { - self.emit_opaque(|this| Ok(tyencode::enc_substs(this, - &ecx.ty_str_ctxt(), - substs))); + self.emit_opaque(|this| Ok(tyencode::enc_substs(&mut this.cursor, + &ecx.ty_str_ctxt(), + substs))); } fn emit_auto_adjustment<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>, @@ -878,10 +869,6 @@ trait rbml_decoder_decoder_helpers<'tcx> { -> adjustment::AutoDerefRef<'tcx>; fn read_autoref<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>) -> adjustment::AutoRef<'tcx>; - fn convert_def_id(&mut self, - dcx: &DecodeContext, - did: DefId) - -> DefId; // Versions of the type reading functions that don't need the full // DecodeContext. @@ -933,12 +920,12 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> { fn read_ty_encoded<'b, 'c, F, R>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>, op: F) -> R where F: for<'x> FnOnce(&mut tydecode::TyDecoder<'x,'tcx>) -> R { - return self.read_opaque(|this, doc| { + return self.read_opaque(|_, doc| { debug!("read_ty_encoded({})", type_string(doc)); Ok(op( &mut tydecode::TyDecoder::with_doc( dcx.tcx, dcx.cdata.cnum, doc, - &mut |a| this.convert_def_id(dcx, a)))) + &mut |d| convert_def_id(dcx, d)))) }).unwrap(); fn type_string(doc: rbml::Doc) -> String { @@ -989,9 +976,9 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> { fn read_substs<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>) -> subst::Substs<'tcx> { - self.read_opaque(|this, doc| { + self.read_opaque(|_, doc| { Ok(tydecode::TyDecoder::with_doc(dcx.tcx, dcx.cdata.cnum, doc, - &mut |a| this.convert_def_id(dcx, a)) + &mut |d| convert_def_id(dcx, d)) .parse_substs()) }).unwrap() } @@ -1097,47 +1084,46 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> { { Decodable::decode(self).unwrap() } +} - /// Converts a def-id that appears in a type. The correct - /// translation will depend on what kind of def-id this is. - /// This is a subtle point: type definitions are not - /// inlined into the current crate, so if the def-id names - /// a nominal type or type alias, then it should be - /// translated to refer to the source crate. - /// - /// However, *type parameters* are cloned along with the function - /// they are attached to. So we should translate those def-ids - /// to refer to the new, cloned copy of the type parameter. - /// We only see references to free type parameters in the body of - /// an inlined function. In such cases, we need the def-id to - /// be a local id so that the TypeContents code is able to lookup - /// the relevant info in the ty_param_defs table. - /// - /// *Region parameters*, unfortunately, are another kettle of fish. - /// In such cases, def_id's can appear in types to distinguish - /// shadowed bound regions and so forth. It doesn't actually - /// matter so much what we do to these, since regions are erased - /// at trans time, but it's good to keep them consistent just in - /// case. We translate them with `tr_def_id()` which will map - /// the crate numbers back to the original source crate. - /// - /// Scopes will end up as being totally bogus. This can actually - /// be fixed though. - /// - /// Unboxed closures are cloned along with the function being - /// inlined, and all side tables use interned node IDs, so we - /// translate their def IDs accordingly. - /// - /// It'd be really nice to refactor the type repr to not include - /// def-ids so that all these distinctions were unnecessary. - fn convert_def_id(&mut self, - dcx: &DecodeContext, - did: DefId) - -> DefId { - let r = dcx.tr_def_id(did); - debug!("convert_def_id(did={:?})={:?}", did, r); - return r; - } +// Converts a def-id that appears in a type. The correct +// translation will depend on what kind of def-id this is. +// This is a subtle point: type definitions are not +// inlined into the current crate, so if the def-id names +// a nominal type or type alias, then it should be +// translated to refer to the source crate. +// +// However, *type parameters* are cloned along with the function +// they are attached to. So we should translate those def-ids +// to refer to the new, cloned copy of the type parameter. +// We only see references to free type parameters in the body of +// an inlined function. In such cases, we need the def-id to +// be a local id so that the TypeContents code is able to lookup +// the relevant info in the ty_param_defs table. +// +// *Region parameters*, unfortunately, are another kettle of fish. +// In such cases, def_id's can appear in types to distinguish +// shadowed bound regions and so forth. It doesn't actually +// matter so much what we do to these, since regions are erased +// at trans time, but it's good to keep them consistent just in +// case. We translate them with `tr_def_id()` which will map +// the crate numbers back to the original source crate. +// +// Scopes will end up as being totally bogus. This can actually +// be fixed though. +// +// Unboxed closures are cloned along with the function being +// inlined, and all side tables use interned node IDs, so we +// translate their def IDs accordingly. +// +// It'd be really nice to refactor the type repr to not include +// def-ids so that all these distinctions were unnecessary. +fn convert_def_id(dcx: &DecodeContext, + did: DefId) + -> DefId { + let r = dcx.tr_def_id(did); + debug!("convert_def_id(did={:?})={:?}", did, r); + return r; } fn decode_side_tables(dcx: &DecodeContext, diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 8126970759e6d..40b196277955a 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -833,9 +833,11 @@ pub fn maybe_get_item_mir<'tcx>(cdata: Cmd, }; let mut decoder = reader::Decoder::new(mir_doc); - let mut mir = tls::enter_decoding_context(&dcx, &mut decoder, |_, decoder| { - Decodable::decode(decoder).unwrap() - }); + let mut mir = decoder.read_opaque(|opaque_decoder, _| { + tls::enter_decoding_context(&dcx, opaque_decoder, |_, opaque_decoder| { + Decodable::decode(opaque_decoder) + }) + }).unwrap(); let mut def_id_and_span_translator = MirDefIdAndSpanTranslator { crate_metadata: cdata, @@ -1643,7 +1645,9 @@ pub fn get_imported_filemaps(metadata: &[u8]) -> Vec { reader::tagged_docs(cm_doc, tag_codemap_filemap).map(|filemap_doc| { let mut decoder = reader::Decoder::new(filemap_doc); - Decodable::decode(&mut decoder).unwrap() + decoder.read_opaque(|opaque_decoder, _| { + Decodable::decode(opaque_decoder) + }).unwrap() }).collect() } diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index cd70172e8fa21..cfb1bca1ea17e 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -140,15 +140,9 @@ fn encode_trait_ref<'a, 'tcx>(rbml_w: &mut Encoder, ecx: &EncodeContext<'a, 'tcx>, trait_ref: ty::TraitRef<'tcx>, tag: usize) { - let ty_str_ctxt = &tyencode::ctxt { - diag: ecx.diag, - ds: def_to_string, - tcx: ecx.tcx, - abbrevs: &ecx.type_abbrevs - }; - rbml_w.start_tag(tag); - tyencode::enc_trait_ref(rbml_w, ty_str_ctxt, trait_ref); + tyencode::enc_trait_ref(rbml_w.writer, &ecx.ty_str_ctxt(), trait_ref); + rbml_w.mark_stable_position(); rbml_w.end_tag(); } @@ -202,59 +196,19 @@ fn encode_variant_id(rbml_w: &mut Encoder, vid: DefId) { rbml_w.wr_tagged_u64(tag_mod_child, id); } -pub fn write_closure_type<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>, - rbml_w: &mut Encoder, - closure_type: &ty::ClosureTy<'tcx>) { - let ty_str_ctxt = &tyencode::ctxt { - diag: ecx.diag, - ds: def_to_string, - tcx: ecx.tcx, - abbrevs: &ecx.type_abbrevs - }; - tyencode::enc_closure_ty(rbml_w, ty_str_ctxt, closure_type); -} - -pub fn write_type<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>, +fn write_closure_type<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>, rbml_w: &mut Encoder, - typ: Ty<'tcx>) { - let ty_str_ctxt = &tyencode::ctxt { - diag: ecx.diag, - ds: def_to_string, - tcx: ecx.tcx, - abbrevs: &ecx.type_abbrevs - }; - tyencode::enc_ty(rbml_w, ty_str_ctxt, typ); -} - -pub fn write_trait_ref<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>, - rbml_w: &mut Encoder, - trait_ref: &ty::TraitRef<'tcx>) { - let ty_str_ctxt = &tyencode::ctxt { - diag: ecx.diag, - ds: def_to_string, - tcx: ecx.tcx, - abbrevs: &ecx.type_abbrevs - }; - tyencode::enc_trait_ref(rbml_w, ty_str_ctxt, *trait_ref); -} - -pub fn write_region(ecx: &EncodeContext, - rbml_w: &mut Encoder, - r: ty::Region) { - let ty_str_ctxt = &tyencode::ctxt { - diag: ecx.diag, - ds: def_to_string, - tcx: ecx.tcx, - abbrevs: &ecx.type_abbrevs - }; - tyencode::enc_region(rbml_w, ty_str_ctxt, r); + closure_type: &ty::ClosureTy<'tcx>) { + tyencode::enc_closure_ty(rbml_w.writer, &ecx.ty_str_ctxt(), closure_type); + rbml_w.mark_stable_position(); } fn encode_type<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>, rbml_w: &mut Encoder, typ: Ty<'tcx>) { rbml_w.start_tag(tag_items_data_item_type); - write_type(ecx, rbml_w, typ); + tyencode::enc_ty(rbml_w.writer, &ecx.ty_str_ctxt(), typ); + rbml_w.mark_stable_position(); rbml_w.end_tag(); } @@ -262,7 +216,8 @@ fn encode_region(ecx: &EncodeContext, rbml_w: &mut Encoder, r: ty::Region) { rbml_w.start_tag(tag_items_data_region); - write_region(ecx, rbml_w, r); + tyencode::enc_region(rbml_w.writer, &ecx.ty_str_ctxt(), r); + rbml_w.mark_stable_position(); rbml_w.end_tag(); } @@ -592,17 +547,10 @@ fn encode_generics<'a, 'tcx>(rbml_w: &mut Encoder, { rbml_w.start_tag(tag); - // Type parameters - let ty_str_ctxt = &tyencode::ctxt { - diag: ecx.diag, - ds: def_to_string, - tcx: ecx.tcx, - abbrevs: &ecx.type_abbrevs - }; - for param in &generics.types { rbml_w.start_tag(tag_type_param_def); - tyencode::enc_type_param_def(rbml_w, ty_str_ctxt, param); + tyencode::enc_type_param_def(rbml_w.writer, &ecx.ty_str_ctxt(), param); + rbml_w.mark_stable_position(); rbml_w.end_tag(); } @@ -871,7 +819,11 @@ fn encode_mir(ecx: &EncodeContext, rbml_w: &mut Encoder, ii: InlinedItemRef) { if let Some(mir) = ecx.mir_map.get(&id) { rbml_w.start_tag(tag_mir as usize); - Encodable::encode(mir, rbml_w).unwrap(); + rbml_w.emit_opaque(|opaque_encoder| { + tls::enter_encoding_context(ecx, opaque_encoder, |_, opaque_encoder| { + Encodable::encode(mir, opaque_encoder) + }) + }).unwrap(); rbml_w.end_tag(); } } @@ -916,23 +868,17 @@ fn encode_xrefs<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>, rbml_w: &mut Encoder, xrefs: FnvHashMap, u32>) { - let ty_str_ctxt = &tyencode::ctxt { - diag: ecx.diag, - ds: def_to_string, - tcx: ecx.tcx, - abbrevs: &ecx.type_abbrevs - }; - let mut xref_positions = vec![0; xrefs.len()]; rbml_w.start_tag(tag_xref_data); for (xref, id) in xrefs.into_iter() { xref_positions[id as usize] = rbml_w.mark_stable_position() as u32; match xref { XRef::Predicate(p) => { - tyencode::enc_predicate(rbml_w, ty_str_ctxt, &p) + tyencode::enc_predicate(rbml_w.writer, &ecx.ty_str_ctxt(), &p) } } } + rbml_w.mark_stable_position(); rbml_w.end_tag(); rbml_w.start_tag(tag_xref_index); @@ -1750,7 +1696,9 @@ fn encode_codemap(ecx: &EncodeContext, rbml_w: &mut Encoder) { } rbml_w.start_tag(tag_codemap_filemap); - filemap.encode(rbml_w); + rbml_w.emit_opaque(|opaque_encoder| { + filemap.encode(opaque_encoder) + }).unwrap(); rbml_w.end_tag(); } @@ -1961,9 +1909,7 @@ pub fn encode_metadata(parms: EncodeParams, krate: &hir::Crate) -> Vec { { let mut rbml_w = Encoder::new(&mut wr); - tls::enter_encoding_context(&ecx, &mut rbml_w, |_, rbml_w| { - encode_metadata_inner(rbml_w, &ecx, krate) - }); + encode_metadata_inner(&mut rbml_w, &ecx, krate) } // RBML compacts the encoded bytes whenever appropriate, @@ -2132,7 +2078,7 @@ fn encode_metadata_inner(rbml_w: &mut Encoder, // Get the encoded string for a type pub fn encoded_ty<'tcx>(tcx: &ty::ctxt<'tcx>, t: Ty<'tcx>) -> Vec { let mut wr = Cursor::new(Vec::new()); - tyencode::enc_ty(&mut Encoder::new(&mut wr), &tyencode::ctxt { + tyencode::enc_ty(&mut wr, &tyencode::ctxt { diag: tcx.sess.diagnostic(), ds: def_to_string, tcx: tcx, diff --git a/src/librustc_metadata/tls_context.rs b/src/librustc_metadata/tls_context.rs index eb82d2df94d15..37e661c21e15a 100644 --- a/src/librustc_metadata/tls_context.rs +++ b/src/librustc_metadata/tls_context.rs @@ -11,8 +11,8 @@ // This module provides implementations for the thread-local encoding and // decoding context traits in rustc::middle::cstore::tls. -use rbml::writer::Encoder as RbmlEncoder; -use rbml::reader::Decoder as RbmlDecoder; +use rbml::opaque::Encoder as OpaqueEncoder; +use rbml::opaque::Decoder as OpaqueDecoder; use rustc::middle::cstore::tls; use rustc::middle::def_id::DefId; use rustc::middle::subst::Substs; @@ -23,25 +23,18 @@ use encoder; use tydecode::TyDecoder; use tyencode; - impl<'a, 'tcx: 'a> tls::EncodingContext<'tcx> for encoder::EncodeContext<'a, 'tcx> { fn tcx<'s>(&'s self) -> &'s ty::ctxt<'tcx> { &self.tcx } - fn encode_ty(&self, rbml_w: &mut RbmlEncoder, t: ty::Ty<'tcx>) { - encoder::write_type(self, rbml_w, t); + fn encode_ty(&self, encoder: &mut OpaqueEncoder, t: ty::Ty<'tcx>) { + tyencode::enc_ty(encoder.cursor, &self.ty_str_ctxt(), t); } - fn encode_substs(&self, rbml_w: &mut RbmlEncoder, substs: &Substs<'tcx>) { - let ty_str_ctxt = &tyencode::ctxt { - diag: self.diag, - ds: encoder::def_to_string, - tcx: self.tcx, - abbrevs: &self.type_abbrevs - }; - tyencode::enc_substs(rbml_w, ty_str_ctxt, substs); + fn encode_substs(&self, encoder: &mut OpaqueEncoder, substs: &Substs<'tcx>) { + tyencode::enc_substs(encoder.cursor, &self.ty_str_ctxt(), substs); } } @@ -56,12 +49,12 @@ impl<'a, 'tcx: 'a> tls::DecodingContext<'tcx> for DecodingContext<'a, 'tcx> { &self.tcx } - fn decode_ty(&self, rbml_r: &mut RbmlDecoder) -> ty::Ty<'tcx> { + fn decode_ty(&self, decoder: &mut OpaqueDecoder) -> ty::Ty<'tcx> { let def_id_convert = &mut |did| { decoder::translate_def_id(self.crate_metadata, did) }; - let starting_position = rbml_r.position(); + let starting_position = decoder.position(); let mut ty_decoder = TyDecoder::new( self.crate_metadata.data.as_slice(), @@ -77,16 +70,16 @@ impl<'a, 'tcx: 'a> tls::DecodingContext<'tcx> for DecodingContext<'a, 'tcx> { // We can just reuse the tydecode implementation for parsing types, but // we have to make sure to leave the rbml reader at the position just // after the type. - rbml_r.advance(end_position - starting_position); + decoder.advance(end_position - starting_position); ty } - fn decode_substs(&self, rbml_r: &mut RbmlDecoder) -> Substs<'tcx> { + fn decode_substs(&self, decoder: &mut OpaqueDecoder) -> Substs<'tcx> { let def_id_convert = &mut |did| { decoder::translate_def_id(self.crate_metadata, did) }; - let starting_position = rbml_r.position(); + let starting_position = decoder.position(); let mut ty_decoder = TyDecoder::new( self.crate_metadata.data.as_slice(), @@ -99,7 +92,7 @@ impl<'a, 'tcx: 'a> tls::DecodingContext<'tcx> for DecodingContext<'a, 'tcx> { let end_position = ty_decoder.position(); - rbml_r.advance(end_position - starting_position); + decoder.advance(end_position - starting_position); substs } diff --git a/src/librustc_metadata/tydecode.rs b/src/librustc_metadata/tydecode.rs index b99431d265618..c7a5faed35cd0 100644 --- a/src/librustc_metadata/tydecode.rs +++ b/src/librustc_metadata/tydecode.rs @@ -25,6 +25,7 @@ use middle::subst::VecPerParamSpace; use middle::ty::{self, ToPredicate, Ty, HasTypeFlags}; use rbml; +use rbml::leb128; use std::str; use syntax::abi; use syntax::ast; @@ -103,9 +104,10 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> { } fn parse_vuint(&mut self) -> usize { - let res = rbml::reader::vuint_at(self.data, self.pos).unwrap(); - self.pos = res.next; - res.val + let (value, bytes_read) = leb128::read_unsigned_leb128(self.data, + self.pos); + self.pos += bytes_read; + value as usize } fn parse_name(&mut self, last: char) -> ast::Name { diff --git a/src/librustc_metadata/tyencode.rs b/src/librustc_metadata/tyencode.rs index 6d42871201b8e..f03c25d698feb 100644 --- a/src/librustc_metadata/tyencode.rs +++ b/src/librustc_metadata/tyencode.rs @@ -31,9 +31,8 @@ use syntax::abi::Abi; use syntax::ast; use syntax::errors::Handler; -use rbml::writer::{self, Encoder}; - -macro_rules! mywrite { ($w:expr, $($arg:tt)*) => ({ write!($w.writer, $($arg)*); }) } +use rbml::leb128; +use encoder; pub struct ctxt<'a, 'tcx: 'a> { pub diag: &'a Handler, @@ -44,6 +43,17 @@ pub struct ctxt<'a, 'tcx: 'a> { pub abbrevs: &'a abbrev_map<'tcx> } +impl<'a, 'tcx> encoder::EncodeContext<'a, 'tcx> { + pub fn ty_str_ctxt<'b>(&'b self) -> ctxt<'b, 'tcx> { + ctxt { + diag: self.tcx.sess.diagnostic(), + ds: encoder::def_to_string, + tcx: self.tcx, + abbrevs: &self.type_abbrevs + } + } +} + // Compact string representation for Ty values. API TyStr & parse_from_str. // Extra parameters are for converting to/from def_ids in the string rep. // Whatever format you choose should not contain pipe characters. @@ -53,125 +63,129 @@ pub struct ty_abbrev { pub type abbrev_map<'tcx> = RefCell, ty_abbrev>>; -pub fn enc_ty<'a, 'tcx>(w: &mut Encoder, cx: &ctxt<'a, 'tcx>, t: Ty<'tcx>) { +pub fn enc_ty<'a, 'tcx>(w: &mut Cursor>, cx: &ctxt<'a, 'tcx>, t: Ty<'tcx>) { match cx.abbrevs.borrow_mut().get(&t) { - Some(a) => { w.writer.write_all(&a.s); return; } + Some(a) => { w.write_all(&a.s); return; } None => {} } - // type abbreviations needs a stable position - let pos = w.mark_stable_position(); + let pos = w.position(); match t.sty { - ty::TyBool => mywrite!(w, "b"), - ty::TyChar => mywrite!(w, "c"), + ty::TyBool => { write!(w, "b"); } + ty::TyChar => { write!(w, "c"); } ty::TyInt(t) => { match t { - ast::TyIs => mywrite!(w, "is"), - ast::TyI8 => mywrite!(w, "MB"), - ast::TyI16 => mywrite!(w, "MW"), - ast::TyI32 => mywrite!(w, "ML"), - ast::TyI64 => mywrite!(w, "MD") - } + ast::TyIs => write!(w, "is"), + ast::TyI8 => write!(w, "MB"), + ast::TyI16 => write!(w, "MW"), + ast::TyI32 => write!(w, "ML"), + ast::TyI64 => write!(w, "MD") + }; } ty::TyUint(t) => { match t { - ast::TyUs => mywrite!(w, "us"), - ast::TyU8 => mywrite!(w, "Mb"), - ast::TyU16 => mywrite!(w, "Mw"), - ast::TyU32 => mywrite!(w, "Ml"), - ast::TyU64 => mywrite!(w, "Md") - } + ast::TyUs => write!(w, "us"), + ast::TyU8 => write!(w, "Mb"), + ast::TyU16 => write!(w, "Mw"), + ast::TyU32 => write!(w, "Ml"), + ast::TyU64 => write!(w, "Md") + }; } ty::TyFloat(t) => { match t { - ast::TyF32 => mywrite!(w, "Mf"), - ast::TyF64 => mywrite!(w, "MF"), - } + ast::TyF32 => write!(w, "Mf"), + ast::TyF64 => write!(w, "MF"), + }; } ty::TyEnum(def, substs) => { - mywrite!(w, "t[{}|", (cx.ds)(def.did)); + write!(w, "t[{}|", (cx.ds)(def.did)); enc_substs(w, cx, substs); - mywrite!(w, "]"); + write!(w, "]"); } ty::TyTrait(box ty::TraitTy { ref principal, ref bounds }) => { - mywrite!(w, "x["); + write!(w, "x["); enc_trait_ref(w, cx, principal.0); enc_existential_bounds(w, cx, bounds); - mywrite!(w, "]"); + write!(w, "]"); } ty::TyTuple(ref ts) => { - mywrite!(w, "T["); + write!(w, "T["); for t in ts { enc_ty(w, cx, *t); } - mywrite!(w, "]"); + write!(w, "]"); } - ty::TyBox(typ) => { mywrite!(w, "~"); enc_ty(w, cx, typ); } - ty::TyRawPtr(mt) => { mywrite!(w, "*"); enc_mt(w, cx, mt); } + ty::TyBox(typ) => { write!(w, "~"); enc_ty(w, cx, typ); } + ty::TyRawPtr(mt) => { write!(w, "*"); enc_mt(w, cx, mt); } ty::TyRef(r, mt) => { - mywrite!(w, "&"); + write!(w, "&"); enc_region(w, cx, *r); enc_mt(w, cx, mt); } ty::TyArray(t, sz) => { - mywrite!(w, "V"); + write!(w, "V"); enc_ty(w, cx, t); - mywrite!(w, "/{}|", sz); + write!(w, "/{}|", sz); } ty::TySlice(t) => { - mywrite!(w, "V"); + write!(w, "V"); enc_ty(w, cx, t); - mywrite!(w, "/|"); + write!(w, "/|"); } ty::TyStr => { - mywrite!(w, "v"); + write!(w, "v"); } ty::TyBareFn(Some(def_id), f) => { - mywrite!(w, "F"); - mywrite!(w, "{}|", (cx.ds)(def_id)); + write!(w, "F"); + write!(w, "{}|", (cx.ds)(def_id)); enc_bare_fn_ty(w, cx, f); } ty::TyBareFn(None, f) => { - mywrite!(w, "G"); + write!(w, "G"); enc_bare_fn_ty(w, cx, f); } ty::TyInfer(_) => { cx.diag.bug("cannot encode inference variable types"); } ty::TyParam(ParamTy {space, idx, name}) => { - mywrite!(w, "p[{}|{}|{}]", idx, space.to_uint(), name) + write!(w, "p[{}|{}|{}]", idx, space.to_uint(), name); } ty::TyStruct(def, substs) => { - mywrite!(w, "a[{}|", (cx.ds)(def.did)); + write!(w, "a[{}|", (cx.ds)(def.did)); enc_substs(w, cx, substs); - mywrite!(w, "]"); + write!(w, "]"); } ty::TyClosure(def, ref substs) => { - mywrite!(w, "k[{}|", (cx.ds)(def)); + write!(w, "k[{}|", (cx.ds)(def)); enc_substs(w, cx, &substs.func_substs); for ty in &substs.upvar_tys { enc_ty(w, cx, ty); } - mywrite!(w, "."); - mywrite!(w, "]"); + write!(w, "."); + write!(w, "]"); } ty::TyProjection(ref data) => { - mywrite!(w, "P["); + write!(w, "P["); enc_trait_ref(w, cx, data.trait_ref); - mywrite!(w, "{}]", data.item_name); + write!(w, "{}]", data.item_name); } ty::TyError => { - mywrite!(w, "e"); + write!(w, "e"); } } - let end = w.mark_stable_position(); + let end = w.position(); let len = end - pos; - let buf: &mut [u8] = &mut [0; 16]; // vuint < 15 bytes - let mut abbrev = Cursor::new(buf); + let mut abbrev = Cursor::new(Vec::with_capacity(16)); abbrev.write_all(b"#"); - writer::write_vuint(&mut abbrev, pos as usize); + { + let start_position = abbrev.position() as usize; + let bytes_written = leb128::write_unsigned_leb128(abbrev.get_mut(), + start_position, + pos); + abbrev.set_position((start_position + bytes_written) as u64); + } cx.abbrevs.borrow_mut().insert(t, ty_abbrev { s: if abbrev.position() < len { @@ -180,101 +194,105 @@ pub fn enc_ty<'a, 'tcx>(w: &mut Encoder, cx: &ctxt<'a, 'tcx>, t: Ty<'tcx>) { // if the abbreviation is longer than the real type, // don't use #-notation. However, insert it here so // other won't have to `mark_stable_position` - w.writer.get_ref()[pos as usize..end as usize].to_owned() + w.get_ref()[pos as usize .. end as usize].to_owned() } }); } -fn enc_mutability(w: &mut Encoder, mt: hir::Mutability) { +fn enc_mutability(w: &mut Cursor>, mt: hir::Mutability) { match mt { hir::MutImmutable => (), - hir::MutMutable => mywrite!(w, "m"), - } + hir::MutMutable => { + write!(w, "m"); + } + }; } -fn enc_mt<'a, 'tcx>(w: &mut Encoder, cx: &ctxt<'a, 'tcx>, +fn enc_mt<'a, 'tcx>(w: &mut Cursor>, cx: &ctxt<'a, 'tcx>, mt: ty::TypeAndMut<'tcx>) { enc_mutability(w, mt.mutbl); enc_ty(w, cx, mt.ty); } -fn enc_opt(w: &mut Encoder, t: Option, enc_f: F) where - F: FnOnce(&mut Encoder, T), +fn enc_opt(w: &mut Cursor>, t: Option, enc_f: F) where + F: FnOnce(&mut Cursor>, T), { match t { - None => mywrite!(w, "n"), + None => { + write!(w, "n"); + } Some(v) => { - mywrite!(w, "s"); + write!(w, "s"); enc_f(w, v); } } } -fn enc_vec_per_param_space<'a, 'tcx, T, F>(w: &mut Encoder, +fn enc_vec_per_param_space<'a, 'tcx, T, F>(w: &mut Cursor>, cx: &ctxt<'a, 'tcx>, v: &VecPerParamSpace, mut op: F) where - F: FnMut(&mut Encoder, &ctxt<'a, 'tcx>, &T), + F: FnMut(&mut Cursor>, &ctxt<'a, 'tcx>, &T), { for &space in &subst::ParamSpace::all() { - mywrite!(w, "["); + write!(w, "["); for t in v.get_slice(space) { op(w, cx, t); } - mywrite!(w, "]"); + write!(w, "]"); } } -pub fn enc_substs<'a, 'tcx>(w: &mut Encoder, cx: &ctxt<'a, 'tcx>, +pub fn enc_substs<'a, 'tcx>(w: &mut Cursor>, cx: &ctxt<'a, 'tcx>, substs: &subst::Substs<'tcx>) { enc_region_substs(w, cx, &substs.regions); enc_vec_per_param_space(w, cx, &substs.types, |w, cx, &ty| enc_ty(w, cx, ty)); } -fn enc_region_substs(w: &mut Encoder, cx: &ctxt, substs: &subst::RegionSubsts) { +fn enc_region_substs(w: &mut Cursor>, cx: &ctxt, substs: &subst::RegionSubsts) { match *substs { subst::ErasedRegions => { - mywrite!(w, "e"); + write!(w, "e"); } subst::NonerasedRegions(ref regions) => { - mywrite!(w, "n"); + write!(w, "n"); enc_vec_per_param_space(w, cx, regions, |w, cx, &r| enc_region(w, cx, r)); } } } -pub fn enc_region(w: &mut Encoder, cx: &ctxt, r: ty::Region) { +pub fn enc_region(w: &mut Cursor>, cx: &ctxt, r: ty::Region) { match r { ty::ReLateBound(id, br) => { - mywrite!(w, "b[{}|", id.depth); + write!(w, "b[{}|", id.depth); enc_bound_region(w, cx, br); - mywrite!(w, "]"); + write!(w, "]"); } ty::ReEarlyBound(ref data) => { - mywrite!(w, "B[{}|{}|{}]", - data.space.to_uint(), - data.index, - data.name); + write!(w, "B[{}|{}|{}]", + data.space.to_uint(), + data.index, + data.name); } ty::ReFree(ref fr) => { - mywrite!(w, "f["); + write!(w, "f["); enc_scope(w, cx, fr.scope); - mywrite!(w, "|"); + write!(w, "|"); enc_bound_region(w, cx, fr.bound_region); - mywrite!(w, "]"); + write!(w, "]"); } ty::ReScope(scope) => { - mywrite!(w, "s"); + write!(w, "s"); enc_scope(w, cx, scope); - mywrite!(w, "|"); + write!(w, "|"); } ty::ReStatic => { - mywrite!(w, "t"); + write!(w, "t"); } ty::ReEmpty => { - mywrite!(w, "e"); + write!(w, "e"); } ty::ReVar(_) | ty::ReSkolemized(..) => { // these should not crop up after typeck @@ -283,107 +301,107 @@ pub fn enc_region(w: &mut Encoder, cx: &ctxt, r: ty::Region) { } } -fn enc_scope(w: &mut Encoder, cx: &ctxt, scope: region::CodeExtent) { +fn enc_scope(w: &mut Cursor>, cx: &ctxt, scope: region::CodeExtent) { match cx.tcx.region_maps.code_extent_data(scope) { region::CodeExtentData::CallSiteScope { - fn_id, body_id } => mywrite!(w, "C[{}|{}]", fn_id, body_id), + fn_id, body_id } => write!(w, "C[{}|{}]", fn_id, body_id), region::CodeExtentData::ParameterScope { - fn_id, body_id } => mywrite!(w, "P[{}|{}]", fn_id, body_id), - region::CodeExtentData::Misc(node_id) => mywrite!(w, "M{}", node_id), + fn_id, body_id } => write!(w, "P[{}|{}]", fn_id, body_id), + region::CodeExtentData::Misc(node_id) => write!(w, "M{}", node_id), region::CodeExtentData::Remainder(region::BlockRemainder { - block: b, first_statement_index: i }) => mywrite!(w, "B[{}|{}]", b, i), - region::CodeExtentData::DestructionScope(node_id) => mywrite!(w, "D{}", node_id), - } + block: b, first_statement_index: i }) => write!(w, "B[{}|{}]", b, i), + region::CodeExtentData::DestructionScope(node_id) => write!(w, "D{}", node_id), + }; } -fn enc_bound_region(w: &mut Encoder, cx: &ctxt, br: ty::BoundRegion) { +fn enc_bound_region(w: &mut Cursor>, cx: &ctxt, br: ty::BoundRegion) { match br { ty::BrAnon(idx) => { - mywrite!(w, "a{}|", idx); + write!(w, "a{}|", idx); } ty::BrNamed(d, name) => { - mywrite!(w, "[{}|{}]", + write!(w, "[{}|{}]", (cx.ds)(d), name); } ty::BrFresh(id) => { - mywrite!(w, "f{}|", id); + write!(w, "f{}|", id); } ty::BrEnv => { - mywrite!(w, "e|"); + write!(w, "e|"); } } } -pub fn enc_trait_ref<'a, 'tcx>(w: &mut Encoder, cx: &ctxt<'a, 'tcx>, +pub fn enc_trait_ref<'a, 'tcx>(w: &mut Cursor>, cx: &ctxt<'a, 'tcx>, s: ty::TraitRef<'tcx>) { - mywrite!(w, "{}|", (cx.ds)(s.def_id)); + write!(w, "{}|", (cx.ds)(s.def_id)); enc_substs(w, cx, s.substs); } -fn enc_unsafety(w: &mut Encoder, p: hir::Unsafety) { +fn enc_unsafety(w: &mut Cursor>, p: hir::Unsafety) { match p { - hir::Unsafety::Normal => mywrite!(w, "n"), - hir::Unsafety::Unsafe => mywrite!(w, "u"), - } + hir::Unsafety::Normal => write!(w, "n"), + hir::Unsafety::Unsafe => write!(w, "u"), + }; } -fn enc_abi(w: &mut Encoder, abi: Abi) { - mywrite!(w, "["); - mywrite!(w, "{}", abi.name()); - mywrite!(w, "]") +fn enc_abi(w: &mut Cursor>, abi: Abi) { + write!(w, "["); + write!(w, "{}", abi.name()); + write!(w, "]"); } -pub fn enc_bare_fn_ty<'a, 'tcx>(w: &mut Encoder, cx: &ctxt<'a, 'tcx>, +pub fn enc_bare_fn_ty<'a, 'tcx>(w: &mut Cursor>, cx: &ctxt<'a, 'tcx>, ft: &ty::BareFnTy<'tcx>) { enc_unsafety(w, ft.unsafety); enc_abi(w, ft.abi); enc_fn_sig(w, cx, &ft.sig); } -pub fn enc_closure_ty<'a, 'tcx>(w: &mut Encoder, cx: &ctxt<'a, 'tcx>, +pub fn enc_closure_ty<'a, 'tcx>(w: &mut Cursor>, cx: &ctxt<'a, 'tcx>, ft: &ty::ClosureTy<'tcx>) { enc_unsafety(w, ft.unsafety); enc_fn_sig(w, cx, &ft.sig); enc_abi(w, ft.abi); } -fn enc_fn_sig<'a, 'tcx>(w: &mut Encoder, cx: &ctxt<'a, 'tcx>, +fn enc_fn_sig<'a, 'tcx>(w: &mut Cursor>, cx: &ctxt<'a, 'tcx>, fsig: &ty::PolyFnSig<'tcx>) { - mywrite!(w, "["); + write!(w, "["); for ty in &fsig.0.inputs { enc_ty(w, cx, *ty); } - mywrite!(w, "]"); + write!(w, "]"); if fsig.0.variadic { - mywrite!(w, "V"); + write!(w, "V"); } else { - mywrite!(w, "N"); + write!(w, "N"); } match fsig.0.output { ty::FnConverging(result_type) => { enc_ty(w, cx, result_type); } ty::FnDiverging => { - mywrite!(w, "z"); + write!(w, "z"); } } } -pub fn enc_builtin_bounds(w: &mut Encoder, _cx: &ctxt, bs: &ty::BuiltinBounds) { +pub fn enc_builtin_bounds(w: &mut Cursor>, _cx: &ctxt, bs: &ty::BuiltinBounds) { for bound in bs { match bound { - ty::BoundSend => mywrite!(w, "S"), - ty::BoundSized => mywrite!(w, "Z"), - ty::BoundCopy => mywrite!(w, "P"), - ty::BoundSync => mywrite!(w, "T"), - } + ty::BoundSend => write!(w, "S"), + ty::BoundSized => write!(w, "Z"), + ty::BoundCopy => write!(w, "P"), + ty::BoundSync => write!(w, "T"), + }; } - mywrite!(w, "."); + write!(w, "."); } -pub fn enc_existential_bounds<'a,'tcx>(w: &mut Encoder, +pub fn enc_existential_bounds<'a,'tcx>(w: &mut Cursor>, cx: &ctxt<'a,'tcx>, bs: &ty::ExistentialBounds<'tcx>) { enc_builtin_bounds(w, cx, &bs.builtin_bounds); @@ -391,90 +409,94 @@ pub fn enc_existential_bounds<'a,'tcx>(w: &mut Encoder, enc_region(w, cx, bs.region_bound); for tp in &bs.projection_bounds { - mywrite!(w, "P"); + write!(w, "P"); enc_projection_predicate(w, cx, &tp.0); } - mywrite!(w, "."); + write!(w, "."); } -pub fn enc_type_param_def<'a, 'tcx>(w: &mut Encoder, cx: &ctxt<'a, 'tcx>, +pub fn enc_type_param_def<'a, 'tcx>(w: &mut Cursor>, cx: &ctxt<'a, 'tcx>, v: &ty::TypeParameterDef<'tcx>) { - mywrite!(w, "{}:{}|{}|{}|{}|", + write!(w, "{}:{}|{}|{}|{}|", v.name, (cx.ds)(v.def_id), v.space.to_uint(), v.index, (cx.ds)(v.default_def_id)); enc_opt(w, v.default, |w, t| enc_ty(w, cx, t)); enc_object_lifetime_default(w, cx, v.object_lifetime_default); } -pub fn enc_region_param_def(w: &mut Encoder, cx: &ctxt, +pub fn enc_region_param_def(w: &mut Cursor>, cx: &ctxt, v: &ty::RegionParameterDef) { - mywrite!(w, "{}:{}|{}|{}|", + write!(w, "{}:{}|{}|{}|", v.name, (cx.ds)(v.def_id), v.space.to_uint(), v.index); for &r in &v.bounds { - mywrite!(w, "R"); + write!(w, "R"); enc_region(w, cx, r); } - mywrite!(w, "."); + write!(w, "."); } -fn enc_object_lifetime_default<'a, 'tcx>(w: &mut Encoder, +fn enc_object_lifetime_default<'a, 'tcx>(w: &mut Cursor>, cx: &ctxt<'a, 'tcx>, default: ty::ObjectLifetimeDefault) { match default { - ty::ObjectLifetimeDefault::Ambiguous => mywrite!(w, "a"), - ty::ObjectLifetimeDefault::BaseDefault => mywrite!(w, "b"), + ty::ObjectLifetimeDefault::Ambiguous => { + write!(w, "a"); + } + ty::ObjectLifetimeDefault::BaseDefault => { + write!(w, "b"); + } ty::ObjectLifetimeDefault::Specific(r) => { - mywrite!(w, "s"); + write!(w, "s"); enc_region(w, cx, r); } } } -pub fn enc_predicate<'a, 'tcx>(w: &mut Encoder, +pub fn enc_predicate<'a, 'tcx>(w: &mut Cursor>, cx: &ctxt<'a, 'tcx>, p: &ty::Predicate<'tcx>) { match *p { ty::Predicate::Trait(ref trait_ref) => { - mywrite!(w, "t"); + write!(w, "t"); enc_trait_ref(w, cx, trait_ref.0.trait_ref); } ty::Predicate::Equate(ty::Binder(ty::EquatePredicate(a, b))) => { - mywrite!(w, "e"); + write!(w, "e"); enc_ty(w, cx, a); enc_ty(w, cx, b); } ty::Predicate::RegionOutlives(ty::Binder(ty::OutlivesPredicate(a, b))) => { - mywrite!(w, "r"); + write!(w, "r"); enc_region(w, cx, a); enc_region(w, cx, b); } ty::Predicate::TypeOutlives(ty::Binder(ty::OutlivesPredicate(a, b))) => { - mywrite!(w, "o"); + write!(w, "o"); enc_ty(w, cx, a); enc_region(w, cx, b); } ty::Predicate::Projection(ty::Binder(ref data)) => { - mywrite!(w, "p"); - enc_projection_predicate(w, cx, data) + write!(w, "p"); + enc_projection_predicate(w, cx, data); } ty::Predicate::WellFormed(data) => { - mywrite!(w, "w"); + write!(w, "w"); enc_ty(w, cx, data); } ty::Predicate::ObjectSafe(trait_def_id) => { - mywrite!(w, "O{}|", (cx.ds)(trait_def_id)); + write!(w, "O{}|", (cx.ds)(trait_def_id)); } } } -fn enc_projection_predicate<'a, 'tcx>(w: &mut Encoder, +fn enc_projection_predicate<'a, 'tcx>(w: &mut Cursor>, cx: &ctxt<'a, 'tcx>, data: &ty::ProjectionPredicate<'tcx>) { enc_trait_ref(w, cx, data.projection_ty.trait_ref); - mywrite!(w, "{}|", data.projection_ty.item_name); + write!(w, "{}|", data.projection_ty.item_name); enc_ty(w, cx, data.ty); } diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs index 838a5435d4fee..be7e94f7d5e26 100644 --- a/src/librustc_trans/trans/base.rs +++ b/src/librustc_trans/trans/base.rs @@ -44,6 +44,7 @@ use middle::pat_util::simple_name; use middle::subst::Substs; use middle::ty::{self, Ty, HasTypeFlags}; use rustc::front::map as hir_map; +use rustc::util::common::time; use rustc_mir::mir_map::MirMap; use session::config::{self, NoDebugInfo, FullDebugInfo}; use session::Session; @@ -3053,7 +3054,9 @@ pub fn trans_crate<'tcx>(tcx: &ty::ctxt<'tcx>, let reachable_symbol_ids = filter_reachable_ids(&shared_ccx); // Translate the metadata. - let metadata = write_metadata(&shared_ccx, krate, &reachable_symbol_ids, mir_map); + let metadata = time(tcx.sess.time_passes(), "write metadata", || { + write_metadata(&shared_ccx, krate, &reachable_symbol_ids, mir_map) + }); if shared_ccx.sess().trans_stats() { let stats = shared_ccx.stats(); diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs index 18659cb2e78f1..19236f2cd98a8 100644 --- a/src/libsyntax/codemap.rs +++ b/src/libsyntax/codemap.rs @@ -164,18 +164,15 @@ impl Eq for Span {} impl Encodable for Span { fn encode(&self, s: &mut S) -> Result<(), S::Error> { - // Encode spans as a single u64 in order to cut down on tagging overhead - // added by the RBML metadata encoding. The should be solved differently - // altogether some time (FIXME #21482) - s.emit_u64( (self.lo.0 as u64) | ((self.hi.0 as u64) << 32) ) + try!(s.emit_u32(self.lo.0)); + s.emit_u32(self.hi.0) } } impl Decodable for Span { fn decode(d: &mut D) -> Result { - let lo_hi: u64 = try! { d.read_u64() }; - let lo = BytePos(lo_hi as u32); - let hi = BytePos((lo_hi >> 32) as u32); + let lo = BytePos(try! { d.read_u32() }); + let hi = BytePos(try! { d.read_u32() }); Ok(mk_sp(lo, hi)) } } From e137c2ad0a4436693a21637edb89424fc7546377 Mon Sep 17 00:00:00 2001 From: Simonas Kazlauskas Date: Mon, 28 Dec 2015 21:18:24 +0200 Subject: [PATCH 4/6] [MIR] Translate ConstVal::Function This moves back (essentially reverts #30265) into MIR-specific translation code, but keeps the funcition split out, since it is expected to eventually become recursive. --- src/librustc_trans/trans/consts.rs | 33 ------------------- src/librustc_trans/trans/mir/constant.rs | 42 ++++++++++++++++++++++-- src/test/run-pass/mir_refs_correct.rs | 7 ++++ 3 files changed, 46 insertions(+), 36 deletions(-) diff --git a/src/librustc_trans/trans/consts.rs b/src/librustc_trans/trans/consts.rs index 0fafe08178a27..fe7d29297a960 100644 --- a/src/librustc_trans/trans/consts.rs +++ b/src/librustc_trans/trans/consts.rs @@ -31,7 +31,6 @@ use trans::{adt, closure, debuginfo, expr, inline, machine}; use trans::base::{self, push_ctxt}; use trans::common::{self, type_is_sized, ExprOrMethodCall, node_id_substs, C_nil, const_get_elt}; use trans::common::{CrateContext, C_integral, C_floating, C_bool, C_str_slice, C_bytes, val_ty}; -use trans::common::C_floating_f64; use trans::common::{C_struct, C_undef, const_to_opt_int, const_to_opt_uint, VariantInfo, C_uint}; use trans::common::{type_is_fat_ptr, Field, C_vector, C_array, C_null, ExprId, MethodCallKey}; use trans::declare; @@ -108,38 +107,6 @@ pub fn const_lit(cx: &CrateContext, e: &hir::Expr, lit: &ast::Lit) } } -pub fn trans_constval<'blk, 'tcx>(bcx: common::Block<'blk, 'tcx>, - cv: &ConstVal, - ty: Ty<'tcx>, - param_substs: &'tcx Substs<'tcx>) - -> ValueRef -{ - let ccx = bcx.ccx(); - let llty = type_of::type_of(ccx, ty); - match *cv { - ConstVal::Float(v) => C_floating_f64(v, llty), - ConstVal::Bool(v) => C_bool(ccx, v), - ConstVal::Int(v) => C_integral(llty, v as u64, true), - ConstVal::Uint(v) => C_integral(llty, v, false), - ConstVal::Str(ref v) => C_str_slice(ccx, v.clone()), - ConstVal::ByteStr(ref v) => addr_of(ccx, C_bytes(ccx, v), 1, "byte_str"), - ConstVal::Struct(id) | ConstVal::Tuple(id) => { - let expr = bcx.tcx().map.expect_expr(id); - match const_expr(ccx, expr, param_substs, None, TrueConst::Yes) { - Ok((val, _)) => val, - Err(e) => panic!("const eval failure: {}", e.description()), - } - }, - ConstVal::Array(id, _) | ConstVal::Repeat(id, _) => { - let expr = bcx.tcx().map.expect_expr(id); - expr::trans(bcx, expr).datum.val - }, - ConstVal::Function(_) => { - unimplemented!() - }, - } -} - pub fn ptrcast(val: ValueRef, ty: Type) -> ValueRef { unsafe { llvm::LLVMConstPointerCast(val, ty.to_ref()) diff --git a/src/librustc_trans/trans/mir/constant.rs b/src/librustc_trans/trans/mir/constant.rs index 70a56990efd03..12839df87b159 100644 --- a/src/librustc_trans/trans/mir/constant.rs +++ b/src/librustc_trans/trans/mir/constant.rs @@ -9,11 +9,14 @@ // except according to those terms. use back::abi; +use llvm::ValueRef; +use middle::subst::Substs; use middle::ty::{Ty, HasTypeFlags}; use rustc::middle::const_eval::ConstVal; use rustc::mir::repr as mir; -use trans::consts; -use trans::common::{self, Block}; +use trans::common::{self, Block, C_bool, C_bytes, C_floating_f64, C_integral, C_str_slice}; +use trans::consts::{self, TrueConst}; +use trans::{type_of, expr}; use super::operand::{OperandRef, OperandValue}; @@ -27,7 +30,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { -> OperandRef<'tcx> { let ccx = bcx.ccx(); - let val = consts::trans_constval(bcx, cv, ty, bcx.fcx.param_substs); + let val = self.trans_constval_inner(bcx, cv, ty, bcx.fcx.param_substs); let val = if common::type_is_immediate(ccx, ty) { OperandValue::Immediate(val) } else if common::type_is_fat_ptr(bcx.tcx(), ty) { @@ -46,6 +49,39 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { } } + /// Translate ConstVal into a bare LLVM ValueRef. + fn trans_constval_inner(&mut self, + bcx: common::Block<'bcx, 'tcx>, + cv: &ConstVal, + ty: Ty<'tcx>, + param_substs: &'tcx Substs<'tcx>) + -> ValueRef + { + let ccx = bcx.ccx(); + let llty = type_of::type_of(ccx, ty); + match *cv { + ConstVal::Float(v) => C_floating_f64(v, llty), + ConstVal::Bool(v) => C_bool(ccx, v), + ConstVal::Int(v) => C_integral(llty, v as u64, true), + ConstVal::Uint(v) => C_integral(llty, v, false), + ConstVal::Str(ref v) => C_str_slice(ccx, v.clone()), + ConstVal::ByteStr(ref v) => consts::addr_of(ccx, C_bytes(ccx, v), 1, "byte_str"), + ConstVal::Struct(id) | ConstVal::Tuple(id) => { + let expr = bcx.tcx().map.expect_expr(id); + match consts::const_expr(ccx, expr, param_substs, None, TrueConst::Yes) { + Ok((val, _)) => val, + Err(e) => panic!("const eval failure: {}", e.description()), + } + }, + ConstVal::Array(id, _) | ConstVal::Repeat(id, _) => { + let expr = bcx.tcx().map.expect_expr(id); + expr::trans(bcx, expr).datum.val + }, + ConstVal::Function(did) => + self.trans_fn_ref(bcx, ty, param_substs, did).immediate() + } + } + pub fn trans_constant(&mut self, bcx: Block<'bcx, 'tcx>, constant: &mir::Constant<'tcx>) diff --git a/src/test/run-pass/mir_refs_correct.rs b/src/test/run-pass/mir_refs_correct.rs index b46ec0d8764d9..93953e3f58ae0 100644 --- a/src/test/run-pass/mir_refs_correct.rs +++ b/src/test/run-pass/mir_refs_correct.rs @@ -68,6 +68,7 @@ enum CEnum { const C: u8 = 84; const C2: [u8; 5] = [42; 5]; const C3: [u8; 3] = [42, 41, 40]; +const C4: fn(u8) -> S = S; fn regular() -> u8 { 21 @@ -198,6 +199,11 @@ fn t23() -> (CEnum, CEnum) { (CEnum::A, CEnum::B) } +#[rustc_mir] +fn t24() -> fn(u8) -> S { + C4 +} + fn main(){ unsafe { assert_eq!(t1()(), regular()); @@ -240,5 +246,6 @@ fn main(){ assert_eq!(t21(), Unit); assert_eq!(t22(), None); assert_eq!(t23(), (CEnum::A, CEnum::B)); + assert_eq!(t24(), C4); } } From b65277496c8848cd6f08b55e8b413096c74b92af Mon Sep 17 00:00:00 2001 From: Scott Olson Date: Tue, 29 Dec 2015 22:55:38 -0600 Subject: [PATCH 5/6] Fix argument indices in MIR for closures. Previously, all references to closure arguments went to the argument before the one they should (e.g. to arg1 when it was supposed to be arg2). This was because the MIR builder did not account for the implicit arguments that come before the explicit arguments, and closures have one implicit argument - the struct containing the captures. --- src/librustc_mir/build/mod.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index bd94f4e5bf257..7ea9301664f99 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -139,6 +139,7 @@ impl<'a,'tcx> Builder<'a,'tcx> { { self.in_scope(argument_extent, block, |this| { let arg_decls = { + let num_implicit_args = implicit_arguments.len(); let implicit_arg_decls = implicit_arguments.into_iter() .map(|ty| ArgDecl { ty: ty }); @@ -149,7 +150,7 @@ impl<'a,'tcx> Builder<'a,'tcx> { .into_iter() .enumerate() .map(|(index, (ty, pattern))| { - let lvalue = Lvalue::Arg(index as u32); + let lvalue = Lvalue::Arg((num_implicit_args + index) as u32); let pattern = this.hir.irrefutable_pat(pattern); unpack!(block = this.lvalue_into_pattern(block, argument_extent, From f8b61340e33bbb24709a862fd834ec10c871413c Mon Sep 17 00:00:00 2001 From: Scott Olson Date: Wed, 30 Dec 2015 06:55:51 -0600 Subject: [PATCH 6/6] Refactor MIR building for arguments. --- src/librustc_mir/build/mod.rs | 32 ++++++++++++++------------------ 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index 7ea9301664f99..8347a03cda6f7 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -138,29 +138,25 @@ impl<'a,'tcx> Builder<'a,'tcx> { -> BlockAnd>> { self.in_scope(argument_extent, block, |this| { - let arg_decls = { - let num_implicit_args = implicit_arguments.len(); - let implicit_arg_decls = implicit_arguments.into_iter() - .map(|ty| ArgDecl { ty: ty }); - - // to start, translate the argument patterns and collect the - // argument types. - let explicit_arg_decls = - explicit_arguments - .into_iter() - .enumerate() - .map(|(index, (ty, pattern))| { - let lvalue = Lvalue::Arg((num_implicit_args + index) as u32); + // to start, translate the argument patterns and collect the argument types. + let implicits = implicit_arguments.into_iter().map(|ty| (ty, None)); + let explicits = explicit_arguments.into_iter().map(|(ty, pat)| (ty, Some(pat))); + let arg_decls = + implicits + .chain(explicits) + .enumerate() + .map(|(index, (ty, pattern))| { + if let Some(pattern) = pattern { + let lvalue = Lvalue::Arg(index as u32); let pattern = this.hir.irrefutable_pat(pattern); unpack!(block = this.lvalue_into_pattern(block, argument_extent, pattern, &lvalue)); - ArgDecl { ty: ty } - }); - - implicit_arg_decls.chain(explicit_arg_decls).collect() - }; + } + ArgDecl { ty: ty } + }) + .collect(); // start the first basic block and translate the body unpack!(block = this.ast_block(&Lvalue::ReturnPointer, block, ast_block));