From 8e105c0dfa765795fdb78c0905c8b11fc97c0a04 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Wed, 28 Feb 2018 05:20:30 +0200 Subject: [PATCH 1/3] rustc_metadata: support encoding/decoding Span's from other crates. --- src/librustc_metadata/creader.rs | 1 + src/librustc_metadata/cstore.rs | 2 + src/librustc_metadata/cstore_impl.rs | 2 +- src/librustc_metadata/decoder.rs | 100 ++++++++++++++++----------- src/librustc_metadata/encoder.rs | 27 ++++++-- src/librustc_metadata/lib.rs | 3 + src/librustc_metadata/schema.rs | 4 +- 7 files changed, 91 insertions(+), 48 deletions(-) diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 246f5c9255ef4..fd533adfcc4bb 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -248,6 +248,7 @@ impl<'a> CrateLoader<'a> { cnum_map: RefCell::new(cnum_map), cnum, codemap_import_info: RefCell::new(vec![]), + last_filemap_index: Cell::new(0), attribute_cache: RefCell::new([Vec::new(), Vec::new()]), dep_kind: Cell::new(dep_kind), source: cstore::CrateSource { diff --git a/src/librustc_metadata/cstore.rs b/src/librustc_metadata/cstore.rs index f3d0b38cfc060..1ec797841c323 100644 --- a/src/librustc_metadata/cstore.rs +++ b/src/librustc_metadata/cstore.rs @@ -67,6 +67,8 @@ pub struct CrateMetadata { pub cnum_map: RefCell, pub cnum: CrateNum, pub codemap_import_info: RefCell>, + // Cache the last used filemap for translating spans as an optimization. + pub last_filemap_index: Cell, pub attribute_cache: RefCell<[Vec>>; 2]>, pub root: schema::CrateRoot, diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index c1340d0a28a44..b16661d005fbf 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -67,7 +67,7 @@ macro_rules! provide { let $cdata = $tcx.crate_data_as_rc_any($def_id.krate); let $cdata = $cdata.downcast_ref::() - .expect("CrateStore crated ata is not a CrateMetadata"); + .expect("CrateStore crate data is not a CrateMetadata"); $compute })* diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 06728b2e6257c..e8cd1ed7f5efa 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -33,6 +33,7 @@ use std::cell::Ref; use std::collections::BTreeMap; use std::io; use std::mem; +use std::ops::RangeInclusive; use std::rc::Rc; use std::u32; @@ -50,9 +51,6 @@ pub struct DecodeContext<'a, 'tcx: 'a> { sess: Option<&'a Session>, tcx: Option>, - // Cache the last used filemap for translating spans as an optimization. - last_filemap_index: usize, - lazy_state: LazyState, } @@ -70,7 +68,7 @@ pub trait Metadata<'a, 'tcx>: Copy { cdata: self.cdata(), sess: self.sess().or(tcx.map(|tcx| tcx.sess)), tcx, - last_filemap_index: 0, + lazy_state: LazyState::NoNode, } } @@ -270,17 +268,17 @@ impl<'a, 'tcx> SpecializedDecoder for DecodeContext<'a, 'tcx> { impl<'a, 'tcx> SpecializedDecoder for DecodeContext<'a, 'tcx> { fn specialized_decode(&mut self) -> Result { - let tag = u8::decode(self)?; + let cnum_tag = u32::decode(self)?; - if tag == TAG_INVALID_SPAN { + if cnum_tag == TAG_INVALID_SPAN_CNUM { return Ok(DUMMY_SP) } - debug_assert_eq!(tag, TAG_VALID_SPAN); + let original_cnum = CrateNum::from_u32(cnum_tag - TAG_VALID_SPAN_CNUM_START); + let cnum = self.map_encoded_cnum_to_current(original_cnum); let lo = BytePos::decode(self)?; let len = BytePos::decode(self)?; - let hi = lo + len; let sess = if let Some(sess) = self.sess { sess @@ -288,45 +286,28 @@ impl<'a, 'tcx> SpecializedDecoder for DecodeContext<'a, 'tcx> { bug!("Cannot decode Span without Session.") }; - let imported_filemaps = self.cdata().imported_filemaps(&sess.codemap()); - let filemap = { - // Optimize for the case that most spans within a translated item - // originate from the same filemap. - let last_filemap = &imported_filemaps[self.last_filemap_index]; - - if lo >= last_filemap.original_start_pos && - lo <= last_filemap.original_end_pos { - last_filemap - } else { - let mut a = 0; - let mut b = imported_filemaps.len(); - - while b - a > 1 { - let m = (a + b) / 2; - if imported_filemaps[m].original_start_pos > lo { - b = m; - } else { - a = m; - } - } - - self.last_filemap_index = a; - &imported_filemaps[a] - } + let span_cdata_rc_any; + let span_cdata = if original_cnum == LOCAL_CRATE { + self.cdata() + } else { + // FIXME(eddyb) this requires the `tcx` which isn't always available. + // However, currently only MIR inlining can end up producing such + // cross-crate spans, and decoding MIR always provides a `tcx`. + span_cdata_rc_any = self.tcx().crate_data_as_rc_any(cnum); + span_cdata_rc_any.downcast_ref::() + .expect("CrateStore crate data is not a CrateMetadata") }; - // Make sure our binary search above is correct. - debug_assert!(lo >= filemap.original_start_pos && - lo <= filemap.original_end_pos); + let filemap = span_cdata.imported_filemap_containing(&sess.codemap(), lo, |filemap| { + filemap.original_start_pos..=filemap.original_end_pos + }); // Make sure we correctly filtered out invalid spans during encoding - debug_assert!(hi >= filemap.original_start_pos && - hi <= filemap.original_end_pos); + debug_assert!(lo + len >= filemap.original_start_pos && + lo + len <= filemap.original_end_pos); let lo = (lo + filemap.translated_filemap.start_pos) - filemap.original_start_pos; - let hi = (hi + filemap.translated_filemap.start_pos) - filemap.original_start_pos; - - Ok(Span::new(lo, hi, NO_EXPANSION)) + Ok(Span::new(lo, lo + len, NO_EXPANSION)) } } @@ -1169,4 +1150,41 @@ impl<'a, 'tcx> CrateMetadata { *self.codemap_import_info.borrow_mut() = imported_filemaps; self.codemap_import_info.borrow() } + + pub fn imported_filemap_containing(&'a self, + local_codemap: &codemap::CodeMap, + pos: BytePos, + range_of: F) + -> Ref<'a, cstore::ImportedFileMap> + where F: Fn(&cstore::ImportedFileMap) -> RangeInclusive + { + Ref::map(self.imported_filemaps(local_codemap), |imported_filemaps| { + // Optimize for the case that most spans within a translated item + // originate from the same filemap. + let last_filemap = &imported_filemaps[self.last_filemap_index.get()]; + if range_of(last_filemap).contains(pos) { + last_filemap + } else { + let mut a = 0; + let mut b = imported_filemaps.len(); + + while b - a > 1 { + let m = (a + b) / 2; + if range_of(&imported_filemaps[m]).start > pos { + b = m; + } else { + a = m; + } + } + + self.last_filemap_index.set(a); + let filemap = &imported_filemaps[a]; + + // Make sure our binary search above is correct. + debug_assert!(range_of(filemap).contains(pos)); + + filemap + } + }) + } } diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 78578ca179c82..96a841e590c5d 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use cstore::CrateMetadata; use index::Index; use index_builder::{FromId, IndexBuilder, Untracked}; use isolated_encoder::IsolatedEncoder; @@ -147,7 +148,7 @@ impl<'a, 'tcx> SpecializedEncoder for EncodeContext<'a, 'tcx> { impl<'a, 'tcx> SpecializedEncoder for EncodeContext<'a, 'tcx> { fn specialized_encode(&mut self, span: &Span) -> Result<(), Self::Error> { if *span == DUMMY_SP { - return TAG_INVALID_SPAN.encode(self) + return TAG_INVALID_SPAN_CNUM.encode(self) } let span = span.data(); @@ -164,11 +165,29 @@ impl<'a, 'tcx> SpecializedEncoder for EncodeContext<'a, 'tcx> { if !self.filemap_cache.contains(span.hi) { // Unfortunately, macro expansion still sometimes generates Spans // that malformed in this way. - return TAG_INVALID_SPAN.encode(self) + return TAG_INVALID_SPAN_CNUM.encode(self) } - TAG_VALID_SPAN.encode(self)?; - span.lo.encode(self)?; + let cnum = CrateNum::from_u32(self.filemap_cache.crate_of_origin); + let cnum_tag = TAG_VALID_SPAN_CNUM_START + cnum.as_u32(); + cnum_tag.encode(self)?; + let original_lo = if cnum == LOCAL_CRATE { + span.lo + } else { + // Imported spans were adjusted when they were decoded, so + // they have to be translated back into their crate of origin. + let codemap = self.tcx.sess.codemap(); + let span_cdata_rc_any = self.tcx.crate_data_as_rc_any(cnum); + let span_cdata = span_cdata_rc_any.downcast_ref::() + .expect("CrateStore crate data is not a CrateMetadata"); + // FIXME(eddyb) It'd be easier to just put `original_{start,end}_pos` + // in `syntax_pos::FileMap` instead of `ImportedFileMap`. + let filemap = span_cdata.imported_filemap_containing(&codemap, span.lo, |filemap| { + filemap.translated_filemap.start_pos..=filemap.translated_filemap.end_pos + }); + (span.lo + filemap.original_start_pos) - filemap.translated_filemap.start_pos + }; + original_lo.encode(self)?; // Encode length which is usually less than span.hi and profits more // from the variable-length integer encoding that we use. diff --git a/src/librustc_metadata/lib.rs b/src/librustc_metadata/lib.rs index 2d015fa81f925..51c78f7f7174e 100644 --- a/src/librustc_metadata/lib.rs +++ b/src/librustc_metadata/lib.rs @@ -17,9 +17,12 @@ #![feature(conservative_impl_trait)] #![feature(fs_read_write)] #![feature(i128_type)] +#![feature(inclusive_range)] +#![feature(inclusive_range_syntax)] #![feature(libc)] #![feature(proc_macro_internals)] #![feature(quote)] +#![feature(range_contains)] #![feature(rustc_diagnostic_macros)] #![feature(specialization)] #![feature(rustc_private)] diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index c542f65dcecf3..b5252fcfcd124 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -521,5 +521,5 @@ pub struct GeneratorData<'tcx> { impl_stable_hash_for!(struct GeneratorData<'tcx> { layout }); // Tags used for encoding Spans: -pub const TAG_VALID_SPAN: u8 = 0; -pub const TAG_INVALID_SPAN: u8 = 1; +pub const TAG_INVALID_SPAN_CNUM: u32 = 0; +pub const TAG_VALID_SPAN_CNUM_START: u32 = 1; From c44a20f1db42ee24df58309694c8e690b07e21a5 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Wed, 28 Feb 2018 05:20:42 +0200 Subject: [PATCH 2/3] rustc_mir: always run the inlining pass. --- src/librustc_mir/transform/inline.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs index 08a9757fb326a..776c7d0da327c 100644 --- a/src/librustc_mir/transform/inline.rs +++ b/src/librustc_mir/transform/inline.rs @@ -52,9 +52,7 @@ impl MirPass for Inline { tcx: TyCtxt<'a, 'tcx, 'tcx>, source: MirSource, mir: &mut Mir<'tcx>) { - if tcx.sess.opts.debugging_opts.mir_opt_level >= 2 { - Inliner { tcx, source }.run_pass(mir); - } + Inliner { tcx, source }.run_pass(mir); } } From f1878ff690160e0743511584040a47997581a817 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Wed, 28 Feb 2018 06:09:15 +0200 Subject: [PATCH 3/3] tests: hackily add some #[inline(never)]. --- src/test/codegen/internalize-closures.rs | 4 +++- src/test/codegen/remap_path_prefix/aux_mod.rs | 6 +++--- .../remap_path_prefix/auxiliary/remap_path_prefix_aux.rs | 6 +++--- src/test/codegen/remap_path_prefix/main.rs | 6 +++--- src/test/compile-fail/issue-22638.rs | 1 + src/test/compile-fail/type_length_limit.rs | 3 +++ src/test/debuginfo/associated-types.rs | 1 + 7 files changed, 17 insertions(+), 10 deletions(-) diff --git a/src/test/codegen/internalize-closures.rs b/src/test/codegen/internalize-closures.rs index 90aafd6a3bb3b..d7bbfa0043d71 100644 --- a/src/test/codegen/internalize-closures.rs +++ b/src/test/codegen/internalize-closures.rs @@ -10,11 +10,13 @@ // compile-flags: -C no-prepopulate-passes +#![feature(stmt_expr_attributes)] + pub fn main() { // We want to make sure that closures get 'internal' linkage instead of // 'weak_odr' when they are not shared between codegen units // CHECK: define internal {{.*}}_ZN20internalize_closures4main{{.*}}$u7b$$u7b$closure$u7d$$u7d$ - let c = |x:i32| { x + 1 }; + let c = #[inline(never)] |x:i32| { x + 1 }; let _ = c(1); } diff --git a/src/test/codegen/remap_path_prefix/aux_mod.rs b/src/test/codegen/remap_path_prefix/aux_mod.rs index 2a7019957af15..485478c77a4d1 100644 --- a/src/test/codegen/remap_path_prefix/aux_mod.rs +++ b/src/test/codegen/remap_path_prefix/aux_mod.rs @@ -10,7 +10,7 @@ // ignore-test: this is not a test -#[inline] -pub fn some_aux_mod_function() -> i32 { - 1234 +#[inline(never)] +pub fn some_aux_mod_function() -> usize { + ::std::mem::size_of::() } diff --git a/src/test/codegen/remap_path_prefix/auxiliary/remap_path_prefix_aux.rs b/src/test/codegen/remap_path_prefix/auxiliary/remap_path_prefix_aux.rs index 5543a091680f1..4941c29f8d39f 100644 --- a/src/test/codegen/remap_path_prefix/auxiliary/remap_path_prefix_aux.rs +++ b/src/test/codegen/remap_path_prefix/auxiliary/remap_path_prefix_aux.rs @@ -12,7 +12,7 @@ // compile-flags: -g -Zremap-path-prefix-from={{cwd}} -Zremap-path-prefix-to=/the/aux-cwd -Zremap-path-prefix-from={{src-base}}/remap_path_prefix/auxiliary -Zremap-path-prefix-to=/the/aux-src -#[inline] -pub fn some_aux_function() -> i32 { - 1234 +#[inline(never)] +pub fn some_aux_function() -> usize { + std::mem::size_of::() } diff --git a/src/test/codegen/remap_path_prefix/main.rs b/src/test/codegen/remap_path_prefix/main.rs index ea0c9ad2b8324..38d5cec8999d8 100644 --- a/src/test/codegen/remap_path_prefix/main.rs +++ b/src/test/codegen/remap_path_prefix/main.rs @@ -26,9 +26,9 @@ include!("aux_mod.rs"); pub static FILE_PATH: &'static str = file!(); fn main() { - remap_path_prefix_aux::some_aux_function(); - aux_mod::some_aux_mod_function(); - some_aux_mod_function(); + remap_path_prefix_aux::some_aux_function::<()>(); + aux_mod::some_aux_mod_function::<()>(); + some_aux_mod_function::<()>(); } // Here we check that local debuginfo is mapped correctly. diff --git a/src/test/compile-fail/issue-22638.rs b/src/test/compile-fail/issue-22638.rs index 1c534ebbd4350..db94cf7558875 100644 --- a/src/test/compile-fail/issue-22638.rs +++ b/src/test/compile-fail/issue-22638.rs @@ -57,6 +57,7 @@ impl C { struct D (Box); impl D { + #[inline(never)] pub fn matches(&self, f: &F) { //~^ ERROR reached the type-length limit while instantiating `D::matches::<[closure let &D(ref a) = self; diff --git a/src/test/compile-fail/type_length_limit.rs b/src/test/compile-fail/type_length_limit.rs index d283f392d7628..c9f8ad47eb950 100644 --- a/src/test/compile-fail/type_length_limit.rs +++ b/src/test/compile-fail/type_length_limit.rs @@ -30,6 +30,9 @@ link! { F, G } pub struct G; +#[inline(never)] +fn drop(_: T) {} + fn main() { drop::>(None); } diff --git a/src/test/debuginfo/associated-types.rs b/src/test/debuginfo/associated-types.rs index ccd94022711cd..f19788c01c293 100644 --- a/src/test/debuginfo/associated-types.rs +++ b/src/test/debuginfo/associated-types.rs @@ -125,6 +125,7 @@ fn assoc_return_value(arg: T) -> T::Type { return arg.get_value(); } +#[inline(never)] fn assoc_tuple(arg: (T, T::Type)) { zzz(); // #break }