diff --git a/lld/test/wasm/lto/tls.ll b/lld/test/wasm/lto/tls.ll new file mode 100644 --- /dev/null +++ b/lld/test/wasm/lto/tls.ll @@ -0,0 +1,45 @@ +; Test that LTO objects build with TLS and threading support can be linked into +; a single threaded binary. Specifically the references to `__tls_base` that +; can be generated at LTO-time need to trigger the creation of the internal/fake +; `__tls_base` symbol in the linker. + +; RUN: llvm-as %s -o %t1.o +; RUN: wasm-ld --export=tls_int --export=get_tls %t1.o -o %t +; RUN: obj2yaml %t | FileCheck %s + +target datalayout = "e-m:e-p:32:32-i64:64-f128:64-n32:64-S128-ni:1:10:20" +target triple = "wasm32-unknown-emscripten" + +@tls_int = dso_local thread_local global i32 99 + +define i32 @get_tls() #0 { + %val = load i32, i32* @tls_int + ret i32 %val +} + +define void @_start() #0 { + ret void +} + +attributes #0 = { noinline nounwind optnone "target-features"="+atomics,+bulk-memory,+mutable-globals,+sign-ext" } + +; CHECK: - Type: GLOBAL +; CHECK-NEXT: Globals: +; CHECK-NEXT: - Index: 0 +; CHECK-NEXT: Type: I32 +; CHECK-NEXT: Mutable: true +; CHECK-NEXT: InitExpr: +; CHECK-NEXT: Opcode: I32_CONST +; CHECK-NEXT: Value: 66576 +; CHECK-NEXT: - Index: 1 +; CHECK-NEXT: Type: I32 +; CHECK-NEXT: Mutable: false +; CHECK-NEXT: InitExpr: +; CHECK-NEXT: Opcode: I32_CONST +; CHECK-NEXT: Value: 1024 + +; CHECK: GlobalNames: +; CHECK-NEXT: - Index: 0 +; CHECK-NEXT: Name: __stack_pointer +; CHECK-NEXT: - Index: 1 +; CHECK-NEXT: Name: __tls_base diff --git a/lld/wasm/Driver.cpp b/lld/wasm/Driver.cpp --- a/lld/wasm/Driver.cpp +++ b/lld/wasm/Driver.cpp @@ -947,8 +947,6 @@ } } - createOptionalSymbols(); - if (errorCount()) return; @@ -976,6 +974,8 @@ if (errorCount()) return; + createOptionalSymbols(); + // Resolve any variant symbols that were created due to signature // mismatchs. symtab->handleSymbolVariants(); diff --git a/lld/wasm/SymbolTable.cpp b/lld/wasm/SymbolTable.cpp --- a/lld/wasm/SymbolTable.cpp +++ b/lld/wasm/SymbolTable.cpp @@ -258,11 +258,11 @@ DefinedGlobal *SymbolTable::addOptionalGlobalSymbol(StringRef name, InputGlobal *global) { - LLVM_DEBUG(dbgs() << "addOptionalGlobalSymbol: " << name << " -> " << global - << "\n"); Symbol *s = find(name); if (!s || s->isDefined()) return nullptr; + LLVM_DEBUG(dbgs() << "addOptionalGlobalSymbol: " << name << " -> " << global + << "\n"); syntheticGlobals.emplace_back(global); return replaceSymbol(s, name, WASM_SYMBOL_VISIBILITY_HIDDEN, nullptr, global);