Skip to content

Commit 6f9df55

Browse files
committedMay 28, 2021
Auto merge of #85700 - Bobo1239:dso_local_ppc64, r=nagisa
Fix static relocation model for PowerPC64 We now also use `should_assume_dso_local()` for declarations and port two additional cases from clang: - Exclude PPC64 [1] - Exclude thread-local variables [2] [1]: https://github.com/llvm/llvm-project/blob/033138ea452f5f493fb5095e5963419905ad12e1/clang/lib/CodeGen/CodeGenModule.cpp#L1038-L1040 [2]: https://github.com/llvm/llvm-project/blob/033138ea452f5f493fb5095e5963419905ad12e1/clang/lib/CodeGen/CodeGenModule.cpp#L1048-L1050 Tbh I don't know enough about PowerPC(64) to explain why the TOC (table of contents; like the GOT in x86?) is still needed even with the static relocation model. But with these changes [Rust-For-Linux](https://github.com/Rust-for-Linux/linux) runs again on ppc64le. (instead of [getting loaded successfully but crashing](https://github.com/Bobo1239/linux/runs/2646478783?check_suite_focus=true#step:47:358)) r? `@nagisa`
2 parents ce0d64e + 4a76934 commit 6f9df55

File tree

6 files changed

+46
-46
lines changed

6 files changed

+46
-46
lines changed
 

‎compiler/rustc_codegen_llvm/src/base.rs

-24
Original file line numberDiff line numberDiff line change
@@ -218,27 +218,3 @@ pub fn visibility_to_llvm(linkage: Visibility) -> llvm::Visibility {
218218
Visibility::Protected => llvm::Visibility::Protected,
219219
}
220220
}
221-
222-
pub fn linkage_from_llvm(linkage: llvm::Linkage) -> Linkage {
223-
match linkage {
224-
llvm::Linkage::ExternalLinkage => Linkage::External,
225-
llvm::Linkage::AvailableExternallyLinkage => Linkage::AvailableExternally,
226-
llvm::Linkage::LinkOnceAnyLinkage => Linkage::LinkOnceAny,
227-
llvm::Linkage::LinkOnceODRLinkage => Linkage::LinkOnceODR,
228-
llvm::Linkage::WeakAnyLinkage => Linkage::WeakAny,
229-
llvm::Linkage::WeakODRLinkage => Linkage::WeakODR,
230-
llvm::Linkage::AppendingLinkage => Linkage::Appending,
231-
llvm::Linkage::InternalLinkage => Linkage::Internal,
232-
llvm::Linkage::PrivateLinkage => Linkage::Private,
233-
llvm::Linkage::ExternalWeakLinkage => Linkage::ExternalWeak,
234-
llvm::Linkage::CommonLinkage => Linkage::Common,
235-
}
236-
}
237-
238-
pub fn visibility_from_llvm(linkage: llvm::Visibility) -> Visibility {
239-
match linkage {
240-
llvm::Visibility::Default => Visibility::Default,
241-
llvm::Visibility::Hidden => Visibility::Hidden,
242-
llvm::Visibility::Protected => Visibility::Protected,
243-
}
244-
}

‎compiler/rustc_codegen_llvm/src/callee.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ use tracing::debug;
1414

1515
use rustc_middle::ty::layout::{FnAbiExt, HasTyCtxt};
1616
use rustc_middle::ty::{self, Instance, TypeFoldable};
17-
use rustc_target::spec::RelocModel;
1817

1918
/// Codegens a reference to a fn/method item, monomorphizing and
2019
/// inlining as it goes.
@@ -181,7 +180,7 @@ pub fn get_fn(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'tcx>) -> &'ll Value
181180
llvm::LLVMSetDLLStorageClass(llfn, llvm::DLLStorageClass::DllImport);
182181
}
183182

184-
if cx.tcx.sess.relocation_model() == RelocModel::Static {
183+
if cx.should_assume_dso_local(llfn, true) {
185184
llvm::LLVMRustSetDSOLocal(llfn, true);
186185
}
187186
}

