Index: llvm/trunk/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp =================================================================== --- llvm/trunk/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp +++ llvm/trunk/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp @@ -126,6 +126,22 @@ } namespace { +class StripThreadLocal final : public ModulePass { + // The default thread model for wasm is single, where thread-local variables + // are identical to regular globals and should be treated the same. So this + // pass just converts all GlobalVariables to NotThreadLocal + static char ID; + + public: + StripThreadLocal() : ModulePass(ID) {} + bool runOnModule(Module &M) override { + for (auto &GV : M.globals()) + GV.setThreadLocalMode(GlobalValue::ThreadLocalMode::NotThreadLocal); + return true; + } +}; +char StripThreadLocal::ID = 0; + /// WebAssembly Code Generator Pass Configuration Options. class WebAssemblyPassConfig final : public TargetPassConfig { public: @@ -166,13 +182,15 @@ //===----------------------------------------------------------------------===// void WebAssemblyPassConfig::addIRPasses() { - if (TM->Options.ThreadModel == ThreadModel::Single) + if (TM->Options.ThreadModel == ThreadModel::Single) { // In "single" mode, atomics get lowered to non-atomics. addPass(createLowerAtomicPass()); - else + addPass(new StripThreadLocal()); + } else { // Expand some atomic operations. WebAssemblyTargetLowering has hooks which // control specifically what gets lowered. addPass(createAtomicExpandPass()); + } // Lower .llvm.global_dtors into .llvm_global_ctors with __cxa_atexit calls. addPass(createWebAssemblyLowerGlobalDtors()); Index: llvm/trunk/test/CodeGen/WebAssembly/tls.ll =================================================================== --- llvm/trunk/test/CodeGen/WebAssembly/tls.ll +++ llvm/trunk/test/CodeGen/WebAssembly/tls.ll @@ -0,0 +1,17 @@ +; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals -thread-model=single | FileCheck --check-prefix=SINGLE %s +target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" +target triple = "wasm32-unknown-unknown-wasm" + +; SINGLE-LABEL: address_of_tls: +define i32 @address_of_tls() { + ; SINGLE: i32.const $push0=, tls + ; SINGLE-NEXT: return $pop0 + ret i32 ptrtoint(i32* @tls to i32) +} + +; SINGLE: .type tls,@object +; SINGLE-NEXT: .section .bss.tls,"",@ +; SINGLE-NEXT: .p2align 2 +; SINGLE-NEXT: tls: +; SINGLE-NEXT: .int32 0 +@tls = internal thread_local global i32 0