diff options
| author | David Wood <david.wood@huawei.com> | 2021-10-01 17:08:06 +0000 |
|---|---|---|
| committer | David Wood <david.wood@huawei.com> | 2021-10-01 17:08:06 +0000 |
| commit | 76b05531cab9bc24a54791b46b5bb9a7c3dcdd7c (patch) | |
| tree | 0ade4d9fac829bbf1b14af0437540c3546c11de1 /compiler/rustc_monomorphize/src | |
| parent | 4528b8e581eb1bb24f4f264d43244d7912f812f7 (diff) | |
| download | rust-76b05531cab9bc24a54791b46b5bb9a7c3dcdd7c.tar.gz rust-76b05531cab9bc24a54791b46b5bb9a7c3dcdd7c.zip | |
polymorphize: polymorphize shims
This commit removes the restriction of `InstanceDef::Item` on polymorphization, so that shims can now be polymorphized. Signed-off-by: David Wood <david.wood@huawei.com>
Diffstat (limited to 'compiler/rustc_monomorphize/src')
| -rw-r--r-- | compiler/rustc_monomorphize/src/collector.rs | 20 | ||||
| -rw-r--r-- | compiler/rustc_monomorphize/src/polymorphize.rs | 89 |
2 files changed, 65 insertions, 44 deletions
diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 5ccf8997d28..7b7c4d23af5 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -936,21 +936,13 @@ fn visit_instance_use<'tcx>( } } -// Returns `true` if we should codegen an instance in the local crate. -// Returns `false` if we can just link to the upstream crate and therefore don't -// need a mono item. +/// Returns `true` if we should codegen an instance in the local crate, or returns `false` if we +/// can just link to the upstream crate and therefore don't need a mono item. fn should_codegen_locally<'tcx>(tcx: TyCtxt<'tcx>, instance: &Instance<'tcx>) -> bool { - let def_id = match instance.def { - ty::InstanceDef::Item(def) => def.did, - ty::InstanceDef::DropGlue(def_id, Some(_)) => def_id, - ty::InstanceDef::VtableShim(..) - | ty::InstanceDef::ReifyShim(..) - | ty::InstanceDef::ClosureOnceShim { .. } - | ty::InstanceDef::Virtual(..) - | ty::InstanceDef::FnPtrShim(..) - | ty::InstanceDef::DropGlue(..) - | ty::InstanceDef::Intrinsic(_) - | ty::InstanceDef::CloneShim(..) => return true, + let def_id = if let Some(def_id) = instance.def.def_id_if_not_guaranteed_local_codegen() { + def_id + } else { + return true; }; if tcx.is_foreign_item(def_id) { diff --git a/compiler/rustc_monomorphize/src/polymorphize.rs b/compiler/rustc_monomorphize/src/polymorphize.rs index bb04f91e5ac..e6e4438b6d4 100644 --- a/compiler/rustc_monomorphize/src/polymorphize.rs +++ b/compiler/rustc_monomorphize/src/polymorphize.rs @@ -27,20 +27,23 @@ pub fn provide(providers: &mut Providers) { providers.unused_generic_params = unused_generic_params; } -/// Determine which generic parameters are used by the function/method/closure represented by -/// `def_id`. Returns a bitset where bits representing unused parameters are set (`is_empty` -/// indicates all parameters are used). +/// Determine which generic parameters are used by the instance. +/// +/// Returns a bitset where bits representing unused parameters are set (`is_empty` indicates all +/// parameters are used). #[instrument(level = "debug", skip(tcx))] -fn unused_generic_params(tcx: TyCtxt<'_>, def_id: DefId) -> FiniteBitSet<u32> { +fn unused_generic_params<'tcx>( + tcx: TyCtxt<'tcx>, + instance: ty::InstanceDef<'tcx>, +) -> FiniteBitSet<u32> { if !tcx.sess.opts.debugging_opts.polymorphize { // If polymorphization disabled, then all parameters are used. return FiniteBitSet::new_empty(); } - // Polymorphization results are stored in cross-crate metadata only when there are unused - // parameters, so assume that non-local items must have only used parameters (else this query - // would not be invoked, and the cross-crate metadata used instead). - if !def_id.is_local() { + let def_id = instance.def_id(); + // Exit early if this instance should not be polymorphized. + if !should_polymorphize(tcx, def_id, instance) { return FiniteBitSet::new_empty(); } @@ -52,38 +55,20 @@ fn unused_generic_params(tcx: TyCtxt<'_>, def_id: DefId) -> FiniteBitSet<u32> { return FiniteBitSet::new_empty(); } - // Exit early for foreign items, these have no bodies to analyze. - if tcx.is_foreign_item(def_id) { - return FiniteBitSet::new_empty(); - } - - // Exit early when there is no MIR available. - let context = tcx.hir().body_const_context(def_id.expect_local()); - match context { - Some(ConstContext::ConstFn) | None if !tcx.is_mir_available(def_id) => { - debug!("no mir available"); - return FiniteBitSet::new_empty(); - } - Some(_) if !tcx.is_ctfe_mir_available(def_id) => { - debug!("no ctfe mir available"); - return FiniteBitSet::new_empty(); - } - _ => {} - } - // Create a bitset with N rightmost ones for each parameter. let generics_count: u32 = generics.count().try_into().expect("more generic parameters than can fit into a `u32`"); let mut unused_parameters = FiniteBitSet::<u32>::new_empty(); unused_parameters.set_range(0..generics_count); debug!(?unused_parameters, "(start)"); + mark_used_by_default_parameters(tcx, def_id, generics, &mut unused_parameters); debug!(?unused_parameters, "(after default)"); // Visit MIR and accumululate used generic parameters. - let body = match context { + let body = match tcx.hir().body_const_context(def_id.expect_local()) { // Const functions are actually called and should thus be considered for polymorphization - // via their runtime MIR + // via their runtime MIR. Some(ConstContext::ConstFn) | None => tcx.optimized_mir(def_id), Some(_) => tcx.mir_for_ctfe(def_id), }; @@ -99,6 +84,49 @@ fn unused_generic_params(tcx: TyCtxt<'_>, def_id: DefId) -> FiniteBitSet<u32> { unused_parameters } +/// Returns `true` if the instance should be polymorphized. +fn should_polymorphize<'tcx>( + tcx: TyCtxt<'tcx>, + def_id: DefId, + instance: ty::InstanceDef<'tcx>, +) -> bool { + // If an instance's MIR body is not polymorphic then the modified substitutions that are + // derived from polymorphization's result won't make any difference. + if !instance.has_polymorphic_mir_body() { + return false; + } + + // Don't polymorphize intrinsics or virtual calls - calling `instance_mir` will panic. + if matches!(instance, ty::InstanceDef::Intrinsic(..) | ty::InstanceDef::Virtual(..)) { + return false; + } + + // Polymorphization results are stored in cross-crate metadata only when there are unused + // parameters, so assume that non-local items must have only used parameters (else this query + // would not be invoked, and the cross-crate metadata used instead). + if !def_id.is_local() { + return false; + } + + // Foreign items have no bodies to analyze. + if tcx.is_foreign_item(def_id) { + return false; + } + + // Make sure there is MIR available. + match tcx.hir().body_const_context(def_id.expect_local()) { + Some(ConstContext::ConstFn) | None if !tcx.is_mir_available(def_id) => { + debug!("no mir available"); + return false; + } + Some(_) if !tcx.is_ctfe_mir_available(def_id) => { + debug!("no ctfe mir available"); + return false; + } + _ => true, + } +} + /// Some parameters are considered used-by-default, such as non-generic parameters and the dummy /// generic parameters from closures, this function marks them as used. `leaf_is_closure` should /// be `true` if the item that `unused_generic_params` was invoked on is a closure. @@ -207,7 +235,8 @@ impl<'a, 'tcx> MarkUsedGenericParams<'a, 'tcx> { /// a closure, generator or constant). #[instrument(level = "debug", skip(self, def_id, substs))] fn visit_child_body(&mut self, def_id: DefId, substs: SubstsRef<'tcx>) { - let unused = self.tcx.unused_generic_params(def_id); + let instance = ty::InstanceDef::Item(ty::WithOptConstParam::unknown(def_id)); + let unused = self.tcx.unused_generic_params(instance); debug!(?self.unused_parameters, ?unused); for (i, arg) in substs.iter().enumerate() { let i = i.try_into().unwrap(); |
