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

rustbuild: Build libstd with ThinLTO #45529

Closed
wants to merge 1 commit into from

Conversation

alexcrichton
Copy link
Member

This commit moves the standard library to get compiled with multiple codegen
units and ThinLTO like the compiler itself. This I would hope is the last major
step towards closing out #45320

This commit moves the standard library to get compiled with multiple codegen
units and ThinLTO like the compiler itself. This I would hope is the last major
step towards closing out rust-lang#45320
@alexcrichton
Copy link
Member Author

cc #45400, which enabled this for rustc

@alexcrichton
Copy link
Member Author

@kennytm kennytm added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Oct 25, 2017
@Mark-Simulacrum
Copy link
Member

@bors r+

@bors
Copy link
Contributor

bors commented Oct 25, 2017

📌 Commit 578feb5 has been approved by Mark-Simulacrum

@Mark-Simulacrum Mark-Simulacrum 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 Oct 25, 2017
@bors
Copy link
Contributor

bors commented Oct 27, 2017

⌛ Testing commit 578feb5 with merge e462ee9c3d8c56966579d0c9c861617e9f162f86...

@bors
Copy link
Contributor

bors commented Oct 27, 2017

💔 Test failed - status-travis

@kennytm
Copy link
Member

kennytm commented Oct 27, 2017

Cannot link stage1-libstd for the MIPS targets, something's wrong with TLS.

