From 1f5fb3e056428c3eb130ebb6fc95c7e1b7a2d20e Mon Sep 17 00:00:00 2001 From: oli Date: Wed, 28 Oct 2020 13:12:49 +0000 Subject: [PATCH] Differentiate between the availability of ctfe MIR and runtime MIR --- compiler/rustc_metadata/src/rmeta/decoder.rs | 5 ++++- .../src/rmeta/decoder/cstore_impl.rs | 1 + compiler/rustc_middle/src/mir/query.rs | 2 +- compiler/rustc_middle/src/query/mod.rs | 13 ++++--------- compiler/rustc_middle/src/ty/mod.rs | 11 ++++++++++- .../rustc_mir/src/interpret/eval_context.rs | 2 +- .../src/monomorphize/polymorphize.rs | 19 +++++++++++++++---- compiler/rustc_mir/src/transform/mod.rs | 14 ++------------ 8 files changed, 38 insertions(+), 29 deletions(-) diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index ae8b379703a..a4cf4f096e0 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -1160,9 +1160,12 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { } } + fn is_ctfe_mir_available(&self, id: DefIndex) -> bool { + self.root.tables.mir_for_ctfe.get(self, id).is_some() + } + fn is_item_mir_available(&self, id: DefIndex) -> bool { self.root.tables.mir.get(self, id).is_some() - || self.root.tables.mir_for_ctfe.get(self, id).is_some() } fn module_expansion(&self, id: DefIndex, sess: &Session) -> ExpnId { diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 0398f9667b6..96db0157422 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -146,6 +146,7 @@ provide! { <'tcx> tcx, def_id, other, cdata, impl_parent => { cdata.get_parent_impl(def_id.index) } trait_of_item => { cdata.get_trait_of_item(def_id.index) } is_mir_available => { cdata.is_item_mir_available(def_id.index) } + is_ctfe_mir_available => { cdata.is_ctfe_mir_available(def_id.index) } dylib_dependency_formats => { cdata.get_dylib_dependency_formats(tcx) } is_panic_runtime => { cdata.root.panic_runtime } diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index 0fff7d98b29..3e4490e4915 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs @@ -444,7 +444,7 @@ impl<'tcx> TyCtxt<'tcx> { def: ty::WithOptConstParam, ) -> &'tcx Body<'tcx> { if let Some((did, param_did)) = def.as_const_arg() { - self.optimized_mir_of_const_arg((did, param_did)) + self.mir_for_ctfe_of_const_arg((did, param_did)) } else { self.optimized_mir(def.did) } diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 5edeb8c9e65..6da61486a55 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -346,15 +346,6 @@ rustc_queries! { cache_on_disk_if { key.is_local() } } - // FIXME: now that we have `mir_for_ctfe_of_const_arg` can we get - // rid of this query? - query optimized_mir_of_const_arg(key: (LocalDefId, DefId)) -> &'tcx mir::Body<'tcx> { - desc { - |tcx| "optimizing MIR for the const argument `{}`", - tcx.def_path_str(key.0.to_def_id()) - } - } - /// Returns coverage summary info for a function, after executing the `InstrumentCoverage` /// MIR pass (assuming the -Zinstrument-coverage option is enabled). query coverageinfo(key: DefId) -> mir::CoverageInfo { @@ -944,6 +935,10 @@ rustc_queries! { } Codegen { + // FIXME: remove after figuring out how to make miri able to detect non-Rust function calls + query is_ctfe_mir_available(key: DefId) -> bool { + desc { |tcx| "checking if item has ctfe mir available: `{}`", tcx.def_path_str(key) } + } query is_mir_available(key: DefId) -> bool { desc { |tcx| "checking if item has mir available: `{}`", tcx.def_path_str(key) } } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 1fe1400fabe..ca4db8abc0c 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -3010,7 +3010,16 @@ impl<'tcx> TyCtxt<'tcx> { /// Returns the possibly-auto-generated MIR of a `(DefId, Subst)` pair. pub fn instance_mir(self, instance: ty::InstanceDef<'tcx>) -> &'tcx Body<'tcx> { match instance { - ty::InstanceDef::Item(def) => self.optimized_mir_opt_const_arg(def), + ty::InstanceDef::Item(def) => match self.def_kind(def.did) { + DefKind::Const + | DefKind::Static + | DefKind::AssocConst + | DefKind::Ctor(..) + | DefKind::AnonConst => self.mir_for_ctfe_opt_const_arg(def), + // If the caller wants `mir_for_ctfe` they should not be using `instance_mir`, so + // we'll assume const fn also wants the optimized version. + _ => self.optimized_mir_opt_const_arg(def), + }, ty::InstanceDef::VtableShim(..) | ty::InstanceDef::ReifyShim(..) | ty::InstanceDef::Intrinsic(..) diff --git a/compiler/rustc_mir/src/interpret/eval_context.rs b/compiler/rustc_mir/src/interpret/eval_context.rs index 8cd09613074..b3b7c55db62 100644 --- a/compiler/rustc_mir/src/interpret/eval_context.rs +++ b/compiler/rustc_mir/src/interpret/eval_context.rs @@ -479,7 +479,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } match instance { ty::InstanceDef::Item(def) => { - if self.tcx.is_mir_available(def.did) { + if self.tcx.is_ctfe_mir_available(def.did) { Ok(self.tcx.mir_for_ctfe_opt_const_arg(def)) } else { throw_unsup!(NoMirFor(def.did)) diff --git a/compiler/rustc_mir/src/monomorphize/polymorphize.rs b/compiler/rustc_mir/src/monomorphize/polymorphize.rs index 7a8f630315f..d4185c063ef 100644 --- a/compiler/rustc_mir/src/monomorphize/polymorphize.rs +++ b/compiler/rustc_mir/src/monomorphize/polymorphize.rs @@ -54,9 +54,17 @@ fn unused_generic_params(tcx: TyCtxt<'_>, def_id: DefId) -> FiniteBitSet { } // Exit early when there is no MIR available. - if !tcx.is_mir_available(def_id) { - debug!("unused_generic_params: (no mir available) def_id={:?}", def_id); - return FiniteBitSet::new_empty(); + let context = tcx.hir().body_const_context(def_id.expect_local()); + match context { + None if !tcx.is_mir_available(def_id) => { + debug!("unused_generic_params: (no mir available) def_id={:?}", def_id); + return FiniteBitSet::new_empty(); + } + Some(_) if !tcx.is_ctfe_mir_available(def_id) => { + debug!("unused_generic_params: (no ctfe mir available) def_id={:?}", def_id); + return FiniteBitSet::new_empty(); + } + _ => {} } // Create a bitset with N rightmost ones for each parameter. @@ -69,8 +77,11 @@ fn unused_generic_params(tcx: TyCtxt<'_>, def_id: DefId) -> FiniteBitSet { debug!("unused_generic_params: (after default) unused_parameters={:?}", unused_parameters); // Visit MIR and accumululate used generic parameters. - let body = match tcx.hir().body_const_context(def_id.expect_local()) { + let body = match context { None => tcx.optimized_mir(def_id), + // FIXME(oli-obk): since this is solely used for codegen (I think?), should we keep using + // the optimized MIR for `const fn`? Need to adjust the above `is_mir_available` check + // in that case. Some(_) => tcx.mir_for_ctfe(def_id), }; let mut vis = MarkUsedGenericParams { tcx, def_id, unused_parameters: &mut unused_parameters }; diff --git a/compiler/rustc_mir/src/transform/mod.rs b/compiler/rustc_mir/src/transform/mod.rs index 52c2ba212a5..8a4c5c1ef69 100644 --- a/compiler/rustc_mir/src/transform/mod.rs +++ b/compiler/rustc_mir/src/transform/mod.rs @@ -74,8 +74,8 @@ pub(crate) fn provide(providers: &mut Providers) { mir_for_ctfe, mir_for_ctfe_of_const_arg, optimized_mir, - optimized_mir_of_const_arg, is_mir_available, + is_ctfe_mir_available: |tcx, did| is_mir_available(tcx, did), promoted_mir: |tcx, def_id| { let def_id = def_id.expect_local(); if let Some(def) = ty::WithOptConstParam::try_lookup(def_id, tcx) { @@ -518,22 +518,12 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { fn optimized_mir<'tcx>(tcx: TyCtxt<'tcx>, did: DefId) -> &'tcx Body<'tcx> { let did = did.expect_local(); if let Some(def) = ty::WithOptConstParam::try_lookup(did, tcx) { - tcx.optimized_mir_of_const_arg(def) + tcx.mir_for_ctfe_of_const_arg(def) } else { tcx.arena.alloc(inner_optimized_mir(tcx, ty::WithOptConstParam::unknown(did))) } } -fn optimized_mir_of_const_arg<'tcx>( - tcx: TyCtxt<'tcx>, - (did, param_did): (LocalDefId, DefId), -) -> &'tcx Body<'tcx> { - tcx.arena.alloc(inner_optimized_mir( - tcx, - ty::WithOptConstParam { did, const_param_did: Some(param_did) }, - )) -} - fn inner_optimized_mir(tcx: TyCtxt<'_>, def: ty::WithOptConstParam) -> Body<'_> { if tcx.is_constructor(def.did.to_def_id()) { // There's no reason to run all of the MIR passes on constructors when