Skip to content

Commit 4cee31e

Browse files
authored
Rollup merge of rust-lang#36200 - mattico:fix-llvm-linkage, r=alexcrichton
Fix incorrect LLVM Linkage enum Followup of rust-lang#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. 3. The test only runs on Linux. Fixes rust-lang#33992 r? @alexcrichton
2 parents 1c4e799 + 4ce90a2 commit 4cee31e

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
@@ -49,6 +49,10 @@ pub enum CallConv {
4949

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

7276
/// LLVMDiagnosticSeverity
@@ -821,8 +825,8 @@ extern {
821825
/* Operations on global variables, functions, and aliases (globals) */
822826
pub fn LLVMGetGlobalParent(Global: ValueRef) -> ModuleRef;
823827
pub fn LLVMIsDeclaration(Global: ValueRef) -> Bool;
824-
pub fn LLVMGetLinkage(Global: ValueRef) -> c_uint;
825-
pub fn LLVMSetLinkage(Global: ValueRef, Link: Linkage);
828+
pub fn LLVMRustGetLinkage(Global: ValueRef) -> Linkage;
829+
pub fn LLVMRustSetLinkage(Global: ValueRef, RustLinkage: Linkage);
826830
pub fn LLVMGetSection(Global: ValueRef) -> *const c_char;
827831
pub fn LLVMSetSection(Global: ValueRef, Section: *const c_char);
828832
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)