84 #include "llvm/IR/IntrinsicsWebAssembly.h"
90 #define DEBUG_TYPE "wasmehprepare"
94 Type *LPadContextTy =
nullptr;
98 Value *LPadIndexField =
nullptr;
99 Value *LSDAField =
nullptr;
100 Value *SelectorField =
nullptr;
119 bool doInitialization(
Module &
M)
override;
123 return "WebAssembly Exception handling preparation";
130 "Prepare WebAssembly exceptions",
false,
false)
136 bool WasmEHPrepare::doInitialization(
Module &M) {
147 template <
typename Container>
150 while (!WL.empty()) {
160 bool Changed =
false;
161 Changed |= prepareThrows(
F);
162 Changed |= prepareEHPads(
F);
166 bool WasmEHPrepare::prepareThrows(
Function &
F) {
169 bool Changed =
false;
179 auto *ThrowI = cast<CallInst>(U);
180 if (ThrowI->getFunction() != &
F)
183 auto *
BB = ThrowI->getParent();
185 auto &InstList =
BB->getInstList();
187 IRB.SetInsertPoint(
BB);
188 IRB.CreateUnreachable();
195 bool WasmEHPrepare::prepareEHPads(
Function &
F) {
204 auto *Pad =
BB.getFirstNonPHI();
205 if (isa<CatchPadInst>(Pad))
206 CatchPads.push_back(&
BB);
207 else if (isa<CleanupPadInst>(Pad))
208 CleanupPads.push_back(&
BB);
210 if (CatchPads.empty() && CleanupPads.empty())
213 assert(
F.hasPersonalityFn() &&
"Personality function not found");
220 LPadContextGV = cast<GlobalVariable>(
221 M.getOrInsertGlobal(
"__wasm_lpad_context", LPadContextTy));
224 LPadIndexField = IRB.CreateConstGEP2_32(LPadContextTy, LPadContextGV, 0, 0,
227 IRB.CreateConstGEP2_32(LPadContextTy, LPadContextGV, 0, 1,
"lsda_gep");
228 SelectorField = IRB.CreateConstGEP2_32(LPadContextTy, LPadContextGV, 0, 2,
246 CallPersonalityF =
M.getOrInsertFunction(
247 "_Unwind_CallPersonality", IRB.getInt32Ty(), IRB.getInt8PtrTy());
248 if (
Function *
F = dyn_cast<Function>(CallPersonalityF.getCallee()))
249 F->setDoesNotThrow();
252 for (
auto *
BB : CatchPads) {
253 auto *CPI = cast<CatchPadInst>(
BB->getFirstNonPHI());
256 if (CPI->getNumArgOperands() == 1 &&
257 cast<Constant>(CPI->getArgOperand(0))->isNullValue())
258 prepareEHPad(
BB,
false);
260 prepareEHPad(
BB,
true,
Index++);
264 for (
auto *
BB : CleanupPads)
265 prepareEHPad(
BB,
false);
272 void WasmEHPrepare::prepareEHPad(
BasicBlock *
BB,
bool NeedPersonality,
274 assert(
BB->isEHPad() &&
"BB is not an EHPad!");
276 IRB.SetInsertPoint(&*
BB->getFirstInsertionPt());
278 auto *FPI = cast<FuncletPadInst>(
BB->getFirstNonPHI());
279 Instruction *GetExnCI =
nullptr, *GetSelectorCI =
nullptr;
280 for (
auto &U : FPI->uses()) {
281 if (
auto *CI = dyn_cast<CallInst>(U.getUser())) {
282 if (CI->getCalledOperand() == GetExnF)
284 if (CI->getCalledOperand() == GetSelectorF)
293 "wasm.get.ehselector() cannot exist w/o wasm.get.exception()");
308 if (!NeedPersonality) {
310 assert(GetSelectorCI->use_empty() &&
311 "wasm.get.ehselector() still has uses!");
312 GetSelectorCI->eraseFromParent();
321 IRB.CreateCall(LPadIndexF, {FPI, IRB.getInt32(
Index)});
324 IRB.CreateStore(IRB.getInt32(
Index), LPadIndexField);
326 auto *CPI = cast<CatchPadInst>(FPI);
331 IRB.CreateStore(IRB.CreateCall(LSDAF), LSDAField);
334 CallInst *PersCI = IRB.CreateCall(CallPersonalityF, CatchCI,
340 IRB.CreateLoad(IRB.getInt32Ty(), SelectorField,
"selector");
344 assert(GetSelectorCI &&
"wasm.get.ehselector() call does not exist");
345 GetSelectorCI->replaceAllUsesWith(Selector);
346 GetSelectorCI->eraseFromParent();
354 for (
const auto &
BB : *
F) {
359 if (
const auto *CatchPad = dyn_cast<CatchPadInst>(Pad)) {
360 const auto *UnwindBB = CatchPad->getCatchSwitch()->getUnwindDest();
363 const Instruction *UnwindPad = UnwindBB->getFirstNonPHI();
364 if (
const auto *CatchSwitch = dyn_cast<CatchSwitchInst>(UnwindPad))