diff options
Diffstat (limited to 'lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp')
-rw-r--r-- | lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp | 95 |
1 files changed, 50 insertions, 45 deletions
diff --git a/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp b/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp index 0491f71cea7f..960d5134f6e9 100644 --- a/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp +++ b/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp @@ -1,9 +1,8 @@ //=== WebAssemblyLowerEmscriptenEHSjLj.cpp - Lower exceptions for Emscripten =// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// /// @@ -240,16 +239,16 @@ class WebAssemblyLowerEmscriptenEHSjLj final : public ModulePass { bool EnableEH; // Enable exception handling bool EnableSjLj; // Enable setjmp/longjmp handling - GlobalVariable *ThrewGV; - GlobalVariable *ThrewValueGV; - Function *GetTempRet0Func; - Function *SetTempRet0Func; - Function *ResumeF; - Function *EHTypeIDF; - Function *EmLongjmpF; - Function *EmLongjmpJmpbufF; - Function *SaveSetjmpF; - Function *TestSetjmpF; + GlobalVariable *ThrewGV = nullptr; + GlobalVariable *ThrewValueGV = nullptr; + Function *GetTempRet0Func = nullptr; + Function *SetTempRet0Func = nullptr; + Function *ResumeF = nullptr; + Function *EHTypeIDF = nullptr; + Function *EmLongjmpF = nullptr; + Function *EmLongjmpJmpbufF = nullptr; + Function *SaveSetjmpF = nullptr; + Function *TestSetjmpF = nullptr; // __cxa_find_matching_catch_N functions. // Indexed by the number of clauses in an original landingpad instruction. @@ -282,11 +281,7 @@ public: static char ID; WebAssemblyLowerEmscriptenEHSjLj(bool EnableEH = true, bool EnableSjLj = true) - : ModulePass(ID), EnableEH(EnableEH), EnableSjLj(EnableSjLj), - ThrewGV(nullptr), ThrewValueGV(nullptr), GetTempRet0Func(nullptr), - SetTempRet0Func(nullptr), ResumeF(nullptr), EHTypeIDF(nullptr), - EmLongjmpF(nullptr), EmLongjmpJmpbufF(nullptr), SaveSetjmpF(nullptr), - TestSetjmpF(nullptr) { + : ModulePass(ID), EnableEH(EnableEH), EnableSjLj(EnableSjLj) { EHWhitelistSet.insert(EHWhitelist.begin(), EHWhitelist.end()); } bool runOnModule(Module &M) override; @@ -339,11 +334,12 @@ static bool canThrow(const Value *V) { // which will generate an import and asssumes that it will exist at link time. static GlobalVariable *getGlobalVariableI32(Module &M, IRBuilder<> &IRB, const char *Name) { - if (M.getNamedGlobal(Name)) - report_fatal_error(Twine("variable name is reserved: ") + Name); - return new GlobalVariable(M, IRB.getInt32Ty(), false, - GlobalValue::ExternalLinkage, nullptr, Name); + auto* GV = dyn_cast<GlobalVariable>(M.getOrInsertGlobal(Name, IRB.getInt32Ty())); + if (!GV) + report_fatal_error(Twine("unable to create global: ") + Name); + + return GV; } // Simple function name mangler. @@ -433,8 +429,8 @@ Value *WebAssemblyLowerEmscriptenEHSjLj::wrapInvoke(CallOrInvoke *CI) { // No attributes for the callee pointer. ArgAttributes.push_back(AttributeSet()); // Copy the argument attributes from the original - for (unsigned i = 0, e = CI->getNumArgOperands(); i < e; ++i) - ArgAttributes.push_back(InvokeAL.getParamAttributes(i)); + for (unsigned I = 0, E = CI->getNumArgOperands(); I < E; ++I) + ArgAttributes.push_back(InvokeAL.getParamAttributes(I)); // Reconstruct the AttributesList based on the vector we constructed. AttributeList NewCallAL = @@ -446,7 +442,8 @@ Value *WebAssemblyLowerEmscriptenEHSjLj::wrapInvoke(CallOrInvoke *CI) { // Post-invoke // %__THREW__.val = __THREW__; __THREW__ = 0; - Value *Threw = IRB.CreateLoad(ThrewGV, ThrewGV->getName() + ".val"); + Value *Threw = + IRB.CreateLoad(IRB.getInt32Ty(), ThrewGV, ThrewGV->getName() + ".val"); IRB.CreateStore(IRB.getInt32(0), ThrewGV); return Threw; } @@ -488,6 +485,13 @@ bool WebAssemblyLowerEmscriptenEHSjLj::canLongjmp(Module &M, if (CalleeF->isIntrinsic()) return false; + // Attempting to transform inline assembly will result in something like: + // call void @__invoke_void(void ()* asm ...) + // which is invalid because inline assembly blocks do not have addresses + // and can't be passed by pointer. The result is a crash with illegal IR. + if (isa<InlineAsm>(Callee)) + return false; + // The reason we include malloc/free here is to exclude the malloc/free // calls generated in setjmp prep / cleanup routines. Function *SetjmpF = M.getFunction("setjmp"); @@ -549,8 +553,8 @@ void WebAssemblyLowerEmscriptenEHSjLj::wrapTestSetjmp( BasicBlock *ElseBB1 = BasicBlock::Create(C, "if.else1", F); BasicBlock *EndBB1 = BasicBlock::Create(C, "if.end", F); Value *ThrewCmp = IRB.CreateICmpNE(Threw, IRB.getInt32(0)); - Value *ThrewValue = - IRB.CreateLoad(ThrewValueGV, ThrewValueGV->getName() + ".val"); + Value *ThrewValue = IRB.CreateLoad(IRB.getInt32Ty(), ThrewValueGV, + ThrewValueGV->getName() + ".val"); Value *ThrewValueCmp = IRB.CreateICmpNE(ThrewValue, IRB.getInt32(0)); Value *Cmp1 = IRB.CreateAnd(ThrewCmp, ThrewValueCmp, "cmp1"); IRB.CreateCondBr(Cmp1, ThenBB1, ElseBB1); @@ -562,8 +566,8 @@ void WebAssemblyLowerEmscriptenEHSjLj::wrapTestSetjmp( BasicBlock *EndBB2 = BasicBlock::Create(C, "if.end2", F); Value *ThrewInt = IRB.CreateIntToPtr(Threw, Type::getInt32PtrTy(C), Threw->getName() + ".i32p"); - Value *LoadedThrew = - IRB.CreateLoad(ThrewInt, ThrewInt->getName() + ".loaded"); + Value *LoadedThrew = IRB.CreateLoad(IRB.getInt32Ty(), ThrewInt, + ThrewInt->getName() + ".loaded"); Value *ThenLabel = IRB.CreateCall( TestSetjmpF, {LoadedThrew, SetjmpTable, SetjmpTableSize}, "label"); Value *Cmp2 = IRB.CreateICmpEQ(ThenLabel, IRB.getInt32(0)); @@ -606,11 +610,11 @@ void WebAssemblyLowerEmscriptenEHSjLj::rebuildSSA(Function &F) { ++UI; SSA.Initialize(I.getType(), I.getName()); SSA.AddAvailableValue(&BB, &I); - Instruction *User = cast<Instruction>(U.getUser()); + auto *User = cast<Instruction>(U.getUser()); if (User->getParent() == &BB) continue; - if (PHINode *UserPN = dyn_cast<PHINode>(User)) + if (auto *UserPN = dyn_cast<PHINode>(User)) if (UserPN->getIncomingBlock(U) == &BB) continue; @@ -769,7 +773,8 @@ bool WebAssemblyLowerEmscriptenEHSjLj::runEHOnFunction(Function &F) { // This can't throw, and we don't need this invoke, just replace it with a // call+branch SmallVector<Value *, 16> Args(II->arg_begin(), II->arg_end()); - CallInst *NewCall = IRB.CreateCall(II->getCalledValue(), Args); + CallInst *NewCall = + IRB.CreateCall(II->getFunctionType(), II->getCalledValue(), Args); NewCall->takeName(II); NewCall->setCallingConv(II->getCallingConv()); NewCall->setDebugLoc(II->getDebugLoc()); @@ -836,15 +841,15 @@ bool WebAssemblyLowerEmscriptenEHSjLj::runEHOnFunction(Function &F) { for (LandingPadInst *LPI : LandingPads) { IRB.SetInsertPoint(LPI); SmallVector<Value *, 16> FMCArgs; - for (unsigned i = 0, e = LPI->getNumClauses(); i < e; ++i) { - Constant *Clause = LPI->getClause(i); + for (unsigned I = 0, E = LPI->getNumClauses(); I < E; ++I) { + Constant *Clause = LPI->getClause(I); // As a temporary workaround for the lack of aggregate varargs support // in the interface between JS and wasm, break out filter operands into // their component elements. - if (LPI->isFilter(i)) { + if (LPI->isFilter(I)) { auto *ATy = cast<ArrayType>(Clause->getType()); - for (unsigned j = 0, e = ATy->getNumElements(); j < e; ++j) { - Value *EV = IRB.CreateExtractValue(Clause, makeArrayRef(j), "filter"); + for (unsigned J = 0, E = ATy->getNumElements(); J < E; ++J) { + Value *EV = IRB.CreateExtractValue(Clause, makeArrayRef(J), "filter"); FMCArgs.push_back(EV); } } else @@ -954,8 +959,8 @@ bool WebAssemblyLowerEmscriptenEHSjLj::runSjLjOnFunction(Function &F) { BBs.push_back(&BB); // BBs.size() will change within the loop, so we query it every time - for (unsigned i = 0; i < BBs.size(); i++) { - BasicBlock *BB = BBs[i]; + for (unsigned I = 0; I < BBs.size(); I++) { + BasicBlock *BB = BBs[I]; for (Instruction &I : *BB) { assert(!isa<InvokeInst>(&I)); auto *CI = dyn_cast<CallInst>(&I); @@ -1028,9 +1033,9 @@ bool WebAssemblyLowerEmscriptenEHSjLj::runSjLjOnFunction(Function &F) { // switch case). 0 means a longjmp that is not ours to handle, needs a // rethrow. Otherwise the index is the same as the index in P+1 (to avoid // 0). - for (unsigned i = 0; i < SetjmpRetPHIs.size(); i++) { - SI->addCase(IRB.getInt32(i + 1), SetjmpRetPHIs[i]->getParent()); - SetjmpRetPHIs[i]->addIncoming(LongjmpResult, EndBB); + for (unsigned I = 0; I < SetjmpRetPHIs.size(); I++) { + SI->addCase(IRB.getInt32(I + 1), SetjmpRetPHIs[I]->getParent()); + SetjmpRetPHIs[I]->addIncoming(LongjmpResult, EndBB); } // We are splitting the block here, and must continue to find other calls @@ -1077,7 +1082,7 @@ bool WebAssemblyLowerEmscriptenEHSjLj::runSjLjOnFunction(Function &F) { Use &U = *UI; // Increment the iterator before removing the use from the list. ++UI; - if (Instruction *I = dyn_cast<Instruction>(U.getUser())) + if (auto *I = dyn_cast<Instruction>(U.getUser())) if (I->getParent() != &EntryBB) SetjmpTableSSA.RewriteUse(U); } @@ -1085,7 +1090,7 @@ bool WebAssemblyLowerEmscriptenEHSjLj::runSjLjOnFunction(Function &F) { UI != UE;) { Use &U = *UI; ++UI; - if (Instruction *I = dyn_cast<Instruction>(U.getUser())) + if (auto *I = dyn_cast<Instruction>(U.getUser())) if (I->getParent() != &EntryBB) SetjmpTableSizeSSA.RewriteUse(U); } |