Change:
Update: this is due to LLVM assuming 16-byte alignment for a static that is in fact 8-bytes aligned. Bisected PR might not be directly related, and might only have moved the static from a location that happened to be 16-bytes aligned by chance? Reproduced on three CI builders with macOS 10.10.5, but not on two with 10.11.6. Not reproduced with the previous Nightly, nightly-2018-06-23. Commit range: Of the PRs merged in this range, eliminating those I’m fairly certain are unrelated leaves and which I think are unrelated but am less confident about, and which touched 69 files in 19 commits. (Found while upgrading Servo to today’s Nightly: )
Could possibly be ?
Can't repro on 10.13. Could you use or  to bisect and find out the offending commit?
Based on reading surrounding assembly, happens when reading where is the pointer returned by the call to which is: So yeah, thread locals on old macOS suggest the same underlying issue as and possibly
requires 16-bytes alignment but is used to read form address which is only 8-bytes-aligned. This matches the description of
With rustup-toolchain-install-master, this reproduces with but not , which makes the PR that uncovered this bug (but likely not the root cause).
To try and reduce further, the code below is somewhat similar to part of . It does not segfault (maybe this static happens to be sufficently-aligned?), but the optimized assembly does contain a similar and the LLVM IR contains instructions that I think (?) are annotated to assume 32-bytes alignment (in both Nightly versions). Is there an LLVM bug to open about reducing that assumption?
Hi, I've also run into this... Is there a good workaround? I read somewhere that enabling LTO will solve the problem, but I'm guessing that will increase compile times significantly.
An arguably better workaround is to build on macOS 10.11 / XCode 8, or more recent. (That built program should still be able to run on some earlier OS versions.) But of course that can be more involved than flipping an LTO switch.
Ok, I was under the impression that XCode 8 and later doesn't support OSX 10.11. I just tried installing the Xcode 8.3 command line tools, but the installer refuses to go ahead, saying it needs 10.12. Has anyone been able to make this work on 10.11 by upgrading XCode?
Per ), XCode 8.2.1 runs on macOS 10.11.5.
Is it possible to test this with Xcode 9.3? Given how many times this TLS problem appears it is worth adding the test case to CI, however can't just switch our CI images back to Xcode 7 as that would be too slow for normal tests.
Per the root cause is a bug in XCode which is fixed in XCode 8. I think that the two realistic outcomes are: Try to find a reproducible test case that does not involve rustc or std, and file an LLVM bug to reduce the alignment assumption Or document in some old toolchain versions as unsupported or not Tier-1
XCode 8.2.1 is listed as running on 10.11.5, but does only include OS X SDK version 10.12.2, so I would be reluctant to remove 7.3 and install 8.2.1 if I wanted to keep using xcode to build for 10.11. Anyway, what just worked for me on 10.11 is to install the XCode 8.2 Command Line Tools (CLT) only, downloaded from here: (you may need an apple dev account) Running the installer will keep the current CLT installation and install the new one in /Library/Developer/CommandLineTools/ I then ran: After this, I'm able to run my rust test program (using regex) using both rust 1.27 and rust nightly in debug and release without getting a segfault. You may need to run to revert back to the original CLT before being able to build with XCode again, although macports did seem to be able to build a simple command line app using the new CLT.
Tagging as P-high but seems to have this in hand
If this is a linker bug, using a different linker naively seems like it could be a solution. Shipping lld with rustc and having at least an easy opt-in for it, if not enabling it by default, could be another way forward:
It is a dynamic linker bug (the linker that runs when the program starts). Switching to LLD won't fix it.
When building a program on 10.10.5 / XCode 7.2.1 and running it on a machine with a more recent OS (and presumably a more recent dynamic linker?) I still reproduce the issue.

