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 more items #85276

Merged
merged 2 commits into from
May 19, 2021
Merged

Set dso_local for more items #85276

merged 2 commits into from
May 19, 2021

Conversation

Bobo1239
Copy link
Contributor

Related to #83592. (cc @nagisa)

Noticed that on x86_64 with relocation-model: static R_X86_64_GOTPCREL relocations were still generated in some cases. (related: Rust-for-Linux/linux#135; Rust-for-Linux needs these fixes to successfully build)

First time doing anything with LLVM so not sure whether this is correct but the following are some of the things I've tried to convince myself.

C equivalent

Example from clang which also sets dso_local in these cases:
clang-12 -fno-PIC -S -emit-llvm test.c

extern int A;

int* a() {
    return &A;
}

int B;

int* b() {
    return &B;
}
; ModuleID = 'test.c'
source_filename = "test.c"
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

@A = external dso_local global i32, align 4
@B = dso_local global i32 0, align 4

; Function Attrs: noinline nounwind optnone uwtable
define dso_local i32* @a() #0 {
  ret i32* @A
}

; Function Attrs: noinline nounwind optnone uwtable
define dso_local i32* @b() #0 {
  ret i32* @B
}

attributes #0 = { noinline nounwind optnone uwtable "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" "unsafe-fp-math"="false" "use-soft-float"="false" }

!llvm.module.flags = !{!0}
!llvm.ident = !{!1}

!0 = !{i32 1, !"wchar_size", i32 4}
!1 = !{!"clang version 12.0.0 (https://github.com/llvm/llvm-project/ b978a93635b584db380274d7c8963c73989944a1)"}

clang-12 -fno-PIC -c test.c
objdump test.o -r:

test.o:     file format elf64-x86-64

RELOCATION RECORDS FOR [.text]:
OFFSET           TYPE              VALUE
0000000000000006 R_X86_64_64       A
0000000000000016 R_X86_64_64       B


RELOCATION RECORDS FOR [.eh_frame]:
OFFSET           TYPE              VALUE
0000000000000020 R_X86_64_PC32     .text
0000000000000040 R_X86_64_PC32     .text+0x0000000000000010

Comparison to pre-LLVM 12 output

rustc --emit=obj,llvm-ir --target=x86_64-unknown-none-linuxkernel --crate-type rlib test.rs

#![feature(no_core, lang_items)]
#![no_core]

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

#[lang="sync"]
trait Sync {}

#[lang = "drop_in_place"]
pub unsafe fn drop_in_place<T: ?Sized>(_: *mut T) {}

impl Sync for i32 {}

pub static STATIC: i32 = 32;

extern {
    pub static EXT_STATIC: i32;
}

pub fn a() -> &'static i32 {
    &STATIC
}
pub fn b() -> &'static i32 {
    unsafe {&EXT_STATIC}
}

objdump test.o -r
nightly-2021-02-20 (rustc target is x86_64-linux-kernel):

RELOCATION RECORDS FOR [.text._ZN4test1a17h1024ba65f3424175E]:
OFFSET           TYPE              VALUE
0000000000000007 R_X86_64_32S      _ZN4test6STATIC17h3adc41a83746c9ffE


RELOCATION RECORDS FOR [.text._ZN4test1b17h86a6a80c1190ac8dE]:
OFFSET           TYPE              VALUE
0000000000000007 R_X86_64_32S      EXT_STATIC

nightly-2021-05-10:

RELOCATION RECORDS FOR [.text._ZN4test1a17he846f03bf37b2d20E]:
OFFSET           TYPE              VALUE
0000000000000007 R_X86_64_GOTPCREL  _ZN4test6STATIC17h5a059515bf3d4968E-0x0000000000000004


RELOCATION RECORDS FOR [.text._ZN4test1b17h7e0f7f80fbd91125E]:
OFFSET           TYPE              VALUE
0000000000000007 R_X86_64_GOTPCREL  EXT_STATIC-0x0000000000000004

This PR:

RELOCATION RECORDS FOR [.text._ZN4test1a17he846f03bf37b2d20E]:
OFFSET           TYPE              VALUE
0000000000000007 R_X86_64_32S      _ZN4test6STATIC17h5a059515bf3d4968E


