From d9403bf3fdd0d924e38d781fae79402edd069c76 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Mon, 11 Mar 2019 20:36:29 +0100 Subject: [PATCH] Implement weak linkage for statics --- example/mini_core_hello_world.rs | 16 ++++++++++++- src/constant.rs | 39 ++++++++++++++++++++++++++++---- src/lib.rs | 18 +++++---------- src/linkage.rs | 29 ++++++++++++++++++++++++ 4 files changed, 85 insertions(+), 17 deletions(-) create mode 100644 src/linkage.rs diff --git a/example/mini_core_hello_world.rs b/example/mini_core_hello_world.rs index e07dcf6ba9e..4dea94e3687 100644 --- a/example/mini_core_hello_world.rs +++ b/example/mini_core_hello_world.rs @@ -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); } } diff --git a/src/constant.rs b/src/constant.rs index 19fce47358c..14e7585b812 100644 --- a/src/constant.rs +++ b/src/constant.rs @@ -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::>() + .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) } }; diff --git a/src/lib.rs b/src/lib.rs index bbcf0928553..f9f899a8575 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -29,6 +29,7 @@ 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 intrinsics; mod link; mod link_copied; +mod linkage; mod main_shim; mod metadata; mod pretty_clif; @@ -368,7 +370,7 @@ fn join_codegen_and_link( .downcast::() .expect("Expected CraneliftCodegenBackend's CodegenResult, found Box"); - 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::>(); 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); }); } diff --git a/src/linkage.rs b/src/linkage.rs new file mode 100644 index 00000000000..3edfba61e33 --- /dev/null +++ b/src/linkage.rs @@ -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 + } +} -- 2.44.0