1
1
use crate :: hir:: def_id:: { DefId , CrateNum , LOCAL_CRATE } ;
2
2
use crate :: hir:: HirId ;
3
3
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 } ;
5
7
use crate :: util:: nodemap:: FxHashMap ;
8
+ use crate :: ty:: print:: obsolete:: DefPathBasedNames ;
9
+ use crate :: dep_graph:: { WorkProductId , DepNode , WorkProduct , DepConstructor } ;
6
10
use rustc_data_structures:: base_n;
7
11
use rustc_data_structures:: stable_hasher:: { HashStable , StableHasherResult ,
8
12
StableHasher } ;
9
13
use crate :: ich:: { Fingerprint , StableHashingContext , NodeIdHashingMode } ;
14
+ use crate :: session:: config:: OptLevel ;
10
15
use std:: fmt;
11
16
use std:: hash:: Hash ;
12
17
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
+
13
43
#[ derive( PartialEq , Eq , Clone , Copy , Debug , Hash ) ]
14
44
pub enum MonoItem < ' tcx > {
15
45
Fn ( Instance < ' tcx > ) ,
@@ -31,6 +61,166 @@ impl<'tcx> MonoItem<'tcx> {
31
61
MonoItem :: GlobalAsm ( _) => 1 ,
32
62
}
33
63
}
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
+ }
34
224
}
35
225
36
226
impl < ' a , ' tcx > HashStable < StableHashingContext < ' a > > for MonoItem < ' tcx > {
@@ -161,6 +351,73 @@ impl<'tcx> CodegenUnit<'tcx> {
161
351
self . size_estimate = Some ( size_estimate + delta) ;
162
352
}
163
353
}
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
+ }
164
421
}
165
422
166
423
impl < ' a , ' tcx > HashStable < StableHashingContext < ' a > > for CodegenUnit < ' tcx > {
0 commit comments