Errors from mipsel-unknown-linux-gnu
[00:36:44] error: linking with `mipsel-linux-gnu-gcc` failed: exit code: 1
[00:36:44]   |
[00:36:44]   = note: "mipsel-linux-gnu-gcc" "-Wl,--as-needed" "-Wl,-z,noexecstack" "-L" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage1/lib/rustlib/mipsel-unknown-linux-gnu/lib" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage1-std/mipsel-unknown-linux-gnu/release/deps/std-7c965c802728f5e9.std0-4002fe3fe0c341d9d273b78043339b52.rs.rust-cgu.o" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage1-std/mipsel-unknown-linux-gnu/release/deps/std-7c965c802728f5e9.std1-4002fe3fe0c341d9d273b78043339b52.rs.rust-cgu.o" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage1-std/mipsel-unknown-linux-gnu/release/deps/std-7c965c802728f5e9.std10-4002fe3fe0c341d9d273b78043339b52.rs.rust-cgu.o" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage1-std/mipsel-unknown-linux-gnu/release/deps/std-7c965c802728f5e9.std11-4002fe3fe0c341d9d273b78043339b52.rs.rust-cgu.o" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage1-std/mipsel-unknown-linux-gnu/release/deps/std-7c965c802728f5e9.std12-4002fe3fe0c341d9d273b78043339b52.rs.rust-cgu.o" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage1-std/mipsel-unknown-linux-gnu/release/deps/std-7c965c802728f5e9.std13-4002fe3fe0c341d9d273b78043339b52.rs.rust-cgu.o" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage1-std/mipsel-unknown-linux-gnu/release/deps/std-7c965c802728f5e9.std14-4002fe3fe0c341d9d273b78043339b52.rs.rust-cgu.o" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage1-std/mipsel-unknown-linux-gnu/release/deps/std-7c965c802728f5e9.std15-4002fe3fe0c341d9d273b78043339b52.rs.rust-cgu.o" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage1-std/mipsel-unknown-linux-gnu/release/deps/std-7c965c802728f5e9.std2-4002fe3fe0c341d9d273b78043339b52.rs.rust-cgu.o" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage1-std/mipsel-unknown-linux-gnu/release/deps/std-7c965c802728f5e9.std3-4002fe3fe0c341d9d273b78043339b52.rs.rust-cgu.o" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage1-std/mipsel-unknown-linux-gnu/release/deps/std-7c965c802728f5e9.std4-4002fe3fe0c341d9d273b78043339b52.rs.rust-cgu.o" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage1-std/mipsel-unknown-linux-gnu/release/deps/std-7c965c802728f5e9.std5-4002fe3fe0c341d9d273b78043339b52.rs.rust-cgu.o" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage1-std/mipsel-unknown-linux-gnu/release/deps/std-7c965c802728f5e9.std6-4002fe3fe0c341d9d273b78043339b52.rs.rust-cgu.o" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage1-std/mipsel-unknown-linux-gnu/release/deps/std-7c965c802728f5e9.std7-4002fe3fe0c341d9d273b78043339b52.rs.rust-cgu.o" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage1-std/mipsel-unknown-linux-gnu/release/deps/std-7c965c802728f5e9.std8-4002fe3fe0c341d9d273b78043339b52.rs.rust-cgu.o" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage1-std/mipsel-unknown-linux-gnu/release/deps/std-7c965c802728f5e9.std9-4002fe3fe0c341d9d273b78043339b52.rs.rust-cgu.o" "-o" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage1-std/mipsel-unknown-linux-gnu/release/deps/libstd-7c965c802728f5e9.so" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage1-std/mipsel-unknown-linux-gnu/release/deps/std-7c965c802728f5e9.crate.metadata.rust-cgu.o" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage1-std/mipsel-unknown-linux-gnu/release/deps/std-7c965c802728f5e9.crate.allocator.rust-cgu.o" "-Wl,-z,relro,-z,now" "-Wl,-O1" "-nodefaultlibs" "-L" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage1-std/mipsel-unknown-linux-gnu/release/deps" "-L" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage1-std/release/deps" "-L" "/checkout/obj/build/mipsel-unknown-linux-gnu/native/libbacktrace/.libs" "-L" "/checkout/obj/build/mipsel-unknown-linux-gnu/native/jemalloc/lib" "-L" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage1-std/mipsel-unknown-linux-gnu/release/build/compiler_builtins-b35284903664e723/out" "-L" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage1/lib/rustlib/mipsel-unknown-linux-gnu/lib" "-Wl,-Bstatic" "-Wl,--whole-archive" "-l" "backtrace" "-Wl,--no-whole-archive" "-Wl,-Bdynamic" "-l" "dl" "-l" "rt" "-l" "pthread" "-Wl,-Bstatic" "-Wl,--whole-archive" "/tmp/rustc.44iCWUziArle/libpanic_unwind-c92b29e034f8e7cb.rlib" "-Wl,--no-whole-archive" "-Wl,--whole-archive" "/tmp/rustc.44iCWUziArle/libunwind-2d935de4cacbf5dc.rlib" "-Wl,--no-whole-archive" "-Wl,--whole-archive" "/tmp/rustc.44iCWUziArle/librand-fd1e55635809b0bd.rlib" "-Wl,--no-whole-archive" "-Wl,--whole-archive" "/tmp/rustc.44iCWUziArle/liballoc_system-65d1f1bb1aee6baa.rlib" "-Wl,--no-whole-archive" "-Wl,--whole-archive" "/tmp/rustc.44iCWUziArle/liblibc-a91ce6cc1c3b5ee9.rlib" "-Wl,--no-whole-archive" "-Wl,--whole-archive" "/tmp/rustc.44iCWUziArle/liballoc-316c7f53a631a4ec.rlib" "-Wl,--no-whole-archive" "-Wl,--whole-archive" "/tmp/rustc.44iCWUziArle/libstd_unicode-c8eccaa111844a81.rlib" "-Wl,--no-whole-archive" "-Wl,--whole-archive" "/tmp/rustc.44iCWUziArle/libcore-481d9b2371842499.rlib" "-Wl,--no-whole-archive" "/tmp/rustc.44iCWUziArle/libcompiler_builtins-bdcc681457e28caa.rlib" "-Wl,-Bdynamic" "-l" "gcc_s" "-l" "c" "-l" "m" "-l" "rt" "-l" "pthread" "-l" "util" "-shared" "-Wl,-rpath,$ORIGIN/../lib"
[00:36:44]   = note: /usr/lib/gcc-cross/mipsel-linux-gnu/5/../../../../mipsel-linux-gnu/bin/ld: _ZN3std9panicking12LOCAL_STDERR7__getit5__KEY17h014c6e46b53aa78aE.llvm.7C4350C9: TLS definition in /checkout/obj/build/x86_64-unknown-linux-gnu/stage1-std/mipsel-unknown-linux-gnu/release/deps/std-7c965c802728f5e9.std15-4002fe3fe0c341d9d273b78043339b52.rs.rust-cgu.o section .tdata._ZN3std9panicking12LOCAL_STDERR7__getit5__KEY17h014c6e46b53aa78aE.llvm.7C4350C9 mismatches non-TLS reference in /checkout/obj/build/x86_64-unknown-linux-gnu/stage1-std/mipsel-unknown-linux-gnu/release/deps/std-7c965c802728f5e9.std10-4002fe3fe0c341d9d273b78043339b52.rs.rust-cgu.o
[00:36:44]           /checkout/obj/build/x86_64-unknown-linux-gnu/stage1-std/mipsel-unknown-linux-gnu/release/deps/std-7c965c802728f5e9.std15-4002fe3fe0c341d9d273b78043339b52.rs.rust-cgu.o: error adding symbols: Bad value
[00:36:44]           collect2: error: ld returned 1 exit status
[00:36:44]           
[00:36:44] 
[00:36:44] error: aborting due to previous error
[00:36:44] 
[00:36:44] error: Could not compile `std`.
Errors from mips64el-unknown-linux-gnuabi64
[00:38:03] error: linking with `mips64el-linux-gnuabi64-gcc` failed: exit code: 1
[00:38:03]   |
[00:38:03]   = note: "mips64el-linux-gnuabi64-gcc" "-Wl,--as-needed" "-Wl,-z,noexecstack" "-L" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage1/lib/rustlib/mips64el-unknown-linux-gnuabi64/lib" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage1-std/mips64el-unknown-linux-gnuabi64/release/deps/std-7c965c802728f5e9.std0-4002fe3fe0c341d9d273b78043339b52.rs.rust-cgu.o" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage1-std/mips64el-unknown-linux-gnuabi64/release/deps/std-7c965c802728f5e9.std1-4002fe3fe0c341d9d273b78043339b52.rs.rust-cgu.o" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage1-std/mips64el-unknown-linux-gnuabi64/release/deps/std-7c965c802728f5e9.std10-4002fe3fe0c341d9d273b78043339b52.rs.rust-cgu.o" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage1-std/mips64el-unknown-linux-gnuabi64/release/deps/std-7c965c802728f5e9.std11-4002fe3fe0c341d9d273b78043339b52.rs.rust-cgu.o" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage1-std/mips64el-unknown-linux-gnuabi64/release/deps/std-7c965c802728f5e9.std12-4002fe3fe0c341d9d273b78043339b52.rs.rust-cgu.o" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage1-std/mips64el-unknown-linux-gnuabi64/release/deps/std-7c965c802728f5e9.std13-4002fe3fe0c341d9d273b78043339b52.rs.rust-cgu.o" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage1-std/mips64el-unknown-linux-gnuabi64/release/deps/std-7c965c802728f5e9.std14-4002fe3fe0c341d9d273b78043339b52.rs.rust-cgu.o" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage1-std/mips64el-unknown-linux-gnuabi64/release/deps/std-7c965c802728f5e9.std15-4002fe3fe0c341d9d273b78043339b52.rs.rust-cgu.o" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage1-std/mips64el-unknown-linux-gnuabi64/release/deps/std-7c965c802728f5e9.std2-4002fe3fe0c341d9d273b78043339b52.rs.rust-cgu.o" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage1-std/mips64el-unknown-linux-gnuabi64/release/deps/std-7c965c802728f5e9.std3-4002fe3fe0c341d9d273b78043339b52.rs.rust-cgu.o" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage1-std/mips64el-unknown-linux-gnuabi64/release/deps/std-7c965c802728f5e9.std4-4002fe3fe0c341d9d273b78043339b52.rs.rust-cgu.o" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage1-std/mips64el-unknown-linux-gnuabi64/release/deps/std-7c965c802728f5e9.std5-4002fe3fe0c341d9d273b78043339b52.rs.rust-cgu.o" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage1-std/mips64el-unknown-linux-gnuabi64/release/deps/std-7c965c802728f5e9.std6-4002fe3fe0c341d9d273b78043339b52.rs.rust-cgu.o" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage1-std/mips64el-unknown-linux-gnuabi64/release/deps/std-7c965c802728f5e9.std7-4002fe3fe0c341d9d273b78043339b52.rs.rust-cgu.o" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage1-std/mips64el-unknown-linux-gnuabi64/release/deps/std-7c965c802728f5e9.std8-4002fe3fe0c341d9d273b78043339b52.rs.rust-cgu.o" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage1-std/mips64el-unknown-linux-gnuabi64/release/deps/std-7c965c802728f5e9.std9-4002fe3fe0c341d9d273b78043339b52.rs.rust-cgu.o" "-o" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage1-std/mips64el-unknown-linux-gnuabi64/release/deps/libstd-7c965c802728f5e9.so" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage1-std/mips64el-unknown-linux-gnuabi64/release/deps/std-7c965c802728f5e9.crate.metadata.rust-cgu.o" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage1-std/mips64el-unknown-linux-gnuabi64/release/deps/std-7c965c802728f5e9.crate.allocator.rust-cgu.o" "-Wl,-z,relro,-z,now" "-Wl,-O1" "-nodefaultlibs" "-L" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage1-std/mips64el-unknown-linux-gnuabi64/release/deps" "-L" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage1-std/release/deps" "-L" "/checkout/obj/build/mips64el-unknown-linux-gnuabi64/native/libbacktrace/.libs" "-L" "/checkout/obj/build/mips64el-unknown-linux-gnuabi64/native/jemalloc/lib" "-L" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage1-std/mips64el-unknown-linux-gnuabi64/release/build/compiler_builtins-b35284903664e723/out" "-L" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage1/lib/rustlib/mips64el-unknown-linux-gnuabi64/lib" "-Wl,-Bstatic" "-Wl,--whole-archive" "-l" "backtrace" "-Wl,--no-whole-archive" "-Wl,-Bdynamic" "-l" "dl" "-l" "rt" "-l" "pthread" "-Wl,-Bstatic" "-Wl,--whole-archive" "/tmp/rustc.iQZsRAUqYPpk/libpanic_unwind-c92b29e034f8e7cb.rlib" "-Wl,--no-whole-archive" "-Wl,--whole-archive" "/tmp/rustc.iQZsRAUqYPpk/libunwind-2d935de4cacbf5dc.rlib" "-Wl,--no-whole-archive" "-Wl,--whole-archive" "/tmp/rustc.iQZsRAUqYPpk/librand-fd1e55635809b0bd.rlib" "-Wl,--no-whole-archive" "-Wl,--whole-archive" "/tmp/rustc.iQZsRAUqYPpk/liballoc_system-65d1f1bb1aee6baa.rlib" "-Wl,--no-whole-archive" "-Wl,--whole-archive" "/tmp/rustc.iQZsRAUqYPpk/liblibc-a91ce6cc1c3b5ee9.rlib" "-Wl,--no-whole-archive" "-Wl,--whole-archive" "/tmp/rustc.iQZsRAUqYPpk/liballoc-316c7f53a631a4ec.rlib" "-Wl,--no-whole-archive" "-Wl,--whole-archive" "/tmp/rustc.iQZsRAUqYPpk/libstd_unicode-c8eccaa111844a81.rlib" "-Wl,--no-whole-archive" "-Wl,--whole-archive" "/tmp/rustc.iQZsRAUqYPpk/libcore-481d9b2371842499.rlib" "-Wl,--no-whole-archive" "/tmp/rustc.iQZsRAUqYPpk/libcompiler_builtins-bdcc681457e28caa.rlib" "-Wl,-Bdynamic" "-l" "gcc_s" "-l" "c" "-l" "m" "-l" "rt" "-l" "pthread" "-l" "util" "-shared" "-Wl,-rpath,$ORIGIN/../lib"
[00:38:03]   = note: /usr/lib/gcc-cross/mips64el-linux-gnuabi64/5/../../../../mips64el-linux-gnuabi64/bin/ld: _ZN3std9panicking12LOCAL_STDERR7__getit5__KEY17h014c6e46b53aa78aE.llvm.4F4FFD30: TLS definition in /checkout/obj/build/x86_64-unknown-linux-gnu/stage1-std/mips64el-unknown-linux-gnuabi64/release/deps/std-7c965c802728f5e9.std15-4002fe3fe0c341d9d273b78043339b52.rs.rust-cgu.o section .tdata._ZN3std9panicking12LOCAL_STDERR7__getit5__KEY17h014c6e46b53aa78aE.llvm.4F4FFD30 mismatches non-TLS reference in /checkout/obj/build/x86_64-unknown-linux-gnu/stage1-std/mips64el-unknown-linux-gnuabi64/release/deps/std-7c965c802728f5e9.std10-4002fe3fe0c341d9d273b78043339b52.rs.rust-cgu.o
[00:38:03]           /checkout/obj/build/x86_64-unknown-linux-gnu/stage1-std/mips64el-unknown-linux-gnuabi64/release/deps/std-7c965c802728f5e9.std15-4002fe3fe0c341d9d273b78043339b52.rs.rust-cgu.o: error adding symbols: Bad value
[00:38:03]           collect2: error: ld returned 1 exit status
[00:38:03]           
[00:38:03] 
[00:38:03] error: aborting due to previous error
[00:38:03] 
[00:38:03] error: Could not compile `std`.

