1
1
#[ cfg( feature = "master" ) ]
2
2
use gccjit:: { FnAttribute , VarAttribute , Visibility } ;
3
- use gccjit:: { Function , GlobalKind , LValue , RValue , ToRValue } ;
3
+ use gccjit:: { Function , GlobalKind , LValue , RValue , ToRValue , Type } ;
4
4
use rustc_codegen_ssa:: traits:: { BaseTypeMethods , ConstMethods , DerivedTypeMethods , StaticMethods } ;
5
+ use rustc_hir:: def:: DefKind ;
6
+ use rustc_middle:: bug;
5
7
use rustc_middle:: middle:: codegen_fn_attrs:: { CodegenFnAttrFlags , CodegenFnAttrs } ;
6
8
use rustc_middle:: mir:: interpret:: {
7
9
self , read_target_uint, ConstAllocation , ErrorHandled , Scalar as InterpScalar ,
8
10
} ;
9
11
use rustc_middle:: mir:: mono:: MonoItem ;
10
12
use rustc_middle:: span_bug;
11
13
use rustc_middle:: ty:: layout:: LayoutOf ;
12
- use rustc_middle:: ty:: { self , Instance , Ty } ;
14
+ use rustc_middle:: ty:: { self , Instance } ;
13
15
use rustc_span:: def_id:: DefId ;
14
16
use rustc_target:: abi:: { self , Align , HasDataLayout , Primitive , Size , WrappingRange } ;
15
17
@@ -63,16 +65,15 @@ impl<'gcc, 'tcx> StaticMethods for CodegenCx<'gcc, 'tcx> {
63
65
global_value
64
66
}
65
67
68
+ #[ cfg_attr( not( feature = "master" ) , allow( unused_mut) ) ]
66
69
fn codegen_static ( & self , def_id : DefId ) {
67
70
let attrs = self . tcx . codegen_fn_attrs ( def_id) ;
68
71
69
- let value = match codegen_static_initializer ( self , def_id) {
70
- Ok ( ( value, _) ) => value,
72
+ let Ok ( ( value, alloc) ) = codegen_static_initializer ( self , def_id) else {
71
73
// Error has already been reported
72
- Err ( _ ) => return ,
74
+ return ;
73
75
} ;
74
-
75
- let global = self . get_static ( def_id) ;
76
+ let alloc = alloc. inner ( ) ;
76
77
77
78
// boolean SSA values are i1, but they have to be stored in i8 slots,
78
79
// otherwise some LLVM optimization passes don't work as expected
@@ -81,23 +82,31 @@ impl<'gcc, 'tcx> StaticMethods for CodegenCx<'gcc, 'tcx> {
81
82
unimplemented ! ( ) ;
82
83
} ;
83
84
84
- let instance = Instance :: mono ( self . tcx , def_id) ;
85
- let ty = instance. ty ( self . tcx , ty:: ParamEnv :: reveal_all ( ) ) ;
86
- let gcc_type = self . layout_of ( ty) . gcc_type ( self ) ;
85
+ let is_thread_local = attrs. flags . contains ( CodegenFnAttrFlags :: THREAD_LOCAL ) ;
86
+ let mut global = self . get_static_inner ( def_id, val_llty) ;
87
87
88
- set_global_alignment ( self , global, self . align_of ( ty) ) ;
88
+ #[ cfg( feature = "master" ) ]
89
+ if global. to_rvalue ( ) . get_type ( ) != val_llty {
90
+ let instance = Instance :: mono ( self . tcx , def_id) ;
91
+ self . instances . borrow_mut ( ) . remove ( & instance) ;
92
+
93
+ global. remove ( ) ;
94
+ let name = self . tcx . symbol_name ( instance) . name ;
95
+ self . globals . borrow_mut ( ) . remove ( name) ;
96
+ global = self . get_static_inner ( def_id, val_llty) ;
97
+ }
98
+ set_global_alignment ( self , global, alloc. align ) ;
89
99
90
- let value = self . bitcast_if_needed ( value, gcc_type) ;
91
100
global. global_set_initializer_rvalue ( value) ;
92
101
93
102
// As an optimization, all shared statics which do not have interior
94
103
// mutability are placed into read-only memory.
95
- if ! self . tcx . static_mutability ( def_id ) . unwrap ( ) . is_mut ( ) && self . type_is_freeze ( ty ) {
104
+ if alloc . mutability . is_not ( ) {
96
105
#[ cfg( feature = "master" ) ]
97
106
global. global_set_readonly ( ) ;
98
107
}
99
108
100
- if attrs . flags . contains ( CodegenFnAttrFlags :: THREAD_LOCAL ) {
109
+ if is_thread_local {
101
110
// Do not allow LLVM to change the alignment of a TLS on macOS.
102
111
//
103
112
// By default a global's alignment can be freely increased.
@@ -205,34 +214,48 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
205
214
206
215
pub fn get_static ( & self , def_id : DefId ) -> LValue < ' gcc > {
207
216
let instance = Instance :: mono ( self . tcx , def_id) ;
208
- let fn_attrs = self . tcx . codegen_fn_attrs ( def_id) ;
217
+ let DefKind :: Static { nested, .. } = self . tcx . def_kind ( def_id) else { bug ! ( ) } ;
218
+ // Nested statics do not have a type, so pick a random type and let `define_static` figure out
219
+ // the gcc type from the actual evaluated initializer.
220
+ let gcc_type = if nested {
221
+ self . type_i8 ( )
222
+ } else {
223
+ let ty = instance. ty ( self . tcx , ty:: ParamEnv :: reveal_all ( ) ) ;
224
+ self . layout_of ( ty) . gcc_type ( self )
225
+ } ;
226
+
227
+ self . get_static_inner ( def_id, gcc_type)
228
+ }
229
+
230
+ pub ( crate ) fn get_static_inner ( & self , def_id : DefId , gcc_type : Type < ' gcc > ) -> LValue < ' gcc > {
231
+ let instance = Instance :: mono ( self . tcx , def_id) ;
209
232
if let Some ( & global) = self . instances . borrow ( ) . get ( & instance) {
233
+ trace ! ( "used cached value" ) ;
210
234
return global;
211
235
}
212
236
213
- let defined_in_current_codegen_unit =
214
- self . codegen_unit . items ( ) . contains_key ( & MonoItem :: Static ( def_id) ) ;
215
- assert ! (
216
- !defined_in_current_codegen_unit,
217
- "consts::get_static() should always hit the cache for \
218
- statics defined in the same CGU, but did not for `{:?}`",
219
- def_id
220
- ) ;
221
-
222
- let ty = instance. ty ( self . tcx , ty:: ParamEnv :: reveal_all ( ) ) ;
237
+ // FIXME: Once we stop removing globals in `codegen_static`, we can uncomment this code.
238
+ // let defined_in_current_codegen_unit =
239
+ // self.codegen_unit.items().contains_key(&MonoItem::Static(def_id));
240
+ // assert!(
241
+ // !defined_in_current_codegen_unit,
242
+ // "consts::get_static() should always hit the cache for \
243
+ // statics defined in the same CGU, but did not for `{:?}`",
244
+ // def_id
245
+ // );
223
246
let sym = self . tcx . symbol_name ( instance) . name ;
247
+ let fn_attrs = self . tcx . codegen_fn_attrs ( def_id) ;
224
248
225
249
let global = if def_id. is_local ( ) && !self . tcx . is_foreign_item ( def_id) {
226
- let llty = self . layout_of ( ty) . gcc_type ( self ) ;
227
250
if let Some ( global) = self . get_declared_value ( sym) {
228
- if self . val_ty ( global) != self . type_ptr_to ( llty ) {
251
+ if self . val_ty ( global) != self . type_ptr_to ( gcc_type ) {
229
252
span_bug ! ( self . tcx. def_span( def_id) , "Conflicting types for static" ) ;
230
253
}
231
254
}
232
255
233
256
let is_tls = fn_attrs. flags . contains ( CodegenFnAttrFlags :: THREAD_LOCAL ) ;
234
257
let global =
235
- self . declare_global ( sym, llty , GlobalKind :: Exported , is_tls, fn_attrs. link_section ) ;
258
+ self . declare_global ( sym, gcc_type , GlobalKind :: Exported , is_tls, fn_attrs. link_section ) ;
236
259
237
260
if !self . tcx . is_reachable_non_generic ( def_id) {
238
261
#[ cfg( feature = "master" ) ]
@@ -241,7 +264,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
241
264
242
265
global
243
266
} else {
244
- check_and_apply_linkage ( self , fn_attrs, ty , sym)
267
+ check_and_apply_linkage ( self , fn_attrs, gcc_type , sym)
245
268
} ;
246
269
247
270
if !def_id. is_local ( ) {
@@ -355,11 +378,10 @@ fn codegen_static_initializer<'gcc, 'tcx>(
355
378
fn check_and_apply_linkage < ' gcc , ' tcx > (
356
379
cx : & CodegenCx < ' gcc , ' tcx > ,
357
380
attrs : & CodegenFnAttrs ,
358
- ty : Ty < ' tcx > ,
381
+ gcc_type : Type < ' gcc > ,
359
382
sym : & str ,
360
383
) -> LValue < ' gcc > {
361
384
let is_tls = attrs. flags . contains ( CodegenFnAttrFlags :: THREAD_LOCAL ) ;
362
- let gcc_type = cx. layout_of ( ty) . gcc_type ( cx) ;
363
385
if let Some ( linkage) = attrs. import_linkage {
364
386
// Declare a symbol `foo` with the desired linkage.
365
387
let global1 =
0 commit comments