Skip to content

Commit

Permalink
Fix static relocation model for PowerPC64
Browse files Browse the repository at this point in the history
  • Loading branch information
Bobo1239 committed May 28, 2021
1 parent e51830b commit 4a76934
Show file tree
Hide file tree
Showing 6 changed files with 46 additions and 46 deletions.
24 changes: 0 additions & 24 deletions compiler/rustc_codegen_llvm/src/base.rs
Expand Up @@ -218,27 +218,3 @@ pub fn visibility_to_llvm(linkage: Visibility) -> llvm::Visibility {
Visibility::Protected => llvm::Visibility::Protected,
}
}

pub fn linkage_from_llvm(linkage: llvm::Linkage) -> Linkage {
match linkage {
llvm::Linkage::ExternalLinkage => Linkage::External,
llvm::Linkage::AvailableExternallyLinkage => Linkage::AvailableExternally,
llvm::Linkage::LinkOnceAnyLinkage => Linkage::LinkOnceAny,
llvm::Linkage::LinkOnceODRLinkage => Linkage::LinkOnceODR,
llvm::Linkage::WeakAnyLinkage => Linkage::WeakAny,
llvm::Linkage::WeakODRLinkage => Linkage::WeakODR,
llvm::Linkage::AppendingLinkage => Linkage::Appending,
llvm::Linkage::InternalLinkage => Linkage::Internal,
llvm::Linkage::PrivateLinkage => Linkage::Private,
llvm::Linkage::ExternalWeakLinkage => Linkage::ExternalWeak,
llvm::Linkage::CommonLinkage => Linkage::Common,
}
}

pub fn visibility_from_llvm(linkage: llvm::Visibility) -> Visibility {
match linkage {
llvm::Visibility::Default => Visibility::Default,
llvm::Visibility::Hidden => Visibility::Hidden,
llvm::Visibility::Protected => Visibility::Protected,
}
}
3 changes: 1 addition & 2 deletions compiler/rustc_codegen_llvm/src/callee.rs
Expand Up @@ -14,7 +14,6 @@ use tracing::debug;

use rustc_middle::ty::layout::{FnAbiExt, HasTyCtxt};
use rustc_middle::ty::{self, Instance, TypeFoldable};
use rustc_target::spec::RelocModel;

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

if cx.tcx.sess.relocation_model() == RelocModel::Static {
if cx.should_assume_dso_local(llfn, true) {
llvm::LLVMRustSetDSOLocal(llfn, true);
}
}
Expand Down
9 changes: 3 additions & 6 deletions compiler/rustc_codegen_llvm/src/consts.rs
Expand Up @@ -17,7 +17,6 @@ use rustc_middle::mir::mono::MonoItem;
use rustc_middle::ty::{self, Instance, Ty};
use rustc_middle::{bug, span_bug};
use rustc_target::abi::{AddressSpace, Align, HasDataLayout, LayoutOf, Primitive, Scalar, Size};
use rustc_target::spec::RelocModel;
use tracing::debug;

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