@kennytm kennytm added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. labels Oct 27, 2017
@alexcrichton
Copy link
Member Author

I've been trying to debug this locally and figure out what's going on. I wasn't able to reproduce until I was able to reproduce. Then I found out it's nondeterministic. That's... oh boy.

@alexcrichton
Copy link
Member Author

Ok so... Investigation so far:

First I wanted to rule out a "trivial bug" in ThinLTO or LLVM. Let's start with this source code:

#![feature(thread_local)]

#[thread_local]
static mut FOO: u32 = 3;

fn foo() -> &'static u32 {
    unsafe { &*(&A as *const _) }
}

pub mod a {
    pub fn bar() -> u32 {
        *super::foo()
    }
}

Compile that with:

$ rustc +nightly -Z thinlto -C codegen-units=16 -O foo.rs  --crate-type rlib --emit llvm-ir

Next up we search through the output files for our thread local

$ rg FOO *.ll
foo.foo1-8787f43e282added376259c1adb08b80.rs.rust-cgu.ll:@_ZN3foo3FOO17h556917dcc656cbe0E.llvm.54FD3A5C = hidden thread_local global i32 3, align 4
foo.foo1-8787f43e282added376259c1adb08b80.rs.rust-cgu.ll:  ret i32* @_ZN3foo3FOO17h556917dcc656cbe0E.llvm.54FD3A5C
foo.foo0-8787f43e282added376259c1adb08b80.rs.rust-cgu.ll:@_ZN3foo3FOO17h556917dcc656cbe0E.llvm.54FD3A5C = external hidden thread_local local_unnamed_addr global i32, align 4
foo.foo0-8787f43e282added376259c1adb08b80.rs.rust-cgu.ll: %0 = load i32, i32* @_ZN3foo3FOO17h556917dcc656cbe0E.llvm.54FD3A5C, align 4

