diff --git a/lld/test/ELF/lto/riscv-no-emutls.ll b/lld/test/ELF/lto/riscv-no-emutls.ll new file mode 100644 --- /dev/null +++ b/lld/test/ELF/lto/riscv-no-emutls.ll @@ -0,0 +1,39 @@ +; Ensure targets that normally enable emulated TLS by default, don't run the +; LowerEmuTLSPass under LTO in RISCV64. Under LTO the backend options for +; emulated TLS won't be propagated unless passed explicitly as part of the +; link. Since LLVM doesn't support emulated TLS on RISCV64, we want to be sure +; related transforms don't take place. + +; RUN: opt -module-summary < %s -o %t.bc --mtriple=riscv64-unknown-linux-android10000 +; RUN: ld.lld --plugin-opt=-debug-pass=Structure %t.bc -o /dev/null --no-undefined -shared 2>&1 | FileCheck %s --allow-empty + +; Ensure the backend pass we want to avoid doesn't run: LowerEmuTLSPass +; so we check for its output under pass structure +; CHECK-NOT: Add __emutls_ + +; Also check that we don't end up creating thread_locals that are undefined in +; the final link. This used to happen because the LowerEmuTLSPass would be +; added when targeting platforms with default emulated TLS. +; CHECK-NOT: error: undefined symbol: Mem + +target datalayout = "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128" + +%struct.Memory = type { i32, i32 } + +@Mem = internal thread_local global ptr null, align 8 + +; Give a bogus definition to satisfy the linker +define ptr @__tls_get_addr(ptr nonnull) { + ret ptr null +} + +define void @baz(i32 noundef signext %n) { +entry: + %loc = inttoptr i64 66 to ptr + %threadlocal = call align 8 ptr @llvm.threadlocal.address.p0(ptr align 8 @Mem) + store ptr %loc, ptr %threadlocal, align 8 + + ret void +} + +declare nonnull ptr @llvm.threadlocal.address.p0(ptr nonnull) diff --git a/llvm/include/llvm/TargetParser/Triple.h b/llvm/include/llvm/TargetParser/Triple.h --- a/llvm/include/llvm/TargetParser/Triple.h +++ b/llvm/include/llvm/TargetParser/Triple.h @@ -950,9 +950,15 @@ isOSBinFormatDXContainer()); } + /// Tests whether the target supports emulated tls + bool supportsEmulatedTLS() const { + return !isRISCV64(); + } + /// Tests whether the target uses emulated TLS as default. bool hasDefaultEmulatedTLS() const { - return isAndroid() || isOSOpenBSD() || isWindowsCygwinEnvironment(); + return supportsEmulatedTLS() && + (isAndroid() || isOSOpenBSD() || isWindowsCygwinEnvironment()); } /// Tests whether the target uses -data-sections as default.