11#[ cfg( feature = "master" ) ]
22use gccjit:: { FnAttribute , VarAttribute , Visibility } ;
3- use gccjit:: { Function , GlobalKind , LValue , RValue , ToRValue } ;
3+ use gccjit:: { Function , GlobalKind , LValue , RValue , ToRValue , Type } ;
44use rustc_codegen_ssa:: traits:: { BaseTypeMethods , ConstMethods , DerivedTypeMethods , StaticMethods } ;
5+ use rustc_hir:: def:: DefKind ;
6+ use rustc_middle:: bug;
57use rustc_middle:: middle:: codegen_fn_attrs:: { CodegenFnAttrFlags , CodegenFnAttrs } ;
68use rustc_middle:: mir:: interpret:: {
79 self , read_target_uint, ConstAllocation , ErrorHandled , Scalar as InterpScalar ,
810} ;
911use rustc_middle:: mir:: mono:: MonoItem ;
1012use rustc_middle:: span_bug;
1113use rustc_middle:: ty:: layout:: LayoutOf ;
12- use rustc_middle:: ty:: { self , Instance , Ty } ;
14+ use rustc_middle:: ty:: { self , Instance } ;
1315use rustc_span:: def_id:: DefId ;
1416use rustc_target:: abi:: { self , Align , HasDataLayout , Primitive , Size , WrappingRange } ;
1517
@@ -63,16 +65,15 @@ impl<'gcc, 'tcx> StaticMethods for CodegenCx<'gcc, 'tcx> {
6365 global_value
6466 }
6567
68+ #[ cfg_attr( not( feature = "master" ) , allow( unused_mut) ) ]
6669 fn codegen_static ( & self , def_id : DefId ) {
6770 let attrs = self . tcx . codegen_fn_attrs ( def_id) ;
6871
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 {
7173 // Error has already been reported
72- Err ( _ ) => return ,
74+ return ;
7375 } ;
74-
75- let global = self . get_static ( def_id) ;
76+ let alloc = alloc. inner ( ) ;
7677
7778 // boolean SSA values are i1, but they have to be stored in i8 slots,
7879 // otherwise some LLVM optimization passes don't work as expected
@@ -81,23 +82,31 @@ impl<'gcc, 'tcx> StaticMethods for CodegenCx<'gcc, 'tcx> {
8182 unimplemented ! ( ) ;
8283 } ;
8384
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) ;
8787
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 ) ;
8999
90- let value = self . bitcast_if_needed ( value, gcc_type) ;
91100 global. global_set_initializer_rvalue ( value) ;
92101
93102 // As an optimization, all shared statics which do not have interior
94103 // 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 ( ) {
96105 #[ cfg( feature = "master" ) ]
97106 global. global_set_readonly ( ) ;
98107 }
99108
100- if attrs . flags . contains ( CodegenFnAttrFlags :: THREAD_LOCAL ) {
109+ if is_thread_local {
101110 // Do not allow LLVM to change the alignment of a TLS on macOS.
102111 //
103112 // By default a global's alignment can be freely increased.
@@ -205,39 +214,48 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
205214
206215 pub fn get_static ( & self , def_id : DefId ) -> LValue < ' gcc > {
207216 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) ;
209232 if let Some ( & global) = self . instances . borrow ( ) . get ( & instance) {
233+ trace ! ( "used cached value" ) ;
210234 return global;
211235 }
212236
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+ // );
223246 let sym = self . tcx . symbol_name ( instance) . name ;
247+ let fn_attrs = self . tcx . codegen_fn_attrs ( def_id) ;
224248
225249 let global = if def_id. is_local ( ) && !self . tcx . is_foreign_item ( def_id) {
226- let llty = self . layout_of ( ty) . gcc_type ( self ) ;
227250 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 ) {
229252 span_bug ! ( self . tcx. def_span( def_id) , "Conflicting types for static" ) ;
230253 }
231254 }
232255
233256 let is_tls = fn_attrs. flags . contains ( CodegenFnAttrFlags :: THREAD_LOCAL ) ;
234- let global = self . declare_global (
235- & sym,
236- llty,
237- GlobalKind :: Exported ,
238- is_tls,
239- fn_attrs. link_section ,
240- ) ;
257+ let global =
258+ self . declare_global ( sym, gcc_type, GlobalKind :: Exported , is_tls, fn_attrs. link_section ) ;
241259
242260 if !self . tcx . is_reachable_non_generic ( def_id) {
243261 #[ cfg( feature = "master" ) ]
@@ -246,7 +264,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
246264
247265 global
248266 } else {
249- check_and_apply_linkage ( & self , & fn_attrs, ty , sym)
267+ check_and_apply_linkage ( self , fn_attrs, gcc_type , sym)
250268 } ;
251269
252270 if !def_id. is_local ( ) {
@@ -360,11 +378,10 @@ fn codegen_static_initializer<'gcc, 'tcx>(
360378fn check_and_apply_linkage < ' gcc , ' tcx > (
361379 cx : & CodegenCx < ' gcc , ' tcx > ,
362380 attrs : & CodegenFnAttrs ,
363- ty : Ty < ' tcx > ,
381+ gcc_type : Type < ' gcc > ,
364382 sym : & str ,
365383) -> LValue < ' gcc > {
366384 let is_tls = attrs. flags . contains ( CodegenFnAttrFlags :: THREAD_LOCAL ) ;
367- let gcc_type = cx. layout_of ( ty) . gcc_type ( cx) ;
368385 if let Some ( linkage) = attrs. import_linkage {
369386 // Declare a symbol `foo` with the desired linkage.
370387 let global1 = cx. declare_global_with_linkage (
0 commit comments