about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbjorn3 <bjorn3@users.noreply.github.com>2020-08-16 21:20:12 +0200
committerbjorn3 <bjorn3@users.noreply.github.com>2020-08-20 15:24:33 +0200
commitca9fc101c00e33a0735a3bd2fa44eeeb7841422f (patch)
treed09008e0c73f798f98c0bca0838c0e1b04c4ac26 /src
parent02b7cdc316b733649635fe7df1051429b0dfe25b (diff)
downloadrust-ca9fc101c00e33a0735a3bd2fa44eeeb7841422f.tar.gz
rust-ca9fc101c00e33a0735a3bd2fa44eeeb7841422f.zip
Fix weak linkage
This removes the last sysroot patch apart from the few patches that disable tests
Diffstat (limited to 'src')
-rw-r--r--src/constant.rs80
-rw-r--r--src/linkage.rs8
2 files changed, 50 insertions, 38 deletions
diff --git a/src/constant.rs b/src/constant.rs
index e3d96528972..0ed05c56d74 100644
--- a/src/constant.rs
+++ b/src/constant.rs
@@ -43,8 +43,7 @@ pub(crate) fn codegen_tls_ref<'tcx>(
     def_id: DefId,
     layout: TyAndLayout<'tcx>,
 ) -> CValue<'tcx> {
-    let linkage = crate::linkage::get_static_ref_linkage(fx.tcx, def_id);
-    let data_id = data_id_for_static(fx.tcx, fx.module, def_id, linkage);
+    let data_id = data_id_for_static(fx.tcx, fx.module, def_id, false);
     let local_data_id = fx.module.declare_data_in_func(data_id, &mut fx.bcx.func);
     #[cfg(debug_assertions)]
     fx.add_comment(local_data_id, format!("tls {:?}", def_id));
@@ -57,8 +56,7 @@ fn codegen_static_ref<'tcx>(
     def_id: DefId,
     layout: TyAndLayout<'tcx>,
 ) -> CPlace<'tcx> {
-    let linkage = crate::linkage::get_static_ref_linkage(fx.tcx, def_id);
-    let data_id = data_id_for_static(fx.tcx, fx.module, def_id, linkage);
+    let data_id = data_id_for_static(fx.tcx, fx.module, def_id, false);
     let local_data_id = fx.module.declare_data_in_func(data_id, &mut fx.bcx.func);
     #[cfg(debug_assertions)]
     fx.add_comment(local_data_id, format!("{:?}", def_id));