‎compiler/rustc_codegen_llvm/src/consts.rs

+3-6
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ use rustc_middle::mir::mono::MonoItem;
1717
use rustc_middle::ty::{self, Instance, Ty};
1818
use rustc_middle::{bug, span_bug};
1919
use rustc_target::abi::{AddressSpace, Align, HasDataLayout, LayoutOf, Primitive, Scalar, Size};
20-
use rustc_target::spec::RelocModel;
2120
use tracing::debug;
2221

2322
pub fn const_alloc_to_llvm(cx: &CodegenCx<'ll, '_>, alloc: &Allocation) -> &'ll Value {
@@ -283,8 +282,8 @@ impl CodegenCx<'ll, 'tcx> {
283282
}
284283
}
285284

286-
if self.tcx.sess.relocation_model() == RelocModel::Static {
287-
unsafe {
285+
unsafe {
286+
if self.should_assume_dso_local(g, true) {
288287
llvm::LLVMRustSetDSOLocal(g, true);
289288
}
290289
}
@@ -370,9 +369,7 @@ impl StaticMethods for CodegenCx<'ll, 'tcx> {
370369
set_global_alignment(&self, g, self.align_of(ty));
371370
llvm::LLVMSetInitializer(g, v);
372371

373-
let linkage = base::linkage_from_llvm(llvm::LLVMRustGetLinkage(g));
374-
let visibility = base::visibility_from_llvm(llvm::LLVMRustGetVisibility(g));
375-
if self.should_assume_dso_local(linkage, visibility) {
372+
if self.should_assume_dso_local(g, true) {
376373
llvm::LLVMRustSetDSOLocal(g, true);
377374
}
378375

‎compiler/rustc_codegen_llvm/src/llvm/ffi.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ pub enum Linkage {
7272

7373
// LLVMRustVisibility
7474
#[repr(C)]
75-
#[derive(Copy, Clone)]
75+
#[derive(Copy, Clone, PartialEq)]
7676
pub enum Visibility {
7777
Default = 0,
7878
Hidden = 1,
@@ -1035,6 +1035,7 @@ extern "C" {
10351035
pub fn LLVMDeleteGlobal(GlobalVar: &Value);
10361036
pub fn LLVMGetInitializer(GlobalVar: &Value) -> Option<&Value>;
10371037
pub fn LLVMSetInitializer(GlobalVar: &'a Value, ConstantVal: &'a Value);
1038+
pub fn LLVMIsThreadLocal(GlobalVar: &Value) -> Bool;
10381039
pub fn LLVMSetThreadLocal(GlobalVar: &Value, IsThreadLocal: Bool);
10391040
pub fn LLVMSetThreadLocalMode(GlobalVar: &Value, Mode: ThreadLocalMode);
10401041
pub fn LLVMIsGlobalConstant(GlobalVar: &Value) -> Bool;

‎compiler/rustc_codegen_llvm/src/mono_item.rs

+31-11
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ impl PreDefineMethods<'tcx> for CodegenCx<'ll, 'tcx> {
3737
unsafe {
3838
llvm::LLVMRustSetLinkage(g, base::linkage_to_llvm(linkage));
3939
llvm::LLVMRustSetVisibility(g, base::visibility_to_llvm(visibility));
40-
if self.should_assume_dso_local(linkage, visibility) {
40+
if self.should_assume_dso_local(g, false) {
4141
llvm::LLVMRustSetDSOLocal(g, true);
4242
}
4343
}
@@ -85,7 +85,7 @@ impl PreDefineMethods<'tcx> for CodegenCx<'ll, 'tcx> {
8585
attributes::from_fn_attrs(self, lldecl, instance);
8686

8787
unsafe {
88-
if self.should_assume_dso_local(linkage, visibility) {
88+
if self.should_assume_dso_local(lldecl, false) {
8989
llvm::LLVMRustSetDSOLocal(lldecl, true);
9090
}
9191
}
@@ -95,28 +95,48 @@ impl PreDefineMethods<'tcx> for CodegenCx<'ll, 'tcx> {
9595
}
9696

9797
impl CodegenCx<'ll, 'tcx> {
98-
/// Whether a definition (NB: not declaration!) can be assumed to be local to a group of
98+
/// Whether a definition or declaration can be assumed to be local to a group of
9999
/// libraries that form a single DSO or executable.
100100
pub(crate) unsafe fn should_assume_dso_local(
101101
&self,
102-
linkage: Linkage,
103-
visibility: Visibility,
102+
llval: &llvm::Value,
103+
is_declaration: bool,
104104
) -> bool {
105-
if matches!(linkage, Linkage::Internal | Linkage::Private) {
105+
let linkage = llvm::LLVMRustGetLinkage(llval);
106+
let visibility = llvm::LLVMRustGetVisibility(llval);
107+
108+
if matches!(linkage, llvm::Linkage::InternalLinkage | llvm::Linkage::PrivateLinkage) {
106109
return true;
107110
}
108111

109-
if visibility != Visibility::Default && linkage != Linkage::ExternalWeak {
112+
if visibility != llvm::Visibility::Default && linkage != llvm::Linkage::ExternalWeakLinkage
113+
{
110114
return true;
111115
}
112116

113-
// Static relocation model should force copy relocations everywhere.
114-
if self.tcx.sess.relocation_model() == RelocModel::Static {
117+
// Symbols from executables can't really be imported any further.
118+
let all_exe = self.tcx.sess.crate_types().iter().all(|ty| *ty == CrateType::Executable);
119+
let is_declaration_for_linker =
120+
is_declaration || linkage == llvm::Linkage::AvailableExternallyLinkage;
121+
if all_exe && !is_declaration_for_linker {
115122
return true;
116123
}
117124

118-
// Symbols from executables can't really be imported any further.
119-
if self.tcx.sess.crate_types().iter().all(|ty| *ty == CrateType::Executable) {
125+
// PowerPC64 prefers TOC indirection to avoid copy relocations.
126+
if matches!(&*self.tcx.sess.target.arch, "powerpc64" | "powerpc64le") {
127+
return false;
128+
}
129+
130+
// Thread-local variables generally don't support copy relocations.
131+
let is_thread_local_var = llvm::LLVMIsAGlobalVariable(llval)
132+
.map(|v| llvm::LLVMIsThreadLocal(v) == llvm::True)
133+
.unwrap_or(false);
134+
if is_thread_local_var {
135+
return false;
136+
}
137+
138+
// Static relocation model should force copy relocations everywhere.
139+
if self.tcx.sess.relocation_model() == RelocModel::Static {
120140
return true;
121141
}
122142

‎src/test/assembly/static-relocation-model.rs

+9-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
// min-llvm-version: 12.0.0
2-
// needs-llvm-components: aarch64 x86
3-
// revisions:x64 A64
2+
// needs-llvm-components: aarch64 x86 powerpc
3+
// revisions: x64 A64 ppc64le
44
// assembly-output: emit-asm
55
// [x64] compile-flags: --target x86_64-unknown-linux-gnu -Crelocation-model=static
66
// [A64] compile-flags: --target aarch64-unknown-linux-gnu -Crelocation-model=static
7+
// [ppc64le] compile-flags: --target powerpc64le-unknown-linux-gnu -Crelocation-model=static
78

89
#![feature(no_core, lang_items)]
910
#![no_core]
@@ -75,3 +76,9 @@ pub fn mango() -> u8 {
7576
pub fn orange() -> &'static u8 {
7677
&PIERIS
7778
}
79+
80+
// For ppc64 we need to make sure to generate TOC entries even with the static relocation model
81+
// ppc64le: .tc chaenomeles[TC],chaenomeles
82+
// ppc64le: .tc banana[TC],banana
83+
// ppc64le: .tc EXOCHORDA[TC],EXOCHORDA
84+
// ppc64le: .tc PIERIS[TC],PIERIS

0 commit comments

Comments
 (0)
Please sign in to comment.