Skip to content

Commit da9ebc8

Browse files
committed
Auto merge of #61062 - mark-i-m:mono-mv, r=eddyb,oli-obk
Remove _all_ codegen dependencies on `rustc_mir` 🎉 ~This code is pretty self-contained. It has no references to the rest of `rustc_mir`. Moving it to its own crate means that almost all of the references from `rustc_codegen_*` to `rustc_mir` are instead moved to `rustc_monomorphize`, which should help improve compile times for the compiler a bit...~ With the help of eddyb and oli-obk, all of the dependencies of `librustc_codegen_*` on `librustc_mir` have been removed: - dependencies on `rustc_mir::monomorphize` were moved to `rustc::mir::mono` - `rustc_mir::const_eval::const_field` is made into a query. - `rustc_mir::interpret::type_name` is made into a query. This should help reduce compile time when working on `rustc_mir` 🕐 cc #47849 r? @eddyb
2 parents c57ed9d + 0f822d7 commit da9ebc8

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+733
-636
lines changed

Cargo.lock

-2
Original file line numberDiff line numberDiff line change
@@ -2684,7 +2684,6 @@ dependencies = [
26842684
"rustc_errors 0.0.0",
26852685
"rustc_fs_util 0.0.0",
26862686
"rustc_incremental 0.0.0",
2687-
"rustc_mir 0.0.0",
26882687
"rustc_target 0.0.0",
26892688
"serialize 0.0.0",
26902689
"syntax 0.0.0",
@@ -2703,7 +2702,6 @@ dependencies = [
27032702
"rustc-demangle 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
27042703
"rustc_data_structures 0.0.0",
27052704
"rustc_metadata 0.0.0",
2706-
"rustc_mir 0.0.0",
27072705
"rustc_target 0.0.0",
27082706
"syntax 0.0.0",
27092707
"syntax_pos 0.0.0",

src/librustc/dep_graph/dep_node.rs

+1
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
//! user of the `DepNode` API of having to know how to compute the expected
5050
//! fingerprint for a given set of node parameters.
5151
52+
use crate::mir;
5253
use crate::mir::interpret::GlobalId;
5354
use crate::hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX};
5455
use crate::hir::map::DefPathHash;

src/librustc/mir/mono.rs

+258-1
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,45 @@
11
use crate::hir::def_id::{DefId, CrateNum, LOCAL_CRATE};
22
use crate::hir::HirId;
33
use syntax::symbol::InternedString;
4-
use crate::ty::{Instance, TyCtxt};
4+
use syntax::attr::InlineAttr;
5+
use syntax::source_map::Span;
6+
use crate::ty::{Instance, InstanceDef, TyCtxt, SymbolName, subst::InternalSubsts};
57
use crate::util::nodemap::FxHashMap;
8+
use crate::ty::print::obsolete::DefPathBasedNames;
9+
use crate::dep_graph::{WorkProductId, DepNode, WorkProduct, DepConstructor};
610
use rustc_data_structures::base_n;
711
use rustc_data_structures::stable_hasher::{HashStable, StableHasherResult,
812
StableHasher};
913
use crate::ich::{Fingerprint, StableHashingContext, NodeIdHashingMode};
14+
use crate::session::config::OptLevel;
1015
use std::fmt;
1116
use std::hash::Hash;
1217

18+
/// Describes how a monomorphization will be instantiated in object files.
19+
#[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)]
20+
pub enum InstantiationMode {
21+
/// There will be exactly one instance of the given MonoItem. It will have
22+
/// external linkage so that it can be linked to from other codegen units.
23+
GloballyShared {
24+
/// In some compilation scenarios we may decide to take functions that
25+
/// are typically `LocalCopy` and instead move them to `GloballyShared`
26+
/// to avoid codegenning them a bunch of times. In this situation,
27+
/// however, our local copy may conflict with other crates also
28+
/// inlining the same function.
29+
///
30+
/// This flag indicates that this situation is occurring, and informs
31+
/// symbol name calculation that some extra mangling is needed to
32+
/// avoid conflicts. Note that this may eventually go away entirely if
33+
/// ThinLTO enables us to *always* have a globally shared instance of a
34+
/// function within one crate's compilation.
35+
may_conflict: bool,
36+
},
37+
38+
/// Each codegen unit containing a reference to the given MonoItem will
39+
/// have its own private copy of the function (with internal linkage).
40+
LocalCopy,
41+
}
42+
1343
#[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)]
1444
pub enum MonoItem<'tcx> {
1545
Fn(Instance<'tcx>),
@@ -31,6 +61,166 @@ impl<'tcx> MonoItem<'tcx> {
3161
MonoItem::GlobalAsm(_) => 1,
3262
}
3363
}
64+
65+
pub fn is_generic_fn(&self) -> bool {
66+
match *self {
67+
MonoItem::Fn(ref instance) => {
68+
instance.substs.non_erasable_generics().next().is_some()
69+
}
70+
MonoItem::Static(..) |
71+
MonoItem::GlobalAsm(..) => false,
72+
}
73+
}
74+
75+
pub fn symbol_name(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> SymbolName {
76+
match *self {
77+
MonoItem::Fn(instance) => tcx.symbol_name(instance),
78+
MonoItem::Static(def_id) => {
79+
tcx.symbol_name(Instance::mono(tcx, def_id))
80+
}
81+
MonoItem::GlobalAsm(hir_id) => {
82+
let def_id = tcx.hir().local_def_id_from_hir_id(hir_id);
83+
SymbolName {
84+
name: InternedString::intern(&format!("global_asm_{:?}", def_id))
85+
}
86+
}
87+
}
88+
}
89+
90+
pub fn instantiation_mode(&self,
91+
tcx: TyCtxt<'a, 'tcx, 'tcx>)
92+
-> InstantiationMode {
93+
let inline_in_all_cgus =
94+
tcx.sess.opts.debugging_opts.inline_in_all_cgus.unwrap_or_else(|| {
95+
tcx.sess.opts.optimize != OptLevel::No
96+
}) && !tcx.sess.opts.cg.link_dead_code;
97+
98+
match *self {
99+
MonoItem::Fn(ref instance) => {
100+
let entry_def_id = tcx.entry_fn(LOCAL_CRATE).map(|(id, _)| id);
101+
// If this function isn't inlined or otherwise has explicit
102+
// linkage, then we'll be creating a globally shared version.
103+
if self.explicit_linkage(tcx).is_some() ||
104+
!instance.def.requires_local(tcx) ||
105+
Some(instance.def_id()) == entry_def_id
106+
{
107+
return InstantiationMode::GloballyShared { may_conflict: false }
108+
}
109+
110+
// At this point we don't have explicit linkage and we're an
111+
// inlined function. If we're inlining into all CGUs then we'll
112+
// be creating a local copy per CGU
113+
if inline_in_all_cgus {
114+
return InstantiationMode::LocalCopy
115+
}
116+
117+
// Finally, if this is `#[inline(always)]` we're sure to respect
118+
// that with an inline copy per CGU, but otherwise we'll be
119+
// creating one copy of this `#[inline]` function which may
120+
// conflict with upstream crates as it could be an exported
121+
// symbol.
122+
match tcx.codegen_fn_attrs(instance.def_id()).inline {
123+
InlineAttr::Always => InstantiationMode::LocalCopy,
124+
_ => {
125+
InstantiationMode::GloballyShared { may_conflict: true }
126+
}
127+
}
128+
}
129+
MonoItem::Static(..) |
130+
MonoItem::GlobalAsm(..) => {
131+
InstantiationMode::GloballyShared { may_conflict: false }
132+
}
133+
}
134+
}
135+
136+
pub fn explicit_linkage(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Option<Linkage> {
137+
let def_id = match *self {
138+
MonoItem::Fn(ref instance) => instance.def_id(),
139+
MonoItem::Static(def_id) => def_id,
140+
MonoItem::GlobalAsm(..) => return None,
141+
};
142+
143+
let codegen_fn_attrs = tcx.codegen_fn_attrs(def_id);
144+
codegen_fn_attrs.linkage
145+
}
146+
147+
/// Returns `true` if this instance is instantiable - whether it has no unsatisfied
148+
/// predicates.
149+
///
150+
/// In order to codegen an item, all of its predicates must hold, because
151+
/// otherwise the item does not make sense. Type-checking ensures that
152+
/// the predicates of every item that is *used by* a valid item *do*
153+
/// hold, so we can rely on that.
154+
///
155+
/// However, we codegen collector roots (reachable items) and functions
156+
/// in vtables when they are seen, even if they are not used, and so they
157+
/// might not be instantiable. For example, a programmer can define this
158+
/// public function:
159+
///
160+
/// pub fn foo<'a>(s: &'a mut ()) where &'a mut (): Clone {
161+
/// <&mut () as Clone>::clone(&s);
162+
/// }
163+
///
164+
/// That function can't be codegened, because the method `<&mut () as Clone>::clone`
165+
/// does not exist. Luckily for us, that function can't ever be used,
166+
/// because that would require for `&'a mut (): Clone` to hold, so we
167+
/// can just not emit any code, or even a linker reference for it.
168+
///
169+
/// Similarly, if a vtable method has such a signature, and therefore can't
170+
/// be used, we can just not emit it and have a placeholder (a null pointer,
171+
/// which will never be accessed) in its place.
172+
pub fn is_instantiable(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> bool {
173+
debug!("is_instantiable({:?})", self);
174+
let (def_id, substs) = match *self {
175+
MonoItem::Fn(ref instance) => (instance.def_id(), instance.substs),
176+
MonoItem::Static(def_id) => (def_id, InternalSubsts::empty()),
177+
// global asm never has predicates
178+
MonoItem::GlobalAsm(..) => return true
179+
};
180+
181+
tcx.substitute_normalize_and_test_predicates((def_id, &substs))
182+
}
183+
184+
pub fn to_string(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, debug: bool) -> String {
185+
return match *self {
186+
MonoItem::Fn(instance) => {
187+
to_string_internal(tcx, "fn ", instance, debug)
188+
},
189+
MonoItem::Static(def_id) => {
190+
let instance = Instance::new(def_id, tcx.intern_substs(&[]));
191+
to_string_internal(tcx, "static ", instance, debug)
192+
},
193+
MonoItem::GlobalAsm(..) => {
194+
"global_asm".to_string()
195+
}
196+
};
197+
198+
fn to_string_internal<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
199+
prefix: &str,
200+
instance: Instance<'tcx>,
201+
debug: bool)
202+
-> String {
203+
let mut result = String::with_capacity(32);
204+
result.push_str(prefix);
205+
let printer = DefPathBasedNames::new(tcx, false, false);
206+
printer.push_instance_as_string(instance, &mut result, debug);
207+
result
208+
}
209+
}
210+
211+
pub fn local_span(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Option<Span> {
212+
match *self {
213+
MonoItem::Fn(Instance { def, .. }) => {
214+
tcx.hir().as_local_hir_id(def.def_id())
215+
}
216+
MonoItem::Static(def_id) => {
217+
tcx.hir().as_local_hir_id(def_id)
218+
}
219+
MonoItem::GlobalAsm(hir_id) => {
220+
Some(hir_id)
221+
}
222+
}.map(|hir_id| tcx.hir().span_by_hir_id(hir_id))
223+
}
34224
}
35225

36226
impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for MonoItem<'tcx> {
@@ -161,6 +351,73 @@ impl<'tcx> CodegenUnit<'tcx> {
161351
self.size_estimate = Some(size_estimate + delta);
162352
}
163353
}
354+
355+
pub fn contains_item(&self, item: &MonoItem<'tcx>) -> bool {
356+
self.items().contains_key(item)
357+
}
358+
359+
pub fn work_product_id(&self) -> WorkProductId {
360+
WorkProductId::from_cgu_name(&self.name().as_str())
361+
}
362+
363+
pub fn work_product(&self, tcx: TyCtxt<'_, '_, '_>) -> WorkProduct {
364+
let work_product_id = self.work_product_id();
365+
tcx.dep_graph
366+
.previous_work_product(&work_product_id)
367+
.unwrap_or_else(|| {
368+
panic!("Could not find work-product for CGU `{}`", self.name())
369+
})
370+
}
371+
372+
pub fn items_in_deterministic_order<'a>(&self,
373+
tcx: TyCtxt<'a, 'tcx, 'tcx>)
374+
-> Vec<(MonoItem<'tcx>,
375+
(Linkage, Visibility))> {
376+
// The codegen tests rely on items being process in the same order as
377+
// they appear in the file, so for local items, we sort by node_id first
378+
#[derive(PartialEq, Eq, PartialOrd, Ord)]
379+
pub struct ItemSortKey(Option<HirId>, SymbolName);
380+
381+
fn item_sort_key<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
382+
item: MonoItem<'tcx>) -> ItemSortKey {
383+
ItemSortKey(match item {
384+
MonoItem::Fn(ref instance) => {
385+
match instance.def {
386+
// We only want to take HirIds of user-defined
387+
// instances into account. The others don't matter for
388+
// the codegen tests and can even make item order
389+
// unstable.
390+
InstanceDef::Item(def_id) => {
391+
tcx.hir().as_local_hir_id(def_id)
392+
}
393+
InstanceDef::VtableShim(..) |
394+
InstanceDef::Intrinsic(..) |
395+
InstanceDef::FnPtrShim(..) |
396+
InstanceDef::Virtual(..) |
397+
InstanceDef::ClosureOnceShim { .. } |
398+
InstanceDef::DropGlue(..) |
399+
InstanceDef::CloneShim(..) => {
400+
None
401+
}
402+
}
403+
}
404+
MonoItem::Static(def_id) => {
405+
tcx.hir().as_local_hir_id(def_id)
406+
}
407+
MonoItem::GlobalAsm(hir_id) => {
408+
Some(hir_id)
409+
}
410+
}, item.symbol_name(tcx))
411+
}
412+
413+
let mut items: Vec<_> = self.items().iter().map(|(&i, &l)| (i, l)).collect();
414+
items.sort_by_cached_key(|&(i, _)| item_sort_key(tcx, i));
415+
items
416+
}
417+
418+
pub fn codegen_dep_node(&self, tcx: TyCtxt<'_, 'tcx, 'tcx>) -> DepNode {
419+
DepNode::new(tcx, DepConstructor::CompileCodegenUnit(self.name().clone()))
420+
}
164421
}
165422

166423
impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for CodegenUnit<'tcx> {

src/librustc/query/mod.rs

+19
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use crate::ty::{self, ParamEnvAnd, Ty, TyCtxt};
44
use crate::ty::subst::SubstsRef;
55
use crate::dep_graph::SerializedDepNodeIndex;
66
use crate::hir::def_id::{CrateNum, DefId, DefIndex};
7+
use crate::mir;
78
use crate::mir::interpret::GlobalId;
89
use crate::traits;
910
use crate::traits::query::{
@@ -431,6 +432,24 @@ rustc_queries! {
431432
tcx.queries.on_disk_cache.try_load_query_result(tcx, id).map(Ok)
432433
}
433434
}
435+
436+
/// Extracts a field of a (variant of a) const.
437+
query const_field(
438+
key: ty::ParamEnvAnd<'tcx, (&'tcx ty::Const<'tcx>, mir::Field)>
439+
) -> &'tcx ty::Const<'tcx> {
440+
eval_always
441+
no_force
442+
desc { "extract field of const" }
443+
}
444+
445+
/// Produces an absolute path representation of the given type. See also the documentation
446+
/// on `std::any::type_name`.
447+
query type_name(key: Ty<'tcx>) -> &'tcx ty::Const<'tcx> {
448+
eval_always
449+
no_force
450+
desc { "get absolute path of type" }
451+
}
452+
434453
}
435454

436455
TypeChecking {

0 commit comments

Comments
 (0)