Ok so far so good. One IR file imports one IR file exports. ThinLTO inlined the constant/function call across module boundaries. Despite all that we retain thread_local and hidden, as expected.

Next up let's take a look at the object files:

$ rustc +nightly -Z thinlto -C codegen-units=16 -O foo.rs  --crate-type rlib --emit obj
$ readelf -Ws *.o
File: foo.foo0-8787f43e282added376259c1adb08b80.rs.rust-cgu.o

Symbol table '.symtab' contains 6 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS foo0-8787f43e282added376259c1adb08b80.rs
     2: 0000000000000000     0 SECTION LOCAL  DEFAULT    3 
     3: 0000000000000000    21 FUNC    GLOBAL DEFAULT    3 _ZN3foo1a3bar17hef56ac03a5da7c66E
     4: 0000000000000000     0 TLS     GLOBAL HIDDEN   UND _ZN3foo3FOO17h556917dcc656cbe0E.llvm.54FD3A5C
     5: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND __tls_get_addr

File: foo.foo1-8787f43e282added376259c1adb08b80.rs.rust-cgu.o

Symbol table '.symtab' contains 7 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS foo1-8787f43e282added376259c1adb08b80.rs
     2: 0000000000000000     0 TLS     LOCAL  DEFAULT    5 .tdata._ZN3foo3FOO17h556917dcc656cbe0E.llvm.54FD3A5C
     3: 0000000000000000     0 SECTION LOCAL  DEFAULT    3 
     4: 0000000000000000     4 TLS     GLOBAL HIDDEN     5 _ZN3foo3FOO17h556917dcc656cbe0E.llvm.54FD3A5C
     5: 0000000000000000    22 FUNC    GLOBAL HIDDEN     3 _ZN3foo3foo17hac5efa801639546aE
6: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND __tls_get_addr

Ok still looking good. One object defines a TLS type global and one imports a TLS type global. Everything looks ok. As expected, everything links ok as well.


So that rules out to me at least any casual oversight. Let's take a look at the test case in question. As I mentioned above it's nondeterministic, but I managed to catch a failure. A failure right now leaves a bunch of *.o and *.bytecode.encoded files lying around, so that's what we've got to work with.

I rigged up a script to decode *.bytecode.encoded and took a look at the output files.

$ rg '^@.*LOCAL_STDERR.*getit.*KEY' *.ll
std-dd31f45ce123dc4e.std10-e3a8009faa3029556ddf816a26150ca2.rs.rust-cgu.bytecode.encoded.ll:@_ZN3std9panicking12LOCAL_STDERR7__getit5__KEY17hb64b0469a41a4a6fE.llvm.44A09093 = external hidden thread_local global { { { i32, [12 x i8] } }, { { i1 } }, { { i1 } }, [2 x i8] }, align 4, !dbg !399
std-dd31f45ce123dc4e.std15-e3a8009faa3029556ddf816a26150ca2.rs.rust-cgu.bytecode.encoded.ll:@_ZN3std9panicking12LOCAL_STDERR7__getit5__KEY17hb64b0469a41a4a6fE.llvm.44A09093 = hidden thread_local global { { { i32, [12 x i8] } }, { { i1 } }, { { i1 } }, [2 x i8] } { { { i32, [12 x i8] } } { { i32, [12 x i8] } { i32 0, [12 x i8] undef } }, { { i1 } } zeroinitializer, { { i1 } } zeroinitializer, [2 x i8] undef }, align 4, !dbg !107