RELOCATION RECORDS FOR [.text._ZN4test1b17h7e0f7f80fbd91125E]:
OFFSET           TYPE              VALUE
0000000000000007 R_X86_64_32S      EXT_STATIC

@rust-highfive
Copy link
Collaborator

r? @estebank

(rust-highfive has picked a reviewer for you, use r? to override)

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label May 14, 2021
@nagisa
Copy link
Member

nagisa commented May 14, 2021

r? @nagisa

@rust-highfive rust-highfive assigned nagisa and unassigned estebank May 14, 2021
@@ -353,6 +361,7 @@ impl StaticMethods for CodegenCx<'ll, 'tcx> {

llvm::LLVMRustSetLinkage(new_g, linkage);
llvm::LLVMRustSetVisibility(new_g, visibility);
llvm::LLVMRustSetDSOLocal(new_g, dso_local);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The "other piece of code" is here. Since we're defining the static here, I think you can, and probably should, just unconditionally set dso_local based on should_assume_dso_local here.

I think.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do things still work if this is moved outside of this conditional (e.g. to near set_global_alignment call below)?

Copy link
Contributor Author

@Bobo1239 Bobo1239 May 15, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Testsuite passes locally at least and rust-for-linux builds. But I have to query linkage/visibility again or pull these lines before the if block making it a little bit harder to follow. Should I go forward with the change or were you just wondering what if?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should go ahead with it. I'm quite worried that there may be places in the codegen where a static is declared with the right type, but misses setting dso_local, in which case this branch would not be hit.


On another note is I think the code should look a more like:

if self.should_assume_dso_local(...) { 
     llvm::LLVMRustSetDSOLocal(g, true);
}

There's almost never a reason to unset the flag and the part of the backend that has declared the static may have a better idea as to whether the static can be a dso_local based on factors that should_assume_dso_local can't consider.


The fact that it is necessary to get the linkage/visibility back from LLVM I think is indicative of some larger refactor being necessary here so that the linkage/visibility derived from the Rust source is available more directly here. But that's out of scope for this PR. I thin it is perfectly fine to do whatever necessary to obtain the information you need to pass into should_assume_dso_global here.

Copy link
Contributor Author

@Bobo1239 Bobo1239 May 16, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good thinking. And indeed if I apply the following patch on top of my latest commit we have a few tests which trigger the assertion. Should be out of scope for this PR though since that will need a deeper investigation.

Patch
diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs
index 245842df1b0..2748fbe0190 100644
--- a/compiler/rustc_codegen_llvm/src/consts.rs
+++ b/compiler/rustc_codegen_llvm/src/consts.rs
@@ -361,6 +361,12 @@ fn codegen_static(&self, def_id: DefId, is_mutable: bool) {
                 llvm::LLVMRustSetLinkage(new_g, linkage);
                 llvm::LLVMRustSetVisibility(new_g, visibility);
 
+                let linkage = base::linkage_from_llvm(linkage);
+                let visibility = base::visibility_from_llvm(visibility);
+                if self.should_assume_dso_local(linkage, visibility) {
+                    llvm::LLVMRustSetDSOLocal(g, true);
+                }
+
                 // To avoid breaking any invariants, we leave around the old
                 // global for the moment; we'll replace all references to it
                 // with the new global later. (See base::codegen_backend.)
@@ -372,9 +378,10 @@ fn codegen_static(&self, def_id: DefId, is_mutable: bool) {
 
             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) {
-                llvm::LLVMRustSetDSOLocal(g, true);
-            }
+            assert_eq!(
+                llvm::LLVMRustIsDSOLocal(g),
+                self.should_assume_dso_local(linkage, visibility)
+            );
 
             // As an optimization, all shared statics which do not have interior
             // mutability are placed into read-only memory.
diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
index 7fb978d61dc..2b515983c6e 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
@@ -1014,6 +1014,7 @@ pub fn LLVMConstExtractValue(
     pub fn LLVMSetSection(Global: &Value, Section: *const c_char);
     pub fn LLVMRustGetVisibility(Global: &Value) -> Visibility;
     pub fn LLVMRustSetVisibility(Global: &Value, Viz: Visibility);
+    pub fn LLVMRustIsDSOLocal(Global: &Value) -> bool;
     pub fn LLVMRustSetDSOLocal(Global: &Value, is_dso_local: bool);
     pub fn LLVMGetAlignment(Global: &Value) -> c_uint;
     pub fn LLVMSetAlignment(Global: &Value, Bytes: c_uint);
diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
index 2e135fbe2bd..0fd19d55903 100644
--- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
@@ -1648,6 +1648,10 @@ extern "C" void LLVMRustSetVisibility(LLVMValueRef V,
   LLVMSetVisibility(V, fromRust(RustVisibility));
 }
 
+extern "C" bool LLVMRustIsDSOLocal(LLVMValueRef Global) {
+  return unwrap<GlobalValue>(Global)->isDSOLocal();
+}
+
 extern "C" void LLVMRustSetDSOLocal(LLVMValueRef Global, bool is_dso_local) {
   unwrap<GlobalValue>(Global)->setDSOLocal(is_dso_local);
 }
failures:
    [ui] ui/issues/issue-33992.rs
    [ui] ui/linkage-attr/linkage-detect-extern-generated-name-collision.rs
    [ui] ui/linkage-attr/linkage-detect-local-generated-name-collision.rs
    [ui] ui/type-alias-impl-trait/bound_reduction.rs#full_tait
    [ui] ui/type-alias-impl-trait/bound_reduction.rs#min_tait

@nagisa
Copy link
Member

nagisa commented May 17, 2021

Can you please squash the commits together?

@Bobo1239
Copy link
Contributor Author

Done. Left the typo fix for the existing test in a separate commit unless you want me to squash it as well.

@nagisa
Copy link
Member

nagisa commented May 17, 2021

@bors r+

Thanks!

@bors
Copy link
Contributor

bors commented May 17, 2021

📌 Commit bfecc1ecf13c1a9541d3519a4e19c81776c7787d has been approved by nagisa

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels May 17, 2021
@nagisa
Copy link
Member

nagisa commented May 17, 2021

@bors rollup=never

@bors
Copy link
Contributor

bors commented May 18, 2021

⌛ Testing commit bfecc1ecf13c1a9541d3519a4e19c81776c7787d with merge 18bf98e745b9feb479eeafaa54d72476fc50e59a...

@rust-log-analyzer

This comment has been minimized.

@bors
Copy link
Contributor

bors commented May 18, 2021

💔 Test failed - checks-actions

@bors bors added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. labels May 18, 2021
The test case wasn't actually checked for x64 due to a small difference in the name.
@Bobo1239
Copy link
Contributor Author

Needed to account for unspecified register and a different mov variant when building without optimizations. Applied the following changes across the two commits:

diff --git a/src/test/assembly/static-relocation-model.rs b/src/test/assembly/static-relocation-model.rs
index bd456817199..ce2b3b1cfa4 100644
--- a/src/test/assembly/static-relocation-model.rs
+++ b/src/test/assembly/static-relocation-model.rs
@@ -34,7 +34,7 @@ impl Sync for u8 {}
 }
 
 // CHECK-LABEL: banana:
-// x64: movb   chaenomeles(%{{[a-z0-9]+}}), %{{[a-z]+}}
+// x64: movb   chaenomeles{{(\(%[a-z0-9]+\))?}}, %{{[a-z0-9]+}}
 // A64:      adrp    [[REG:[a-z0-9]+]], chaenomeles
 // A64-NEXT: ldrb    {{[a-z0-9]+}}, {{\[}}[[REG]], :lo12:chaenomeles]
 #[no_mangle]
@@ -45,7 +45,7 @@ pub fn banana() -> u8 {
 }
 
 // CHECK-LABEL: peach:
-// x64: movb    banana(%{{[a-z0-9]+}}), %{{[a-z]+}}
+// x64: movb    banana{{(\(%[a-z0-9]+\))?}}, %{{[a-z0-9]+}}
 // A64:      adrp    [[REG2:[a-z0-9]+]], banana
 // A64-NEXT: ldrb    {{[a-z0-9]+}}, {{\[}}[[REG2]], :lo12:banana]
 #[no_mangle]
@@ -56,8 +56,8 @@ pub fn peach() -> u8 {
 }
 
 // CHECK-LABEL: mango:
-// x64:      movq    EXOCHORDA(%{{[a-z0-9]+}}), %{{[a-z]+}}
-// x64-NEXT: movb (%rax), %al
+// x64:      movq    EXOCHORDA{{(\(%[a-z0-9]+\))?}}, %[[REG:[a-z0-9]+]]
+// x64-NEXT: movb    (%[[REG]]), %{{[a-z0-9]+}}
 // A64:      adrp    [[REG2:[a-z0-9]+]], EXOCHORDA
 // A64-NEXT: ldr     {{[a-z0-9]+}}, {{\[}}[[REG2]], :lo12:EXOCHORDA]
 #[no_mangle]
@@ -68,7 +68,7 @@ pub fn mango() -> u8 {
 }
 
 // CHECK-LABEL: orange:
-// x64:  movl    $PIERIS, %{{[a-z]+}}
+// x64: mov{{l|absq}}    $PIERIS, %{{[a-z0-9]+}}
 // A64:      adrp    [[REG2:[a-z0-9]+]], PIERIS
 // A64-NEXT: add     {{[a-z0-9]+}}, [[REG2]], :lo12:PIERIS
 #[no_mangle]

Tested locally with the CI docker containers so should hopefully succeed now. (only x86_64-gnu and x86_64-gnu-nopt though)

@nagisa
Copy link
Member

nagisa commented May 18, 2021

@bors r+

@bors
Copy link
Contributor

bors commented May 18, 2021

📌 Commit f7ed4a7 has been approved by nagisa

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels May 18, 2021
@bors
Copy link
Contributor

bors commented May 19, 2021

⌛ Testing commit f7ed4a7 with merge be8450e...

@bors
Copy link
Contributor

bors commented May 19, 2021

☀️ Test successful - checks-actions
Approved by: nagisa
Pushing be8450e to master...

@bors bors added the merged-by-bors This PR was explicitly merged by bors. label May 19, 2021
@bors bors merged commit be8450e into rust-lang:master May 19, 2021
@rustbot rustbot added this to the 1.54.0 milestone May 19, 2021
Bobo1239 added a commit to Bobo1239/linux that referenced this pull request May 22, 2021
Includes rust-lang/rust#83592 and rust-lang/rust#85276 which were needed
to build correctly again after rustc's upgrade to LLVM 12.

Signed-off-by: Boris-Chengbiao Zhou <bobo1239@web.de>
Bobo1239 added a commit to Bobo1239/linux that referenced this pull request May 22, 2021
Includes rust-lang/rust#83592 and rust-lang/rust#85276 which are needed
to build correctly again after rustc's upgrade to LLVM 12.

Signed-off-by: Boris-Chengbiao Zhou <bobo1239@web.de>
Bobo1239 added a commit to Bobo1239/linux that referenced this pull request May 29, 2021
Includes rust-lang/rust#83592 and rust-lang/rust#85276 which are needed
to build correctly again after rustc's upgrade to LLVM 12.

Signed-off-by: Boris-Chengbiao Zhou <bobo1239@web.de>
Bobo1239 added a commit to Bobo1239/linux that referenced this pull request May 29, 2021
Includes rust-lang/rust#83592, rust-lang/rust#85276 and rust-lang/rust#85700
which are needed to build correctly again after rustc's upgrade to LLVM 12.

Signed-off-by: Boris-Chengbiao Zhou <bobo1239@web.de>
Bobo1239 added a commit to Bobo1239/linux that referenced this pull request May 29, 2021
Includes rust-lang/rust#83592, rust-lang/rust#85276 and
rust-lang/rust#85700 which are needed to build correctly again after
rustc's upgrade to LLVM 12.

Signed-off-by: Boris-Chengbiao Zhou <bobo1239@web.de>
Bobo1239 added a commit to Bobo1239/linux that referenced this pull request May 29, 2021
Includes rust-lang/rust#83592, rust-lang/rust#85276 and
rust-lang/rust#85700 which are needed to build correctly again after
rustc's upgrade to LLVM 12.

Also fixes a newly introduced clippy warning.

Signed-off-by: Boris-Chengbiao Zhou <bobo1239@web.de>
Bobo1239 added a commit to Bobo1239/linux that referenced this pull request May 29, 2021
Includes rust-lang/rust#83592, rust-lang/rust#85276 and
rust-lang/rust#85700 which are needed to build correctly again after
rustc's upgrade to LLVM 12.

Signed-off-by: Boris-Chengbiao Zhou <bobo1239@web.de>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
merged-by-bors This PR was explicitly merged by bors. S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants