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
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 {
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
ObjectFile,
}
-/// Enum pinned in LLVMContext, used in
-/// LLVMSetMetadata so ABI-stable.
+/// LLVMMetadataType
#[derive(Copy, Clone)]
#[repr(C)]
pub enum MetadataType {
/* 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;
// 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,
}
}
// 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 {
// 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)
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);
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();
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);
}
}
}
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("[");
// 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);
}
}
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);
}
}
});
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
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;
});
llvm::LLVMSetInitializer(gv, cv);
llvm::LLVMSetAlignment(gv, align);
- llvm::LLVMSetLinkage(gv, InternalLinkage);
+ llvm::LLVMRustSetLinkage(gv, llvm::Linkage::InternalLinkage);
SetUnnamedAddr(gv, true);
gv
}
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
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
}
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);
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
}
&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);
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);
}
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);
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));
+}
--- /dev/null
+// 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