mirror of
https://github.com/rust-lang/rust.git
synced 2025-06-04 19:29: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
|
// 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]
|
#![no_core]
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
|
||||||
@ -192,4 +192,18 @@ fn main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
assert_eq!(((|()| 42u8) as fn(()) -> u8)(()), 42);
|
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>,
|
fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
|
||||||
static_: &Static<'tcx>,
|
static_: &Static<'tcx>,
|
||||||
) -> CPlace<'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)
|
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)
|
!tcx.type_of(def_id)
|
||||||
.is_freeze(tcx, ParamEnv::reveal_all(), DUMMY_SP)
|
.is_freeze(tcx, ParamEnv::reveal_all(), DUMMY_SP)
|
||||||
};
|
};
|
||||||
module
|
|
||||||
|
let data_id = module
|
||||||
.declare_data(&*symbol_name, linkage, is_mutable)
|
.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>(
|
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) => {
|
TodoItem::Static(def_id) => {
|
||||||
//println!("static {:?}", def_id);
|
//println!("static {:?}", def_id);
|
||||||
|
|
||||||
|
if tcx.is_foreign_item(def_id) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
let instance = ty::Instance::mono(tcx, def_id);
|
let instance = ty::Instance::mono(tcx, def_id);
|
||||||
let cid = GlobalId {
|
let cid = GlobalId {
|
||||||
instance,
|
instance,
|
||||||
@ -234,6 +263,7 @@ fn define_all_allocs<'a, 'tcx: 'a, B: Backend + 'a>(
|
|||||||
_ => bug!("static const eval returned {:#?}", const_),
|
_ => bug!("static const eval returned {:#?}", const_),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// FIXME set correct linkage
|
||||||
let data_id = data_id_for_static(tcx, module, def_id, Linkage::Export);
|
let data_id = data_id_for_static(tcx, module, def_id, Linkage::Export);
|
||||||
(data_id, alloc)
|
(data_id, alloc)
|
||||||
}
|
}
|
||||||
@ -271,7 +301,8 @@ fn define_all_allocs<'a, 'tcx: 'a, B: Backend + 'a>(
|
|||||||
}
|
}
|
||||||
AllocKind::Static(def_id) => {
|
AllocKind::Static(def_id) => {
|
||||||
cx.todo.insert(TodoItem::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_ssa::CrateInfo;
|
||||||
use rustc_codegen_utils::codegen_backend::CodegenBackend;
|
use rustc_codegen_utils::codegen_backend::CodegenBackend;
|
||||||
use rustc_codegen_utils::link::out_filename;
|
use rustc_codegen_utils::link::out_filename;
|
||||||
|
use rustc_mir::monomorphize::partitioning::CodegenUnitExt;
|
||||||
|
|
||||||
use cranelift::codegen::settings;
|
use cranelift::codegen::settings;
|
||||||
use cranelift_faerie::*;
|
use cranelift_faerie::*;
|
||||||
@ -47,6 +48,7 @@ mod debuginfo;
|
|||||||
mod intrinsics;
|
mod intrinsics;
|
||||||
mod link;
|
mod link;
|
||||||
mod link_copied;
|
mod link_copied;
|
||||||
|
mod linkage;
|
||||||
mod main_shim;
|
mod main_shim;
|
||||||
mod metadata;
|
mod metadata;
|
||||||
mod pretty_clif;
|
mod pretty_clif;
|
||||||
@ -368,7 +370,7 @@ impl CodegenBackend for CraneliftCodegenBackend {
|
|||||||
.downcast::<CodegenResults>()
|
.downcast::<CodegenResults>()
|
||||||
.expect("Expected CraneliftCodegenBackend's CodegenResult, found Box<Any>");
|
.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());
|
let output_name = out_filename(sess, crate_type, &outputs, &res.crate_name.as_str());
|
||||||
match crate_type {
|
match crate_type {
|
||||||
CrateType::Rlib => link::link_rlib(sess, &res, output_name),
|
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 (_, cgus) = tcx.collect_and_partition_mono_items(LOCAL_CRATE);
|
||||||
let mono_items = cgus
|
let mono_items = cgus
|
||||||
.iter()
|
.iter()
|
||||||
.map(|cgu| cgu.items().iter())
|
.map(|cgu| cgu.items_in_deterministic_order(tcx).into_iter())
|
||||||
.flatten()
|
.flatten()
|
||||||
.map(|(&mono_item, &(linkage, vis))| (mono_item, (linkage, vis)))
|
|
||||||
.collect::<FxHashMap<_, (_, _)>>();
|
.collect::<FxHashMap<_, (_, _)>>();
|
||||||
|
|
||||||
codegen_mono_items(tcx, module, debug.as_mut(), log, mono_items);
|
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);
|
let mut cx = CodegenCx::new(tcx, module, debug_context);
|
||||||
time("codegen mono items", move || {
|
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, || {
|
unimpl::try_unimpl(tcx, log, || {
|
||||||
let linkage = match (linkage, vis) {
|
let linkage = crate::linkage::get_clif_linkage(mono_item, 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, vis),
|
|
||||||
};
|
|
||||||
base::trans_mono_item(&mut cx, mono_item, linkage);
|
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