Skip to content

Commit a80d642

Browse files
authored
Merge pull request #1074 from bjorn3/fix_weak_linkage
Fix weak linkage
2 parents 02b7cdc + ca9fc10 commit a80d642

File tree

4 files changed

+60
-90
lines changed

4 files changed

+60
-90
lines changed

example/mini_core_hello_world.rs

+10-7
Original file line numberDiff line numberDiff line change
@@ -241,19 +241,22 @@ fn main() {
241241

242242
assert_eq!(((|()| 42u8) as fn(()) -> u8)(()), 42);
243243

244-
extern {
245-
#[linkage = "extern_weak"]
246-
static ABC: *const u8;
247-
}
248-
244+
#[cfg(not(jit))]
249245
{
250246
extern {
251247
#[linkage = "extern_weak"]
252248
static ABC: *const u8;
253249
}
254-
}
255250

256-
unsafe { assert_eq!(ABC as usize, 0); }
251+
{
252+
extern {
253+
#[linkage = "extern_weak"]
254+
static ABC: *const u8;
255+
}
256+
}
257+
258+
unsafe { assert_eq!(ABC as usize, 0); }
259+
}
257260

258261
&mut (|| Some(0 as *const ())) as &mut dyn FnMut() -> Option<*const ()>;
259262

patches/0025-Remove-usage-of-extern_weak-in-thread_local_dtor.patch

-45
This file was deleted.

src/constant.rs

+44-36
Original file line numberDiff line numberDiff line change
@@ -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

280302
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
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

src/linkage.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ pub(crate) fn get_clif_linkage(mono_item: MonoItem<'_>, linkage: RLinkage, visib
1111
}
1212
}
1313

14-
pub(crate) fn get_static_ref_linkage(tcx: TyCtxt<'_>, def_id: DefId) -> Linkage {
14+
pub(crate) fn get_static_linkage(tcx: TyCtxt<'_>, def_id: DefId) -> Linkage {
1515
let fn_attrs = tcx.codegen_fn_attrs(def_id);
1616

1717
if let Some(linkage) = fn_attrs.linkage {
@@ -22,6 +22,10 @@ pub(crate) fn get_static_ref_linkage(tcx: TyCtxt<'_>, def_id: DefId) -> Linkage
2222
_ => panic!("{:?}", linkage),
2323
}
2424
} else {
25-
Linkage::Import
25+
if tcx.is_reachable_non_generic(def_id) {
26+
Linkage::Export
27+
} else {
28+
Linkage::Export // FIXME use Linkage::Hidden
29+
}
2630
}
2731
}

0 commit comments

Comments
 (0)