Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Set dso_local for hidden, private and local items #83592

Merged
merged 1 commit into from
Apr 6, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions compiler/rustc_codegen_llvm/src/attributes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,7 @@ pub fn from_fn_attrs(cx: &CodegenCx<'ll, 'tcx>, llfn: &'ll Value, instance: ty::
attributes::emit_uwtable(llfn, true);
}

// FIXME: none of these three functions interact with source level attributes.
set_frame_pointer_elimination(cx, llfn);
set_instrument_function(cx, llfn);
set_probestack(cx, llfn);
Expand Down
19 changes: 11 additions & 8 deletions compiler/rustc_codegen_llvm/src/callee.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ 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 @@ -170,17 +171,19 @@ pub fn get_fn(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'tcx>) -> &'ll Value
}
}
}
}

// MinGW: For backward compatibility we rely on the linker to decide whether it
// should use dllimport for functions.
if cx.use_dll_storage_attrs
&& tcx.is_dllimport_foreign_item(instance_def_id)
&& tcx.sess.target.env != "gnu"
{
unsafe {
// MinGW: For backward compatibility we rely on the linker to decide whether it
// should use dllimport for functions.
if cx.use_dll_storage_attrs
&& tcx.is_dllimport_foreign_item(instance_def_id)
&& tcx.sess.target.env != "gnu"
{
llvm::LLVMSetDLLStorageClass(llfn, llvm::DLLStorageClass::DllImport);
}

if cx.tcx.sess.relocation_model() == RelocModel::Static {
llvm::LLVMRustSetDSOLocal(llfn, true);
}
}

llfn
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_codegen_llvm/src/llvm/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1031,6 +1031,7 @@ extern "C" {
pub fn LLVMSetSection(Global: &Value, Section: *const c_char);
pub fn LLVMRustGetVisibility(Global: &Value) -> Visibility;
pub fn LLVMRustSetVisibility(Global: &Value, Viz: Visibility);
pub fn LLVMRustSetDSOLocal(Global: &Value, is_dso_local: bool);
pub fn LLVMGetAlignment(Global: &Value) -> c_uint;
pub fn LLVMSetAlignment(Global: &Value, Bytes: c_uint);
pub fn LLVMSetDLLStorageClass(V: &Value, C: DLLStorageClass);
Expand Down
41 changes: 41 additions & 0 deletions compiler/rustc_codegen_llvm/src/mono_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ pub use rustc_middle::mir::mono::MonoItem;
use rustc_middle::mir::mono::{Linkage, Visibility};
use rustc_middle::ty::layout::FnAbiExt;
use rustc_middle::ty::{self, Instance, TypeFoldable};
use rustc_session::config::CrateType;
use rustc_target::abi::LayoutOf;
use rustc_target::spec::RelocModel;
use tracing::debug;

impl PreDefineMethods<'tcx> for CodegenCx<'ll, 'tcx> {
Expand All @@ -35,6 +37,9 @@ 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) {
llvm::LLVMRustSetDSOLocal(g, true);
}
}

self.instances.borrow_mut().insert(instance, g);
Expand Down Expand Up @@ -79,6 +84,42 @@ impl PreDefineMethods<'tcx> for CodegenCx<'ll, 'tcx> {

attributes::from_fn_attrs(self, lldecl, instance);

unsafe {
if self.should_assume_dso_local(linkage, visibility) {
llvm::LLVMRustSetDSOLocal(lldecl, true);
}
}

self.instances.borrow_mut().insert(instance, lldecl);
}
}

impl CodegenCx<'ll, 'tcx> {
/// Whether a definition (NB: not 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,
) -> bool {
if matches!(linkage, Linkage::Internal | Linkage::Private) {
return true;
}

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

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

// Symbols from executables can't really be imported any further.
if self.tcx.sess.crate_types().iter().all(|ty| *ty == CrateType::Executable) {
return true;
}

return false;
}
}
4 changes: 4 additions & 0 deletions compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1636,6 +1636,10 @@ extern "C" void LLVMRustSetVisibility(LLVMValueRef V,
LLVMSetVisibility(V, fromRust(RustVisibility));
}