Intersting! LLVM IR checks out as one module is importing a thread_local and the other is exporting a thread_local, both hidden and global. Let's dig deeper in the object files

$ readelf -Ws *.o | grep 'LOCAL_STDERR.*getit.*KEY'
  1658: 00000000     0 NOTYPE  GLOBAL HIDDEN   UND _ZN3std9panicking12LOCAL_STDERR7__getit5__KEY17hb64b0469a41a4a6fE.llvm.44A09093
  1409: 00000000     0 TLS     LOCAL  DEFAULT  549 .tdata._ZN3std9panicking12LOCAL_STDERR7__getit5__KEY17hb64b0469a41a4a6fE.llvm.44A09093
1871: 00000000 20 TLS GLOBAL HIDDEN 549 _ZN3std9panicking12LOCAL_STDERR7__getit5__KEY17hb64b0469a41a4a6fE.llvm.44A09093

Aha! Sure enough one object file has NOTYPE listed instead of TLS. That explains the mismatch in the error message.

Next up is to figure out why if the LLVM module looks correct the object file looks incorrect. That... smells like an LLVM bug? A data race? Who knows!

@alexcrichton
Copy link
Member Author

Dohoho the plot thickens! Turns out in a successful build there's not two object files. The one that has the "bad reference" didn't have the object file in the successful build, presumably optimized out? Desires for deterministic builds aside, that raised an interesting question.

