From 87a9ae224d946b44f325f42263bf8190584ba21d Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Wed, 7 Dec 2016 13:22:21 +0100 Subject: [PATCH 1/5] add a -Z flag to guarantee that MIR is generated for all functions --- src/librustc/session/config.rs | 2 ++ src/librustc_metadata/encoder.rs | 6 ++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 47f0de3ce5770..17b572e7f9e43 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -928,6 +928,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "print some statistics about AST and HIR"), mir_stats: bool = (false, parse_bool, [UNTRACKED], "print some statistics about MIR"), + always_encode_mir: bool = (false, parse_bool, [TRACKED], + "encode MIR of all functions into the crate metadata"), } pub fn default_lib_output() -> CrateType { diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 01cb0f823e8ef..d9bcdb36026e5 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -577,7 +577,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let types = generics.parent_types as usize + generics.types.len(); let needs_inline = types > 0 || attr::requests_inline(&ast_item.attrs); let is_const_fn = sig.constness == hir::Constness::Const; - (is_const_fn, needs_inline || is_const_fn) + let always_encode_mir = self.tcx.sess.opts.debugging_opts.always_encode_mir; + (is_const_fn, needs_inline || is_const_fn || always_encode_mir) } else { (false, false) }; @@ -842,7 +843,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { hir::ItemFn(_, _, constness, _, ref generics, _) => { let tps_len = generics.ty_params.len(); let needs_inline = tps_len > 0 || attr::requests_inline(&item.attrs); - if needs_inline || constness == hir::Constness::Const { + let always_encode_mir = self.tcx.sess.opts.debugging_opts.always_encode_mir; + if needs_inline || constness == hir::Constness::Const || always_encode_mir { self.encode_mir(def_id) } else { None From 9e158c5c087bab515e428916dbde1b5d3908c624 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Thu, 8 Dec 2016 10:34:44 +0100 Subject: [PATCH 2/5] also generate MIR for statics --- src/librustc_metadata/encoder.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index d9bcdb36026e5..443f3fbaa6e41 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -839,6 +839,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { _ => None, }, mir: match item.node { + hir::ItemStatic(..) | hir::ItemConst(..) => self.encode_mir(def_id), hir::ItemFn(_, _, constness, _, ref generics, _) => { let tps_len = generics.ty_params.len(); From acfb06fd593ed803a3da056c9d5acb399697d0e8 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Fri, 9 Dec 2016 11:27:45 +0100 Subject: [PATCH 3/5] remove double negation in comment --- src/librustc_trans/collector.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/librustc_trans/collector.rs b/src/librustc_trans/collector.rs index 087fe4decbf1d..d64fb95cbb631 100644 --- a/src/librustc_trans/collector.rs +++ b/src/librustc_trans/collector.rs @@ -706,9 +706,9 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { fn can_have_local_instance<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> bool { - // Take a look if we have the definition available. If not, we - // will not emit code for this item in the local crate, and thus - // don't create a translation item for it. + // Take a look if we have the definition available. If so, we + // will emit code for this item in the local crate, and thus + // create a translation item for it. def_id.is_local() || tcx.sess.cstore.is_item_mir_available(def_id) } From 910c369c9297b7e6a508bcc84b38fada8d5f4d7b Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Fri, 9 Dec 2016 16:31:53 +0100 Subject: [PATCH 4/5] enable checking for const fn without needing to go through `entry` --- src/librustc_metadata/decoder.rs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 2a6063cc4bda9..e07868877283f 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -504,6 +504,14 @@ impl<'tcx> EntryKind<'tcx> { EntryKind::Closure(_) => return None, }) } + fn is_const_fn(&self, meta: &CrateMetadata) -> bool { + let constness = match *self { + EntryKind::Method(data) => data.decode(meta).fn_data.constness, + EntryKind::Fn(data) => data.decode(meta).constness, + _ => hir::Constness::NotConst, + }; + constness == hir::Constness::Const + } } impl<'a, 'tcx> CrateMetadata { @@ -1051,12 +1059,7 @@ impl<'a, 'tcx> CrateMetadata { } pub fn is_const_fn(&self, id: DefIndex) -> bool { - let constness = match self.entry(id).kind { - EntryKind::Method(data) => data.decode(self).fn_data.constness, - EntryKind::Fn(data) => data.decode(self).constness, - _ => hir::Constness::NotConst, - }; - constness == hir::Constness::Const + self.entry(id).kind.is_const_fn(self) } pub fn is_foreign_item(&self, id: DefIndex) -> bool { From d74d15345cab54860a6e8cf19021372665ce0577 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Fri, 9 Dec 2016 17:29:01 +0100 Subject: [PATCH 5/5] move the check for instantiation from metadata encoding to the actual decision site before it was assumed that anything that had a MIR was fair game for local instatiation --- src/librustc/middle/cstore.rs | 8 ++++++++ src/librustc_metadata/cstore_impl.rs | 5 +++++ src/librustc_metadata/decoder.rs | 23 +++++++++++++++++++++++ src/librustc_trans/collector.rs | 5 +---- 4 files changed, 37 insertions(+), 4 deletions(-) diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index 78bbb03f40dac..f2be97c832370 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -355,6 +355,11 @@ pub trait CrateStore<'tcx> { fn get_item_mir<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> Mir<'tcx>; fn is_item_mir_available(&self, def: DefId) -> bool; + /// Take a look if we need to inline or monomorphize this. If so, we + /// will emit code for this item in the local crate, and thus + /// create a translation item for it. + fn can_have_local_instance<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> bool; + // This is basically a 1-based range of ints, which is a little // silly - I may fix that. fn crates(&self) -> Vec; @@ -528,6 +533,9 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore { fn is_item_mir_available(&self, def: DefId) -> bool { bug!("is_item_mir_available") } + fn can_have_local_instance<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> bool { + bug!("can_have_local_instance") + } // This is basically a 1-based range of ints, which is a little // silly - I may fix that. diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index 2882efb75b072..1a1bb1432eec1 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -527,6 +527,11 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { self.get_crate_data(def.krate).is_item_mir_available(def.index) } + fn can_have_local_instance<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> bool { + self.dep_graph.read(DepNode::MetaData(def)); + def.is_local() || self.get_crate_data(def.krate).can_have_local_instance(tcx, def.index) + } + fn crates(&self) -> Vec { let mut result = vec![]; diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index e07868877283f..54c195b188162 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -847,6 +847,29 @@ impl<'a, 'tcx> CrateMetadata { self.maybe_entry(id).and_then(|item| item.decode(self).mir).is_some() } + pub fn can_have_local_instance(&self, + tcx: TyCtxt<'a, 'tcx, 'tcx>, + id: DefIndex) -> bool { + self.maybe_entry(id).map_or(false, |item| { + let item = item.decode(self); + // if we don't have a MIR, then this item was never meant to be locally instantiated + // or we have a bug in the metadata serialization + item.mir.is_some() && ( + // items with generics always can have local instances if monomorphized + item.generics.map_or(false, |generics| { + let generics = generics.decode((self, tcx)); + generics.parent_types != 0 || !generics.types.is_empty() + }) || + match item.kind { + EntryKind::Closure(_) => true, + _ => false, + } || + item.kind.is_const_fn(self) || + attr::requests_inline(&self.get_attributes(&item)) + ) + }) + } + pub fn maybe_get_item_mir(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, id: DefIndex) diff --git a/src/librustc_trans/collector.rs b/src/librustc_trans/collector.rs index d64fb95cbb631..3af3ada66b3e9 100644 --- a/src/librustc_trans/collector.rs +++ b/src/librustc_trans/collector.rs @@ -706,10 +706,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { fn can_have_local_instance<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> bool { - // Take a look if we have the definition available. If so, we - // will emit code for this item in the local crate, and thus - // create a translation item for it. - def_id.is_local() || tcx.sess.cstore.is_item_mir_available(def_id) + tcx.sess.cstore.can_have_local_instance(tcx, def_id) } fn find_drop_glue_neighbors<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,