@@ -43,8 +43,7 @@ pub(crate) fn codegen_tls_ref<'tcx>(
4343 def_id : DefId ,
4444 layout : TyAndLayout < ' tcx > ,
4545) -> CValue < ' tcx > {
46- let linkage = crate :: linkage:: get_static_ref_linkage ( fx. tcx , def_id) ;
47- let data_id = data_id_for_static ( fx. tcx , fx. module , def_id, linkage) ;
46+ let data_id = data_id_for_static ( fx. tcx , fx. module , def_id, false ) ;
4847 let local_data_id = fx. module . declare_data_in_func ( data_id, & mut fx. bcx . func ) ;
4948 #[ cfg( debug_assertions) ]
5049 fx. add_comment ( local_data_id, format ! ( "tls {:?}" , def_id) ) ;
@@ -57,8 +56,7 @@ fn codegen_static_ref<'tcx>(
5756 def_id : DefId ,
5857 layout : TyAndLayout < ' tcx > ,
5958) -> CPlace < ' tcx > {
60- let linkage = crate :: linkage:: get_static_ref_linkage ( fx. tcx , def_id) ;
61- let data_id = data_id_for_static ( fx. tcx , fx. module , def_id, linkage) ;
59+ let data_id = data_id_for_static ( fx. tcx , fx. module , def_id, false ) ;
6260 let local_data_id = fx. module . declare_data_in_func ( data_id, & mut fx. bcx . func ) ;
6361 #[ cfg( debug_assertions) ]
6462 fx. add_comment ( local_data_id, format ! ( "{:?}" , def_id) ) ;
@@ -159,8 +157,7 @@ pub(crate) fn trans_const_value<'tcx>(
159157 }
160158 Some ( GlobalAlloc :: Static ( def_id) ) => {
161159 assert ! ( fx. tcx. is_static( def_id) ) ;
162- let linkage = crate :: linkage:: get_static_ref_linkage ( fx. tcx , def_id) ;
163- let data_id = data_id_for_static ( fx. tcx , fx. module , def_id, linkage) ;
160+ let data_id = data_id_for_static ( fx. tcx , fx. module , def_id, false ) ;
164161 let local_data_id = fx. module . declare_data_in_func ( data_id, & mut fx. bcx . func ) ;
165162 #[ cfg( debug_assertions) ]
166163 fx. add_comment ( local_data_id, format ! ( "{:?}" , def_id) ) ;
@@ -226,8 +223,20 @@ fn data_id_for_static(
226223 tcx : TyCtxt < ' _ > ,
227224 module : & mut Module < impl Backend > ,
228225 def_id : DefId ,
229- linkage : Linkage ,
226+ definition : bool ,
230227) -> DataId {
228+ let rlinkage = tcx. codegen_fn_attrs ( def_id) . linkage ;
229+ let linkage = if definition {
230+ crate :: linkage:: get_static_linkage ( tcx, def_id)
231+ } else {
232+ if rlinkage == Some ( rustc_middle:: mir:: mono:: Linkage :: ExternalWeak )
233+ || rlinkage == Some ( rustc_middle:: mir:: mono:: Linkage :: WeakAny ) {
234+ Linkage :: Preemptible
235+ } else {
236+ Linkage :: Import
237+ }
238+ } ;
239+
231240 let instance = Instance :: mono ( tcx, def_id) . polymorphize ( tcx) ;
232241 let symbol_name = tcx. symbol_name ( instance) . name ;
233242 let ty = instance. ty ( tcx, ParamEnv :: reveal_all ( ) ) ;
@@ -255,26 +264,39 @@ fn data_id_for_static(
255264 )
256265 . unwrap ( ) ;
257266
258- if linkage == Linkage :: Preemptible {
259- if let ty:: RawPtr ( _) = ty. kind {
260- } else {
261- tcx. sess . span_fatal (
262- tcx. def_span ( def_id) ,
263- "must have type `*const T` or `*mut T` due to `#[linkage]` attribute" ,
267+ if rlinkage. is_some ( ) {
268+ // Comment copied from https://github.com/rust-lang/rust/blob/45060c2a66dfd667f88bd8b94261b28a58d85bd5/src/librustc_codegen_llvm/consts.rs#L141
269+ // Declare an internal global `extern_with_linkage_foo` which
270+ // is initialized with the address of `foo`. If `foo` is
271+ // discarded during linking (for example, if `foo` has weak
272+ // linkage and there are no definitions), then
273+ // `extern_with_linkage_foo` will instead be initialized to
274+ // zero.
275+
276+ let ref_name = format ! ( "_rust_extern_with_linkage_{}" , symbol_name) ;
277+ let ref_data_id = module
278+ . declare_data (
279+ & ref_name,
280+ Linkage :: Local ,
281+ true ,
282+ false ,
283+ Some ( align. try_into ( ) . unwrap ( ) ) ,
264284 )
265- }
266-
285+ . unwrap ( ) ;
267286 let mut data_ctx = DataContext :: new ( ) ;
268- data_ctx. define_zeroinit ( pointer_ty ( tcx) . bytes ( ) as usize ) ;
269- match module. define_data ( data_id, & data_ctx) {
270- // Everytime a weak static is referenced, there will be a zero pointer definition,
287+ let data = module. declare_data_in_data ( data_id, & mut data_ctx) ;
288+ data_ctx. define ( std:: iter:: repeat ( 0 ) . take ( pointer_ty ( tcx) . bytes ( ) as usize ) . collect ( ) ) ;
289+ data_ctx. write_data_addr ( 0 , data, 0 ) ;
290+ match module. define_data ( ref_data_id, & data_ctx) {
291+ // Every time the static is referenced there will be another definition of this global,
271292 // so duplicate definitions are expected and allowed.
272293 Err ( ModuleError :: DuplicateDefinition ( _) ) => { }
273294 res => res. unwrap ( ) ,
274295 }
296+ ref_data_id
297+ } else {
298+ data_id
275299 }
276-
277- data_id
278300}
279301
280302fn define_all_allocs ( tcx : TyCtxt < ' _ > , module : & mut Module < impl Backend > , cx : & mut ConstantCx ) {
@@ -301,16 +323,7 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut Module<impl Backend>, cx: &mu
301323 _ => bug ! ( "static const eval returned {:#?}" , const_) ,
302324 } ;
303325
304- let data_id = data_id_for_static (
305- tcx,
306- module,
307- def_id,
308- if tcx. is_reachable_non_generic ( def_id) {
309- Linkage :: Export
310- } else {
311- Linkage :: Export // FIXME Set hidden visibility
312- } ,
313- ) ;
326+ let data_id = data_id_for_static ( tcx, module, def_id, true ) ;
314327 ( data_id, alloc, section_name)
315328 }
316329 } ;
@@ -360,12 +373,7 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut Module<impl Backend>, cx: &mu
360373 // Don't push a `TodoItem::Static` here, as it will cause statics used by
361374 // multiple crates to be duplicated between them. It isn't necessary anyway,
362375 // as it will get pushed by `codegen_static` when necessary.
363- data_id_for_static (
364- tcx,
365- module,
366- def_id,
367- crate :: linkage:: get_static_ref_linkage ( tcx, def_id) ,
368- )
376+ data_id_for_static ( tcx, module, def_id, false )
369377 }
370378 } ;
371379
0 commit comments