mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-09 05:23:07 +00:00
Implement weak linkage for statics
This commit is contained in:
parent
bfe8c89d41
commit
d9403bf3fd
@ -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); }
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
};
|
||||
|
||||
|
18
src/lib.rs
18
src/lib.rs
@ -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
29
src/linkage.rs
Normal 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
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user