Discussion:
unsafe { let g = get_static(cx, def_id); <del> let v = match ::mir::codegen_static_initializer(cx, def_id) { </del> <ins> let (v, alloc) = match ::mir::codegen_static_initializer(cx, def_id) { </ins> Ok(v) => v, // Error has already been reported Err(_) => return,

if attr::contains_name(attrs, "thread_local") { llvm::set_thread_local_mode(g, cx.tls_model); <ins> // Do not allow LLVM to change the alignment of a TLS on macOS. // // By default a global's alignment can be freely increased. // This allows LLVM to generate more performant instructions // e.g. using load-aligned into a SIMD register. // // However, on macOS 10.10 or below, the dynamic linker does not // respect any alignment given on the TLS (radar 24221680). // This will violate the alignment assumption, and causing segfault at runtime. // // This bug is very easy to trigger. In `println!` and `panic!`, // the `LOCAL_STDOUT`/`LOCAL_STDERR` handles are stored in a TLS, // which the values would be `mem::replace`d on initialization. // The implementation of `mem::replace` will use SIMD // whenever the size is 32 bytes or higher. LLVM notices SIMD is used // and tries to align `LOCAL_STDOUT`/`LOCAL_STDERR` to a 32-byte boundary, // which macOS's dyld disregarded and causing crashes // (see issues #51794, #51758, #50867, #48866 and #44056). // // To workaround the bug, we trick LLVM into not increasing // the global's alignment by explicitly assigning a section to it // (equivalent to automatically generating a `#[link_section]` attribute). // See the comment in the `GlobalValue::canIncreaseAlignment()` function // of `lib/IR/Globals.cpp` for why this works. // // When the alignment is not increased, the optimized `mem::replace` // will use load-unaligned instructions instead, and thus avoiding the crash. // // We could remove this hack whenever we decide to drop macOS 10.10 support. if cx.tcx.sess.target.target.options.is_like_osx { let sect_name = if alloc.bytes.iter().all(|b| *b == 0) { CStr::from_bytes_with_nul_unchecked(b"__DATA,__thread_bss0") } else { CStr::from_bytes_with_nul_unchecked(b"__DATA,__thread_data0") }; llvm::LLVMSetSection(g, sect_name.as_ptr()); } </ins> } base::set_link_section(cx, g, attrs);

pub fn codegen_static_initializer<'a, 'tcx>( cx: &CodegenCx<'a, 'tcx>, def_id: DefId) <del> -> Result<ValueRef, Lrc<ConstEvalErr<'tcx>>> </del> <ins> -> Result<(ValueRef, &'tcx Allocation), Lrc<ConstEvalErr<'tcx>>> </ins> { let instance = ty::Instance::mono(cx.tcx, def_id); let cid = GlobalId {

ConstValue::ByRef(alloc, n) if n.bytes() == 0 => alloc, _ => bug!("static const eval returned {:#?}", static_), }; <del> Ok(const_alloc_to_llvm(cx, alloc)) </del> <ins> Ok((const_alloc_to_llvm(cx, alloc), alloc)) </ins> } impl<'a, 'tcx> FunctionCx<'a, 'tcx> {

<ins> // Copyright 2018 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms. // ignore-tidy-linelength // only-macos // no-system-llvm // min-llvm-version 6.0 // compile-flags: -O #![crate_type = "rlib"] #![feature(thread_local)] // CHECK: @STATIC_VAR_1 = internal thread_local unnamed_addr global <{ [32 x i8] }> zeroinitializer, section "__DATA,__thread_bss", align 4 #[no_mangle] #[allow(private_no_mangle_statics)] #[thread_local] static mut STATIC_VAR_1: [u32; 8] = [0; 8]; // CHECK: @STATIC_VAR_2 = internal thread_local unnamed_addr global <{ [32 x i8] }> <{{[^>]*}}>, section "__DATA,__thread_data", align 4 #[no_mangle] #[allow(private_no_mangle_statics)] #[thread_local] static mut STATIC_VAR_2: [u32; 8] = [4; 8]; #[no_mangle] pub unsafe fn f(x: &mut [u32; 8]) { std::mem::swap(x, &mut STATIC_VAR_1) } #[no_mangle] pub unsafe fn g(x: &mut [u32; 8]) { std::mem::swap(x, &mut STATIC_VAR_2) } </ins>

<ins> // Copyright 2018 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms. // only-x86_64 // no-prefer-dynamic // compile-flags: -Ctarget-feature=+avx -Clto fn main() {} </ins>