1
1
#[ cfg( feature = "master" ) ]
2
2
use gccjit:: { FnAttribute , VarAttribute , Visibility } ;
3
3
use gccjit:: { Function , GlobalKind , LValue , RValue , ToRValue } ;
4
- use rustc_codegen_ssa:: traits:: { BaseTypeMethods , ConstMethods , DerivedTypeMethods , StaticMethods } ;
4
+ use rustc_codegen_ssa:: traits:: { BaseTypeMethods , ConstMethods , StaticMethods } ;
5
+ use rustc_hir:: def:: DefKind ;
5
6
use rustc_middle:: middle:: codegen_fn_attrs:: { CodegenFnAttrFlags , CodegenFnAttrs } ;
6
7
use rustc_middle:: mir:: interpret:: {
7
8
self , read_target_uint, ConstAllocation , ErrorHandled , Scalar as InterpScalar ,
8
9
} ;
9
10
use rustc_middle:: mir:: mono:: MonoItem ;
10
- use rustc_middle:: span_bug;
11
11
use rustc_middle:: ty:: layout:: LayoutOf ;
12
- use rustc_middle:: ty:: { self , Instance , Ty } ;
12
+ use rustc_middle:: ty:: { self , Instance } ;
13
+ use rustc_middle:: { bug, span_bug} ;
13
14
use rustc_span:: def_id:: DefId ;
14
15
use rustc_target:: abi:: { self , Align , HasDataLayout , Primitive , Size , WrappingRange } ;
15
16
@@ -66,33 +67,31 @@ impl<'gcc, 'tcx> StaticMethods for CodegenCx<'gcc, 'tcx> {
66
67
fn codegen_static ( & self , def_id : DefId ) {
67
68
let attrs = self . tcx . codegen_fn_attrs ( def_id) ;
68
69
69
- let value = match codegen_static_initializer ( self , def_id) {
70
- Ok ( ( value, _) ) => value,
70
+ let Ok ( ( value, alloc) ) = codegen_static_initializer ( self , def_id) else {
71
71
// Error has already been reported
72
- Err ( _ ) => return ,
72
+ return ;
73
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
79
79
let val_llty = self . val_ty ( value) ;
80
80
if val_llty == self . type_i1 ( ) {
81
81
unimplemented ! ( ) ;
82
82
} ;
83
+ let global = self . get_static_inner ( def_id, val_llty) ;
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 gcc_type = self . val_ty ( global. to_rvalue ( ) ) ;
87
86
88
- set_global_alignment ( self , global, self . align_of ( ty ) ) ;
87
+ set_global_alignment ( self , global, alloc . align ) ;
89
88
90
89
let value = self . bitcast_if_needed ( value, gcc_type) ;
91
90
global. global_set_initializer_rvalue ( value) ;
92
91
93
92
// As an optimization, all shared statics which do not have interior
94
93
// mutability are placed into read-only memory.
95
- if !self . tcx . static_mutability ( def_id ) . unwrap ( ) . is_mut ( ) && self . type_is_freeze ( ty ) {
94
+ if !alloc . mutability . is_not ( ) {
96
95
#[ cfg( feature = "master" ) ]
97
96
global. global_set_readonly ( ) ;
98
97
}
@@ -205,7 +204,21 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
205
204
206
205
pub fn get_static ( & self , def_id : DefId ) -> LValue < ' gcc > {
207
206
let instance = Instance :: mono ( self . tcx , def_id) ;
208
- let fn_attrs = self . tcx . codegen_fn_attrs ( def_id) ;
207
+
208
+ let DefKind :: Static { nested, .. } = self . tcx . def_kind ( def_id) else { bug ! ( ) } ;
209
+ // Nested statics do not have a type, so pick a dummy type and let `codegen_static` figure out
210
+ // the llvm type from the actual evaluated initializer.
211
+ let llty = if nested {
212
+ self . type_i8 ( )
213
+ } else {
214
+ let ty = instance. ty ( self . tcx , ty:: ParamEnv :: reveal_all ( ) ) ;
215
+ self . layout_of ( ty) . gcc_type ( self )
216
+ } ;
217
+ self . get_static_inner ( def_id, llty)
218
+ }
219
+
220
+ pub fn get_static_inner ( & self , def_id : DefId , llty : gccjit:: Type < ' gcc > ) -> LValue < ' gcc > {
221
+ let instance = Instance :: mono ( self . tcx , def_id) ;
209
222
if let Some ( & global) = self . instances . borrow ( ) . get ( & instance) {
210
223
return global;
211
224
}
@@ -219,18 +232,17 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
219
232
def_id
220
233
) ;
221
234
222
- let ty = instance. ty ( self . tcx , ty:: ParamEnv :: reveal_all ( ) ) ;
223
235
let sym = self . tcx . symbol_name ( instance) . name ;
236
+ let fn_attrs = self . tcx . codegen_fn_attrs ( def_id) ;
224
237
238
+ let is_tls = fn_attrs. flags . contains ( CodegenFnAttrFlags :: THREAD_LOCAL ) ;
225
239
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
240
if let Some ( global) = self . get_declared_value ( sym) {
228
241
if self . val_ty ( global) != self . type_ptr_to ( llty) {
229
242
span_bug ! ( self . tcx. def_span( def_id) , "Conflicting types for static" ) ;
230
243
}
231
244
}
232
245
233
- let is_tls = fn_attrs. flags . contains ( CodegenFnAttrFlags :: THREAD_LOCAL ) ;
234
246
let global =
235
247
self . declare_global ( sym, llty, GlobalKind :: Exported , is_tls, fn_attrs. link_section ) ;
236
248
@@ -241,7 +253,11 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
241
253
242
254
global
243
255
} else {
244
- check_and_apply_linkage ( self , fn_attrs, ty, sym)
256
+ let global = check_and_apply_linkage ( self , fn_attrs, llty, sym) ;
257
+ if is_tls {
258
+ global. set_tls_model ( self . tls_model ) ;
259
+ }
260
+ global
245
261
} ;
246
262
247
263
if !def_id. is_local ( ) {
@@ -355,11 +371,10 @@ fn codegen_static_initializer<'gcc, 'tcx>(
355
371
fn check_and_apply_linkage < ' gcc , ' tcx > (
356
372
cx : & CodegenCx < ' gcc , ' tcx > ,
357
373
attrs : & CodegenFnAttrs ,
358
- ty : Ty < ' tcx > ,
374
+ gcc_type : gccjit :: Type < ' gcc > ,
359
375
sym : & str ,
360
376
) -> LValue < ' gcc > {
361
377
let is_tls = attrs. flags . contains ( CodegenFnAttrFlags :: THREAD_LOCAL ) ;
362
- let gcc_type = cx. layout_of ( ty) . gcc_type ( cx) ;
363
378
if let Some ( linkage) = attrs. import_linkage {
364
379
// Declare a symbol `foo` with the desired linkage.
365
380
let global1 =
0 commit comments