if self.tcx.sess.relocation_model() == RelocModel::Static {
unsafe {
unsafe {
if self.should_assume_dso_local(g, true) {
llvm::LLVMRustSetDSOLocal(g, true);
}
}
Expand Down Expand Up @@ -370,9 +369,7 @@ impl StaticMethods for CodegenCx<'ll, 'tcx> {
set_global_alignment(&self, g, self.align_of(ty));
llvm::LLVMSetInitializer(g, v);

let linkage = base::linkage_from_llvm(llvm::LLVMRustGetLinkage(g));
let visibility = base::visibility_from_llvm(llvm::LLVMRustGetVisibility(g));
if self.should_assume_dso_local(linkage, visibility) {
if self.should_assume_dso_local(g, true) {
llvm::LLVMRustSetDSOLocal(g, true);
}

Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_codegen_llvm/src/llvm/ffi.rs
Expand Up @@ -72,7 +72,7 @@ pub enum Linkage {

// LLVMRustVisibility
#[repr(C)]
#[derive(Copy, Clone)]
#[derive(Copy, Clone, PartialEq)]
pub enum Visibility {
Default = 0,
Hidden = 1,
Expand Down Expand Up @@ -1035,6 +1035,7 @@ extern "C" {
pub fn LLVMDeleteGlobal(GlobalVar: &Value);
pub fn LLVMGetInitializer(GlobalVar: &Value) -> Option<&Value>;
pub fn LLVMSetInitializer(GlobalVar: &'a Value, ConstantVal: &'a Value);
pub fn LLVMIsThreadLocal(GlobalVar: &Value) -> Bool;
pub fn LLVMSetThreadLocal(GlobalVar: &Value, IsThreadLocal: Bool);
pub fn LLVMSetThreadLocalMode(GlobalVar: &Value, Mode: ThreadLocalMode);
pub fn LLVMIsGlobalConstant(GlobalVar: &Value) -> Bool;
Expand Down
42 changes: 31 additions & 11 deletions compiler/rustc_codegen_llvm/src/mono_item.rs
Expand Up @@ -37,7 +37,7 @@ impl PreDefineMethods<'tcx> for CodegenCx<'ll, 'tcx> {
unsafe {
llvm::LLVMRustSetLinkage(g, base::linkage_to_llvm(linkage));
llvm::LLVMRustSetVisibility(g, base::visibility_to_llvm(visibility));
if self.should_assume_dso_local(linkage, visibility) {
if self.should_assume_dso_local(g, false) {
llvm::LLVMRustSetDSOLocal(g, true);
}
}
Expand Down Expand Up @@ -85,7 +85,7 @@ impl PreDefineMethods<'tcx> for CodegenCx<'ll, 'tcx> {
attributes::from_fn_attrs(self, lldecl, instance);

unsafe {
if self.should_assume_dso_local(linkage, visibility) {
if self.should_assume_dso_local(lldecl, false) {
llvm::LLVMRustSetDSOLocal(lldecl, true);
}
}
Expand All @@ -95,28 +95,48 @@ impl PreDefineMethods<'tcx> for CodegenCx<'ll, 'tcx> {
}

impl CodegenCx<'ll, 'tcx> {
/// Whether a definition (NB: not declaration!) can be assumed to be local to a group of
/// Whether a definition or declaration can be assumed to be local to a group of
/// libraries that form a single DSO or executable.
pub(crate) unsafe fn should_assume_dso_local(
&self,
linkage: Linkage,
visibility: Visibility,
llval: &llvm::Value,
is_declaration: bool,
) -> bool {
if matches!(linkage, Linkage::Internal | Linkage::Private) {
let linkage = llvm::LLVMRustGetLinkage(llval);
let visibility = llvm::LLVMRustGetVisibility(llval);

if matches!(linkage, llvm::Linkage::InternalLinkage | llvm::Linkage::PrivateLinkage) {
return true;
}

if visibility != Visibility::Default && linkage != Linkage::ExternalWeak {
if visibility != llvm::Visibility::Default && linkage != llvm::Linkage::ExternalWeakLinkage
{
return true;
}

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

// Symbols from executables can't really be imported any further.
if self.tcx.sess.crate_types().iter().all(|ty| *ty == CrateType::Executable) {
// PowerPC64 prefers TOC indirection to avoid copy relocations.
if matches!(&*self.tcx.sess.target.arch, "powerpc64" | "powerpc64le") {
return false;
}

// Thread-local variables generally don't support copy relocations.
let is_thread_local_var = llvm::LLVMIsAGlobalVariable(llval)
.map(|v| llvm::LLVMIsThreadLocal(v) == llvm::True)
.unwrap_or(false);
if is_thread_local_var {
return false;
}

// Static relocation model should force copy relocations everywhere.
if self.tcx.sess.relocation_model() == RelocModel::Static {
return true;
}

Expand Down
11 changes: 9 additions & 2 deletions src/test/assembly/static-relocation-model.rs
@@ -1,9 +1,10 @@
// min-llvm-version: 12.0.0
// needs-llvm-components: aarch64 x86
// revisions:x64 A64
// needs-llvm-components: aarch64 x86 powerpc
// revisions: x64 A64 ppc64le
// assembly-output: emit-asm
// [x64] compile-flags: --target x86_64-unknown-linux-gnu -Crelocation-model=static
// [A64] compile-flags: --target aarch64-unknown-linux-gnu -Crelocation-model=static
// [ppc64le] compile-flags: --target powerpc64le-unknown-linux-gnu -Crelocation-model=static

#![feature(no_core, lang_items)]
#![no_core]
Expand Down Expand Up @@ -75,3 +76,9 @@ pub fn mango() -> u8 {
pub fn orange() -> &'static u8 {
&PIERIS
}

// For ppc64 we need to make sure to generate TOC entries even with the static relocation model
// ppc64le: .tc chaenomeles[TC],chaenomeles
// ppc64le: .tc banana[TC],banana
// ppc64le: .tc EXOCHORDA[TC],EXOCHORDA
// ppc64le: .tc PIERIS[TC],PIERIS

0 comments on commit 4a76934

Please sign in to comment.