summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_monomorphize
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-18 02:49:50 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-18 02:49:50 +0000
commit9835e2ae736235810b4ea1c162ca5e65c547e770 (patch)
tree3fcebf40ed70e581d776a8a4c65923e8ec20e026 /compiler/rustc_monomorphize
parentReleasing progress-linux version 1.70.0+dfsg2-1~progress7.99u1. (diff)
downloadrustc-9835e2ae736235810b4ea1c162ca5e65c547e770.tar.xz
rustc-9835e2ae736235810b4ea1c162ca5e65c547e770.zip
Merging upstream version 1.71.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_monomorphize')
-rw-r--r--compiler/rustc_monomorphize/Cargo.toml2
-rw-r--r--compiler/rustc_monomorphize/messages.ftl34
-rw-r--r--compiler/rustc_monomorphize/src/collector.rs10
-rw-r--r--compiler/rustc_monomorphize/src/lib.rs12
-rw-r--r--compiler/rustc_monomorphize/src/partitioning/default.rs170
-rw-r--r--compiler/rustc_monomorphize/src/partitioning/merging.rs111
-rw-r--r--compiler/rustc_monomorphize/src/partitioning/mod.rs197
-rw-r--r--compiler/rustc_monomorphize/src/polymorphize.rs12
-rw-r--r--compiler/rustc_monomorphize/src/util.rs4
9 files changed, 299 insertions, 253 deletions
diff --git a/compiler/rustc_monomorphize/Cargo.toml b/compiler/rustc_monomorphize/Cargo.toml
index c8af10576..6d3a3bf90 100644
--- a/compiler/rustc_monomorphize/Cargo.toml
+++ b/compiler/rustc_monomorphize/Cargo.toml
@@ -8,11 +8,11 @@ edition = "2021"
[dependencies]
serde = "1"
serde_json = "1"
-smallvec = { version = "1.8.1", features = [ "union", "may_dangle" ] }
tracing = "0.1"
rustc_data_structures = { path = "../rustc_data_structures" }
rustc_errors = { path = "../rustc_errors" }
rustc_hir = { path = "../rustc_hir" }
+rustc_fluent_macro = { path = "../rustc_fluent_macro" }
rustc_index = { path = "../rustc_index" }
rustc_macros = { path = "../rustc_macros" }
rustc_middle = { path = "../rustc_middle" }
diff --git a/compiler/rustc_monomorphize/messages.ftl b/compiler/rustc_monomorphize/messages.ftl
index 6cea6a603..fdd47e6f7 100644
--- a/compiler/rustc_monomorphize/messages.ftl
+++ b/compiler/rustc_monomorphize/messages.ftl
@@ -1,32 +1,32 @@
-monomorphize_recursion_limit =
- reached the recursion limit while instantiating `{$shrunk}`
- .note = `{$def_path_str}` defined here
-
-monomorphize_written_to_path = the full type name has been written to '{$path}'
-
-monomorphize_type_length_limit = reached the type-length limit while instantiating `{$shrunk}`
-
monomorphize_consider_type_length_limit =
consider adding a `#![type_length_limit="{$type_length}"]` attribute to your crate
-monomorphize_fatal_error = {$error_message}
-
-monomorphize_unknown_partition_strategy = unknown partitioning strategy
+monomorphize_couldnt_dump_mono_stats =
+ unexpected error occurred while dumping monomorphization stats: {$error}
-monomorphize_symbol_already_defined = symbol `{$symbol}` is already defined
+monomorphize_encountered_error_while_instantiating =
+ the above error was encountered while instantiating `{$formatted_item}`
-monomorphize_unused_generic_params = item has unused generic parameters
+monomorphize_fatal_error = {$error_message}
monomorphize_large_assignments =
moving {$size} bytes
.label = value moved from here
.note = The current maximum size is {$limit}, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]`
-monomorphize_couldnt_dump_mono_stats =
- unexpected error occurred while dumping monomorphization stats: {$error}
+monomorphize_recursion_limit =
+ reached the recursion limit while instantiating `{$shrunk}`
+ .note = `{$def_path_str}` defined here
-monomorphize_encountered_error_while_instantiating =
- the above error was encountered while instantiating `{$formatted_item}`
+monomorphize_symbol_already_defined = symbol `{$symbol}` is already defined
+
+monomorphize_type_length_limit = reached the type-length limit while instantiating `{$shrunk}`
monomorphize_unknown_cgu_collection_mode =
unknown codegen-item collection mode '{$mode}', falling back to 'lazy' mode
+
+monomorphize_unknown_partition_strategy = unknown partitioning strategy
+
+monomorphize_unused_generic_params = item has unused generic parameters
+
+monomorphize_written_to_path = the full type name has been written to '{$path}'
diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs
index 7bcff7e07..35b154b7b 100644
--- a/compiler/rustc_monomorphize/src/collector.rs
+++ b/compiler/rustc_monomorphize/src/collector.rs
@@ -185,9 +185,9 @@ use rustc_middle::mir::interpret::{ErrorHandled, GlobalAlloc, Scalar};
use rustc_middle::mir::mono::{InstantiationMode, MonoItem};
use rustc_middle::mir::visit::Visitor as MirVisitor;
use rustc_middle::mir::{self, Local, Location};
+use rustc_middle::query::TyCtxtAt;
use rustc_middle::ty::adjustment::{CustomCoerceUnsized, PointerCast};
use rustc_middle::ty::print::with_no_trimmed_paths;
-use rustc_middle::ty::query::TyCtxtAt;
use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts};
use rustc_middle::ty::{
self, GenericParamDefKind, Instance, InstanceDef, Ty, TyCtxt, TypeFoldable, TypeVisitableExt,
@@ -402,7 +402,7 @@ fn collect_roots(tcx: TyCtxt<'_>, mode: MonoItemCollectionMode) -> Vec<MonoItem<
}
/// Collect all monomorphized items reachable from `starting_point`, and emit a note diagnostic if a
-/// post-monorphization error is encountered during a collection step.
+/// post-monomorphization error is encountered during a collection step.
#[instrument(skip(tcx, visited, recursion_depths, recursion_limit, inlining_map), level = "debug")]
fn collect_items_rec<'tcx>(
tcx: TyCtxt<'tcx>,
@@ -677,7 +677,7 @@ impl<'a, 'tcx> MirNeighborCollector<'a, 'tcx> {
self.instance.subst_mir_and_normalize_erasing_regions(
self.tcx,
ty::ParamEnv::reveal_all(),
- value,
+ ty::EarlyBinder(value),
)
}
}
@@ -843,7 +843,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
}
}
mir::TerminatorKind::Assert { ref msg, .. } => {
- let lang_item = match msg {
+ let lang_item = match &**msg {
mir::AssertKind::BoundsCheck { .. } => LangItem::PanicBoundsCheck,
_ => LangItem::Panic,
};
@@ -1230,7 +1230,7 @@ impl<'v> RootCollector<'_, 'v> {
DefKind::GlobalAsm => {
debug!(
"RootCollector: ItemKind::GlobalAsm({})",
- self.tcx.def_path_str(id.owner_id.to_def_id())
+ self.tcx.def_path_str(id.owner_id)
);
self.output.push(dummy_spanned(MonoItem::GlobalAsm(id)));
}
diff --git a/compiler/rustc_monomorphize/src/lib.rs b/compiler/rustc_monomorphize/src/lib.rs
index 5000fb719..ecc50c3f6 100644
--- a/compiler/rustc_monomorphize/src/lib.rs
+++ b/compiler/rustc_monomorphize/src/lib.rs
@@ -10,11 +10,11 @@ extern crate tracing;
extern crate rustc_middle;
use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
+use rustc_fluent_macro::fluent_messages;
use rustc_hir::lang_items::LangItem;
-use rustc_macros::fluent_messages;
+use rustc_middle::query::{Providers, TyCtxtAt};
use rustc_middle::traits;
use rustc_middle::ty::adjustment::CustomCoerceUnsized;
-use rustc_middle::ty::query::{Providers, TyCtxtAt};
use rustc_middle::ty::{self, Ty};
mod collector;
@@ -30,8 +30,12 @@ fn custom_coerce_unsize_info<'tcx>(
source_ty: Ty<'tcx>,
target_ty: Ty<'tcx>,
) -> CustomCoerceUnsized {
- let trait_ref =
- ty::Binder::dummy(tcx.mk_trait_ref(LangItem::CoerceUnsized, [source_ty, target_ty]));
+ let trait_ref = ty::Binder::dummy(ty::TraitRef::from_lang_item(
+ tcx.tcx,
+ LangItem::CoerceUnsized,
+ tcx.span,
+ [source_ty, target_ty],
+ ));
match tcx.codegen_select_candidate((ty::ParamEnv::reveal_all(), trait_ref)) {
Ok(traits::ImplSource::UserDefined(traits::ImplSourceUserDefinedData {
diff --git a/compiler/rustc_monomorphize/src/partitioning/default.rs b/compiler/rustc_monomorphize/src/partitioning/default.rs
index 482b78d42..603b3ddc1 100644
--- a/compiler/rustc_monomorphize/src/partitioning/default.rs
+++ b/compiler/rustc_monomorphize/src/partitioning/default.rs
@@ -1,3 +1,4 @@
+use std::cmp;
use std::collections::hash_map::Entry;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
@@ -14,19 +15,19 @@ use rustc_span::symbol::Symbol;
use super::PartitioningCx;
use crate::collector::InliningMap;
-use crate::partitioning::merging;
-use crate::partitioning::{
- MonoItemPlacement, Partitioner, PostInliningPartitioning, PreInliningPartitioning,
-};
+use crate::partitioning::{MonoItemPlacement, Partition, PlacedRootMonoItems};
pub struct DefaultPartitioning;
-impl<'tcx> Partitioner<'tcx> for DefaultPartitioning {
- fn place_root_mono_items(
+impl<'tcx> Partition<'tcx> for DefaultPartitioning {
+ fn place_root_mono_items<I>(
&mut self,
cx: &PartitioningCx<'_, 'tcx>,
- mono_items: &mut dyn Iterator<Item = MonoItem<'tcx>>,
- ) -> PreInliningPartitioning<'tcx> {
+ mono_items: &mut I,
+ ) -> PlacedRootMonoItems<'tcx>
+ where
+ I: Iterator<Item = MonoItem<'tcx>>,
+ {
let mut roots = FxHashSet::default();
let mut codegen_units = FxHashMap::default();
let is_incremental_build = cx.tcx.sess.opts.incremental.is_some();
@@ -88,38 +89,120 @@ impl<'tcx> Partitioner<'tcx> for DefaultPartitioning {
codegen_units.insert(codegen_unit_name, CodegenUnit::new(codegen_unit_name));
}
- PreInliningPartitioning {
- codegen_units: codegen_units.into_values().map(|codegen_unit| codegen_unit).collect(),
- roots,
- internalization_candidates,
- }
+ let codegen_units = codegen_units.into_values().collect();
+ PlacedRootMonoItems { codegen_units, roots, internalization_candidates }
}
fn merge_codegen_units(
&mut self,
cx: &PartitioningCx<'_, 'tcx>,
- initial_partitioning: &mut PreInliningPartitioning<'tcx>,
+ codegen_units: &mut Vec<CodegenUnit<'tcx>>,
) {
- merging::merge_codegen_units(cx, initial_partitioning);
+ assert!(cx.target_cgu_count >= 1);
+
+ // Note that at this point in time the `codegen_units` here may not be
+ // in a deterministic order (but we know they're deterministically the
+ // same set). We want this merging to produce a deterministic ordering
+ // of codegen units from the input.
+ //
+ // Due to basically how we've implemented the merging below (merge the
+ // two smallest into each other) we're sure to start off with a
+ // deterministic order (sorted by name). This'll mean that if two cgus
+ // have the same size the stable sort below will keep everything nice
+ // and deterministic.
+ codegen_units.sort_by(|a, b| a.name().as_str().cmp(b.name().as_str()));
+
+ // This map keeps track of what got merged into what.
+ let mut cgu_contents: FxHashMap<Symbol, Vec<Symbol>> =
+ codegen_units.iter().map(|cgu| (cgu.name(), vec![cgu.name()])).collect();
+
+ // Merge the two smallest codegen units until the target size is
+ // reached.
+ while codegen_units.len() > cx.target_cgu_count {
+ // Sort small cgus to the back
+ codegen_units.sort_by_cached_key(|cgu| cmp::Reverse(cgu.size_estimate()));
+ let mut smallest = codegen_units.pop().unwrap();
+ let second_smallest = codegen_units.last_mut().unwrap();
+
+ // Move the mono-items from `smallest` to `second_smallest`
+ second_smallest.modify_size_estimate(smallest.size_estimate());
+ for (k, v) in smallest.items_mut().drain() {
+ second_smallest.items_mut().insert(k, v);
+ }
+
+ // Record that `second_smallest` now contains all the stuff that was
+ // in `smallest` before.
+ let mut consumed_cgu_names = cgu_contents.remove(&smallest.name()).unwrap();
+ cgu_contents.get_mut(&second_smallest.name()).unwrap().append(&mut consumed_cgu_names);
+
+ debug!(
+ "CodegenUnit {} merged into CodegenUnit {}",
+ smallest.name(),
+ second_smallest.name()
+ );
+ }
+
+ let cgu_name_builder = &mut CodegenUnitNameBuilder::new(cx.tcx);
+
+ if cx.tcx.sess.opts.incremental.is_some() {
+ // If we are doing incremental compilation, we want CGU names to
+ // reflect the path of the source level module they correspond to.
+ // For CGUs that contain the code of multiple modules because of the
+ // merging done above, we use a concatenation of the names of all
+ // contained CGUs.
+ let new_cgu_names: FxHashMap<Symbol, String> = cgu_contents
+ .into_iter()
+ // This `filter` makes sure we only update the name of CGUs that
+ // were actually modified by merging.
+ .filter(|(_, cgu_contents)| cgu_contents.len() > 1)
+ .map(|(current_cgu_name, cgu_contents)| {
+ let mut cgu_contents: Vec<&str> =
+ cgu_contents.iter().map(|s| s.as_str()).collect();
+
+ // Sort the names, so things are deterministic and easy to
+ // predict. We are sorting primitive `&str`s here so we can
+ // use unstable sort.
+ cgu_contents.sort_unstable();
+
+ (current_cgu_name, cgu_contents.join("--"))
+ })
+ .collect();
+
+ for cgu in codegen_units.iter_mut() {
+ if let Some(new_cgu_name) = new_cgu_names.get(&cgu.name()) {
+ if cx.tcx.sess.opts.unstable_opts.human_readable_cgu_names {
+ cgu.set_name(Symbol::intern(&new_cgu_name));
+ } else {
+ // If we don't require CGU names to be human-readable,
+ // we use a fixed length hash of the composite CGU name
+ // instead.
+ let new_cgu_name = CodegenUnit::mangle_name(&new_cgu_name);
+ cgu.set_name(Symbol::intern(&new_cgu_name));
+ }
+ }
+ }
+ } else {
+ // If we are compiling non-incrementally we just generate simple CGU
+ // names containing an index.
+ for (index, cgu) in codegen_units.iter_mut().enumerate() {
+ let numbered_codegen_unit_name =
+ cgu_name_builder.build_cgu_name_no_mangle(LOCAL_CRATE, &["cgu"], Some(index));
+ cgu.set_name(numbered_codegen_unit_name);
+ }
+ }
}
fn place_inlined_mono_items(
&mut self,
cx: &PartitioningCx<'_, 'tcx>,
- initial_partitioning: PreInliningPartitioning<'tcx>,
- ) -> PostInliningPartitioning<'tcx> {
- let mut new_partitioning = Vec::new();
+ codegen_units: &mut [CodegenUnit<'tcx>],
+ roots: FxHashSet<MonoItem<'tcx>>,
+ ) -> FxHashMap<MonoItem<'tcx>, MonoItemPlacement> {
let mut mono_item_placements = FxHashMap::default();
- let PreInliningPartitioning {
- codegen_units: initial_cgus,
- roots,
- internalization_candidates,
- } = initial_partitioning;
-
- let single_codegen_unit = initial_cgus.len() == 1;
+ let single_codegen_unit = codegen_units.len() == 1;
- for old_codegen_unit in initial_cgus {
+ for old_codegen_unit in codegen_units.iter_mut() {
// Collect all items that need to be available in this codegen unit.
let mut reachable = FxHashSet::default();
for root in old_codegen_unit.items().keys() {
@@ -171,14 +254,10 @@ impl<'tcx> Partitioner<'tcx> for DefaultPartitioning {
}
}
- new_partitioning.push(new_codegen_unit);
+ *old_codegen_unit = new_codegen_unit;
}
- return PostInliningPartitioning {
- codegen_units: new_partitioning,
- mono_item_placements,
- internalization_candidates,
- };
+ return mono_item_placements;
fn follow_inlining<'tcx>(
mono_item: MonoItem<'tcx>,
@@ -198,14 +277,16 @@ impl<'tcx> Partitioner<'tcx> for DefaultPartitioning {
fn internalize_symbols(
&mut self,
cx: &PartitioningCx<'_, 'tcx>,
- partitioning: &mut PostInliningPartitioning<'tcx>,
+ codegen_units: &mut [CodegenUnit<'tcx>],
+ mono_item_placements: FxHashMap<MonoItem<'tcx>, MonoItemPlacement>,
+ internalization_candidates: FxHashSet<MonoItem<'tcx>>,
) {
- if partitioning.codegen_units.len() == 1 {
+ if codegen_units.len() == 1 {
// Fast path for when there is only one codegen unit. In this case we
// can internalize all candidates, since there is nowhere else they
// could be accessed from.
- for cgu in &mut partitioning.codegen_units {
- for candidate in &partitioning.internalization_candidates {
+ for cgu in codegen_units {
+ for candidate in &internalization_candidates {
cgu.items_mut().insert(*candidate, (Linkage::Internal, Visibility::Default));
}
}
@@ -222,15 +303,13 @@ impl<'tcx> Partitioner<'tcx> for DefaultPartitioning {
}
});
- let mono_item_placements = &partitioning.mono_item_placements;
-
// For each internalization candidates in each codegen unit, check if it is
// accessed from outside its defining codegen unit.
- for cgu in &mut partitioning.codegen_units {
+ for cgu in codegen_units {
let home_cgu = MonoItemPlacement::SingleCgu { cgu_name: cgu.name() };
for (accessee, linkage_and_visibility) in cgu.items_mut() {
- if !partitioning.internalization_candidates.contains(accessee) {
+ if !internalization_candidates.contains(accessee) {
// This item is no candidate for internalizing, so skip it.
continue;
}
@@ -267,7 +346,7 @@ fn characteristic_def_id_of_mono_item<'tcx>(
match mono_item {
MonoItem::Fn(instance) => {
let def_id = match instance.def {
- ty::InstanceDef::Item(def) => def.did,
+ ty::InstanceDef::Item(def) => def,
ty::InstanceDef::VTableShim(..)
| ty::InstanceDef::ReifyShim(..)
| ty::InstanceDef::FnPtrShim(..)
@@ -302,12 +381,12 @@ fn characteristic_def_id_of_mono_item<'tcx>(
// When polymorphization is enabled, methods which do not depend on their generic
// parameters, but the self-type of their impl block do will fail to normalize.
- if !tcx.sess.opts.unstable_opts.polymorphize || !instance.needs_subst() {
+ if !tcx.sess.opts.unstable_opts.polymorphize || !instance.has_param() {
// This is a method within an impl, find out what the self-type is:
let impl_self_ty = tcx.subst_and_normalize_erasing_regions(
instance.substs,
ty::ParamEnv::reveal_all(),
- tcx.type_of(impl_def_id).skip_binder(),
+ tcx.type_of(impl_def_id),
);
if let Some(def_id) = characteristic_def_id_of_type(impl_self_ty) {
return Some(def_id);
@@ -421,10 +500,9 @@ fn mono_item_visibility<'tcx>(
};
let def_id = match instance.def {
- InstanceDef::Item(def) => def.did,
- InstanceDef::DropGlue(def_id, Some(_)) => def_id,
+ InstanceDef::Item(def_id) | InstanceDef::DropGlue(def_id, Some(_)) => def_id,
- // We match the visiblity of statics here
+ // We match the visibility of statics here
InstanceDef::ThreadLocalShim(def_id) => {
return static_visibility(tcx, can_be_internalized, def_id);
}
diff --git a/compiler/rustc_monomorphize/src/partitioning/merging.rs b/compiler/rustc_monomorphize/src/partitioning/merging.rs
deleted file mode 100644
index 5c524a184..000000000
--- a/compiler/rustc_monomorphize/src/partitioning/merging.rs
+++ /dev/null
@@ -1,111 +0,0 @@
-use std::cmp;
-
-use rustc_data_structures::fx::FxHashMap;
-use rustc_hir::def_id::LOCAL_CRATE;
-use rustc_middle::mir::mono::{CodegenUnit, CodegenUnitNameBuilder};
-use rustc_span::symbol::Symbol;
-
-use super::PartitioningCx;
-use crate::partitioning::PreInliningPartitioning;
-
-pub fn merge_codegen_units<'tcx>(
- cx: &PartitioningCx<'_, 'tcx>,
- initial_partitioning: &mut PreInliningPartitioning<'tcx>,
-) {
- assert!(cx.target_cgu_count >= 1);
- let codegen_units = &mut initial_partitioning.codegen_units;
-
- // Note that at this point in time the `codegen_units` here may not be in a
- // deterministic order (but we know they're deterministically the same set).
- // We want this merging to produce a deterministic ordering of codegen units
- // from the input.
- //
- // Due to basically how we've implemented the merging below (merge the two
- // smallest into each other) we're sure to start off with a deterministic
- // order (sorted by name). This'll mean that if two cgus have the same size
- // the stable sort below will keep everything nice and deterministic.
- codegen_units.sort_by(|a, b| a.name().as_str().cmp(b.name().as_str()));
-
- // This map keeps track of what got merged into what.
- let mut cgu_contents: FxHashMap<Symbol, Vec<Symbol>> =
- codegen_units.iter().map(|cgu| (cgu.name(), vec![cgu.name()])).collect();
-
- // Merge the two smallest codegen units until the target size is reached.
- while codegen_units.len() > cx.target_cgu_count {
- // Sort small cgus to the back
- codegen_units.sort_by_cached_key(|cgu| cmp::Reverse(cgu.size_estimate()));
- let mut smallest = codegen_units.pop().unwrap();
- let second_smallest = codegen_units.last_mut().unwrap();
-
- // Move the mono-items from `smallest` to `second_smallest`
- second_smallest.modify_size_estimate(smallest.size_estimate());
- for (k, v) in smallest.items_mut().drain() {
- second_smallest.items_mut().insert(k, v);
- }
-
- // Record that `second_smallest` now contains all the stuff that was in
- // `smallest` before.
- let mut consumed_cgu_names = cgu_contents.remove(&smallest.name()).unwrap();
- cgu_contents.get_mut(&second_smallest.name()).unwrap().append(&mut consumed_cgu_names);
-
- debug!(
- "CodegenUnit {} merged into CodegenUnit {}",
- smallest.name(),
- second_smallest.name()
- );
- }
-
- let cgu_name_builder = &mut CodegenUnitNameBuilder::new(cx.tcx);
-
- if cx.tcx.sess.opts.incremental.is_some() {
- // If we are doing incremental compilation, we want CGU names to
- // reflect the path of the source level module they correspond to.
- // For CGUs that contain the code of multiple modules because of the
- // merging done above, we use a concatenation of the names of
- // all contained CGUs.
- let new_cgu_names: FxHashMap<Symbol, String> = cgu_contents
- .into_iter()
- // This `filter` makes sure we only update the name of CGUs that
- // were actually modified by merging.
- .filter(|(_, cgu_contents)| cgu_contents.len() > 1)
- .map(|(current_cgu_name, cgu_contents)| {
- let mut cgu_contents: Vec<&str> = cgu_contents.iter().map(|s| s.as_str()).collect();
-
- // Sort the names, so things are deterministic and easy to
- // predict.
-
- // We are sorting primitive &strs here so we can use unstable sort
- cgu_contents.sort_unstable();
-
- (current_cgu_name, cgu_contents.join("--"))
- })
- .collect();
-
- for cgu in codegen_units.iter_mut() {
- if let Some(new_cgu_name) = new_cgu_names.get(&cgu.name()) {
- if cx.tcx.sess.opts.unstable_opts.human_readable_cgu_names {
- cgu.set_name(Symbol::intern(&new_cgu_name));
- } else {
- // If we don't require CGU names to be human-readable, we
- // use a fixed length hash of the composite CGU name
- // instead.
- let new_cgu_name = CodegenUnit::mangle_name(&new_cgu_name);
- cgu.set_name(Symbol::intern(&new_cgu_name));
- }
- }
- }
- } else {
- // If we are compiling non-incrementally we just generate simple CGU
- // names containing an index.
- for (index, cgu) in codegen_units.iter_mut().enumerate() {
- cgu.set_name(numbered_codegen_unit_name(cgu_name_builder, index));
- }
- }
-}
-
-fn numbered_codegen_unit_name(
- name_builder: &mut CodegenUnitNameBuilder<'_>,
- index: usize,
-) -> Symbol {
- name_builder.build_cgu_name_no_mangle(LOCAL_CRATE, &["cgu"], Some(index))
-}
diff --git a/compiler/rustc_monomorphize/src/partitioning/mod.rs b/compiler/rustc_monomorphize/src/partitioning/mod.rs
index 18aa0742c..d0b23ca9e 100644
--- a/compiler/rustc_monomorphize/src/partitioning/mod.rs
+++ b/compiler/rustc_monomorphize/src/partitioning/mod.rs
@@ -93,7 +93,6 @@
//! inlining, even when they are not marked `#[inline]`.
mod default;
-mod merging;
use std::cmp;
use std::fs::{self, File};
@@ -106,8 +105,8 @@ use rustc_hir::def_id::{DefIdSet, LOCAL_CRATE};
use rustc_middle::mir;
use rustc_middle::mir::mono::MonoItem;
use rustc_middle::mir::mono::{CodegenUnit, Linkage};
+use rustc_middle::query::Providers;
use rustc_middle::ty::print::with_no_trimmed_paths;
-use rustc_middle::ty::query::Providers;
use rustc_middle::ty::TyCtxt;
use rustc_session::config::{DumpMonoStatsFormat, SwitchWithOptPath};
use rustc_span::symbol::Symbol;
@@ -118,58 +117,135 @@ use crate::errors::{
CouldntDumpMonoStats, SymbolAlreadyDefined, UnknownCguCollectionMode, UnknownPartitionStrategy,
};
-pub struct PartitioningCx<'a, 'tcx> {
+enum Partitioner {
+ Default(default::DefaultPartitioning),
+ // Other partitioning strategies can go here.
+ Unknown,
+}
+
+impl<'tcx> Partition<'tcx> for Partitioner {
+ fn place_root_mono_items<I>(
+ &mut self,
+ cx: &PartitioningCx<'_, 'tcx>,
+ mono_items: &mut I,
+ ) -> PlacedRootMonoItems<'tcx>
+ where
+ I: Iterator<Item = MonoItem<'tcx>>,
+ {
+ match self {
+ Partitioner::Default(partitioner) => partitioner.place_root_mono_items(cx, mono_items),
+ Partitioner::Unknown => cx.tcx.sess.emit_fatal(UnknownPartitionStrategy),
+ }
+ }
+
+ fn merge_codegen_units(
+ &mut self,
+ cx: &PartitioningCx<'_, 'tcx>,
+ codegen_units: &mut Vec<CodegenUnit<'tcx>>,
+ ) {
+ match self {
+ Partitioner::Default(partitioner) => partitioner.merge_codegen_units(cx, codegen_units),
+ Partitioner::Unknown => cx.tcx.sess.emit_fatal(UnknownPartitionStrategy),
+ }
+ }
+
+ fn place_inlined_mono_items(
+ &mut self,
+ cx: &PartitioningCx<'_, 'tcx>,
+ codegen_units: &mut [CodegenUnit<'tcx>],
+ roots: FxHashSet<MonoItem<'tcx>>,
+ ) -> FxHashMap<MonoItem<'tcx>, MonoItemPlacement> {
+ match self {
+ Partitioner::Default(partitioner) => {
+ partitioner.place_inlined_mono_items(cx, codegen_units, roots)
+ }
+ Partitioner::Unknown => cx.tcx.sess.emit_fatal(UnknownPartitionStrategy),
+ }
+ }
+
+ fn internalize_symbols(
+ &mut self,
+ cx: &PartitioningCx<'_, 'tcx>,
+ codegen_units: &mut [CodegenUnit<'tcx>],
+ mono_item_placements: FxHashMap<MonoItem<'tcx>, MonoItemPlacement>,
+ internalization_candidates: FxHashSet<MonoItem<'tcx>>,
+ ) {
+ match self {
+ Partitioner::Default(partitioner) => partitioner.internalize_symbols(
+ cx,
+ codegen_units,
+ mono_item_placements,
+ internalization_candidates,
+ ),
+ Partitioner::Unknown => cx.tcx.sess.emit_fatal(UnknownPartitionStrategy),
+ }
+ }
+}
+
+struct PartitioningCx<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
target_cgu_count: usize,
inlining_map: &'a InliningMap<'tcx>,
}
-trait Partitioner<'tcx> {
- fn place_root_mono_items(
+pub struct PlacedRootMonoItems<'tcx> {
+ codegen_units: Vec<CodegenUnit<'tcx>>,
+ roots: FxHashSet<MonoItem<'tcx>>,
+ internalization_candidates: FxHashSet<MonoItem<'tcx>>,
+}
+
+trait Partition<'tcx> {
+ fn place_root_mono_items<I>(
&mut self,
cx: &PartitioningCx<'_, 'tcx>,
- mono_items: &mut dyn Iterator<Item = MonoItem<'tcx>>,
- ) -> PreInliningPartitioning<'tcx>;
+ mono_items: &mut I,
+ ) -> PlacedRootMonoItems<'tcx>
+ where
+ I: Iterator<Item = MonoItem<'tcx>>;
fn merge_codegen_units(
&mut self,
cx: &PartitioningCx<'_, 'tcx>,
- initial_partitioning: &mut PreInliningPartitioning<'tcx>,
+ codegen_units: &mut Vec<CodegenUnit<'tcx>>,
);
fn place_inlined_mono_items(
&mut self,
cx: &PartitioningCx<'_, 'tcx>,
- initial_partitioning: PreInliningPartitioning<'tcx>,
- ) -> PostInliningPartitioning<'tcx>;
+ codegen_units: &mut [CodegenUnit<'tcx>],
+ roots: FxHashSet<MonoItem<'tcx>>,
+ ) -> FxHashMap<MonoItem<'tcx>, MonoItemPlacement>;
fn internalize_symbols(
&mut self,
cx: &PartitioningCx<'_, 'tcx>,
- partitioning: &mut PostInliningPartitioning<'tcx>,
+ codegen_units: &mut [CodegenUnit<'tcx>],
+ mono_item_placements: FxHashMap<MonoItem<'tcx>, MonoItemPlacement>,
+ internalization_candidates: FxHashSet<MonoItem<'tcx>>,
);
}
-fn get_partitioner<'tcx>(tcx: TyCtxt<'tcx>) -> Box<dyn Partitioner<'tcx>> {
+fn get_partitioner(tcx: TyCtxt<'_>) -> Partitioner {
let strategy = match &tcx.sess.opts.unstable_opts.cgu_partitioning_strategy {
None => "default",
Some(s) => &s[..],
};
match strategy {
- "default" => Box::new(default::DefaultPartitioning),
- _ => {
- tcx.sess.emit_fatal(UnknownPartitionStrategy);
- }
+ "default" => Partitioner::Default(default::DefaultPartitioning),
+ _ => Partitioner::Unknown,
}
}
-pub fn partition<'tcx>(
+fn partition<'tcx, I>(
tcx: TyCtxt<'tcx>,
- mono_items: &mut dyn Iterator<Item = MonoItem<'tcx>>,
+ mono_items: &mut I,
max_cgu_count: usize,
inlining_map: &InliningMap<'tcx>,
-) -> Vec<CodegenUnit<'tcx>> {
+) -> Vec<CodegenUnit<'tcx>>
+where
+ I: Iterator<Item = MonoItem<'tcx>>,
+{
let _prof_timer = tcx.prof.generic_activity("cgu_partitioning");
let mut partitioner = get_partitioner(tcx);
@@ -177,40 +253,51 @@ pub fn partition<'tcx>(
// In the first step, we place all regular monomorphizations into their
// respective 'home' codegen unit. Regular monomorphizations are all
// functions and statics defined in the local crate.
- let mut initial_partitioning = {
+ let PlacedRootMonoItems { mut codegen_units, roots, internalization_candidates } = {
let _prof_timer = tcx.prof.generic_activity("cgu_partitioning_place_roots");
partitioner.place_root_mono_items(cx, mono_items)
};
- initial_partitioning.codegen_units.iter_mut().for_each(|cgu| cgu.create_size_estimate(tcx));
+ for cgu in &mut codegen_units {
+ cgu.create_size_estimate(tcx);
+ }
- debug_dump(tcx, "INITIAL PARTITIONING:", initial_partitioning.codegen_units.iter());
+ debug_dump(tcx, "INITIAL PARTITIONING", &codegen_units);
// Merge until we have at most `max_cgu_count` codegen units.
+ // `merge_codegen_units` is responsible for updating the CGU size
+ // estimates.
{
let _prof_timer = tcx.prof.generic_activity("cgu_partitioning_merge_cgus");
- partitioner.merge_codegen_units(cx, &mut initial_partitioning);
- debug_dump(tcx, "POST MERGING:", initial_partitioning.codegen_units.iter());
+ partitioner.merge_codegen_units(cx, &mut codegen_units);
+ debug_dump(tcx, "POST MERGING", &codegen_units);
}
// In the next step, we use the inlining map to determine which additional
// monomorphizations have to go into each codegen unit. These additional
// monomorphizations can be drop-glue, functions from external crates, and
// local functions the definition of which is marked with `#[inline]`.
- let mut post_inlining = {
+ let mono_item_placements = {
let _prof_timer = tcx.prof.generic_activity("cgu_partitioning_place_inline_items");
- partitioner.place_inlined_mono_items(cx, initial_partitioning)
+ partitioner.place_inlined_mono_items(cx, &mut codegen_units, roots)
};
- post_inlining.codegen_units.iter_mut().for_each(|cgu| cgu.create_size_estimate(tcx));
+ for cgu in &mut codegen_units {
+ cgu.create_size_estimate(tcx);
+ }
- debug_dump(tcx, "POST INLINING:", post_inlining.codegen_units.iter());
+ debug_dump(tcx, "POST INLINING", &codegen_units);
// Next we try to make as many symbols "internal" as possible, so LLVM has
// more freedom to optimize.
if !tcx.sess.link_dead_code() {
let _prof_timer = tcx.prof.generic_activity("cgu_partitioning_internalize_symbols");
- partitioner.internalize_symbols(cx, &mut post_inlining);
+ partitioner.internalize_symbols(
+ cx,
+ &mut codegen_units,
+ mono_item_placements,
+ internalization_candidates,
+ );
}
let instrument_dead_code =
@@ -218,7 +305,7 @@ pub fn partition<'tcx>(
if instrument_dead_code {
assert!(
- post_inlining.codegen_units.len() > 0,
+ codegen_units.len() > 0,
"There must be at least one CGU that code coverage data can be generated in."
);
@@ -229,7 +316,7 @@ pub fn partition<'tcx>(
// the object file (CGU) containing the dead function stubs is included
// in the final binary. This will probably require forcing these
// function symbols to be included via `-u` or `/include` linker args.
- let mut cgus: Vec<_> = post_inlining.codegen_units.iter_mut().collect();
+ let mut cgus: Vec<_> = codegen_units.iter_mut().collect();
cgus.sort_by_key(|cgu| cgu.size_estimate());
let dead_code_cgu =
@@ -240,27 +327,17 @@ pub fn partition<'tcx>(
} else {
// If there are no CGUs that have externally linked items,
// then we just pick the first CGU as a fallback.
- &mut post_inlining.codegen_units[0]
+ &mut codegen_units[0]
};
dead_code_cgu.make_code_coverage_dead_code_cgu();
}
// Finally, sort by codegen unit name, so that we get deterministic results.
- let PostInliningPartitioning {
- codegen_units: mut result,
- mono_item_placements: _,
- internalization_candidates: _,
- } = post_inlining;
+ codegen_units.sort_by(|a, b| a.name().as_str().cmp(b.name().as_str()));
- result.sort_by(|a, b| a.name().as_str().cmp(b.name().as_str()));
+ debug_dump(tcx, "FINAL", &codegen_units);
- result
-}
-
-pub struct PreInliningPartitioning<'tcx> {
- codegen_units: Vec<CodegenUnit<'tcx>>,
- roots: FxHashSet<MonoItem<'tcx>>,
- internalization_candidates: FxHashSet<MonoItem<'tcx>>,
+ codegen_units
}
/// For symbol internalization, we need to know whether a symbol/mono-item is
@@ -272,39 +349,37 @@ enum MonoItemPlacement {
MultipleCgus,
}
-struct PostInliningPartitioning<'tcx> {
- codegen_units: Vec<CodegenUnit<'tcx>>,
- mono_item_placements: FxHashMap<MonoItem<'tcx>, MonoItemPlacement>,
- internalization_candidates: FxHashSet<MonoItem<'tcx>>,
-}
-
-fn debug_dump<'a, 'tcx, I>(tcx: TyCtxt<'tcx>, label: &str, cgus: I)
-where
- I: Iterator<Item = &'a CodegenUnit<'tcx>>,
- 'tcx: 'a,
-{
+fn debug_dump<'a, 'tcx: 'a>(tcx: TyCtxt<'tcx>, label: &str, cgus: &[CodegenUnit<'tcx>]) {
let dump = move || {
use std::fmt::Write;
+ let num_cgus = cgus.len();
+ let max = cgus.iter().map(|cgu| cgu.size_estimate()).max().unwrap();
+ let min = cgus.iter().map(|cgu| cgu.size_estimate()).min().unwrap();
+ let ratio = max as f64 / min as f64;
+
let s = &mut String::new();
- let _ = writeln!(s, "{label}");
+ let _ = writeln!(
+ s,
+ "{label} ({num_cgus} CodegenUnits, max={max}, min={min}, max/min={ratio:.1}):"
+ );
for cgu in cgus {
let _ =
- writeln!(s, "CodegenUnit {} estimated size {} :", cgu.name(), cgu.size_estimate());
+ writeln!(s, "CodegenUnit {} estimated size {}:", cgu.name(), cgu.size_estimate());
for (mono_item, linkage) in cgu.items() {
let symbol_name = mono_item.symbol_name(tcx).name;
let symbol_hash_start = symbol_name.rfind('h');
let symbol_hash = symbol_hash_start.map_or("<no hash>", |i| &symbol_name[i..]);
- let _ = writeln!(
+ let _ = with_no_trimmed_paths!(writeln!(
s,
" - {} [{:?}] [{}] estimated size {}",
mono_item,
linkage,
symbol_hash,
mono_item.size_estimate(tcx)
- );
+ ));
}
let _ = writeln!(s);
@@ -380,7 +455,7 @@ fn collect_and_partition_mono_items(tcx: TyCtxt<'_>, (): ()) -> (&DefIdSet, &[Co
|| {
let mut codegen_units = partition(
tcx,
- &mut items.iter().cloned(),
+ &mut items.iter().copied(),
tcx.sess.codegen_units(),
&inlining_map,
);
diff --git a/compiler/rustc_monomorphize/src/polymorphize.rs b/compiler/rustc_monomorphize/src/polymorphize.rs
index 63263a642..88a3e0285 100644
--- a/compiler/rustc_monomorphize/src/polymorphize.rs
+++ b/compiler/rustc_monomorphize/src/polymorphize.rs
@@ -11,9 +11,9 @@ use rustc_middle::mir::{
visit::{TyContext, Visitor},
Constant, ConstantKind, Local, LocalDecl, Location,
};
+use rustc_middle::query::Providers;
use rustc_middle::ty::{
self,
- query::Providers,
subst::SubstsRef,
visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor},
Const, Ty, TyCtxt, UnusedGenericParams,
@@ -232,7 +232,7 @@ 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 instance = ty::InstanceDef::Item(ty::WithOptConstParam::unknown(def_id));
+ let instance = ty::InstanceDef::Item(def_id);
let unused = self.tcx.unused_generic_params(instance);
debug!(?self.unused_parameters, ?unused);
for (i, arg) in substs.iter().enumerate() {
@@ -272,10 +272,10 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
// Avoid considering `T` unused when constants are of the form:
// `<Self as Foo<T>>::foo::promoted[p]`
if let Some(p) = promoted {
- if self.def_id == def.did && !self.tcx.generics_of(def.did).has_self {
+ if self.def_id == def && !self.tcx.generics_of(def).has_self {
// If there is a promoted, don't look at the substs - since it will always contain
// the generic parameters, instead, traverse the promoted MIR.
- let promoted = self.tcx.promoted_mir(def.did);
+ let promoted = self.tcx.promoted_mir(def);
self.visit_body(&promoted[p]);
}
}
@@ -305,9 +305,9 @@ impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for MarkUsedGenericParams<'a, 'tcx> {
ControlFlow::Continue(())
}
ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, substs })
- if matches!(self.tcx.def_kind(def.did), DefKind::AnonConst) =>
+ if matches!(self.tcx.def_kind(def), DefKind::AnonConst) =>
{
- self.visit_child_body(def.did, substs);
+ self.visit_child_body(def, substs);
ControlFlow::Continue(())
}
_ => c.super_visit_with(self),
diff --git a/compiler/rustc_monomorphize/src/util.rs b/compiler/rustc_monomorphize/src/util.rs
index 33e1f6ce3..d12bfc6f6 100644
--- a/compiler/rustc_monomorphize/src/util.rs
+++ b/compiler/rustc_monomorphize/src/util.rs
@@ -29,12 +29,12 @@ pub(crate) fn dump_closure_profile<'tcx>(tcx: TyCtxt<'tcx>, closure_instance: In
let before_feature_tys = tcx.subst_and_normalize_erasing_regions(
closure_instance.substs,
param_env,
- before_feature_tys,
+ ty::EarlyBinder(before_feature_tys),
);
let after_feature_tys = tcx.subst_and_normalize_erasing_regions(
closure_instance.substs,
param_env,
- after_feature_tys,
+ ty::EarlyBinder(after_feature_tys),
);
let new_size = tcx