11use crate :: hir:: def_id:: { DefId , CrateNum , LOCAL_CRATE } ;
22use crate :: hir:: HirId ;
33use 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 } ;
57use crate :: util:: nodemap:: FxHashMap ;
8+ use crate :: ty:: print:: obsolete:: DefPathBasedNames ;
9+ use crate :: dep_graph:: { WorkProductId , DepNode , WorkProduct , DepConstructor } ;
610use rustc_data_structures:: base_n;
711use rustc_data_structures:: stable_hasher:: { HashStable , StableHasherResult ,
812 StableHasher } ;
913use crate :: ich:: { Fingerprint , StableHashingContext , NodeIdHashingMode } ;
14+ use crate :: session:: config:: OptLevel ;
1015use std:: fmt;
1116use 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 ) ]
1444pub 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
36226impl < ' 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
166423impl < ' a , ' tcx > HashStable < StableHashingContext < ' a > > for CodegenUnit < ' tcx > {
0 commit comments