I compiled the program above for mipsel-unknown-linux-gnu and got:


File: foo.foo0-8787f43e282added376259c1adb08b80.rs.rust-cgu.o

Symbol table '.symtab' contains 7 entries:
   Num:    Value  Size Type    Bind   Vis      Ndx Name
     0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 00000000     0 FILE    LOCAL  DEFAULT  ABS foo0-8787f43e282added376259c1adb08b80.rs
     2: 00000000     0 SECTION LOCAL  DEFAULT    4 
     3: 00000000    56 FUNC    GLOBAL DEFAULT    4 _ZN3foo1a3bar17hef56ac03a5da7c66E
     4: 00000000     0 NOTYPE  GLOBAL HIDDEN   UND _ZN3foo3FOO17h556917dcc656cbe0E.llvm.2E598A29
     5: 00000000     0 NOTYPE  GLOBAL DEFAULT  UND __tls_get_addr
     6: 00000000     0 NOTYPE  GLOBAL DEFAULT  UND _gp_disp

File: foo.foo1-8787f43e282added376259c1adb08b80.rs.rust-cgu.o

Symbol table '.symtab' contains 8 entries:
   Num:    Value  Size Type    Bind   Vis      Ndx Name
     0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 00000000     0 FILE    LOCAL  DEFAULT  ABS foo1-8787f43e282added376259c1adb08b80.rs
     2: 00000000     0 TLS     LOCAL  DEFAULT    8 .tdata._ZN3foo3FOO17h556917dcc656cbe0E.llvm.2E598A29
     3: 00000000     0 SECTION LOCAL  DEFAULT    4 
     4: 00000000     4 TLS     GLOBAL HIDDEN     8 _ZN3foo3FOO17h556917dcc656cbe0E.llvm.2E598A29
     5: 00000000    56 FUNC    GLOBAL HIDDEN     4 _ZN3foo3foo17hac5efa801639546aE
     6: 00000000     0 NOTYPE  GLOBAL DEFAULT  UND __tls_get_addr
     7: 00000000     0 NOTYPE  GLOBAL DEFAULT  UND _gp_disp

And so aha! Looks like the mipsel backend is deterministically not handling external thread_local references maybe..

@alexcrichton
Copy link
Member Author

And it keeps going...

$ cat foo.ll
@foo = external hidden thread_local global i32

define i32 @bar() {
  %a = load i32, i32* @foo
  ret i32 %a
}
$ llc foo.ll -filetype=obj -o foo.o -mtriple=mipsel-unknown-linux-gnu
$ readelf -Ws foo.o

