@@ -43,8 +43,7 @@ pub(crate) fn codegen_tls_ref<'tcx>(
43
43
def_id : DefId ,
44
44
layout : TyAndLayout < ' tcx > ,
45
45
) -> 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 ) ;
48
47
let local_data_id = fx. module . declare_data_in_func ( data_id, & mut fx. bcx . func ) ;
49
48
#[ cfg( debug_assertions) ]
50
49
fx. add_comment ( local_data_id, format ! ( "tls {:?}" , def_id) ) ;
@@ -57,8 +56,7 @@ fn codegen_static_ref<'tcx>(
57
56
def_id : DefId ,
58
57
layout : TyAndLayout < ' tcx > ,
59
58
) -> 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 ) ;
62
60
let local_data_id = fx. module . declare_data_in_func ( data_id, & mut fx. bcx . func ) ;
63
61
#[ cfg( debug_assertions) ]
64
62
fx. add_comment ( local_data_id, format ! ( "{:?}" , def_id) ) ;
@@ -159,8 +157,7 @@ pub(crate) fn trans_const_value<'tcx>(
159
157
}
160
158
Some ( GlobalAlloc :: Static ( def_id) ) => {
161
159
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 ) ;
164
161
let local_data_id = fx. module . declare_data_in_func ( data_id, & mut fx. bcx . func ) ;
165
162
#[ cfg( debug_assertions) ]
166
163
fx. add_comment ( local_data_id, format ! ( "{:?}" , def_id) ) ;
@@ -226,8 +223,20 @@ fn data_id_for_static(
226
223
tcx : TyCtxt < ' _ > ,
227
224
module : & mut Module < impl Backend > ,
228
225
def_id : DefId ,
229
- linkage : Linkage ,
226
+ definition : bool ,
230
227
) -> 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
+
231
240
let instance = Instance :: mono ( tcx, def_id) . polymorphize ( tcx) ;
232
241
let symbol_name = tcx. symbol_name ( instance) . name ;
233
242
let ty = instance. ty ( tcx, ParamEnv :: reveal_all ( ) ) ;
@@ -255,26 +264,39 @@ fn data_id_for_static(
255
264
)
256
265
. unwrap ( ) ;
257
266
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 ( ) ) ,
264
284
)
265
- }
266
-
285
+ . unwrap ( ) ;
267
286
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,
271
292
// so duplicate definitions are expected and allowed.
272
293
Err ( ModuleError :: DuplicateDefinition ( _) ) => { }
273
294
res => res. unwrap ( ) ,
274
295
}
296
+ ref_data_id
297
+ } else {
298
+ data_id
275
299
}
276
-
277
- data_id
278
300
}
279
301
280
302
fn 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
301
323
_ => bug ! ( "static const eval returned {:#?}" , const_) ,
302
324
} ;
303
325
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 ) ;
314
327
( data_id, alloc, section_name)
315
328
}
316
329
} ;
@@ -360,12 +373,7 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut Module<impl Backend>, cx: &mu
360
373
// Don't push a `TodoItem::Static` here, as it will cause statics used by
361
374
// multiple crates to be duplicated between them. It isn't necessary anyway,
362
375
// 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 )
369
377
}
370
378
} ;
371
379
0 commit comments