Skip to content

Commit 4ce90a2

Browse files
committed
Fix incorrect LLVM Linkage enum
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 rust-lang#33992
1 parent b2799a5 commit 4ce90a2

File tree

11 files changed

+155
-36
lines changed

11 files changed

+155
-36
lines changed

src/librustc_llvm/ffi.rs

+13-9
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,10 @@ pub enum CallConv {
4848

4949
/// LLVMLinkage
5050
///
51+
/// This does not attempt to mirror the similar enum in LLVM, as this is fragile
52+
/// to upstream changes. Use LLVMRustSetLinkage() and LLVMRustGetLinkage() to
53+
/// translate these values to and from the LLVM side.
54+
///
5155
/// This enum omits the obsolete (and no-op) linkage types DLLImportLinkage,
5256
/// DLLExportLinkage, GhostLinkage and LinkOnceODRAutoHideLinkage.
5357
/// LinkerPrivateLinkage and LinkerPrivateWeakLinkage are not included either;
@@ -59,13 +63,13 @@ pub enum Linkage {
5963
AvailableExternallyLinkage = 1,
6064
LinkOnceAnyLinkage = 2,
6165
LinkOnceODRLinkage = 3,
62-
WeakAnyLinkage = 5,
63-
WeakODRLinkage = 6,
64-
AppendingLinkage = 7,
65-
InternalLinkage = 8,
66-
PrivateLinkage = 9,
67-
ExternalWeakLinkage = 12,
68-
CommonLinkage = 14,
66+
WeakAnyLinkage = 4,
67+
WeakODRLinkage = 5,
68+
AppendingLinkage = 6,
69+
InternalLinkage = 7,
70+
PrivateLinkage = 8,
71+
ExternalWeakLinkage = 9,
72+
CommonLinkage = 10,
6973
}
7074

7175
/// LLVMDiagnosticSeverity
@@ -820,8 +824,8 @@ extern {
820824
/* Operations on global variables, functions, and aliases (globals) */
821825
pub fn LLVMGetGlobalParent(Global: ValueRef) -> ModuleRef;
822826
pub fn LLVMIsDeclaration(Global: ValueRef) -> Bool;
823-
pub fn LLVMGetLinkage(Global: ValueRef) -> c_uint;
824-
pub fn LLVMSetLinkage(Global: ValueRef, Link: Linkage);
827+
pub fn LLVMRustGetLinkage(Global: ValueRef) -> Linkage;
828+
pub fn LLVMRustSetLinkage(Global: ValueRef, RustLinkage: Linkage);
825829
pub fn LLVMGetSection(Global: ValueRef) -> *const c_char;
826830
pub fn LLVMSetSection(Global: ValueRef, Section: *const c_char);
827831
pub fn LLVMGetVisibility(Global: ValueRef) -> c_uint;

src/librustc_trans/base.rs

+10-10
Original file line numberDiff line numberDiff line change
@@ -1401,10 +1401,10 @@ fn internalize_symbols<'a, 'tcx>(sess: &Session,
14011401
// are referenced via a declaration in some other codegen unit.
14021402
for ccx in ccxs.iter_need_trans() {
14031403
for val in iter_globals(ccx.llmod()).chain(iter_functions(ccx.llmod())) {
1404-
let linkage = llvm::LLVMGetLinkage(val);
1404+
let linkage = llvm::LLVMRustGetLinkage(val);
14051405
// We only care about external declarations (not definitions)
14061406
// and available_externally definitions.
1407-
let is_available_externally = linkage == llvm::AvailableExternallyLinkage as c_uint;
1407+
let is_available_externally = linkage == llvm::AvailableExternallyLinkage;
14081408
let is_decl = llvm::LLVMIsDeclaration(val) != 0;
14091409

14101410
if is_decl || is_available_externally {
@@ -1446,11 +1446,11 @@ fn internalize_symbols<'a, 'tcx>(sess: &Session,
14461446
// then give it internal linkage.
14471447
for ccx in ccxs.iter_need_trans() {
14481448
for val in iter_globals(ccx.llmod()).chain(iter_functions(ccx.llmod())) {
1449-
let linkage = llvm::LLVMGetLinkage(val);
1449+
let linkage = llvm::LLVMRustGetLinkage(val);
14501450

1451-
let is_externally_visible = (linkage == llvm::ExternalLinkage as c_uint) ||
1452-
(linkage == llvm::LinkOnceODRLinkage as c_uint) ||
1453-
(linkage == llvm::WeakODRLinkage as c_uint);
1451+
let is_externally_visible = (linkage == llvm::Linkage::ExternalLinkage) ||
1452+
(linkage == llvm::Linkage::LinkOnceODRLinkage) ||
1453+
(linkage == llvm::Linkage::WeakODRLinkage);
14541454
let is_definition = llvm::LLVMIsDeclaration(val) == 0;
14551455

14561456
// If this is a definition (as opposed to just a declaration)
@@ -1465,7 +1465,7 @@ fn internalize_symbols<'a, 'tcx>(sess: &Session,
14651465
let has_fixed_linkage = linkage_fixed_explicitly.contains(&name_cow);
14661466

14671467
if !is_referenced_somewhere && !is_reachable && !has_fixed_linkage {
1468-
llvm::LLVMSetLinkage(val, llvm::InternalLinkage);
1468+
llvm::LLVMRustSetLinkage(val, llvm::Linkage::InternalLinkage);
14691469
llvm::LLVMSetDLLStorageClass(val,
14701470
llvm::DLLStorageClass::Default);
14711471
llvm::UnsetComdat(val);
@@ -1495,8 +1495,8 @@ fn create_imps(cx: &CrateContextList) {
14951495
for ccx in cx.iter_need_trans() {
14961496
let exported: Vec<_> = iter_globals(ccx.llmod())
14971497
.filter(|&val| {
1498-
llvm::LLVMGetLinkage(val) ==
1499-
llvm::ExternalLinkage as c_uint &&
1498+
llvm::LLVMRustGetLinkage(val) ==
1499+
llvm::Linkage::ExternalLinkage &&
15001500
llvm::LLVMIsDeclaration(val) == 0
15011501
})
15021502
.collect();
@@ -1512,7 +1512,7 @@ fn create_imps(cx: &CrateContextList) {
15121512
imp_name.as_ptr() as *const _);
15131513
let init = llvm::LLVMConstBitCast(val, i8p_ty.to_ref());
15141514
llvm::LLVMSetInitializer(imp, init);
1515-
llvm::LLVMSetLinkage(imp, llvm::ExternalLinkage);
1515+
llvm::LLVMRustSetLinkage(imp, llvm::Linkage::ExternalLinkage);
15161516
}
15171517
}
15181518
}

src/librustc_trans/callee.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -472,7 +472,7 @@ fn get_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
472472
// FIXME(eddyb) Doubt all extern fn should allow unwinding.
473473
attributes::unwind(llfn, true);
474474
unsafe {
475-
llvm::LLVMSetLinkage(llfn, llvm::ExternalLinkage);
475+
llvm::LLVMRustSetLinkage(llfn, llvm::Linkage::ExternalLinkage);
476476
}
477477
}
478478

src/librustc_trans/closure.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -110,10 +110,10 @@ pub fn trans_closure_body_via_mir<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
110110

111111
unsafe {
112112
if ccx.sess().target.target.options.allows_weak_linkage {
113-
llvm::LLVMSetLinkage(llfn, llvm::WeakODRLinkage);
113+
llvm::LLVMRustSetLinkage(llfn, llvm::Linkage::WeakODRLinkage);
114114
llvm::SetUniqueComdat(ccx.llmod(), llfn);
115115
} else {
116-
llvm::LLVMSetLinkage(llfn, llvm::InternalLinkage);
116+
llvm::LLVMRustSetLinkage(llfn, llvm::Linkage::InternalLinkage);
117117
}
118118
}
119119

src/librustc_trans/common.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -817,7 +817,7 @@ pub fn C_cstr(cx: &CrateContext, s: InternedString, null_terminated: bool) -> Va
817817
});
818818
llvm::LLVMSetInitializer(g, sc);
819819
llvm::LLVMSetGlobalConstant(g, True);
820-
llvm::LLVMSetLinkage(g, llvm::InternalLinkage);
820+
llvm::LLVMRustSetLinkage(g, llvm::Linkage::InternalLinkage);
821821

822822
cx.const_cstr_cache().borrow_mut().insert(s, g);
823823
g

src/librustc_trans/consts.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
use llvm;
1313
use llvm::{SetUnnamedAddr};
14-
use llvm::{InternalLinkage, ValueRef, True};
14+
use llvm::{ValueRef, True};
1515
use rustc_const_eval::ConstEvalErr;
1616
use rustc::hir::def_id::DefId;
1717
use rustc::hir::map as hir_map;
@@ -53,7 +53,7 @@ pub fn addr_of_mut(ccx: &CrateContext,
5353
});
5454
llvm::LLVMSetInitializer(gv, cv);
5555
llvm::LLVMSetAlignment(gv, align);
56-
llvm::LLVMSetLinkage(gv, InternalLinkage);
56+
llvm::LLVMRustSetLinkage(gv, llvm::Linkage::InternalLinkage);
5757
SetUnnamedAddr(gv, true);
5858
gv
5959
}
@@ -142,7 +142,7 @@ pub fn get_static(ccx: &CrateContext, def_id: DefId) -> ValueRef {
142142
unsafe {
143143
// Declare a symbol `foo` with the desired linkage.
144144
let g1 = declare::declare_global(ccx, &sym, llty2);
145-
llvm::LLVMSetLinkage(g1, linkage);
145+
llvm::LLVMRustSetLinkage(g1, linkage);
146146

147147
// Declare an internal global `extern_with_linkage_foo` which
148148
// is initialized with the address of `foo`. If `foo` is
@@ -156,7 +156,7 @@ pub fn get_static(ccx: &CrateContext, def_id: DefId) -> ValueRef {
156156
ccx.sess().span_fatal(span,
157157
&format!("symbol `{}` is already defined", &sym))
158158
});
159-
llvm::LLVMSetLinkage(g2, llvm::InternalLinkage);
159+
llvm::LLVMRustSetLinkage(g2, llvm::Linkage::InternalLinkage);
160160
llvm::LLVMSetInitializer(g2, g1);
161161
g2
162162
}

src/librustc_trans/debuginfo/gdb.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ pub fn get_or_insert_gdb_debug_scripts_section_global(ccx: &CrateContext)
7777
llvm::LLVMSetInitializer(section_var, C_bytes(ccx, section_contents));
7878
llvm::LLVMSetGlobalConstant(section_var, llvm::True);
7979
llvm::LLVMSetUnnamedAddr(section_var, llvm::True);
80-
llvm::LLVMSetLinkage(section_var, llvm::Linkage::LinkOnceODRLinkage);
80+
llvm::LLVMRustSetLinkage(section_var, llvm::Linkage::LinkOnceODRLinkage);
8181
// This should make sure that the whole section is not larger than
8282
// the string it contains. Otherwise we get a warning from GDB.
8383
llvm::LLVMSetAlignment(section_var, 1);

src/librustc_trans/declare.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ pub fn define_internal_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
164164
name: &str,
165165
fn_type: ty::Ty<'tcx>) -> ValueRef {
166166
let llfn = define_fn(ccx, name, fn_type);
167-
unsafe { llvm::LLVMSetLinkage(llfn, llvm::InternalLinkage) };
167+
unsafe { llvm::LLVMRustSetLinkage(llfn, llvm::Linkage::InternalLinkage) };
168168
llfn
169169
}
170170

src/librustc_trans/trans_item.rs

+7-7
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ impl<'a, 'tcx> TransItem<'tcx> {
160160
&format!("symbol `{}` is already defined", symbol_name))
161161
});
162162

163-
unsafe { llvm::LLVMSetLinkage(g, linkage) };
163+
unsafe { llvm::LLVMRustSetLinkage(g, linkage) };
164164

165165
let instance = Instance::mono(ccx.shared(), def_id);
166166
ccx.instances().borrow_mut().insert(instance, g);
@@ -180,10 +180,10 @@ impl<'a, 'tcx> TransItem<'tcx> {
180180

181181
let attrs = ccx.tcx().get_attrs(instance.def);
182182
let lldecl = declare::declare_fn(ccx, symbol_name, mono_ty);
183-
unsafe { llvm::LLVMSetLinkage(lldecl, linkage) };
183+
unsafe { llvm::LLVMRustSetLinkage(lldecl, linkage) };
184184
base::set_link_section(ccx, lldecl, &attrs);
185-
if linkage == llvm::LinkOnceODRLinkage ||
186-
linkage == llvm::WeakODRLinkage {
185+
if linkage == llvm::Linkage::LinkOnceODRLinkage ||
186+
linkage == llvm::Linkage::WeakODRLinkage {
187187
llvm::SetUniqueComdat(ccx.llmod(), lldecl);
188188
}
189189

@@ -214,9 +214,9 @@ impl<'a, 'tcx> TransItem<'tcx> {
214214

215215
assert!(declare::get_defined_value(ccx, symbol_name).is_none());
216216
let llfn = declare::declare_cfn(ccx, symbol_name, llfnty);
217-
unsafe { llvm::LLVMSetLinkage(llfn, linkage) };
218-
if linkage == llvm::LinkOnceODRLinkage ||
219-
linkage == llvm::WeakODRLinkage {
217+
unsafe { llvm::LLVMRustSetLinkage(llfn, linkage) };
218+
if linkage == llvm::Linkage::LinkOnceODRLinkage ||
219+
linkage == llvm::Linkage::WeakODRLinkage {
220220
llvm::SetUniqueComdat(ccx.llmod(), llfn);
221221
}
222222
attributes::set_frame_pointer_elimination(ccx, llfn);

src/rustllvm/RustWrapper.cpp

+69
Original file line numberDiff line numberDiff line change
@@ -1232,3 +1232,72 @@ extern "C" void LLVMRustUnsetComdat(LLVMValueRef V) {
12321232
GlobalObject *GV = unwrap<GlobalObject>(V);
12331233
GV->setComdat(nullptr);
12341234
}
1235+
1236+
extern "C" unsigned LLVMRustGetLinkage(LLVMValueRef V) {
1237+
switch (LLVMGetLinkage(V)) {
1238+
case LLVMExternalLinkage:
1239+
return 0;
1240+
case LLVMAvailableExternallyLinkage:
1241+
return 1;
1242+
case LLVMLinkOnceAnyLinkage:
1243+
return 2;
1244+
case LLVMLinkOnceODRLinkage:
1245+
return 3;
1246+
case LLVMWeakAnyLinkage:
1247+
return 4;
1248+
case LLVMWeakODRLinkage:
1249+
return 5;
1250+
case LLVMAppendingLinkage:
1251+
return 6;
1252+
case LLVMInternalLinkage:
1253+
return 7;
1254+
case LLVMPrivateLinkage:
1255+
return 8;
1256+
case LLVMExternalWeakLinkage:
1257+
return 9;
1258+
case LLVMCommonLinkage:
1259+
return 10;
1260+
default:
1261+
llvm_unreachable("Invalid RustLinkage value!");
1262+
}
1263+
}
1264+
1265+
extern "C" void LLVMRustSetLinkage(LLVMValueRef V, unsigned RustLinkage) {
1266+
switch (RustLinkage) {
1267+
case 0:
1268+
LLVMSetLinkage(V, LLVMExternalLinkage);
1269+
break;
1270+
case 1:
1271+
LLVMSetLinkage(V, LLVMAvailableExternallyLinkage);
1272+
break;
1273+
case 2:
1274+
LLVMSetLinkage(V, LLVMLinkOnceAnyLinkage);
1275+
break;
1276+
case 3:
1277+
LLVMSetLinkage(V, LLVMLinkOnceODRLinkage);
1278+
break;
1279+
case 4:
1280+
LLVMSetLinkage(V, LLVMWeakAnyLinkage);
1281+
break;
1282+
case 5:
1283+
LLVMSetLinkage(V, LLVMWeakODRLinkage);
1284+
break;
1285+
case 6:
1286+
LLVMSetLinkage(V, LLVMAppendingLinkage);
1287+
break;
1288+
case 7:
1289+
LLVMSetLinkage(V, LLVMInternalLinkage);
1290+
break;
1291+
case 8:
1292+
LLVMSetLinkage(V, LLVMPrivateLinkage);
1293+
break;
1294+
case 9:
1295+
LLVMSetLinkage(V, LLVMExternalWeakLinkage);
1296+
break;
1297+
case 10:
1298+
LLVMSetLinkage(V, LLVMCommonLinkage);
1299+
break;
1300+
default:
1301+
llvm_unreachable("Invalid RustLinkage value!");
1302+
}
1303+
}

src/test/run-pass/issue-33992.rs

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// ignore-windows
12+
// ignore-macos
13+
14+
#![feature(linkage)]
15+
16+
#[linkage = "available_externally"]
17+
pub static TEST2: bool = true;
18+
19+
#[linkage = "common"]
20+
pub static mut TEST3: u32 = 0u32;
21+
22+
#[linkage = "extern_weak"]
23+
pub static TEST4: bool = true;
24+
25+
#[linkage = "external"]
26+
pub static TEST5: bool = true;
27+
28+
#[linkage = "internal"]
29+
pub static TEST6: bool = true;
30+
31+
#[linkage = "linkonce"]
32+
pub static TEST7: bool = true;
33+
34+
#[linkage = "linkonce_odr"]
35+
pub static TEST8: bool = true;
36+
37+
#[linkage = "private"]
38+
pub static TEST9: bool = true;
39+
40+
#[linkage = "weak"]
41+
pub static TEST10: bool = true;
42+
43+
#[linkage = "weak_odr"]
44+
pub static TEST11: bool = true;
45+
46+
fn main() {}

0 commit comments

Comments
 (0)