]> git.lizzy.rs Git - rust.git/commitdiff
Fix incorrect LLVM Linkage enum
authorMatt Ickstadt <mattico8@gmail.com>
Thu, 1 Sep 2016 18:52:33 +0000 (13:52 -0500)
committerMatt Ickstadt <mattico8@gmail.com>
Sun, 4 Sep 2016 21:12:01 +0000 (16:12 -0500)
The `Linkage` enum in librustc_llvm got out of sync with the version in LLVM and it caused two variants of the #[linkage=""] attribute to break.

This adds the functions `LLVMRustGetLinkage` and `LLVMRustSetLinkage` which convert between the Rust Linkage enum and the LLVM one, which should stop this from breaking every time LLVM changes it.

Fixes #33992

src/librustc_llvm/ffi.rs
src/librustc_trans/base.rs
src/librustc_trans/callee.rs
src/librustc_trans/closure.rs
src/librustc_trans/common.rs
src/librustc_trans/consts.rs
src/librustc_trans/debuginfo/gdb.rs
src/librustc_trans/declare.rs
src/librustc_trans/trans_item.rs
src/rustllvm/RustWrapper.cpp
src/test/run-pass/issue-33992.rs [new file with mode: 0644]

index 92fe568a72c578f553fc65e4b0299ce051fba5be..50c68d5e75eef18602b86d622119474339ade5a8 100644 (file)
@@ -47,12 +47,7 @@ pub enum CallConv {
     X86_VectorCall = 80
 }
 
