2021-01-08 18:00:25 -05:00
|
|
|
use crate::dep_graph::{DepNode, WorkProduct, WorkProductId};
|
2020-03-24 09:09:42 +01:00
|
|
|
use crate::ich::{NodeIdHashingMode, StableHashingContext};
|
2019-12-22 17:42:04 -05:00
|
|
|
use crate::ty::{subst::InternalSubsts, Instance, InstanceDef, SymbolName, TyCtxt};
|
2021-01-11 16:27:59 -03:00
|
|
|
use rustc_attr::InlineAttr;
|
2018-01-08 12:30:52 +01:00
|
|
|
use rustc_data_structures::base_n;
|
2020-03-24 09:09:42 +01:00
|
|
|
use rustc_data_structures::fingerprint::Fingerprint;
|
2019-12-24 05:02:53 +01:00
|
|
|
use rustc_data_structures::fx::FxHashMap;
|
2019-09-26 18:54:39 -04:00
|
|
|
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
2020-04-18 16:34:41 +01:00
|
|
|
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
|
2021-01-30 19:18:48 +01:00
|
|
|
use rustc_hir::{HirId, ItemId};
|
2020-03-11 12:49:08 +01:00
|
|
|
use rustc_session::config::OptLevel;
|
2020-01-01 19:25:28 +01:00
|
|
|
use rustc_span::source_map::Span;
|
2020-01-01 19:30:57 +01:00
|
|
|
use rustc_span::symbol::Symbol;
|
2018-07-10 19:16:22 +02:00
|
|
|
use std::fmt;
|
2018-01-08 12:30:52 +01:00
|
|
|
use std::hash::Hash;
|
2017-09-12 11:04:46 -07:00
|
|
|
|
2019-05-24 10:57:30 -05:00
|
|
|
/// Describes how a monomorphization will be instantiated in object files.
|
2019-10-20 15:54:53 +11:00
|
|
|
#[derive(PartialEq)]
|
2019-05-24 10:57:30 -05:00
|
|
|
pub enum InstantiationMode {
|
|
|
|
/// There will be exactly one instance of the given MonoItem. It will have
|
|
|
|
/// external linkage so that it can be linked to from other codegen units.
|
|
|
|
GloballyShared {
|
|
|
|
/// In some compilation scenarios we may decide to take functions that
|
|
|
|
/// are typically `LocalCopy` and instead move them to `GloballyShared`
|
|
|
|
/// to avoid codegenning them a bunch of times. In this situation,
|
|
|
|
/// however, our local copy may conflict with other crates also
|
|
|
|
/// inlining the same function.
|
|
|
|
///
|
|
|
|
/// This flag indicates that this situation is occurring, and informs
|
|
|
|
/// symbol name calculation that some extra mangling is needed to
|
|
|
|
/// avoid conflicts. Note that this may eventually go away entirely if
|
|
|
|
/// ThinLTO enables us to *always* have a globally shared instance of a
|
|
|
|
/// function within one crate's compilation.
|
|
|
|
may_conflict: bool,
|
|
|
|
},
|
|
|
|
|
|
|
|
/// Each codegen unit containing a reference to the given MonoItem will
|
|
|
|
/// have its own private copy of the function (with internal linkage).
|
|
|
|
LocalCopy,
|
|
|
|
}
|
|
|
|
|
2017-09-12 11:04:46 -07:00
|
|
|
#[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)]
|
2017-10-25 17:04:24 +02:00
|
|
|
pub enum MonoItem<'tcx> {
|
2017-09-12 11:04:46 -07:00
|
|
|
Fn(Instance<'tcx>),
|
2018-02-19 13:29:22 +01:00
|
|
|
Static(DefId),
|
2021-01-30 19:18:48 +01:00
|
|
|
GlobalAsm(ItemId),
|
2017-09-12 11:04:46 -07:00
|
|
|
}
|
|
|
|
|
2018-01-15 18:28:34 +00:00
|
|
|
impl<'tcx> MonoItem<'tcx> {
|
2019-06-14 00:48:52 +03:00
|
|
|
pub fn size_estimate(&self, tcx: TyCtxt<'tcx>) -> usize {
|
2018-01-15 18:28:34 +00:00
|
|
|
match *self {
|
|
|
|
MonoItem::Fn(instance) => {
|
|
|
|
// Estimate the size of a function based on how many statements
|
|
|
|
// it contains.
|
2018-01-19 00:32:58 +00:00
|
|
|
tcx.instance_def_size_estimate(instance.def)
|
2019-12-22 17:42:04 -05:00
|
|
|
}
|
2018-01-15 18:28:34 +00:00
|
|
|
// Conservatively estimate the size of a static declaration
|
|
|
|
// or assembly to be 1.
|
2019-12-22 17:42:04 -05:00
|
|
|
MonoItem::Static(_) | MonoItem::GlobalAsm(_) => 1,
|
2018-01-15 18:28:34 +00:00
|
|
|
}
|
|
|
|
}
|
2019-05-24 10:57:30 -05:00
|
|
|
|
|
|
|
pub fn is_generic_fn(&self) -> bool {
|
|
|
|
match *self {
|
2019-12-22 17:42:04 -05:00
|
|
|
MonoItem::Fn(ref instance) => instance.substs.non_erasable_generics().next().is_some(),
|
|
|
|
MonoItem::Static(..) | MonoItem::GlobalAsm(..) => false,
|
2019-05-24 10:57:30 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-10 15:45:05 +10:00
|
|
|
pub fn symbol_name(&self, tcx: TyCtxt<'tcx>) -> SymbolName<'tcx> {
|
2019-05-24 10:57:30 -05:00
|
|
|
match *self {
|
|
|
|
MonoItem::Fn(instance) => tcx.symbol_name(instance),
|
2019-12-22 17:42:04 -05:00
|
|
|
MonoItem::Static(def_id) => tcx.symbol_name(Instance::mono(tcx, def_id)),
|
2021-01-30 19:18:48 +01:00
|
|
|
MonoItem::GlobalAsm(item_id) => {
|
2021-01-30 17:47:51 +01:00
|
|
|
SymbolName::new(tcx, &format!("global_asm_{:?}", item_id.def_id))
|
2019-05-24 10:57:30 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-14 00:48:52 +03:00
|
|
|
pub fn instantiation_mode(&self, tcx: TyCtxt<'tcx>) -> InstantiationMode {
|
2021-01-11 16:27:59 -03:00
|
|
|
let generate_cgu_internal_copies = tcx
|
|
|
|
.sess
|
|
|
|
.opts
|
|
|
|
.debugging_opts
|
|
|
|
.inline_in_all_cgus
|
|
|
|
.unwrap_or_else(|| tcx.sess.opts.optimize != OptLevel::No)
|
coverage bug fixes and optimization support
Adjusted LLVM codegen for code compiled with `-Zinstrument-coverage` to
address multiple, somewhat related issues.
Fixed a significant flaw in prior coverage solution: Every counter
generated a new counter variable, but there should have only been one
counter variable per function. This appears to have bloated .profraw
files significantly. (For a small program, it increased the size by
about 40%. I have not tested large programs, but there is anecdotal
evidence that profraw files were way too large. This is a good fix,
regardless, but hopefully it also addresses related issues.
Fixes: #82144
Invalid LLVM coverage data produced when compiled with -C opt-level=1
Existing tests now work up to at least `opt-level=3`. This required a
detailed analysis of the LLVM IR, comparisons with Clang C++ LLVM IR
when compiled with coverage, and a lot of trial and error with codegen
adjustments.
The biggest hurdle was figuring out how to continue to support coverage
results for unused functions and generics. Rust's coverage results have
three advantages over Clang's coverage results:
1. Rust's coverage map does not include any overlapping code regions,
making coverage counting unambiguous.
2. Rust generates coverage results (showing zero counts) for all unused
functions, including generics. (Clang does not generate coverage for
uninstantiated template functions.)
3. Rust's unused functions produce minimal stubbed functions in LLVM IR,
sufficient for including in the coverage results; while Clang must
generate the complete LLVM IR for each unused function, even though
it will never be called.
This PR removes the previous hack of attempting to inject coverage into
some other existing function instance, and generates dedicated instances
for each unused function. This change, and a few other adjustments
(similar to what is required for `-C link-dead-code`, but with lower
impact), makes it possible to support LLVM optimizations.
Fixes: #79651
Coverage report: "Unexecuted instantiation:..." for a generic function
from multiple crates
Fixed by removing the aforementioned hack. Some "Unexecuted
instantiation" notices are unavoidable, as explained in the
`used_crate.rs` test, but `-Zinstrument-coverage` has new options to
back off support for either unused generics, or all unused functions,
which avoids the notice, at the cost of less coverage of unused
functions.
Fixes: #82875
Invalid LLVM coverage data produced with crate brotli_decompressor
Fixed by disabling the LLVM function attribute that forces inlining, if
`-Z instrument-coverage` is enabled. This attribute is applied to
Rust functions with `#[inline(always)], and in some cases, the forced
inlining breaks coverage instrumentation and reports.
2021-03-15 16:32:45 -07:00
|
|
|
&& !tcx.sess.link_dead_code()
|
|
|
|
&& !tcx.sess.instrument_coverage();
|
|
|
|
// Disabled for `-Z instrument-coverage` because some LLVM optimizations can sometimes
|
|
|
|
// break coverage results. A test that failed at certain optimization levels is now
|
|
|
|
// validated at that optimization level (via `compile-flags` directive):
|
|
|
|
// * `src/test/run-make-fulldeps/coverage/closure.rs` broke with `-C opt-level=2`, and
|
|
|
|
// also required disabling `internalize_symbols` in
|
|
|
|
// `rustc_mir/monomorphize/partitioning/mod.rs`
|
2021-01-11 16:27:59 -03:00
|
|
|
|
2019-05-24 10:57:30 -05:00
|
|
|
match *self {
|
|
|
|
MonoItem::Fn(ref instance) => {
|
|
|
|
let entry_def_id = tcx.entry_fn(LOCAL_CRATE).map(|(id, _)| id);
|
2020-06-09 15:49:59 +01:00
|
|
|
// If this function isn't inlined or otherwise has an extern
|
|
|
|
// indicator, then we'll be creating a globally shared version.
|
|
|
|
if tcx.codegen_fn_attrs(instance.def_id()).contains_extern_indicator()
|
2020-01-20 15:54:40 +01:00
|
|
|
|| !instance.def.generates_cgu_internal_copy(tcx)
|
2020-04-18 16:34:41 +01:00
|
|
|
|| Some(instance.def_id()) == entry_def_id.map(LocalDefId::to_def_id)
|
2019-05-24 10:57:30 -05:00
|
|
|
{
|
2019-12-22 17:42:04 -05:00
|
|
|
return InstantiationMode::GloballyShared { may_conflict: false };
|
2019-05-24 10:57:30 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// At this point we don't have explicit linkage and we're an
|
2021-01-11 16:27:59 -03:00
|
|
|
// inlined function. If we're inlining into all CGUs then we'll
|
|
|
|
// be creating a local copy per CGU.
|
2020-06-09 15:49:59 +01:00
|
|
|
if generate_cgu_internal_copies {
|
2021-01-11 16:27:59 -03:00
|
|
|
return InstantiationMode::LocalCopy;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Finally, if this is `#[inline(always)]` we're sure to respect
|
|
|
|
// that with an inline copy per CGU, but otherwise we'll be
|
|
|
|
// creating one copy of this `#[inline]` function which may
|
|
|
|
// conflict with upstream crates as it could be an exported
|
|
|
|
// symbol.
|
|
|
|
match tcx.codegen_fn_attrs(instance.def_id()).inline {
|
|
|
|
InlineAttr::Always => InstantiationMode::LocalCopy,
|
|
|
|
_ => InstantiationMode::GloballyShared { may_conflict: true },
|
2019-05-24 10:57:30 -05:00
|
|
|
}
|
|
|
|
}
|
2019-12-22 17:42:04 -05:00
|
|
|
MonoItem::Static(..) | MonoItem::GlobalAsm(..) => {
|
2019-05-24 10:57:30 -05:00
|
|
|
InstantiationMode::GloballyShared { may_conflict: false }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-14 00:48:52 +03:00
|
|
|
pub fn explicit_linkage(&self, tcx: TyCtxt<'tcx>) -> Option<Linkage> {
|
2019-05-24 10:57:30 -05:00
|
|
|
let def_id = match *self {
|
|
|
|
MonoItem::Fn(ref instance) => instance.def_id(),
|
|
|
|
MonoItem::Static(def_id) => def_id,
|
|
|
|
MonoItem::GlobalAsm(..) => return None,
|
|
|
|
};
|
|
|
|
|
|
|
|
let codegen_fn_attrs = tcx.codegen_fn_attrs(def_id);
|
|
|
|
codegen_fn_attrs.linkage
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns `true` if this instance is instantiable - whether it has no unsatisfied
|
|
|
|
/// predicates.
|
|
|
|
///
|
|
|
|
/// In order to codegen an item, all of its predicates must hold, because
|
|
|
|
/// otherwise the item does not make sense. Type-checking ensures that
|
|
|
|
/// the predicates of every item that is *used by* a valid item *do*
|
|
|
|
/// hold, so we can rely on that.
|
|
|
|
///
|
|
|
|
/// However, we codegen collector roots (reachable items) and functions
|
|
|
|
/// in vtables when they are seen, even if they are not used, and so they
|
|
|
|
/// might not be instantiable. For example, a programmer can define this
|
|
|
|
/// public function:
|
|
|
|
///
|
|
|
|
/// pub fn foo<'a>(s: &'a mut ()) where &'a mut (): Clone {
|
|
|
|
/// <&mut () as Clone>::clone(&s);
|
|
|
|
/// }
|
|
|
|
///
|
|
|
|
/// That function can't be codegened, because the method `<&mut () as Clone>::clone`
|
|
|
|
/// does not exist. Luckily for us, that function can't ever be used,
|
|
|
|
/// because that would require for `&'a mut (): Clone` to hold, so we
|
|
|
|
/// can just not emit any code, or even a linker reference for it.
|
|
|
|
///
|
|
|
|
/// Similarly, if a vtable method has such a signature, and therefore can't
|
|
|
|
/// be used, we can just not emit it and have a placeholder (a null pointer,
|
|
|
|
/// which will never be accessed) in its place.
|
2019-06-14 00:48:52 +03:00
|
|
|
pub fn is_instantiable(&self, tcx: TyCtxt<'tcx>) -> bool {
|
2019-05-24 10:57:30 -05:00
|
|
|
debug!("is_instantiable({:?})", self);
|
|
|
|
let (def_id, substs) = match *self {
|
|
|
|
MonoItem::Fn(ref instance) => (instance.def_id(), instance.substs),
|
|
|
|
MonoItem::Static(def_id) => (def_id, InternalSubsts::empty()),
|
|
|
|
// global asm never has predicates
|
2019-12-22 17:42:04 -05:00
|
|
|
MonoItem::GlobalAsm(..) => return true,
|
2019-05-24 10:57:30 -05:00
|
|
|
};
|
|
|
|
|
2020-06-22 13:22:45 +01:00
|
|
|
!tcx.subst_and_check_impossible_predicates((def_id, &substs))
|
2019-05-24 10:57:30 -05:00
|
|
|
}
|
|
|
|
|
2019-06-14 00:48:52 +03:00
|
|
|
pub fn local_span(&self, tcx: TyCtxt<'tcx>) -> Option<Span> {
|
2019-05-24 10:57:30 -05:00
|
|
|
match *self {
|
2020-04-12 13:45:41 +01:00
|
|
|
MonoItem::Fn(Instance { def, .. }) => {
|
2020-08-12 12:22:56 +02:00
|
|
|
def.def_id().as_local().map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id))
|
2020-04-12 13:45:41 +01:00
|
|
|
}
|
|
|
|
MonoItem::Static(def_id) => {
|
2020-08-12 12:22:56 +02:00
|
|
|
def_id.as_local().map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id))
|
2020-04-12 13:45:41 +01:00
|
|
|
}
|
2021-01-30 19:18:48 +01:00
|
|
|
MonoItem::GlobalAsm(item_id) => Some(item_id.hir_id()),
|
2019-12-22 17:42:04 -05:00
|
|
|
}
|
|
|
|
.map(|hir_id| tcx.hir().span(hir_id))
|
2019-05-24 10:57:30 -05:00
|
|
|
}
|
2018-01-15 18:28:34 +00:00
|
|
|
}
|
|
|
|
|
2018-01-16 10:16:38 +01:00
|
|
|
impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for MonoItem<'tcx> {
|
2019-09-26 18:54:39 -04:00
|
|
|
fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
|
2017-09-18 12:14:52 +02:00
|
|
|
::std::mem::discriminant(self).hash_stable(hcx, hasher);
|
|
|
|
|
|
|
|
match *self {
|
2017-10-25 17:04:24 +02:00
|
|
|
MonoItem::Fn(ref instance) => {
|
2017-09-18 12:14:52 +02:00
|
|
|
instance.hash_stable(hcx, hasher);
|
|
|
|
}
|
2018-07-13 11:30:47 -07:00
|
|
|
MonoItem::Static(def_id) => {
|
2018-02-19 13:29:22 +01:00
|
|
|
def_id.hash_stable(hcx, hasher);
|
|
|
|
}
|
2021-01-30 19:18:48 +01:00
|
|
|
MonoItem::GlobalAsm(item_id) => {
|
2017-09-18 12:14:52 +02:00
|
|
|
hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
|
2021-01-30 19:18:48 +01:00
|
|
|
item_id.hash_stable(hcx, hasher);
|
2017-09-18 12:14:52 +02:00
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-28 14:31:03 +01:00
|
|
|
impl<'tcx> fmt::Display for MonoItem<'tcx> {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
|
|
match *self {
|
|
|
|
MonoItem::Fn(instance) => write!(f, "fn {}", instance),
|
|
|
|
MonoItem::Static(def_id) => {
|
|
|
|
write!(f, "static {}", Instance::new(def_id, InternalSubsts::empty()))
|
|
|
|
}
|
|
|
|
MonoItem::GlobalAsm(..) => write!(f, "global_asm"),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-03 09:19:16 -05:00
|
|
|
#[derive(Debug)]
|
2017-09-12 11:04:46 -07:00
|
|
|
pub struct CodegenUnit<'tcx> {
|
|
|
|
/// A name for this CGU. Incremental compilation requires that
|
2019-02-08 14:53:55 +01:00
|
|
|
/// name be unique amongst **all** crates. Therefore, it should
|
2017-09-12 11:04:46 -07:00
|
|
|
/// contain something unique to this crate (e.g., a module path)
|
|
|
|
/// as well as the crate name and disambiguator.
|
2019-10-21 17:14:03 +11:00
|
|
|
name: Symbol,
|
2017-10-25 17:04:24 +02:00
|
|
|
items: FxHashMap<MonoItem<'tcx>, (Linkage, Visibility)>,
|
2018-01-15 18:28:34 +00:00
|
|
|
size_estimate: Option<usize>,
|
2017-09-12 11:04:46 -07:00
|
|
|
}
|
|
|
|
|
2020-05-12 08:11:58 -04:00
|
|
|
/// Specifies the linkage type for a `MonoItem`.
|
|
|
|
///
|
2020-11-05 14:33:23 +01:00
|
|
|
/// See <https://llvm.org/docs/LangRef.html#linkage-types> for more details about these variants.
|
2020-06-29 21:09:54 +01:00
|
|
|
#[derive(Copy, Clone, PartialEq, Debug, TyEncodable, TyDecodable, HashStable)]
|
2017-09-12 11:04:46 -07:00
|
|
|
pub enum Linkage {
|
|
|
|
External,
|
|
|
|
AvailableExternally,
|
|
|
|
LinkOnceAny,
|
|
|
|
LinkOnceODR,
|
|
|
|
WeakAny,
|
|
|
|
WeakODR,
|
|
|
|
Appending,
|
|
|
|
Internal,
|
|
|
|
Private,
|
|
|
|
ExternalWeak,
|
|
|
|
Common,
|
|
|
|
}
|
|
|
|
|
2019-11-09 23:28:07 +01:00
|
|
|
#[derive(Copy, Clone, PartialEq, Debug, HashStable)]
|
2017-09-12 11:04:46 -07:00
|
|
|
pub enum Visibility {
|
|
|
|
Default,
|
|
|
|
Hidden,
|
|
|
|
Protected,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'tcx> CodegenUnit<'tcx> {
|
2019-10-21 17:14:03 +11:00
|
|
|
pub fn new(name: Symbol) -> CodegenUnit<'tcx> {
|
2020-03-06 19:28:44 +01:00
|
|
|
CodegenUnit { name, items: Default::default(), size_estimate: None }
|
2017-09-12 11:04:46 -07:00
|
|
|
}
|
|
|
|
|
2019-10-21 17:14:03 +11:00
|
|
|
pub fn name(&self) -> Symbol {
|
|
|
|
self.name
|
2017-09-12 11:04:46 -07:00
|
|
|
}
|
|
|
|
|
2019-10-21 17:14:03 +11:00
|
|
|
pub fn set_name(&mut self, name: Symbol) {
|
2017-09-12 11:04:46 -07:00
|
|
|
self.name = name;
|
|
|
|
}
|
|
|
|
|
2017-10-25 17:04:24 +02:00
|
|
|
pub fn items(&self) -> &FxHashMap<MonoItem<'tcx>, (Linkage, Visibility)> {
|
2017-09-12 11:04:46 -07:00
|
|
|
&self.items
|
|
|
|
}
|
|
|
|
|
2019-12-22 17:42:04 -05:00
|
|
|
pub fn items_mut(&mut self) -> &mut FxHashMap<MonoItem<'tcx>, (Linkage, Visibility)> {
|
2017-09-12 11:04:46 -07:00
|
|
|
&mut self.items
|
|
|
|
}
|
2018-01-08 12:30:52 +01:00
|
|
|
|
|
|
|
pub fn mangle_name(human_readable_name: &str) -> String {
|
|
|
|
// We generate a 80 bit hash from the name. This should be enough to
|
|
|
|
// avoid collisions and is still reasonably short for filenames.
|
|
|
|
let mut hasher = StableHasher::new();
|
|
|
|
human_readable_name.hash(&mut hasher);
|
|
|
|
let hash: u128 = hasher.finish();
|
|
|
|
let hash = hash & ((1u128 << 80) - 1);
|
|
|
|
base_n::encode(hash, base_n::CASE_INSENSITIVE)
|
|
|
|
}
|
2018-01-15 18:28:34 +00:00
|
|
|
|
2019-06-14 00:48:52 +03:00
|
|
|
pub fn estimate_size(&mut self, tcx: TyCtxt<'tcx>) {
|
2018-01-15 18:28:34 +00:00
|
|
|
// Estimate the size of a codegen unit as (approximately) the number of MIR
|
|
|
|
// statements it corresponds to.
|
|
|
|
self.size_estimate = Some(self.items.keys().map(|mi| mi.size_estimate(tcx)).sum());
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn size_estimate(&self) -> usize {
|
|
|
|
// Should only be called if `estimate_size` has previously been called.
|
2018-01-19 11:51:48 +00:00
|
|
|
self.size_estimate.expect("estimate_size must be called before getting a size_estimate")
|
2018-01-15 18:28:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn modify_size_estimate(&mut self, delta: usize) {
|
|
|
|
assert!(self.size_estimate.is_some());
|
|
|
|
if let Some(size_estimate) = self.size_estimate {
|
|
|
|
self.size_estimate = Some(size_estimate + delta);
|
|
|
|
}
|
|
|
|
}
|
2019-05-24 11:19:53 -05:00
|
|
|
|
|
|
|
pub fn contains_item(&self, item: &MonoItem<'tcx>) -> bool {
|
|
|
|
self.items().contains_key(item)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn work_product_id(&self) -> WorkProductId {
|
|
|
|
WorkProductId::from_cgu_name(&self.name().as_str())
|
|
|
|
}
|
|
|
|
|
2019-06-14 00:48:52 +03:00
|
|
|
pub fn work_product(&self, tcx: TyCtxt<'_>) -> WorkProduct {
|
2019-05-24 11:19:53 -05:00
|
|
|
let work_product_id = self.work_product_id();
|
|
|
|
tcx.dep_graph
|
2019-12-22 17:42:04 -05:00
|
|
|
.previous_work_product(&work_product_id)
|
|
|
|
.unwrap_or_else(|| panic!("Could not find work-product for CGU `{}`", self.name()))
|
2019-05-24 11:19:53 -05:00
|
|
|
}
|
|
|
|
|
2019-06-12 00:11:55 +03:00
|
|
|
pub fn items_in_deterministic_order(
|
|
|
|
&self,
|
2019-06-14 00:48:52 +03:00
|
|
|
tcx: TyCtxt<'tcx>,
|
2019-06-12 00:11:55 +03:00
|
|
|
) -> Vec<(MonoItem<'tcx>, (Linkage, Visibility))> {
|
2019-05-24 11:19:53 -05:00
|
|
|
// The codegen tests rely on items being process in the same order as
|
|
|
|
// they appear in the file, so for local items, we sort by node_id first
|
|
|
|
#[derive(PartialEq, Eq, PartialOrd, Ord)]
|
2020-07-10 15:45:05 +10:00
|
|
|
pub struct ItemSortKey<'tcx>(Option<HirId>, SymbolName<'tcx>);
|
2019-05-24 11:19:53 -05:00
|
|
|
|
2020-07-10 15:45:05 +10:00
|
|
|
fn item_sort_key<'tcx>(tcx: TyCtxt<'tcx>, item: MonoItem<'tcx>) -> ItemSortKey<'tcx> {
|
2019-12-22 17:42:04 -05:00
|
|
|
ItemSortKey(
|
|
|
|
match item {
|
|
|
|
MonoItem::Fn(ref instance) => {
|
|
|
|
match instance.def {
|
|
|
|
// We only want to take HirIds of user-defined
|
|
|
|
// instances into account. The others don't matter for
|
|
|
|
// the codegen tests and can even make item order
|
|
|
|
// unstable.
|
2020-08-12 12:22:56 +02:00
|
|
|
InstanceDef::Item(def) => def
|
|
|
|
.did
|
|
|
|
.as_local()
|
|
|
|
.map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id)),
|
2019-12-22 17:42:04 -05:00
|
|
|
InstanceDef::VtableShim(..)
|
|
|
|
| InstanceDef::ReifyShim(..)
|
|
|
|
| InstanceDef::Intrinsic(..)
|
|
|
|
| InstanceDef::FnPtrShim(..)
|
|
|
|
| InstanceDef::Virtual(..)
|
|
|
|
| InstanceDef::ClosureOnceShim { .. }
|
|
|
|
| InstanceDef::DropGlue(..)
|
|
|
|
| InstanceDef::CloneShim(..) => None,
|
2019-05-24 11:19:53 -05:00
|
|
|
}
|
|
|
|
}
|
2020-04-12 13:45:41 +01:00
|
|
|
MonoItem::Static(def_id) => {
|
2020-08-12 12:22:56 +02:00
|
|
|
def_id.as_local().map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id))
|
2020-04-12 13:45:41 +01:00
|
|
|
}
|
2021-01-30 19:18:48 +01:00
|
|
|
MonoItem::GlobalAsm(item_id) => Some(item_id.hir_id()),
|
2019-12-22 17:42:04 -05:00
|
|
|
},
|
|
|
|
item.symbol_name(tcx),
|
|
|
|
)
|
2019-05-24 11:19:53 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
let mut items: Vec<_> = self.items().iter().map(|(&i, &l)| (i, l)).collect();
|
|
|
|
items.sort_by_cached_key(|&(i, _)| item_sort_key(tcx, i));
|
|
|
|
items
|
|
|
|
}
|
|
|
|
|
2019-06-14 00:48:52 +03:00
|
|
|
pub fn codegen_dep_node(&self, tcx: TyCtxt<'tcx>) -> DepNode {
|
2021-01-08 18:00:25 -05:00
|
|
|
crate::dep_graph::make_compile_codegen_unit(tcx, self.name())
|
2019-05-24 11:19:53 -05:00
|
|
|
}
|
2017-09-12 11:04:46 -07:00
|
|
|
}
|
2017-09-13 20:26:39 -07:00
|
|
|
|
2018-01-16 10:16:38 +01:00
|
|
|
impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for CodegenUnit<'tcx> {
|
2019-09-26 18:54:39 -04:00
|
|
|
fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
|
2017-09-18 12:14:52 +02:00
|
|
|
let CodegenUnit {
|
|
|
|
ref items,
|
|
|
|
name,
|
2018-01-19 11:51:48 +00:00
|
|
|
// The size estimate is not relevant to the hash
|
|
|
|
size_estimate: _,
|
2017-09-18 12:14:52 +02:00
|
|
|
} = *self;
|
|
|
|
|
|
|
|
name.hash_stable(hcx, hasher);
|
|
|
|
|
2019-12-22 17:42:04 -05:00
|
|
|
let mut items: Vec<(Fingerprint, _)> = items
|
|
|
|
.iter()
|
|
|
|
.map(|(mono_item, &attrs)| {
|
|
|
|
let mut hasher = StableHasher::new();
|
|
|
|
mono_item.hash_stable(hcx, &mut hasher);
|
|
|
|
let mono_item_fingerprint = hasher.finish();
|
|
|
|
(mono_item_fingerprint, attrs)
|
|
|
|
})
|
|
|
|
.collect();
|
2017-09-18 12:14:52 +02:00
|
|
|
|
|
|
|
items.sort_unstable_by_key(|i| i.0);
|
|
|
|
items.hash_stable(hcx, hasher);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-14 00:48:52 +03:00
|
|
|
pub struct CodegenUnitNameBuilder<'tcx> {
|
|
|
|
tcx: TyCtxt<'tcx>,
|
2018-08-14 17:55:22 +02:00
|
|
|
cache: FxHashMap<CrateNum, String>,
|
|
|
|
}
|
|
|
|
|
2019-06-14 00:48:52 +03:00
|
|
|
impl CodegenUnitNameBuilder<'tcx> {
|
|
|
|
pub fn new(tcx: TyCtxt<'tcx>) -> Self {
|
2019-12-22 17:42:04 -05:00
|
|
|
CodegenUnitNameBuilder { tcx, cache: Default::default() }
|
2018-08-14 17:55:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/// CGU names should fulfill the following requirements:
|
|
|
|
/// - They should be able to act as a file name on any kind of file system
|
|
|
|
/// - They should not collide with other CGU names, even for different versions
|
|
|
|
/// of the same crate.
|
|
|
|
///
|
|
|
|
/// Consequently, we don't use special characters except for '.' and '-' and we
|
|
|
|
/// prefix each name with the crate-name and crate-disambiguator.
|
|
|
|
///
|
|
|
|
/// This function will build CGU names of the form:
|
|
|
|
///
|
|
|
|
/// ```
|
2018-09-12 12:46:48 +02:00
|
|
|
/// <crate-name>.<crate-disambiguator>[-in-<local-crate-id>](-<component>)*[.<special-suffix>]
|
|
|
|
/// <local-crate-id> = <local-crate-name>.<local-crate-disambiguator>
|
2018-08-14 17:55:22 +02:00
|
|
|
/// ```
|
|
|
|
///
|
|
|
|
/// The '.' before `<special-suffix>` makes sure that names with a special
|
|
|
|
/// suffix can never collide with a name built out of regular Rust
|
2018-11-27 02:59:49 +00:00
|
|
|
/// identifiers (e.g., module paths).
|
2019-12-22 17:42:04 -05:00
|
|
|
pub fn build_cgu_name<I, C, S>(
|
|
|
|
&mut self,
|
|
|
|
cnum: CrateNum,
|
|
|
|
components: I,
|
|
|
|
special_suffix: Option<S>,
|
|
|
|
) -> Symbol
|
|
|
|
where
|
|
|
|
I: IntoIterator<Item = C>,
|
|
|
|
C: fmt::Display,
|
|
|
|
S: fmt::Display,
|
2018-08-14 17:55:22 +02:00
|
|
|
{
|
2019-12-22 17:42:04 -05:00
|
|
|
let cgu_name = self.build_cgu_name_no_mangle(cnum, components, special_suffix);
|
2018-08-14 17:55:22 +02:00
|
|
|
|
|
|
|
if self.tcx.sess.opts.debugging_opts.human_readable_cgu_names {
|
|
|
|
cgu_name
|
|
|
|
} else {
|
2020-07-08 20:03:37 +10:00
|
|
|
Symbol::intern(&CodegenUnit::mangle_name(&cgu_name.as_str()))
|
2018-08-14 17:55:22 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Same as `CodegenUnit::build_cgu_name()` but will never mangle the
|
|
|
|
/// resulting name.
|
2019-12-22 17:42:04 -05:00
|
|
|
pub fn build_cgu_name_no_mangle<I, C, S>(
|
|
|
|
&mut self,
|
|
|
|
cnum: CrateNum,
|
|
|
|
components: I,
|
|
|
|
special_suffix: Option<S>,
|
|
|
|
) -> Symbol
|
|
|
|
where
|
|
|
|
I: IntoIterator<Item = C>,
|
|
|
|
C: fmt::Display,
|
|
|
|
S: fmt::Display,
|
2018-08-14 17:55:22 +02:00
|
|
|
{
|
|
|
|
use std::fmt::Write;
|
|
|
|
|
|
|
|
let mut cgu_name = String::with_capacity(64);
|
|
|
|
|
|
|
|
// Start out with the crate name and disambiguator
|
|
|
|
let tcx = self.tcx;
|
|
|
|
let crate_prefix = self.cache.entry(cnum).or_insert_with(|| {
|
2018-09-12 12:46:48 +02:00
|
|
|
// Whenever the cnum is not LOCAL_CRATE we also mix in the
|
|
|
|
// local crate's ID. Otherwise there can be collisions between CGUs
|
|
|
|
// instantiating stuff for upstream crates.
|
|
|
|
let local_crate_id = if cnum != LOCAL_CRATE {
|
2019-12-22 17:42:04 -05:00
|
|
|
let local_crate_disambiguator = format!("{}", tcx.crate_disambiguator(LOCAL_CRATE));
|
|
|
|
format!("-in-{}.{}", tcx.crate_name(LOCAL_CRATE), &local_crate_disambiguator[0..8])
|
2018-09-12 12:46:48 +02:00
|
|
|
} else {
|
|
|
|
String::new()
|
|
|
|
};
|
|
|
|
|
2018-10-03 15:07:18 +02:00
|
|
|
let crate_disambiguator = tcx.crate_disambiguator(cnum).to_string();
|
2018-08-14 17:55:22 +02:00
|
|
|
// Using a shortened disambiguator of about 40 bits
|
2019-12-22 17:42:04 -05:00
|
|
|
format!("{}.{}{}", tcx.crate_name(cnum), &crate_disambiguator[0..8], local_crate_id)
|
2018-08-14 17:55:22 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
write!(cgu_name, "{}", crate_prefix).unwrap();
|
|
|
|
|
|
|
|
// Add the components
|
|
|
|
for component in components {
|
|
|
|
write!(cgu_name, "-{}", component).unwrap();
|
|
|
|
}
|
|
|
|
|
|
|
|
if let Some(special_suffix) = special_suffix {
|
|
|
|
// We add a dot in here so it cannot clash with anything in a regular
|
|
|
|
// Rust identifier
|
|
|
|
write!(cgu_name, ".{}", special_suffix).unwrap();
|
|
|
|
}
|
|
|
|
|
2019-10-21 17:14:03 +11:00
|
|
|
Symbol::intern(&cgu_name[..])
|
2018-08-14 17:55:22 +02:00
|
|
|
}
|
|
|
|
}
|