From 58895340ddbc8947988174384a5f99c7792dcce5 Mon Sep 17 00:00:00 2001 From: Cameron Hart Date: Sun, 10 Jul 2016 23:55:53 +1000 Subject: [PATCH 01/10] Add accessors for MCSubtargetInfo CPU and Feature tables This is needed for `-C target-cpu=help` and `-C target-feature=help` in rustc --- llvm/include/llvm/MC/MCSubtargetInfo.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/llvm/include/llvm/MC/MCSubtargetInfo.h b/llvm/include/llvm/MC/MCSubtargetInfo.h index 9490a6ecedadb..146ee8d469d95 100644 --- a/llvm/include/llvm/MC/MCSubtargetInfo.h +++ b/llvm/include/llvm/MC/MCSubtargetInfo.h @@ -221,6 +221,14 @@ class MCSubtargetInfo { auto Found = std::lower_bound(ProcDesc.begin(), ProcDesc.end(), CPU); return Found != ProcDesc.end() && StringRef(Found->Key) == CPU; } + + ArrayRef getCPUTable() const { + return ProcDesc; + } + + ArrayRef getFeatureTable() const { + return ProcFeatures; + } }; } // end namespace llvm From fd5f9e298664c7752707a5907f52c604d2dabeca Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 28 Jul 2017 11:41:14 -0700 Subject: [PATCH 02/10] Fix compile on dist-i686-linux builder If this lines are present then we apparently get errors [1] when compiling in the current [2] dist-i686-linux container. Attempts to upgrade both gcc and binutils did not fix the error, so it appears that this may just be a bug in the super old glibc we're using on the dist-i686-linux container. We don't actually need this code anyway, so just work around these issues by removing references to the `*64` functions. This'll get things compiling locally and shouldn't be a regression in functionality. [1]: https://travis-ci.org/rust-lang/rust/jobs/257578199 [2]: https://github.com/rust-lang/rust/tree/eba9d7f08ce5c90549ee52337aca0010ad566f0d/src/ci/docker/dist-i686-linux --- .../lib/ExecutionEngine/RuntimeDyld/RTDyldMemoryManager.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/RTDyldMemoryManager.cpp b/llvm/lib/ExecutionEngine/RuntimeDyld/RTDyldMemoryManager.cpp index 46604ff4000c1..149704493e347 100644 --- a/llvm/lib/ExecutionEngine/RuntimeDyld/RTDyldMemoryManager.cpp +++ b/llvm/lib/ExecutionEngine/RuntimeDyld/RTDyldMemoryManager.cpp @@ -243,9 +243,9 @@ RTDyldMemoryManager::getSymbolAddressInProcess(const std::string &Name) { if (Name == "stat") return (uint64_t)&stat; if (Name == "fstat") return (uint64_t)&fstat; if (Name == "lstat") return (uint64_t)&lstat; - if (Name == "stat64") return (uint64_t)&stat64; - if (Name == "fstat64") return (uint64_t)&fstat64; - if (Name == "lstat64") return (uint64_t)&lstat64; + // if (Name == "stat64") return (uint64_t)&stat64; + // if (Name == "fstat64") return (uint64_t)&fstat64; + // if (Name == "lstat64") return (uint64_t)&lstat64; if (Name == "atexit") return (uint64_t)&atexit; if (Name == "mknod") return (uint64_t)&mknod; From 606b776f9a10511639bc1d38c1d04e22dd9bf4f7 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 24 Jan 2018 15:28:57 -0800 Subject: [PATCH 03/10] Disable checks for libatomic for now For whatever reason this is failing the i686-freebsd builder in the Rust repo as-of this red-hot moment. The build seems to work fine without it so let's just remove it for now and pray there's a better fix later. Although if you're reading this and know of a better fix, we'd love to remove this! --- llvm/cmake/modules/CheckAtomic.cmake | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/llvm/cmake/modules/CheckAtomic.cmake b/llvm/cmake/modules/CheckAtomic.cmake index 9a4cdf12a6223..de8e54153a741 100644 --- a/llvm/cmake/modules/CheckAtomic.cmake +++ b/llvm/cmake/modules/CheckAtomic.cmake @@ -62,19 +62,20 @@ else() check_working_cxx_atomics64(HAVE_CXX_ATOMICS64_WITHOUT_LIB) endif() -# If not, check if the library exists, and atomics work with it. -if(NOT HAVE_CXX_ATOMICS64_WITHOUT_LIB) - check_library_exists(atomic __atomic_load_8 "" HAVE_CXX_LIBATOMICS64) - if(HAVE_CXX_LIBATOMICS64) - list(APPEND CMAKE_REQUIRED_LIBRARIES "atomic") - check_working_cxx_atomics64(HAVE_CXX_ATOMICS64_WITH_LIB) - if (NOT HAVE_CXX_ATOMICS64_WITH_LIB) - message(FATAL_ERROR "Host compiler must support std::atomic!") - endif() - else() - message(FATAL_ERROR "Host compiler appears to require libatomic, but cannot find it.") - endif() -endif() +# RUST-SPECIFIC - commented out, see commit message +# # If not, check if the library exists, and atomics work with it. +# if(NOT HAVE_CXX_ATOMICS64_WITHOUT_LIB) +# check_library_exists(atomic __atomic_load_8 "" HAVE_CXX_LIBATOMICS64) +# if(HAVE_CXX_LIBATOMICS64) +# list(APPEND CMAKE_REQUIRED_LIBRARIES "atomic") +# check_working_cxx_atomics64(HAVE_CXX_ATOMICS64_WITH_LIB) +# if (NOT HAVE_CXX_ATOMICS64_WITH_LIB) +# message(FATAL_ERROR "Host compiler must support std::atomic!") +# endif() +# else() +# message(FATAL_ERROR "Host compiler appears to require libatomic, but cannot find it.") +# endif() +# endif() ## TODO: This define is only used for the legacy atomic operations in ## llvm's Atomic.h, which should be replaced. Other code simply From 69cb0d1511b5351cf732d7cc057c691d91f99a9a Mon Sep 17 00:00:00 2001 From: Simonas Kazlauskas Date: Sat, 3 Jun 2017 18:55:08 +0300 Subject: [PATCH 04/10] Add knowledge of __rust_{alloc,realloc,dealloc} --- .../llvm/Analysis/TargetLibraryInfo.def | 10 +++++++++ llvm/lib/Analysis/MemoryBuiltins.cpp | 8 +++++-- llvm/lib/Analysis/TargetLibraryInfo.cpp | 22 +++++++++++++++++++ 3 files changed, 38 insertions(+), 2 deletions(-) diff --git a/llvm/include/llvm/Analysis/TargetLibraryInfo.def b/llvm/include/llvm/Analysis/TargetLibraryInfo.def index bbccca4ca664d..cac5114473643 100644 --- a/llvm/include/llvm/Analysis/TargetLibraryInfo.def +++ b/llvm/include/llvm/Analysis/TargetLibraryInfo.def @@ -355,6 +355,16 @@ TLI_DEFINE_STRING_INTERNAL("__powf_finite") /// long double __powl_finite(long double x, long double y); TLI_DEFINE_ENUM_INTERNAL(powl_finite) TLI_DEFINE_STRING_INTERNAL("__powl_finite") + +TLI_DEFINE_ENUM_INTERNAL(rust_alloc) +TLI_DEFINE_STRING_INTERNAL("__rust_alloc") + +TLI_DEFINE_ENUM_INTERNAL(rust_dealloc) +TLI_DEFINE_STRING_INTERNAL("__rust_dealloc") + +TLI_DEFINE_ENUM_INTERNAL(rust_realloc) +TLI_DEFINE_STRING_INTERNAL("__rust_realloc") + /// double __sincospi_stret(double x); TLI_DEFINE_ENUM_INTERNAL(sincospi_stret) TLI_DEFINE_STRING_INTERNAL("__sincospi_stret") diff --git a/llvm/lib/Analysis/MemoryBuiltins.cpp b/llvm/lib/Analysis/MemoryBuiltins.cpp index 082542664821b..fa27a7399c82f 100644 --- a/llvm/lib/Analysis/MemoryBuiltins.cpp +++ b/llvm/lib/Analysis/MemoryBuiltins.cpp @@ -104,7 +104,10 @@ static const std::pair AllocationFnData[] = { {LibFunc_realloc, {ReallocLike, 2, 1, -1}}, {LibFunc_reallocf, {ReallocLike, 2, 1, -1}}, {LibFunc_strdup, {StrDupLike, 1, -1, -1}}, - {LibFunc_strndup, {StrDupLike, 2, 1, -1}} + {LibFunc_strndup, {StrDupLike, 2, 1, -1}}, + + {LibFunc_rust_alloc, {MallocLike, 2, 0, -1}}, + {LibFunc_rust_realloc, {ReallocLike, 4, 3, -1}}, // TODO: Handle "int posix_memalign(void **, size_t, size_t)" }; @@ -398,7 +401,8 @@ const CallInst *llvm::isFreeCall(const Value *I, const TargetLibraryInfo *TLI) { TLIFn == LibFunc_msvc_delete_array_ptr64_nothrow) // delete[](void*, nothrow) ExpectedNumParams = 2; else if (TLIFn == LibFunc_ZdaPvSt11align_val_tRKSt9nothrow_t || // delete(void*, align_val_t, nothrow) - TLIFn == LibFunc_ZdlPvSt11align_val_tRKSt9nothrow_t) // delete[](void*, align_val_t, nothrow) + TLIFn == LibFunc_ZdlPvSt11align_val_tRKSt9nothrow_t || // delete[](void*, align_val_t, nothrow) + TLIFn == LibFunc_rust_dealloc) ExpectedNumParams = 3; else return nullptr; diff --git a/llvm/lib/Analysis/TargetLibraryInfo.cpp b/llvm/lib/Analysis/TargetLibraryInfo.cpp index ef139d3257d2b..e4896f727122b 100644 --- a/llvm/lib/Analysis/TargetLibraryInfo.cpp +++ b/llvm/lib/Analysis/TargetLibraryInfo.cpp @@ -1480,6 +1480,28 @@ bool TargetLibraryInfoImpl::isValidProtoForLibFunc(const FunctionType &FTy, else return false; } + + case LibFunc_rust_alloc: + return (NumParams == 3 && FTy.getReturnType()->isPointerTy() && + FTy.getParamType(0)->isIntegerTy() && + FTy.getParamType(1)->isIntegerTy() && + FTy.getParamType(2)->isPointerTy()); + + case LibFunc_rust_dealloc: + return (NumParams == 3 && FTy.getReturnType()->isVoidTy() && + FTy.getParamType(0)->isPointerTy() && + FTy.getParamType(1)->isIntegerTy() && + FTy.getParamType(2)->isIntegerTy()); + + case LibFunc_rust_realloc: + return (NumParams == 6 && FTy.getReturnType()->isPointerTy() && + FTy.getParamType(0)->isPointerTy() && + FTy.getParamType(1)->isIntegerTy() && + FTy.getParamType(2)->isIntegerTy() && + FTy.getParamType(3)->isIntegerTy() && + FTy.getParamType(4)->isIntegerTy() && + FTy.getParamType(5)->isPointerTy()); + case LibFunc::NumLibFuncs: break; } From a4f32601e380a018f1d0652d692895892b1a1612 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 2 Jul 2018 15:28:26 -0700 Subject: [PATCH 05/10] Fix compile on dist-x86_64-linux builder Apparently glibc is so old it doesn't have the _POSIX_ARG_MAX constant. This shouldn't affect anything we use anyway though. https://travis-ci.org/rust-lang/rust/jobs/399333071 --- llvm/lib/Support/Unix/Program.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/lib/Support/Unix/Program.inc b/llvm/lib/Support/Unix/Program.inc index c4123a64046f6..bb2b5ce6eccc3 100644 --- a/llvm/lib/Support/Unix/Program.inc +++ b/llvm/lib/Support/Unix/Program.inc @@ -462,7 +462,7 @@ bool llvm::sys::commandLineFitsWithinSystemLimits(StringRef Program, static long ArgMax = sysconf(_SC_ARG_MAX); // POSIX requires that _POSIX_ARG_MAX is 4096, which is the lowest possible // value for ARG_MAX on a POSIX compliant system. - static long ArgMin = _POSIX_ARG_MAX; + static long ArgMin = 4096; // This the same baseline used by xargs. long EffectiveArgMax = 128 * 1024; From accc618525c1ca8dd6a71d5bc52ef9ddf19cb50a Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sat, 10 Feb 2018 17:21:38 -0800 Subject: [PATCH 06/10] Compile with /MT on MSVC Can't seem to figure out how to do this without this patch... --- lld/CMakeLists.txt | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/lld/CMakeLists.txt b/lld/CMakeLists.txt index e2fbdbfbbb47f..ccf33f8fd2881 100644 --- a/lld/CMakeLists.txt +++ b/lld/CMakeLists.txt @@ -210,6 +210,19 @@ if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY) ) endif() +if (MSVC) + FOREACH(flag + CMAKE_C_FLAGS_RELEASE CMAKE_C_FLAGS_RELWITHDEBINFO + CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_DEBUG_INIT + CMAKE_CXX_FLAGS_RELEASE CMAKE_CXX_FLAGS_RELWITHDEBINFO + CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_DEBUG_INIT) + if (MSVC) + STRING(REPLACE "/MD" "/MT" "${flag}" "${${flag}}") + SET("${flag}" "${${flag}}") + endif (MSVC) + ENDFOREACH() +endif() + add_subdirectory(Common) add_subdirectory(lib) add_subdirectory(tools/lld) From 9670dbb2803a23826cfbbcc0619266cd20a07693 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 22 May 2019 07:25:02 -0700 Subject: [PATCH 07/10] Fix compilation of sanitizers in Rust containers It's not entertirely clear why this is necessary but this is carrying over an old `compiler-rt` patch to ensure that `compiler-rt` compiles in our super ancient containers that we build sanitizers in. This ideally isn't the worst thing to keep with us going forward, but we'll see! --- compiler-rt/lib/asan/asan_linux.cc | 2 +- .../lib/sanitizer_common/sanitizer_linux_libcdep.cc | 6 +----- .../sanitizer_common/sanitizer_platform_limits_posix.cc | 7 ++++--- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/compiler-rt/lib/asan/asan_linux.cc b/compiler-rt/lib/asan/asan_linux.cc index f9182328916fc..79ab5985abfc7 100644 --- a/compiler-rt/lib/asan/asan_linux.cc +++ b/compiler-rt/lib/asan/asan_linux.cc @@ -214,7 +214,7 @@ void AsanCheckIncompatibleRT() { // the functions in dynamic ASan runtime instead of the functions in // system libraries, causing crashes later in ASan initialization. MemoryMappingLayout proc_maps(/*cache_enabled*/true); - char filename[PATH_MAX]; + char filename[4096]; MemoryMappedSegment segment(filename, sizeof(filename)); while (proc_maps.Next(&segment)) { if (IsDynamicRTName(segment.filename)) { diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cc b/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cc index 0608898a1464d..49bd5b0284023 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cc @@ -698,12 +698,8 @@ u32 GetNumberOfCPUs() { } internal_close(fd); return n_cpus; -#elif SANITIZER_SOLARIS - return sysconf(_SC_NPROCESSORS_ONLN); #else - cpu_set_t CPUs; - CHECK_EQ(sched_getaffinity(0, sizeof(cpu_set_t), &CPUs), 0); - return CPU_COUNT(&CPUs); + return sysconf(_SC_NPROCESSORS_ONLN); #endif } diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cc b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cc index b7fa6e8f7e079..690c602d7d686 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cc @@ -106,6 +106,7 @@ typedef struct user_fpregs elf_fpregset_t; #endif #if SANITIZER_LINUX && !SANITIZER_ANDROID +#include #include #include #include @@ -1010,9 +1011,9 @@ CHECK_SIZE_AND_OFFSET(cmsghdr, cmsg_type); #endif #if SANITIZER_LINUX && (__ANDROID_API__ >= 21 || __GLIBC_PREREQ (2, 14)) -CHECK_TYPE_SIZE(mmsghdr); -CHECK_SIZE_AND_OFFSET(mmsghdr, msg_hdr); -CHECK_SIZE_AND_OFFSET(mmsghdr, msg_len); +// CHECK_TYPE_SIZE(mmsghdr); +// CHECK_SIZE_AND_OFFSET(mmsghdr, msg_hdr); +// CHECK_SIZE_AND_OFFSET(mmsghdr, msg_len); #endif COMPILER_CHECK(sizeof(__sanitizer_dirent) <= sizeof(dirent)); From 2902abd81cb4302e04cae86e9db47434a75808ee Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Mon, 8 Jul 2019 18:00:33 +0200 Subject: [PATCH 08/10] Fix sanitizer build without O_CLOEXEC Define it to 0 if it doesn't exist. --- compiler-rt/lib/sanitizer_common/sanitizer_posix.cc | 3 +++ compiler-rt/lib/xray/xray_x86_64.cc | 3 +++ 2 files changed, 6 insertions(+) diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_posix.cc b/compiler-rt/lib/sanitizer_common/sanitizer_posix.cc index bf7127443c417..ac9db9807adb7 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_posix.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_posix.cc @@ -338,6 +338,9 @@ bool ShouldMockFailureToOpen(const char *path) { } #if SANITIZER_LINUX && !SANITIZER_ANDROID && !SANITIZER_GO +# ifndef O_CLOEXEC +# define O_CLOEXEC 0 +# endif int GetNamedMappingFd(const char *name, uptr size, int *flags) { if (!common_flags()->decorate_proc_maps || !name) return -1; diff --git a/compiler-rt/lib/xray/xray_x86_64.cc b/compiler-rt/lib/xray/xray_x86_64.cc index e63ee1b3bd02e..209aa7a106bbc 100644 --- a/compiler-rt/lib/xray/xray_x86_64.cc +++ b/compiler-rt/lib/xray/xray_x86_64.cc @@ -49,6 +49,9 @@ retryingReadSome(int Fd, char *Begin, char *End) XRAY_NEVER_INSTRUMENT { return std::make_pair(TotalBytesRead, true); } +#ifndef O_CLOEXEC +# define O_CLOEXEC 0 +#endif static bool readValueFromFile(const char *Filename, long long *Value) XRAY_NEVER_INSTRUMENT { int Fd = open(Filename, O_RDONLY | O_CLOEXEC); From ef83c041edecf69c3f2c48dc4e379517f6470798 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Tue, 9 Jul 2019 20:24:44 +0000 Subject: [PATCH 09/10] [SLP] Optimize getSpillCost(); NFCI For a given set of live values, the spill cost will always be the same for each call. Compute the cost once and multiply it by the number of calls. (I'm not sure this spill cost modeling makes sense if there are multiple calls, as the spill cost will likely be shared across calls in that case. But that's how it currently works.) llvm-svn: 365552 --- llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp index 49fce1023acc3..8cd948ee55190 100644 --- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp +++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp @@ -3355,6 +3355,7 @@ int BoUpSLP::getSpillCost() const { }); // Now find the sequence of instructions between PrevInst and Inst. + unsigned NumCalls = 0; BasicBlock::reverse_iterator InstIt = ++Inst->getIterator().getReverse(), PrevInstIt = PrevInst->getIterator().getReverse(); @@ -3367,16 +3368,19 @@ int BoUpSLP::getSpillCost() const { // Debug informations don't impact spill cost. if ((isa(&*PrevInstIt) && !isa(&*PrevInstIt)) && - &*PrevInstIt != PrevInst) { - SmallVector V; - for (auto *II : LiveValues) - V.push_back(VectorType::get(II->getType(), BundleWidth)); - Cost += TTI->getCostOfKeepingLiveOverCall(V); - } + &*PrevInstIt != PrevInst) + NumCalls++; ++PrevInstIt; } + if (NumCalls) { + SmallVector V; + for (auto *II : LiveValues) + V.push_back(VectorType::get(II->getType(), BundleWidth)); + Cost += NumCalls * TTI->getCostOfKeepingLiveOverCall(V); + } + PrevInst = Inst; } From 56b8425750e78974fcc8c64429739bc8c2d84f08 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Thu, 11 Jul 2019 10:10:09 +0000 Subject: [PATCH 10/10] [X86] -fno-plt: use GOT __tls_get_addr only if GOTPCRELX is enabled Summary: As of binutils 2.32, ld has a bogus TLS relaxation error when the GD/LD code sequence using R_X86_64_GOTPCREL (instead of R_X86_64_GOTPCRELX) is attempted to be relaxed to IE/LE (binutils PR24784). gold and lld are good. In gcc/config/i386/i386.md, there is a configure-time check of as/ld support and the GOT relaxation will not be used if as/ld doesn't support it: if (flag_plt || !HAVE_AS_IX86_TLS_GET_ADDR_GOT) return "call\t%P2"; return "call\t{*%p2@GOT(%1)|[DWORD PTR %p2@GOT[%1]]}"; In clang, -DENABLE_X86_RELAX_RELOCATIONS=OFF is the default. The ld.bfd bogus error can be reproduced with: thread_local int a; int main() { return a; } clang -fno-plt -fpic a.cc -fuse-ld=bfd GOTPCRELX gained relative good support in 2016, which is considered relatively new. It is even difficult to conditionally default to -DENABLE_X86_RELAX_RELOCATIONS=ON due to cross compilation reasons. So work around the ld.bfd bug by only using GOT when GOTPCRELX is enabled. Reviewers: dalias, hjl.tools, nikic, rnk Reviewed By: nikic Subscribers: llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D64304 llvm-svn: 365752 --- llvm/lib/Target/X86/X86MCInstLower.cpp | 9 ++++++++- llvm/test/CodeGen/X86/tls-no-plt.ll | 13 +++++++++++-- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/llvm/lib/Target/X86/X86MCInstLower.cpp b/llvm/lib/Target/X86/X86MCInstLower.cpp index 9de2d18e0be11..b1fefaa84be40 100644 --- a/llvm/lib/Target/X86/X86MCInstLower.cpp +++ b/llvm/lib/Target/X86/X86MCInstLower.cpp @@ -705,7 +705,14 @@ void X86AsmPrinter::LowerTlsAddr(X86MCInstLower &MCInstLowering, const MCSymbolRefExpr *Sym = MCSymbolRefExpr::create( MCInstLowering.GetSymbolFromOperand(MI.getOperand(3)), SRVK, Ctx); - bool UseGot = MMI->getModule()->getRtLibUseGOT(); + + // As of binutils 2.32, ld has a bogus TLS relaxation error when the GD/LD + // code sequence using R_X86_64_GOTPCREL (instead of R_X86_64_GOTPCRELX) is + // attempted to be relaxed to IE/LE (binutils PR24784). Work around the bug by + // only using GOT when GOTPCRELX is enabled. + // TODO Delete the workaround when GOTPCRELX becomes commonplace. + bool UseGot = MMI->getModule()->getRtLibUseGOT() && + Ctx.getAsmInfo()->canRelaxRelocations(); if (Is64Bits) { bool NeedsPadding = SRVK == MCSymbolRefExpr::VK_TLSGD; diff --git a/llvm/test/CodeGen/X86/tls-no-plt.ll b/llvm/test/CodeGen/X86/tls-no-plt.ll index 6439843b869f5..5c4944f6f7b2f 100644 --- a/llvm/test/CodeGen/X86/tls-no-plt.ll +++ b/llvm/test/CodeGen/X86/tls-no-plt.ll @@ -1,5 +1,10 @@ -; RUN: llc < %s -mtriple=i386-linux-musl -relocation-model=pic | FileCheck --check-prefixes=CHECK,X86 %s -; RUN: llc < %s -mtriple=x86_64-linux-musl -relocation-model=pic | FileCheck --check-prefixes=CHECK,X64 %s +; RUN: llc < %s -mtriple=i386-linux-musl -relocation-model=pic -relax-elf-relocations=true | FileCheck --check-prefixes=CHECK,X86 %s +; RUN: llc < %s -mtriple=x86_64-linux-musl -relocation-model=pic -relax-elf-relocations=true | FileCheck --check-prefixes=CHECK,X64 %s + +;; If GOTPCRELX is disabled, don't use GOT for __tls_get_addr to work around +;; a ld.bfd bug (binutils PR24784). +; RUN: llc < %s -mtriple=i386-linux-musl -relocation-model=pic | FileCheck --check-prefixes=CHECK,X86-PLT %s +; RUN: llc < %s -mtriple=x86_64-linux-musl -relocation-model=pic | FileCheck --check-prefixes=CHECK,X64-PLT %s @gd = thread_local global i32 0 @ld = internal thread_local global i32 0 @@ -9,9 +14,11 @@ entry: ; CHECK-LABEL: get_gd: ; X86: leal gd@TLSGD(%ebx), %eax ; X86: calll *___tls_get_addr@GOT(%ebx) +; X86-PLT: calll ___tls_get_addr@PLT ; X64: leaq gd@TLSGD(%rip), %rdi ; X64: callq *__tls_get_addr@GOTPCREL(%rip) +; X64-PLT: callq __tls_get_addr@PLT ret i32* @gd } @@ -20,9 +27,11 @@ define i32* @get_ld() { ; CHECK-LABEL: get_ld: ; X86: leal ld@TLSLDM(%ebx), %eax ; X86: calll *___tls_get_addr@GOT(%ebx) +; X86-PLT: calll ___tls_get_addr@PLT ; X64: leaq ld@TLSLD(%rip), %rdi ; X64: callq *__tls_get_addr@GOTPCREL(%rip) +; X64-PLT: callq __tls_get_addr@PLT ret i32* @ld }