Implement weak linkage for statics

This commit is contained in:
bjorn3 2019-03-11 20:36:29 +01:00
parent bfe8c89d41
commit d9403bf3fd
4 changed files with 85 additions and 17 deletions

View File

@ -1,6 +1,6 @@
// Adapted from https://github.com/sunfishcode/mir2cranelift/blob/master/rust-examples/nocore-hello-world.rs
#![feature(no_core, unboxed_closures, start, lang_items, box_syntax, slice_patterns)]
#![feature(no_core, unboxed_closures, start, lang_items, box_syntax, slice_patterns, never_type, linkage)]
#![no_core]
#![allow(dead_code)]
@ -192,4 +192,18 @@ fn main() {
}
assert_eq!(((|()| 42u8) as fn(()) -> u8)(()), 42);
extern {
#[linkage = "weak"]
static ABC: *const u8;
}
{
extern {
#[linkage = "weak"]
static ABC: *const u8;
}
}
unsafe { assert_eq!(ABC as usize, 0); }
}

View File

@ -46,7 +46,8 @@ pub fn codegen_static_ref<'a, 'tcx: 'a>(
fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
static_: &Static<'tcx>,
) -> CPlace<'tcx> {
let data_id = data_id_for_static(fx.tcx, fx.module, static_.def_id, Linkage::Import);
let linkage = crate::linkage::get_static_ref_linkage(fx.tcx, static_.def_id);
let data_id = data_id_for_static(fx.tcx, fx.module, static_.def_id, linkage);
cplace_for_dataid(fx, static_.ty, data_id)
}
@ -188,9 +189,32 @@ fn data_id_for_static<'a, 'tcx: 'a, B: Backend>(
!tcx.type_of(def_id)
.is_freeze(tcx, ParamEnv::reveal_all(), DUMMY_SP)
};
module
let data_id = module
.declare_data(&*symbol_name, linkage, is_mutable)
.unwrap()
.unwrap();
if linkage == Linkage::Preemptible {
if let ty::RawPtr(_) = tcx.type_of(def_id).sty {
} else {
tcx.sess.span_fatal(tcx.def_span(def_id), "must have type `*const T` or `*mut T`")
}
let mut data_ctx = DataContext::new();
let zero_bytes = std::iter::repeat(0)
.take(pointer_ty(tcx).bytes() as usize)
.collect::<Vec<u8>>()
.into_boxed_slice();
data_ctx.define(zero_bytes);
match module.define_data(data_id, &data_ctx) {
// Everytime a weak static is referenced, there will be a zero pointer definition,
// so duplicate definitions are expected and allowed.
Err(ModuleError::DuplicateDefinition(_)) => {}
res => res.unwrap(),
}
}
data_id
}
fn cplace_for_dataid<'a, 'tcx: 'a>(
@ -222,6 +246,11 @@ fn define_all_allocs<'a, 'tcx: 'a, B: Backend + 'a>(
}
TodoItem::Static(def_id) => {
//println!("static {:?}", def_id);
if tcx.is_foreign_item(def_id) {
continue;
}
let instance = ty::Instance::mono(tcx, def_id);
let cid = GlobalId {
instance,
@ -234,6 +263,7 @@ fn define_all_allocs<'a, 'tcx: 'a, B: Backend + 'a>(
_ => bug!("static const eval returned {:#?}", const_),
};
// FIXME set correct linkage
let data_id = data_id_for_static(tcx, module, def_id, Linkage::Export);
(data_id, alloc)
}
@ -271,7 +301,8 @@ fn define_all_allocs<'a, 'tcx: 'a, B: Backend + 'a>(
}
AllocKind::Static(def_id) => {
cx.todo.insert(TodoItem::Static(def_id));
data_id_for_static(tcx, module, def_id, Linkage::Import)
let linkage = crate::linkage::get_static_ref_linkage(tcx, def_id);
data_id_for_static(tcx, module, def_id, linkage)
}
};

View File