Symbol table '.symtab' contains 5 entries:
   Num:    Value  Size Type    Bind   Vis      Ndx Name
     0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND
     1: 00000000     0 FILE    LOCAL  DEFAULT  ABS foo.ll
     2: 00000000     0 SECTION LOCAL  DEFAULT    2
     3: 00000000    24 FUNC    GLOBAL DEFAULT    2 bar
     4: 00000000     0 TLS     GLOBAL HIDDEN   UND foo
$ llc foo.ll -filetype=obj -o foo.o -mtriple=mipsel-unknown-linux-gnu -relocation-model=pic
$ readelf -Ws foo.o

Symbol table '.symtab' contains 7 entries:
   Num:    Value  Size Type    Bind   Vis      Ndx Name
     0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND
     1: 00000000     0 FILE    LOCAL  DEFAULT  ABS foo.ll
     2: 00000000     0 SECTION LOCAL  DEFAULT    2
     3: 00000000     0 NOTYPE  GLOBAL DEFAULT  UND __tls_get_addr
     4: 00000000     0 NOTYPE  GLOBAL DEFAULT  UND _gp_disp
     5: 00000000    56 FUNC    GLOBAL DEFAULT    2 bar
     6: 00000000     0 NOTYPE  GLOBAL HIDDEN   UND foo

Note that if we don't pass -relocation-model=pic then it's correctly tagged as being TLS but if we do pass -relocation-model=pic then it's not. Something about the relocation model is affecting the output object file and causing foo to not be a "TLS" reference.

It looks like this is also related to hidden visibility. If I remove hidden visibility then it works with -relocation-model=pic.

Smells a lot like an LLVM bug...

@alexcrichton
Copy link
Member Author

I've opened an upstream LLVM bug, and I don't think there's much we can do about this in the meantime, so here's to praying that gets a response in the next few days.

@kennytm
Copy link
Member

kennytm commented Oct 31, 2017

@alexcrichton Would changing MIPS to use 1 CGU without ThinLTO workaround the bug? The TLS problem not only affects this PR but also #45187 and #45472.

@michaelwoerister
Copy link
Member

The one that has the "bad reference" didn't have the object file in the successful build, presumably optimized out?

Interesting. As far as I know our builds are pretty deterministic. At least the number of object files should always be the same.

@michaelwoerister
Copy link
Member

That's some awesome debugging there, @alexcrichton, like reading a detective story :) Thanks for writing it up!

I also think we should just default to one CGU on the affected platforms.

@alexcrichton
Copy link
Member Author

@kennytm oh I had no idea that this was affecting other PRs! I'll implement a fix pronto.

@michaelwoerister yeah I'm not entirely certain where the nondeterminism is coming from. It's probably coming from something in ThinLTO, I may do a pass to make sure we're at least feeding things to LLVM in a deterministic order.

alexcrichton added a commit to alexcrichton/rust that referenced this pull request Oct 31, 2017
Discovered in rust-lang#45529 it looks like cross-module TLS imports aren't quite working
today, especially with `hidden` visibility which mostly comes up with multiple
codegen units. As a result this completely disables compiling with ThinLTO and
multiple codegen units on MIPS when bootstrapping.

cc rust-lang#45654, the tracking issue for this
@alexcrichton
Copy link
Member Author

Ok I've opened #45655 to workaround the MIPS issue for now, hopefully unblocking #45187 and #45472.

Once that lands I'll resubmit this to try again with libstd.

@alexcrichton alexcrichton deleted the std-cgu branch October 31, 2017 14:04
bors added a commit that referenced this pull request Oct 31, 2017
rustbuild: Don't build with ThinLTO on MIPS

Discovered in #45529 it looks like cross-module TLS imports aren't quite working
today, especially with `hidden` visibility which mostly comes up with multiple
codegen units. As a result this completely disables compiling with ThinLTO and
multiple codegen units on MIPS when bootstrapping.

cc #45654, the tracking issue for this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants