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 9490a6ecedadb7..146ee8d469d951 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 46604ff4000c11..149704493e347f 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 9a4cdf12a6223d..de8e54153a741a 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 bbccca4ca664d5..cac5114473643d 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 082542664821bf..fa27a7399c82f0 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 ef139d3257d2ba..e4896f727122b0 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 c4123a64046f62..bb2b5ce6eccc32 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 e2fbdbfbbb47f7..ccf33f8fd28817 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 f9182328916fc4..79ab5985abfc74 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 0608898a1464d9..49bd5b02840239 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 b7fa6e8f7e0791..690c602d7d6862 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 bf7127443c4175..ac9db9807adb70 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 e63ee1b3bd02eb..209aa7a106bbcc 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 49fce1023acc37..8cd948ee55190c 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 9de2d18e0be11c..b1fefaa84be40b 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 6439843b869f56..5c4944f6f7b2fe 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 }