|
208 | 208 | ///===----------------------------------------------------------------------===// |
209 | 209 |
|
210 | 210 | #include "WebAssembly.h" |
| 211 | +#include "WebAssemblyTargetMachine.h" |
211 | 212 | #include "llvm/ADT/StringExtras.h" |
| 213 | +#include "llvm/CodeGen/TargetPassConfig.h" |
212 | 214 | #include "llvm/IR/DebugInfoMetadata.h" |
213 | 215 | #include "llvm/IR/Dominators.h" |
214 | 216 | #include "llvm/IR/IRBuilder.h" |
@@ -314,16 +316,23 @@ static bool canThrow(const Value *V) { |
314 | 316 | // Get a global variable with the given name. If it doesn't exist declare it, |
315 | 317 | // which will generate an import and asssumes that it will exist at link time. |
316 | 318 | static GlobalVariable *getGlobalVariableI32(Module &M, IRBuilder<> &IRB, |
| 319 | + WebAssemblyTargetMachine &TM, |
317 | 320 | const char *Name) { |
318 | 321 | auto Int32Ty = IRB.getInt32Ty(); |
319 | | - auto *GV = dyn_cast<GlobalVariable>(M.getOrInsertGlobal(Name, Int32Ty, [&]() { |
320 | | - return new GlobalVariable(M, Int32Ty, false, |
321 | | - GlobalVariable::ExternalLinkage, nullptr, Name, |
322 | | - nullptr, GlobalValue::LocalExecTLSModel); |
323 | | - })); |
| 322 | + auto *GV = dyn_cast<GlobalVariable>(M.getOrInsertGlobal(Name, Int32Ty)); |
324 | 323 | if (!GV) |
325 | 324 | report_fatal_error(Twine("unable to create global: ") + Name); |
326 | 325 |
|
| 326 | + // If the target supports TLS, make this variable thread-local. We can't just |
| 327 | + // unconditionally make it thread-local and depend on |
| 328 | + // CoalesceFeaturesAndStripAtomics to downgrade it, because stripping TLS has |
| 329 | + // the side effect of disallowing the object from being linked into a |
| 330 | + // shared-memory module, which we don't want to be responsible for. |
| 331 | + auto *Subtarget = TM.getSubtargetImpl(); |
| 332 | + auto TLS = Subtarget->hasAtomics() && Subtarget->hasBulkMemory() |
| 333 | + ? GlobalValue::LocalExecTLSModel |
| 334 | + : GlobalValue::NotThreadLocal; |
| 335 | + GV->setThreadLocalMode(TLS); |
327 | 336 | return GV; |
328 | 337 | } |
329 | 338 |
|
@@ -645,11 +654,15 @@ bool WebAssemblyLowerEmscriptenEHSjLj::runOnModule(Module &M) { |
645 | 654 | bool LongjmpUsed = LongjmpF && !LongjmpF->use_empty(); |
646 | 655 | bool DoSjLj = EnableSjLj && (SetjmpUsed || LongjmpUsed); |
647 | 656 |
|
| 657 | + auto *TPC = getAnalysisIfAvailable<TargetPassConfig>(); |
| 658 | + assert(TPC && "Expected a TargetPassConfig"); |
| 659 | + auto &TM = TPC->getTM<WebAssemblyTargetMachine>(); |
| 660 | + |
648 | 661 | // Declare (or get) global variables __THREW__, __threwValue, and |
649 | 662 | // getTempRet0/setTempRet0 function which are used in common for both |
650 | 663 | // exception handling and setjmp/longjmp handling |
651 | | - ThrewGV = getGlobalVariableI32(M, IRB, "__THREW__"); |
652 | | - ThrewValueGV = getGlobalVariableI32(M, IRB, "__threwValue"); |
| 664 | + ThrewGV = getGlobalVariableI32(M, IRB, TM, "__THREW__"); |
| 665 | + ThrewValueGV = getGlobalVariableI32(M, IRB, TM, "__threwValue"); |
653 | 666 | GetTempRet0Func = getEmscriptenFunction( |
654 | 667 | FunctionType::get(IRB.getInt32Ty(), false), "getTempRet0", &M); |
655 | 668 | SetTempRet0Func = getEmscriptenFunction( |
|
0 commit comments