extern "C" void LLVMRustSetDSOLocal(LLVMValueRef Global, bool is_dso_local) {
unwrap<GlobalValue>(Global)->setDSOLocal(is_dso_local);
}

struct LLVMRustModuleBuffer {
std::string data;
};
Expand Down
44 changes: 44 additions & 0 deletions src/test/assembly/static-relocation-model.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// min-llvm-version: 12.0.0
// needs-llvm-components: aarch64 x86
// revisions:X64 A64
// 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

#![feature(no_core, lang_items)]
#![no_core]
#![crate_type="rlib"]

#[lang="sized"]
trait Sized {}

#[lang="copy"]
trait Copy {}

impl Copy for u8 {}

extern "C" {
fn chaenomeles();
}

// CHECK-LABEL: banana:
// x64: movb chaenomeles, %{{[a,z]+}}
// A64: adrp [[REG:[a-z0-9]+]], chaenomeles
// A64-NEXT: ldrb {{[a-z0-9]+}}, {{\[}}[[REG]], :lo12:chaenomeles]
#[no_mangle]
pub fn banana() -> u8 {
unsafe {
*(chaenomeles as *mut u8)
}
}

// CHECK-LABEL: peach:
// x64: movb banana, %{{[a,z]+}}
// A64: adrp [[REG2:[a-z0-9]+]], banana
// A64-NEXT: ldrb {{[a-z0-9]+}}, {{\[}}[[REG2]], :lo12:banana]
#[no_mangle]
pub fn peach() -> u8 {
unsafe {
*(banana as *mut u8)
}
}
6 changes: 3 additions & 3 deletions src/test/codegen/abi-efiapi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ trait Copy { }

//x86_64: define win64cc void @has_efiapi
//i686: define void @has_efiapi
//aarch64: define void @has_efiapi
//arm: define void @has_efiapi
//riscv: define void @has_efiapi
//aarch64: define dso_local void @has_efiapi
//arm: define dso_local void @has_efiapi
//riscv: define dso_local void @has_efiapi
#[no_mangle]
pub extern "efiapi" fn has_efiapi() {}
2 changes: 1 addition & 1 deletion src/test/codegen/abi-repr-ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ pub enum Type {
Type2 = 1
}

// CHECK: define signext i8 @test()
// CHECK: define{{( dso_local)?}} signext i8 @test()
#[no_mangle]
pub extern "C" fn test() -> Type {
Type::Type1
Expand Down
18 changes: 11 additions & 7 deletions src/test/codegen/abi-sysv64.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
// Checks if the correct annotation for the sysv64 ABI is passed to
// llvm. Also checks that the abi-sysv64 feature gate allows usage
// of the sysv64 abi.

// ignore-arm
// ignore-aarch64
// ignore-riscv64 sysv64 not supported

// compile-flags: -C no-prepopulate-passes
//
// needs-llvm-components: x86
// compile-flags: -C no-prepopulate-passes --target=x86_64-unknown-linux-gnu

#![crate_type = "lib"]
#![no_core]
#![feature(abi_x86_interrupt, no_core, lang_items)]

#[lang = "sized"]
trait Sized {}
#[lang = "copy"]
trait Copy {}

// CHECK: define x86_64_sysvcc i64 @has_sysv64_abi
#[no_mangle]
pub extern "sysv64" fn has_sysv64_abi(a: i64) -> i64 {
a * 2
a
}
17 changes: 10 additions & 7 deletions src/test/codegen/abi-x86-interrupt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,20 @@
// llvm. Also checks that the abi_x86_interrupt feature gate allows usage
// of the x86-interrupt abi.

// ignore-arm
// ignore-aarch64
// ignore-riscv64 x86-interrupt is not supported

// compile-flags: -C no-prepopulate-passes
// needs-llvm-components: x86
// compile-flags: -C no-prepopulate-passes --target=x86_64-unknown-linux-gnu

#![crate_type = "lib"]
#![feature(abi_x86_interrupt)]
#![no_core]
#![feature(abi_x86_interrupt, no_core, lang_items)]

#[lang = "sized"]
trait Sized {}
#[lang = "copy"]
trait Copy {}

// CHECK: define x86_intrcc i64 @has_x86_interrupt_abi
#[no_mangle]
pub extern "x86-interrupt" fn has_x86_interrupt_abi(a: i64) -> i64 {
a * 2
a
}
16 changes: 8 additions & 8 deletions src/test/codegen/cdylib-external-inline-fns.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,42 +2,42 @@

#![crate_type = "cdylib"]

// CHECK: define void @a()
// CHECK: define{{( dso_local)?}} void @a()
#[no_mangle]
#[inline]
pub extern "C" fn a() {}

// CHECK: define void @b()
// CHECK: define{{( dso_local)?}} void @b()
#[export_name = "b"]
#[inline]
pub extern "C" fn b() {}

// CHECK: define void @c()
// CHECK: define{{( dso_local)?}} void @c()
#[no_mangle]
#[inline]
extern "C" fn c() {}

// CHECK: define void @d()
// CHECK: define{{( dso_local)?}} void @d()
#[export_name = "d"]
#[inline]
extern "C" fn d() {}

// CHECK: define void @e()
// CHECK: define{{( dso_local)?}} void @e()
#[no_mangle]
#[inline(always)]
pub extern "C" fn e() {}

// CHECK: define void @f()
// CHECK: define{{( dso_local)?}} void @f()
#[export_name = "f"]
#[inline(always)]
pub extern "C" fn f() {}

// CHECK: define void @g()
// CHECK: define{{( dso_local)?}} void @g()
#[no_mangle]
#[inline(always)]
extern "C" fn g() {}

// CHECK: define void @h()
// CHECK: define{{( dso_local)?}} void @h()
#[export_name = "h"]
#[inline(always)]
extern "C" fn h() {}
3 changes: 1 addition & 2 deletions src/test/codegen/dealloc-no-unwind.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
//
// no-system-llvm
// compile-flags: -O

Expand All @@ -15,7 +14,7 @@ impl Drop for A {

#[no_mangle]
pub fn a(a: Box<i32>) {
// CHECK-LABEL: define void @a
// CHECK-LABEL: define{{.*}}void @a
// CHECK: call void @__rust_dealloc
// CHECK-NEXT: call void @foo
let _a = A;
Expand Down
24 changes: 12 additions & 12 deletions src/test/codegen/external-no-mangle-fns.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,30 +4,30 @@
#![crate_type = "lib"]
#![no_std]

// CHECK: define void @a()
// CHECK: define{{( dso_local)?}} void @a()
#[no_mangle]
fn a() {}

// CHECK: define void @b()
// CHECK: define{{( dso_local)?}} void @b()
#[no_mangle]
pub fn b() {}

mod private {
// CHECK: define void @c()
// CHECK: define{{( dso_local)?}} void @c()
#[no_mangle]
fn c() {}

// CHECK: define void @d()
// CHECK: define{{( dso_local)?}} void @d()
#[no_mangle]
pub fn d() {}
}

const HIDDEN: () = {
// CHECK: define void @e()
// CHECK: define{{( dso_local)?}} void @e()
#[no_mangle]
fn e() {}

// CHECK: define void @f()
// CHECK: define{{( dso_local)?}} void @f()
#[no_mangle]
pub fn f() {}
};
Expand All @@ -38,13 +38,13 @@ const HIDDEN: () = {
// CHECK-NEXT: define internal
#[inline(never)]
fn x() {
// CHECK: define void @g()
// CHECK: define{{( dso_local)?}} void @g()
#[no_mangle]
fn g() {
x();
}

// CHECK: define void @h()
// CHECK: define{{( dso_local)?}} void @h()
#[no_mangle]
pub fn h() {}

Expand All @@ -54,22 +54,22 @@ fn x() {
}
}

// CHECK: define void @i()
// CHECK: define{{( dso_local)?}} void @i()
#[no_mangle]
#[inline]
fn i() {}

// CHECK: define void @j()
// CHECK: define{{( dso_local)?}} void @j()
#[no_mangle]
#[inline]
pub fn j() {}

// CHECK: define void @k()
// CHECK: define{{( dso_local)?}} void @k()
#[no_mangle]
#[inline(always)]
fn k() {}

// CHECK: define void @l()
// CHECK: define{{( dso_local)?}} void @l()
#[no_mangle]
#[inline(always)]
pub fn l() {}
Loading