@ -29,6 +29,7 @@ use rustc_codegen_ssa::back::linker::LinkerInfo;
use rustc_codegen_ssa::CrateInfo;
use rustc_codegen_utils::codegen_backend::CodegenBackend;
use rustc_codegen_utils::link::out_filename;
use rustc_mir::monomorphize::partitioning::CodegenUnitExt;
use cranelift::codegen::settings;
use cranelift_faerie::*;
@ -47,6 +48,7 @@ mod debuginfo;
mod intrinsics;
mod link;
mod link_copied;
mod linkage;
mod main_shim;
mod metadata;
mod pretty_clif;
@ -368,7 +370,7 @@ impl CodegenBackend for CraneliftCodegenBackend {
.downcast::<CodegenResults>()
.expect("Expected CraneliftCodegenBackend's CodegenResult, found Box<Any>");
for &crate_type in sess.opts.crate_types.iter() {
for &crate_type in sess.crate_types.borrow().iter() {
let output_name = out_filename(sess, crate_type, &outputs, &res.crate_name.as_str());
match crate_type {
CrateType::Rlib => link::link_rlib(sess, &res, output_name),
@ -423,9 +425,8 @@ fn codegen_cgus<'a, 'tcx: 'a>(
let (_, cgus) = tcx.collect_and_partition_mono_items(LOCAL_CRATE);
let mono_items = cgus
.iter()
.map(|cgu| cgu.items().iter())
.map(|cgu| cgu.items_in_deterministic_order(tcx).into_iter())
.flatten()
.map(|(&mono_item, &(linkage, vis))| (mono_item, (linkage, vis)))
.collect::<FxHashMap<_, (_, _)>>();
codegen_mono_items(tcx, module, debug.as_mut(), log, mono_items);
@ -442,16 +443,9 @@ fn codegen_mono_items<'a, 'tcx: 'a>(
) {
let mut cx = CodegenCx::new(tcx, module, debug_context);
time("codegen mono items", move || {
for (mono_item, (linkage, vis)) in mono_items {
for (mono_item, (linkage, visibility)) in mono_items {
unimpl::try_unimpl(tcx, log, || {
let linkage = match (linkage, vis) {
(RLinkage::External, Visibility::Default) => Linkage::Export,
(RLinkage::Internal, Visibility::Default) => Linkage::Local,
// FIXME this should get external linkage, but hidden visibility,
// not internal linkage and default visibility
(RLinkage::External, Visibility::Hidden) => Linkage::Export,
_ => panic!("{:?} = {:?} {:?}", mono_item, linkage, vis),
};
let linkage = crate::linkage::get_clif_linkage(mono_item, linkage, visibility);
base::trans_mono_item(&mut cx, mono_item, linkage);
});
}

29
src/linkage.rs Normal file
View File

@ -0,0 +1,29 @@
use rustc::mir::mono::{MonoItem, Linkage as RLinkage, Visibility};
use crate::prelude::*;
pub fn get_clif_linkage(mono_item: MonoItem, linkage: RLinkage, visibility: Visibility) -> Linkage {
match (linkage, visibility) {
(RLinkage::External, Visibility::Default) => Linkage::Export,
(RLinkage::Internal, Visibility::Default) => Linkage::Local,
// FIXME this should get external linkage, but hidden visibility,
// not internal linkage and default visibility
(RLinkage::External, Visibility::Hidden) => Linkage::Export,
_ => panic!("{:?} = {:?} {:?}", mono_item, linkage, visibility),
}
}
pub fn get_static_ref_linkage(tcx: TyCtxt, def_id: DefId) -> Linkage {
let fn_attrs = tcx.codegen_fn_attrs(def_id);
if let Some(linkage) = fn_attrs.linkage {
match linkage {
RLinkage::External => Linkage::Export,
RLinkage::Internal => Linkage::Local,
RLinkage::ExternalWeak | RLinkage::WeakAny => Linkage::Preemptible,
_ => panic!("{:?}", linkage),
}
} else {
Linkage::Import
}
}