diff --git a/src/librustc_llvm/ffi.rs b/src/librustc_llvm/ffi.rs index 92fe568a72c57..50c68d5e75eef 100644 --- a/src/librustc_llvm/ffi.rs +++ b/src/librustc_llvm/ffi.rs @@ -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 @@ extern { /* 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; diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index 99126095ede3e..53d55f4a903d7 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -1198,17 +1198,17 @@ pub fn llvm_linkage_by_name(name: &str) -> Option { // 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("["); diff --git a/src/librustc_trans/callee.rs b/src/librustc_trans/callee.rs index 33cacbe194bb0..51e79d1e4b33f 100644 --- a/src/librustc_trans/callee.rs +++ b/src/librustc_trans/callee.rs @@ -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); } } diff --git a/src/librustc_trans/closure.rs b/src/librustc_trans/closure.rs index 842a8fddb83e1..83882c27e8e7b 100644 --- a/src/librustc_trans/closure.rs +++ b/src/librustc_trans/closure.rs @@ -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); } } diff --git a/src/librustc_trans/common.rs b/src/librustc_trans/common.rs index 6ae6f8aead77d..bd98eee8869b1 100644 --- a/src/librustc_trans/common.rs +++ b/src/librustc_trans/common.rs @@ -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 diff --git a/src/librustc_trans/consts.rs b/src/librustc_trans/consts.rs index 2b6e2a23261bd..15f7132e52d2f 100644 --- a/src/librustc_trans/consts.rs +++ b/src/librustc_trans/consts.rs @@ -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 } diff --git a/src/librustc_trans/debuginfo/gdb.rs b/src/librustc_trans/debuginfo/gdb.rs index 0a8d490dcd2dd..8f937d3fe25cb 100644 --- a/src/librustc_trans/debuginfo/gdb.rs +++ b/src/librustc_trans/debuginfo/gdb.rs @@ -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); diff --git a/src/librustc_trans/declare.rs b/src/librustc_trans/declare.rs index 4d9ee187ac50c..0c1156a98743e 100644 --- a/src/librustc_trans/declare.rs +++ b/src/librustc_trans/declare.rs @@ -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 } diff --git a/src/librustc_trans/trans_item.rs b/src/librustc_trans/trans_item.rs index deef0b09a17b0..9a55877a13453 100644 --- a/src/librustc_trans/trans_item.rs +++ b/src/librustc_trans/trans_item.rs @@ -160,7 +160,7 @@ impl<'a, 'tcx> TransItem<'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 @@ impl<'a, 'tcx> TransItem<'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 @@ impl<'a, 'tcx> TransItem<'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); diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp index 82fb2b0918f79..124eb1eba4f7b 100644 --- a/src/rustllvm/RustWrapper.cpp +++ b/src/rustllvm/RustWrapper.cpp @@ -1232,3 +1232,83 @@ extern "C" void LLVMRustUnsetComdat(LLVMValueRef V) { GlobalObject *GV = unwrap(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 index 0000000000000..5729469f69754 --- /dev/null +++ b/src/test/run-pass/issue-33992.rs @@ -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 or the MIT license +// , 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