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