]> git.lizzy.rs Git - rust.git/commitdiff
Implement weak linkage for statics
authorbjorn3 <bjorn3@users.noreply.github.com>
Mon, 11 Mar 2019 19:36:29 +0000 (20:36 +0100)
committerbjorn3 <bjorn3@users.noreply.github.com>
Mon, 11 Mar 2019 19:36:29 +0000 (20:36 +0100)
example/mini_core_hello_world.rs
src/constant.rs
src/lib.rs
src/linkage.rs [new file with mode: 0644]

index e07dcf6ba9e7dde4aeeb41e20d3ec26fc9359138..4dea94e36872c7efda81a7a4477550cd9dde034e 100644 (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); }
 }
index 19fce47358c54560255aa143c4a3afed942630a6..14e7585b812e57c71561b64092415f07159aabda 100644 (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)
                 }
             };
 
index bbcf0928553bbe7074b9c6053ef41b5b341c413a..f9f899a857546438976b1860a72371977b9642f2 100644 (file)
@@ -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::<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);
             });
         }
diff --git a/src/linkage.rs b/src/linkage.rs
new file mode 100644 (file)
index 0000000..3edfba6
--- /dev/null
@@ -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
+    }
+}