@@ -159,8 +157,7 @@ pub(crate) fn trans_const_value<'tcx>(
                         }
                         Some(GlobalAlloc::Static(def_id)) => {
                             assert!(fx.tcx.is_static(def_id));
-                            let linkage = crate::linkage::get_static_ref_linkage(fx.tcx, def_id);
-                            let data_id = data_id_for_static(fx.tcx, fx.module, def_id, linkage);
+                            let data_id = data_id_for_static(fx.tcx, fx.module, def_id, false);
                             let local_data_id = fx.module.declare_data_in_func(data_id, &mut fx.bcx.func);
                             #[cfg(debug_assertions)]
                             fx.add_comment(local_data_id, format!("{:?}", def_id));
@@ -226,8 +223,20 @@ fn data_id_for_static(
     tcx: TyCtxt<'_>,
     module: &mut Module<impl Backend>,
     def_id: DefId,
-    linkage: Linkage,
+    definition: bool,
 ) -> DataId {
+    let rlinkage = tcx.codegen_fn_attrs(def_id).linkage;
+    let linkage = if definition {
+        crate::linkage::get_static_linkage(tcx, def_id)
+    } else {
+        if rlinkage == Some(rustc_middle::mir::mono::Linkage::ExternalWeak)
+        || rlinkage == Some(rustc_middle::mir::mono::Linkage::WeakAny) {
+            Linkage::Preemptible
+        } else {
+            Linkage::Import
+        }
+    };
+
     let instance = Instance::mono(tcx, def_id).polymorphize(tcx);
     let symbol_name = tcx.symbol_name(instance).name;
     let ty = instance.ty(tcx, ParamEnv::reveal_all());
@@ -255,26 +264,39 @@ fn data_id_for_static(
         )
         .unwrap();
 
-    if linkage == Linkage::Preemptible {
-        if let ty::RawPtr(_) = ty.kind {
-        } else {
-            tcx.sess.span_fatal(
-                tcx.def_span(def_id),
-                "must have type `*const T` or `*mut T` due to `#[linkage]` attribute",
+    if rlinkage.is_some() {
+        // Comment copied from https://github.com/rust-lang/rust/blob/45060c2a66dfd667f88bd8b94261b28a58d85bd5/src/librustc_codegen_llvm/consts.rs#L141
+        // Declare an internal global `extern_with_linkage_foo` which
+        // is initialized with the address of `foo`.  If `foo` is
+        // discarded during linking (for example, if `foo` has weak
+        // linkage and there are no definitions), then
+        // `extern_with_linkage_foo` will instead be initialized to
+        // zero.
+
+        let ref_name = format!("_rust_extern_with_linkage_{}", symbol_name);
+        let ref_data_id = module
+            .declare_data(
+                &ref_name,
+                Linkage::Local,
+                true,
+                false,
+                Some(align.try_into().unwrap()),
             )
-        }
-
+            .unwrap();
         let mut data_ctx = DataContext::new();
-        data_ctx.define_zeroinit(pointer_ty(tcx).bytes() as usize);
-        match module.define_data(data_id, &data_ctx) {
-            // Everytime a weak static is referenced, there will be a zero pointer definition,
+        let data = module.declare_data_in_data(data_id, &mut data_ctx);
+        data_ctx.define(std::iter::repeat(0).take(pointer_ty(tcx).bytes() as usize).collect());
+        data_ctx.write_data_addr(0, data, 0);
+        match module.define_data(ref_data_id, &data_ctx) {
+            // Every time the static is referenced there will be another definition of this global,
             // so duplicate definitions are expected and allowed.
             Err(ModuleError::DuplicateDefinition(_)) => {}
             res => res.unwrap(),
         }
+        ref_data_id
+    } else {
+        data_id
     }
-
-    data_id
 }
 
 fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut Module<impl Backend>, cx: &mut ConstantCx) {
@@ -301,16 +323,7 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut Module<impl Backend>, cx: &mu
                     _ => bug!("static const eval returned {:#?}", const_),
                 };
 
-                let data_id = data_id_for_static(
-                    tcx,
-                    module,
-                    def_id,
-                    if tcx.is_reachable_non_generic(def_id) {
-                        Linkage::Export
-                    } else {
-                        Linkage::Export // FIXME Set hidden visibility
-                    },
-                );
+                let data_id = data_id_for_static(tcx, module, def_id, true);
                 (data_id, alloc, section_name)
             }
         };
@@ -360,12 +373,7 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut Module<impl Backend>, cx: &mu
                     // Don't push a `TodoItem::Static` here, as it will cause statics used by
                     // multiple crates to be duplicated between them. It isn't necessary anyway,
                     // as it will get pushed by `codegen_static` when necessary.
-                    data_id_for_static(
-                        tcx,
-                        module,
-                        def_id,
-                        crate::linkage::get_static_ref_linkage(tcx, def_id),
-                    )
+                    data_id_for_static(tcx, module, def_id, false)
                 }
             };
 
diff --git a/src/linkage.rs b/src/linkage.rs
index 379c39ca637..23940c33f1f 100644
--- a/src/linkage.rs
+++ b/src/linkage.rs
@@ -11,7 +11,7 @@ pub(crate) fn get_clif_linkage(mono_item: MonoItem<'_>, linkage: RLinkage, visib
     }
 }
 
-pub(crate) fn get_static_ref_linkage(tcx: TyCtxt<'_>, def_id: DefId) -> Linkage {
+pub(crate) fn get_static_linkage(tcx: TyCtxt<'_>, def_id: DefId) -> Linkage {
     let fn_attrs = tcx.codegen_fn_attrs(def_id);
 
     if let Some(linkage) = fn_attrs.linkage {
@@ -22,6 +22,10 @@ pub(crate) fn get_static_ref_linkage(tcx: TyCtxt<'_>, def_id: DefId) -> Linkage
             _ => panic!("{:?}", linkage),
         }
     } else {
-        Linkage::Import
+        if tcx.is_reachable_non_generic(def_id) {
+            Linkage::Export
+        } else {
+            Linkage::Export // FIXME use Linkage::Hidden
+        }
     }
 }