Auto merge of #36200 - mattico:fix-llvm-linkage, r=arielb1

Fix incorrect LLVM Linkage enum

Followup of #33994 to actually work.

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.

Possible remaining concerns:

1. There could be a codegen test to make sure that the attributes are applied correctly (I don't know how to do this).
2. ~~The test does not exercise the `appending` linkage. I can't figure out how to make a global static raw pointer to an array. This might not even be possible? If not we should probably remove appending linkage as its unusable in rust.~~ Appending linkage is not 'emittable' anyway.
3. The test only runs on Linux.

Fixes #33992

r? @alexcrichton
This commit is contained in:
bors 2016-09-05 08:13:32 -07:00 committed by GitHub
commit 3f50b6342d
11 changed files with 180 additions and 66 deletions

View 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("[");

View 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);
}
}

View 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);
}
}

View 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

View 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
}

View 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);

View 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
}

View file

@ -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);