-/// LLVMLinkage
-///
-/// This enum omits the obsolete (and no-op) linkage types DLLImportLinkage,
-/// DLLExportLinkage, GhostLinkage and LinkOnceODRAutoHideLinkage.
-/// LinkerPrivateLinkage and LinkerPrivateWeakLinkage are not included either;
-/// they've been removed in upstream LLVM commit r203866.
+/// LLVMRustLinkage
 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
 #[repr(C)]
 pub enum Linkage {
@@ -60,13 +55,13 @@ pub enum Linkage {
     AvailableExternallyLinkage = 1,
     LinkOnceAnyLinkage = 2,
     LinkOnceODRLinkage = 3,
-    WeakAnyLinkage = 5,
-    WeakODRLinkage = 6,
-    AppendingLinkage = 7,
-    InternalLinkage = 8,
-    PrivateLinkage = 9,
-    ExternalWeakLinkage = 12,
-    CommonLinkage = 14,
+    WeakAnyLinkage = 4,
+    WeakODRLinkage = 5,
+    AppendingLinkage = 6,
+    InternalLinkage = 7,
+    PrivateLinkage = 8,
+    ExternalWeakLinkage = 9,
+    CommonLinkage = 10,
 }
 
 /// LLVMDiagnosticSeverity
@@ -253,8 +248,7 @@ pub enum FileType {
     ObjectFile,
 }
 
-/// Enum pinned in LLVMContext, used in
-/// LLVMSetMetadata so ABI-stable.
+/// LLVMMetadataType
 #[derive(Copy, Clone)]
 #[repr(C)]
 pub enum MetadataType {
@@ -821,8 +815,8 @@ pub fn LLVMConstInlineAsm(Ty: TypeRef,
     /* Operations on global variables, functions, and aliases (globals) */
     pub fn LLVMGetGlobalParent(Global: ValueRef) -> ModuleRef;
     pub fn LLVMIsDeclaration(Global: ValueRef) -> Bool;
-    pub fn LLVMGetLinkage(Global: ValueRef) -> c_uint;
-    pub fn LLVMSetLinkage(Global: ValueRef, Link: Linkage);
+    pub fn LLVMRustGetLinkage(Global: ValueRef) -> Linkage;
+    pub fn LLVMRustSetLinkage(Global: ValueRef, RustLinkage: Linkage);
     pub fn LLVMGetSection(Global: ValueRef) -> *const c_char;
     pub fn LLVMSetSection(Global: ValueRef, Section: *const c_char);
     pub fn LLVMGetVisibility(Global: ValueRef) -> c_uint;
index 99126095ede3e699d85612b00ef81031b44d67ec..53d55f4a903d7b48327f060f349dff83f846f758 100644 (file)
@@ -1198,17 +1198,17 @@ pub fn llvm_linkage_by_name(name: &str) -> Option<Linkage> {
     // ghost, dllimport, dllexport and linkonce_odr_autohide are not supported
     // and don't have to be, LLVM treats them as no-ops.
     match name {
-        "appending" => Some(llvm::AppendingLinkage),
-        "available_externally" => Some(llvm::AvailableExternallyLinkage),
-        "common" => Some(llvm::CommonLinkage),
-        "extern_weak" => Some(llvm::ExternalWeakLinkage),
-        "external" => Some(llvm::ExternalLinkage),
-        "internal" => Some(llvm::InternalLinkage),
-        "linkonce" => Some(llvm::LinkOnceAnyLinkage),
-        "linkonce_odr" => Some(llvm::LinkOnceODRLinkage),
-        "private" => Some(llvm::PrivateLinkage),
-        "weak" => Some(llvm::WeakAnyLinkage),
-        "weak_odr" => Some(llvm::WeakODRLinkage),
+        "appending" => Some(llvm::Linkage::AppendingLinkage),
+        "available_externally" => Some(llvm::Linkage::AvailableExternallyLinkage),
+        "common" => Some(llvm::Linkage::CommonLinkage),
+        "extern_weak" => Some(llvm::Linkage::ExternalWeakLinkage),
+        "external" => Some(llvm::Linkage::ExternalLinkage),
+        "internal" => Some(llvm::Linkage::InternalLinkage),
+        "linkonce" => Some(llvm::Linkage::LinkOnceAnyLinkage),
+        "linkonce_odr" => Some(llvm::Linkage::LinkOnceODRLinkage),
+        "private" => Some(llvm::Linkage::PrivateLinkage),
+        "weak" => Some(llvm::Linkage::WeakAnyLinkage),
+        "weak_odr" => Some(llvm::Linkage::WeakODRLinkage),
         _ => None,
     }
 }
@@ -1401,10 +1401,10 @@ fn internalize_symbols<'a, 'tcx>(sess: &Session,
         // are referenced via a declaration in some other codegen unit.
         for ccx in ccxs.iter_need_trans() {
             for val in iter_globals(ccx.llmod()).chain(iter_functions(ccx.llmod())) {
-                let linkage = llvm::LLVMGetLinkage(val);
+                let linkage = llvm::LLVMRustGetLinkage(val);
                 // We only care about external declarations (not definitions)
                 // and available_externally definitions.
-                let is_available_externally = linkage == llvm::AvailableExternallyLinkage as c_uint;
+                let is_available_externally = linkage == llvm::Linkage::AvailableExternallyLinkage;
                 let is_decl = llvm::LLVMIsDeclaration(val) != 0;
 
                 if is_decl || is_available_externally {
@@ -1446,11 +1446,11 @@ fn internalize_symbols<'a, 'tcx>(sess: &Session,
         // then give it internal linkage.
         for ccx in ccxs.iter_need_trans() {
             for val in iter_globals(ccx.llmod()).chain(iter_functions(ccx.llmod())) {
-                let linkage = llvm::LLVMGetLinkage(val);
+                let linkage = llvm::LLVMRustGetLinkage(val);
 
-                let is_externally_visible = (linkage == llvm::ExternalLinkage as c_uint) ||
-                                            (linkage == llvm::LinkOnceODRLinkage as c_uint) ||
-                                            (linkage == llvm::WeakODRLinkage as c_uint);
+                let is_externally_visible = (linkage == llvm::Linkage::ExternalLinkage) ||
+                                            (linkage == llvm::Linkage::LinkOnceODRLinkage) ||
+                                            (linkage == llvm::Linkage::WeakODRLinkage);
                 let is_definition = llvm::LLVMIsDeclaration(val) == 0;
 
                 // If this is a definition (as opposed to just a declaration)
@@ -1465,7 +1465,7 @@ fn internalize_symbols<'a, 'tcx>(sess: &Session,
                     let has_fixed_linkage = linkage_fixed_explicitly.contains(&name_cow);
 
                     if !is_referenced_somewhere && !is_reachable && !has_fixed_linkage {
-                        llvm::LLVMSetLinkage(val, llvm::InternalLinkage);
+                        llvm::LLVMRustSetLinkage(val, llvm::Linkage::InternalLinkage);
                         llvm::LLVMSetDLLStorageClass(val,
                                                      llvm::DLLStorageClass::Default);
                         llvm::UnsetComdat(val);
@@ -1495,8 +1495,8 @@ fn create_imps(cx: &CrateContextList) {
         for ccx in cx.iter_need_trans() {
             let exported: Vec<_> = iter_globals(ccx.llmod())
                                        .filter(|&val| {
-                                           llvm::LLVMGetLinkage(val) ==
-                                           llvm::ExternalLinkage as c_uint &&
+                                           llvm::LLVMRustGetLinkage(val) ==
+                                           llvm::Linkage::ExternalLinkage &&
                                            llvm::LLVMIsDeclaration(val) == 0
                                        })
                                        .collect();
@@ -1512,7 +1512,7 @@ fn create_imps(cx: &CrateContextList) {
                                               imp_name.as_ptr() as *const _);
                 let init = llvm::LLVMConstBitCast(val, i8p_ty.to_ref());
                 llvm::LLVMSetInitializer(imp, init);
-                llvm::LLVMSetLinkage(imp, llvm::ExternalLinkage);
+                llvm::LLVMRustSetLinkage(imp, llvm::Linkage::ExternalLinkage);
             }
         }
     }
@@ -1937,17 +1937,17 @@ fn collect_and_partition_translation_items<'a, 'tcx>(scx: &SharedCrateContext<'a
                     output.push_str(&cgu_name[..]);
 
                     let linkage_abbrev = match linkage {
-                        llvm::ExternalLinkage => "External",
-                        llvm::AvailableExternallyLinkage => "Available",
-                        llvm::LinkOnceAnyLinkage => "OnceAny",
-                        llvm::LinkOnceODRLinkage => "OnceODR",
-                        llvm::WeakAnyLinkage => "WeakAny",
-                        llvm::WeakODRLinkage => "WeakODR",
-                        llvm::AppendingLinkage => "Appending",
-                        llvm::InternalLinkage => "Internal",
-                        llvm::PrivateLinkage => "Private",
-                        llvm::ExternalWeakLinkage => "ExternalWeak",
-                        llvm::CommonLinkage => "Common",
+                        llvm::Linkage::ExternalLinkage => "External",
+                        llvm::Linkage::AvailableExternallyLinkage => "Available",
+                        llvm::Linkage::LinkOnceAnyLinkage => "OnceAny",
+                        llvm::Linkage::LinkOnceODRLinkage => "OnceODR",
+                        llvm::Linkage::WeakAnyLinkage => "WeakAny",
+                        llvm::Linkage::WeakODRLinkage => "WeakODR",
+                        llvm::Linkage::AppendingLinkage => "Appending",
+                        llvm::Linkage::InternalLinkage => "Internal",
+                        llvm::Linkage::PrivateLinkage => "Private",
+                        llvm::Linkage::ExternalWeakLinkage => "ExternalWeak",
+                        llvm::Linkage::CommonLinkage => "Common",
                     };
 
                     output.push_str("[");
index 33cacbe194bb0ee1c66bcdcf59d4252076546aa3..51e79d1e4b33f3f7c0df2d0d920d8b0c9e531686 100644 (file)
@@ -472,7 +472,7 @@ fn get_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
             // FIXME(eddyb) Doubt all extern fn should allow unwinding.
             attributes::unwind(llfn, true);
             unsafe {
-                llvm::LLVMSetLinkage(llfn, llvm::ExternalLinkage);
+                llvm::LLVMRustSetLinkage(llfn, llvm::Linkage::ExternalLinkage);
             }
         }
 
index 842a8fddb83e199e03af4a917d117f6a38a236b2..83882c27e8e7b6191ea2b77117a825fbfa9a771c 100644 (file)
@@ -110,10 +110,10 @@ pub fn trans_closure_body_via_mir<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
 
         unsafe {
             if ccx.sess().target.target.options.allows_weak_linkage {
-                llvm::LLVMSetLinkage(llfn, llvm::WeakODRLinkage);
+                llvm::LLVMRustSetLinkage(llfn, llvm::Linkage::WeakODRLinkage);
                 llvm::SetUniqueComdat(ccx.llmod(), llfn);
             } else {
-                llvm::LLVMSetLinkage(llfn, llvm::InternalLinkage);
+                llvm::LLVMRustSetLinkage(llfn, llvm::Linkage::InternalLinkage);
             }
         }
 
index 6ae6f8aead77dff9d511cb1f23234329f184d38c..bd98eee8869b17f957d67218f061d58928cefb6e 100644 (file)
@@ -817,7 +817,7 @@ pub fn C_cstr(cx: &CrateContext, s: InternedString, null_terminated: bool) -> Va
         });
         llvm::LLVMSetInitializer(g, sc);
         llvm::LLVMSetGlobalConstant(g, True);
-        llvm::LLVMSetLinkage(g, llvm::InternalLinkage);
+        llvm::LLVMRustSetLinkage(g, llvm::Linkage::InternalLinkage);
 
         cx.const_cstr_cache().borrow_mut().insert(s, g);
         g
index 2b6e2a23261bdf21c073c45f6f7d047c22f05616..15f7132e52d2f66b8e8dd18f39268dcfca58152d 100644 (file)
@@ -11,7 +11,7 @@
 
 use llvm;
 use llvm::{SetUnnamedAddr};
-use llvm::{InternalLinkage, ValueRef, True};
+use llvm::{ValueRef, True};
 use rustc_const_eval::ConstEvalErr;
 use rustc::hir::def_id::DefId;
 use rustc::hir::map as hir_map;
@@ -53,7 +53,7 @@ pub fn addr_of_mut(ccx: &CrateContext,
         });
         llvm::LLVMSetInitializer(gv, cv);
         llvm::LLVMSetAlignment(gv, align);
-        llvm::LLVMSetLinkage(gv, InternalLinkage);
+        llvm::LLVMRustSetLinkage(gv, llvm::Linkage::InternalLinkage);
         SetUnnamedAddr(gv, true);
         gv
     }
@@ -142,7 +142,7 @@ pub fn get_static(ccx: &CrateContext, def_id: DefId) -> ValueRef {
                     unsafe {
                         // Declare a symbol `foo` with the desired linkage.
                         let g1 = declare::declare_global(ccx, &sym, llty2);
-                        llvm::LLVMSetLinkage(g1, linkage);
+                        llvm::LLVMRustSetLinkage(g1, linkage);
 
                         // Declare an internal global `extern_with_linkage_foo` which
                         // is initialized with the address of `foo`.  If `foo` is
@@ -156,7 +156,7 @@ pub fn get_static(ccx: &CrateContext, def_id: DefId) -> ValueRef {
                             ccx.sess().span_fatal(span,
                                 &format!("symbol `{}` is already defined", &sym))
                         });
-                        llvm::LLVMSetLinkage(g2, llvm::InternalLinkage);
+                        llvm::LLVMRustSetLinkage(g2, llvm::Linkage::InternalLinkage);
                         llvm::LLVMSetInitializer(g2, g1);
                         g2
                     }
index 0a8d490dcd2dd3e54601a69484f44d1eddf7aaea..8f937d3fe25cbd4e6716b22e0c3a9c4baa28bb1b 100644 (file)
@@ -77,7 +77,7 @@ pub fn get_or_insert_gdb_debug_scripts_section_global(ccx: &CrateContext)
             llvm::LLVMSetInitializer(section_var, C_bytes(ccx, section_contents));
             llvm::LLVMSetGlobalConstant(section_var, llvm::True);
             llvm::LLVMSetUnnamedAddr(section_var, llvm::True);
-            llvm::LLVMSetLinkage(section_var, llvm::Linkage::LinkOnceODRLinkage);
+            llvm::LLVMRustSetLinkage(section_var, llvm::Linkage::LinkOnceODRLinkage);
             // This should make sure that the whole section is not larger than
             // the string it contains. Otherwise we get a warning from GDB.
             llvm::LLVMSetAlignment(section_var, 1);
index 4d9ee187ac50c36ddad54d98548175e874b4c26f..0c1156a98743efba996874a151d63979a186ecf4 100644 (file)
@@ -164,7 +164,7 @@ pub fn define_internal_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                                     name: &str,
                                     fn_type: ty::Ty<'tcx>) -> ValueRef {
     let llfn = define_fn(ccx, name, fn_type);
-    unsafe { llvm::LLVMSetLinkage(llfn, llvm::InternalLinkage) };
+    unsafe { llvm::LLVMRustSetLinkage(llfn, llvm::Linkage::InternalLinkage) };
     llfn
 }
 
index deef0b09a17b032dfa1b63b06c5e11418310afec..9a55877a134536cb149a573abedf45908f8a1054 100644 (file)
@@ -160,7 +160,7 @@ fn predefine_static(ccx: &CrateContext<'a, 'tcx>,
                 &format!("symbol `{}` is already defined", symbol_name))
         });
 
-        unsafe { llvm::LLVMSetLinkage(g, linkage) };
+        unsafe { llvm::LLVMRustSetLinkage(g, linkage) };
 
         let instance = Instance::mono(ccx.shared(), def_id);
         ccx.instances().borrow_mut().insert(instance, g);
@@ -180,10 +180,10 @@ fn predefine_fn(ccx: &CrateContext<'a, 'tcx>,
 
         let attrs = ccx.tcx().get_attrs(instance.def);
         let lldecl = declare::declare_fn(ccx, symbol_name, mono_ty);
-        unsafe { llvm::LLVMSetLinkage(lldecl, linkage) };
+        unsafe { llvm::LLVMRustSetLinkage(lldecl, linkage) };
         base::set_link_section(ccx, lldecl, &attrs);
-        if linkage == llvm::LinkOnceODRLinkage ||
-            linkage == llvm::WeakODRLinkage {
+        if linkage == llvm::Linkage::LinkOnceODRLinkage ||
+            linkage == llvm::Linkage::WeakODRLinkage {
             llvm::SetUniqueComdat(ccx.llmod(), lldecl);
         }
 
@@ -214,9 +214,9 @@ fn predefine_drop_glue(ccx: &CrateContext<'a, 'tcx>,
 
         assert!(declare::get_defined_value(ccx, symbol_name).is_none());
         let llfn = declare::declare_cfn(ccx, symbol_name, llfnty);
-        unsafe { llvm::LLVMSetLinkage(llfn, linkage) };
-        if linkage == llvm::LinkOnceODRLinkage ||
-           linkage == llvm::WeakODRLinkage {
+        unsafe { llvm::LLVMRustSetLinkage(llfn, linkage) };
+        if linkage == llvm::Linkage::LinkOnceODRLinkage ||
+           linkage == llvm::Linkage::WeakODRLinkage {
             llvm::SetUniqueComdat(ccx.llmod(), llfn);
         }
         attributes::set_frame_pointer_elimination(ccx, llfn);
index 82fb2b0918f79fcfedb4f37614103f47bbd1dee3..124eb1eba4f7b9f694e40c3d911bcb7a7fd2ad81 100644 (file)
@@ -1232,3 +1232,83 @@ extern "C" void LLVMRustUnsetComdat(LLVMValueRef V) {
     GlobalObject *GV = unwrap<GlobalObject>(V);
     GV->setComdat(nullptr);
 }
+
+enum class LLVMRustLinkage {
+    ExternalLinkage = 0,
+    AvailableExternallyLinkage = 1,
+    LinkOnceAnyLinkage = 2,
+    LinkOnceODRLinkage = 3,
+    WeakAnyLinkage = 4,
+    WeakODRLinkage = 5,
+    AppendingLinkage = 6,
+    InternalLinkage = 7,
+    PrivateLinkage = 8,
+    ExternalWeakLinkage = 9,
+    CommonLinkage = 10,
+};
+
+static LLVMRustLinkage to_rust(LLVMLinkage linkage) {
+    switch (linkage) {
+        case LLVMExternalLinkage:
+            return LLVMRustLinkage::ExternalLinkage;
+        case LLVMAvailableExternallyLinkage:
+            return LLVMRustLinkage::AvailableExternallyLinkage;
+        case LLVMLinkOnceAnyLinkage:
+            return LLVMRustLinkage::LinkOnceAnyLinkage;
+        case LLVMLinkOnceODRLinkage:
+            return LLVMRustLinkage::LinkOnceODRLinkage;
+        case LLVMWeakAnyLinkage:
+            return LLVMRustLinkage::WeakAnyLinkage;
+        case LLVMWeakODRLinkage:
+            return LLVMRustLinkage::WeakODRLinkage;
+        case LLVMAppendingLinkage:
+            return LLVMRustLinkage::AppendingLinkage;
+        case LLVMInternalLinkage:
+            return LLVMRustLinkage::InternalLinkage;
+        case LLVMPrivateLinkage:
+            return LLVMRustLinkage::PrivateLinkage;
+        case LLVMExternalWeakLinkage:
+            return LLVMRustLinkage::ExternalWeakLinkage;
+        case LLVMCommonLinkage:
+            return LLVMRustLinkage::CommonLinkage;
+        default:
+            llvm_unreachable("Invalid LLVMRustLinkage value!");
+    }
+}
+
+static LLVMLinkage from_rust(LLVMRustLinkage linkage) {
+    switch (linkage) {
+        case LLVMRustLinkage::ExternalLinkage:
+            return LLVMExternalLinkage;
+        case LLVMRustLinkage::AvailableExternallyLinkage:
+            return LLVMAvailableExternallyLinkage;
+        case LLVMRustLinkage::LinkOnceAnyLinkage:
+            return LLVMLinkOnceAnyLinkage;
+        case LLVMRustLinkage::LinkOnceODRLinkage:
+            return LLVMLinkOnceODRLinkage;
+        case LLVMRustLinkage::WeakAnyLinkage:
+            return LLVMWeakAnyLinkage;
+        case LLVMRustLinkage::WeakODRLinkage:
+            return LLVMWeakODRLinkage;
+        case LLVMRustLinkage::AppendingLinkage:
+            return LLVMAppendingLinkage;
+        case LLVMRustLinkage::InternalLinkage:
+            return LLVMInternalLinkage;
+        case LLVMRustLinkage::PrivateLinkage:
+            return LLVMPrivateLinkage;
+        case LLVMRustLinkage::ExternalWeakLinkage:
+            return LLVMExternalWeakLinkage;
+        case LLVMRustLinkage::CommonLinkage:
+            return LLVMCommonLinkage;
+        default:
+            llvm_unreachable("Invalid LLVMRustLinkage value!");
+    } 
+}
+
+extern "C" LLVMRustLinkage LLVMRustGetLinkage(LLVMValueRef V) {
+    return to_rust(LLVMGetLinkage(V));
+}
+
+extern "C" void LLVMRustSetLinkage(LLVMValueRef V, LLVMRustLinkage RustLinkage) {
+    LLVMSetLinkage(V, from_rust(RustLinkage));
+}
diff --git a/src/test/run-pass/issue-33992.rs b/src/test/run-pass/issue-33992.rs
new file mode 100644 (file)
index 0000000..5729469
--- /dev/null
@@ -0,0 +1,40 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// ignore-windows
+// ignore-macos
+
+#![feature(linkage)]
+
+#[linkage = "common"]
+pub static mut TEST1: u32 = 0u32;
+
+#[linkage = "external"]
+pub static TEST2: bool = true;
+
+#[linkage = "internal"]
+pub static TEST3: bool = true;
+
+#[linkage = "linkonce"]
+pub static TEST4: bool = true;
+
+#[linkage = "linkonce_odr"]
+pub static TEST5: bool = true;
+
+#[linkage = "private"]
+pub static TEST6: bool = true;
+
+#[linkage = "weak"]
+pub static TEST7: bool = true;
+
+#[linkage = "weak_odr"]
+pub static TEST8: bool = true;
+
+fn main() {}
\ No newline at end of file