14934f76bSHeejin Ahn //=== WebAssemblyLateEHPrepare.cpp - WebAssembly Exception Preparation -===//
24934f76bSHeejin Ahn //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
64934f76bSHeejin Ahn //
74934f76bSHeejin Ahn //===----------------------------------------------------------------------===//
84934f76bSHeejin Ahn ///
94934f76bSHeejin Ahn /// \file
104934f76bSHeejin Ahn /// \brief Does various transformations for exception handling.
114934f76bSHeejin Ahn ///
124934f76bSHeejin Ahn //===----------------------------------------------------------------------===//
134934f76bSHeejin Ahn 
144934f76bSHeejin Ahn #include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
150b2bc69bSHeejin Ahn #include "Utils/WebAssemblyUtilities.h"
164934f76bSHeejin Ahn #include "WebAssembly.h"
174934f76bSHeejin Ahn #include "WebAssemblySubtarget.h"
184e4df1e3SHeejin Ahn #include "llvm/ADT/SmallPtrSet.h"
19989f1c72Sserge-sans-paille #include "llvm/CodeGen/MachineFunctionPass.h"
204934f76bSHeejin Ahn #include "llvm/CodeGen/MachineInstrBuilder.h"
214934f76bSHeejin Ahn #include "llvm/CodeGen/WasmEHFuncInfo.h"
224934f76bSHeejin Ahn #include "llvm/MC/MCAsmInfo.h"
23904cd3e0SReid Kleckner #include "llvm/Support/Debug.h"
24fe0006c8SSimon Pilgrim #include "llvm/Target/TargetMachine.h"
254934f76bSHeejin Ahn using namespace llvm;
264934f76bSHeejin Ahn 
278b49b6beSHeejin Ahn #define DEBUG_TYPE "wasm-late-eh-prepare"
284934f76bSHeejin Ahn 
294934f76bSHeejin Ahn namespace {
304934f76bSHeejin Ahn class WebAssemblyLateEHPrepare final : public MachineFunctionPass {
getPassName() const314934f76bSHeejin Ahn   StringRef getPassName() const override {
32d6f48786SHeejin Ahn     return "WebAssembly Late Prepare Exception";
334934f76bSHeejin Ahn   }
344934f76bSHeejin Ahn 
354934f76bSHeejin Ahn   bool runOnMachineFunction(MachineFunction &MF) override;
364e4df1e3SHeejin Ahn   bool removeUnreachableEHPads(MachineFunction &MF);
374cd3f4b3SHeejin Ahn   void recordCatchRetBBs(MachineFunction &MF);
389e4eadebSHeejin Ahn   bool hoistCatches(MachineFunction &MF);
399e4eadebSHeejin Ahn   bool addCatchAlls(MachineFunction &MF);
40b47a18cdSHeejin Ahn   bool replaceFuncletReturns(MachineFunction &MF);
41b47a18cdSHeejin Ahn   bool removeUnnecessaryUnreachables(MachineFunction &MF);
420bb98650SHeejin Ahn   bool restoreStackPointer(MachineFunction &MF);
434934f76bSHeejin Ahn 
444cd3f4b3SHeejin Ahn   MachineBasicBlock *getMatchingEHPad(MachineInstr *MI);
454e4df1e3SHeejin Ahn   SmallPtrSet<MachineBasicBlock *, 8> CatchRetBBs;
464cd3f4b3SHeejin Ahn 
474934f76bSHeejin Ahn public:
484934f76bSHeejin Ahn   static char ID; // Pass identification, replacement for typeid
WebAssemblyLateEHPrepare()494934f76bSHeejin Ahn   WebAssemblyLateEHPrepare() : MachineFunctionPass(ID) {}
504934f76bSHeejin Ahn };
514934f76bSHeejin Ahn } // end anonymous namespace
524934f76bSHeejin Ahn 
534934f76bSHeejin Ahn char WebAssemblyLateEHPrepare::ID = 0;
544934f76bSHeejin Ahn INITIALIZE_PASS(WebAssemblyLateEHPrepare, DEBUG_TYPE,
55a93e7261SHeejin Ahn                 "WebAssembly Late Exception Preparation", false, false)
564934f76bSHeejin Ahn 
createWebAssemblyLateEHPrepare()574934f76bSHeejin Ahn FunctionPass *llvm::createWebAssemblyLateEHPrepare() {
584934f76bSHeejin Ahn   return new WebAssemblyLateEHPrepare();
594934f76bSHeejin Ahn }
604934f76bSHeejin Ahn 
614934f76bSHeejin Ahn // Returns the nearest EH pad that dominates this instruction. This does not use
624934f76bSHeejin Ahn // dominator analysis; it just does BFS on its predecessors until arriving at an
634934f76bSHeejin Ahn // EH pad. This assumes valid EH scopes so the first EH pad it arrives in all
644934f76bSHeejin Ahn // possible search paths should be the same.
654934f76bSHeejin Ahn // Returns nullptr in case it does not find any EH pad in the search, or finds
664934f76bSHeejin Ahn // multiple different EH pads.
674cd3f4b3SHeejin Ahn MachineBasicBlock *
getMatchingEHPad(MachineInstr * MI)684cd3f4b3SHeejin Ahn WebAssemblyLateEHPrepare::getMatchingEHPad(MachineInstr *MI) {
694934f76bSHeejin Ahn   MachineFunction *MF = MI->getParent()->getParent();
704934f76bSHeejin Ahn   SmallVector<MachineBasicBlock *, 2> WL;
714934f76bSHeejin Ahn   SmallPtrSet<MachineBasicBlock *, 2> Visited;
724934f76bSHeejin Ahn   WL.push_back(MI->getParent());
734934f76bSHeejin Ahn   MachineBasicBlock *EHPad = nullptr;
744934f76bSHeejin Ahn   while (!WL.empty()) {
754934f76bSHeejin Ahn     MachineBasicBlock *MBB = WL.pop_back_val();
76*b254d671SKazu Hirata     if (!Visited.insert(MBB).second)
774934f76bSHeejin Ahn       continue;
784934f76bSHeejin Ahn     if (MBB->isEHPad()) {
794934f76bSHeejin Ahn       if (EHPad && EHPad != MBB)
804934f76bSHeejin Ahn         return nullptr;
814934f76bSHeejin Ahn       EHPad = MBB;
824934f76bSHeejin Ahn       continue;
834934f76bSHeejin Ahn     }
844934f76bSHeejin Ahn     if (MBB == &MF->front())
854934f76bSHeejin Ahn       return nullptr;
864cd3f4b3SHeejin Ahn     for (auto *Pred : MBB->predecessors())
874cd3f4b3SHeejin Ahn       if (!CatchRetBBs.count(Pred)) // We don't go into child scopes
884cd3f4b3SHeejin Ahn         WL.push_back(Pred);
894934f76bSHeejin Ahn   }
904934f76bSHeejin Ahn   return EHPad;
914934f76bSHeejin Ahn }
924934f76bSHeejin Ahn 
93095796a3SHeejin Ahn // Erase the specified BBs if the BB does not have any remaining predecessors,
94095796a3SHeejin Ahn // and also all its dead children.
9583996e4dSBenjamin Kramer template <typename Container>
eraseDeadBBsAndChildren(const Container & MBBs)96095796a3SHeejin Ahn static void eraseDeadBBsAndChildren(const Container &MBBs) {
9783996e4dSBenjamin Kramer   SmallVector<MachineBasicBlock *, 8> WL(MBBs.begin(), MBBs.end());
984e4df1e3SHeejin Ahn   SmallPtrSet<MachineBasicBlock *, 8> Deleted;
994934f76bSHeejin Ahn   while (!WL.empty()) {
1004934f76bSHeejin Ahn     MachineBasicBlock *MBB = WL.pop_back_val();
1014e4df1e3SHeejin Ahn     if (Deleted.count(MBB) || !MBB->pred_empty())
102095796a3SHeejin Ahn       continue;
1030e219b64SKazu Hirata     SmallVector<MachineBasicBlock *, 4> Succs(MBB->successors());
104b68d5914SHeejin Ahn     WL.append(MBB->succ_begin(), MBB->succ_end());
105b68d5914SHeejin Ahn     for (auto *Succ : Succs)
1064934f76bSHeejin Ahn       MBB->removeSuccessor(Succ);
1074e4df1e3SHeejin Ahn     // To prevent deleting the same BB multiple times, which can happen when
1084e4df1e3SHeejin Ahn     // 'MBBs' contain both a parent and a child
1094e4df1e3SHeejin Ahn     Deleted.insert(MBB);
1104934f76bSHeejin Ahn     MBB->eraseFromParent();
1114934f76bSHeejin Ahn   }
1124934f76bSHeejin Ahn }
1134934f76bSHeejin Ahn 
runOnMachineFunction(MachineFunction & MF)1144934f76bSHeejin Ahn bool WebAssemblyLateEHPrepare::runOnMachineFunction(MachineFunction &MF) {
115569f0909SHeejin Ahn   LLVM_DEBUG(dbgs() << "********** Late EH Prepare **********\n"
116569f0909SHeejin Ahn                        "********** Function: "
117569f0909SHeejin Ahn                     << MF.getName() << '\n');
118569f0909SHeejin Ahn 
1194934f76bSHeejin Ahn   if (MF.getTarget().getMCAsmInfo()->getExceptionHandlingType() !=
1204934f76bSHeejin Ahn       ExceptionHandling::Wasm)
1214934f76bSHeejin Ahn     return false;
1224934f76bSHeejin Ahn 
1234934f76bSHeejin Ahn   bool Changed = false;
124b47a18cdSHeejin Ahn   if (MF.getFunction().hasPersonalityFn()) {
1254e4df1e3SHeejin Ahn     Changed |= removeUnreachableEHPads(MF);
1264cd3f4b3SHeejin Ahn     recordCatchRetBBs(MF);
1279e4eadebSHeejin Ahn     Changed |= hoistCatches(MF);
1289e4eadebSHeejin Ahn     Changed |= addCatchAlls(MF);
129b47a18cdSHeejin Ahn     Changed |= replaceFuncletReturns(MF);
130b47a18cdSHeejin Ahn   }
131b47a18cdSHeejin Ahn   Changed |= removeUnnecessaryUnreachables(MF);
1329e4eadebSHeejin Ahn   if (MF.getFunction().hasPersonalityFn())
1330bb98650SHeejin Ahn     Changed |= restoreStackPointer(MF);
1344934f76bSHeejin Ahn   return Changed;
1354934f76bSHeejin Ahn }
1364934f76bSHeejin Ahn 
1374e4df1e3SHeejin Ahn // Remove unreachable EH pads and its children. If they remain, CFG
1384e4df1e3SHeejin Ahn // stackification can be tricky.
removeUnreachableEHPads(MachineFunction & MF)1394e4df1e3SHeejin Ahn bool WebAssemblyLateEHPrepare::removeUnreachableEHPads(MachineFunction &MF) {
1404e4df1e3SHeejin Ahn   SmallVector<MachineBasicBlock *, 4> ToDelete;
1414e4df1e3SHeejin Ahn   for (auto &MBB : MF)
1424e4df1e3SHeejin Ahn     if (MBB.isEHPad() && MBB.pred_empty())
1434e4df1e3SHeejin Ahn       ToDelete.push_back(&MBB);
1444e4df1e3SHeejin Ahn   eraseDeadBBsAndChildren(ToDelete);
1454e4df1e3SHeejin Ahn   return !ToDelete.empty();
1464e4df1e3SHeejin Ahn }
1474e4df1e3SHeejin Ahn 
1484e4df1e3SHeejin Ahn // Record which BB ends with catchret instruction, because this will be replaced
1494e4df1e3SHeejin Ahn // with 'br's later. This set of catchret BBs is necessary in 'getMatchingEHPad'
1504e4df1e3SHeejin Ahn // function.
recordCatchRetBBs(MachineFunction & MF)1514cd3f4b3SHeejin Ahn void WebAssemblyLateEHPrepare::recordCatchRetBBs(MachineFunction &MF) {
1524cd3f4b3SHeejin Ahn   CatchRetBBs.clear();
1534cd3f4b3SHeejin Ahn   for (auto &MBB : MF) {
1544cd3f4b3SHeejin Ahn     auto Pos = MBB.getFirstTerminator();
1554cd3f4b3SHeejin Ahn     if (Pos == MBB.end())
1564cd3f4b3SHeejin Ahn       continue;
1574cd3f4b3SHeejin Ahn     MachineInstr *TI = &*Pos;
1584cd3f4b3SHeejin Ahn     if (TI->getOpcode() == WebAssembly::CATCHRET)
1594cd3f4b3SHeejin Ahn       CatchRetBBs.insert(&MBB);
1604cd3f4b3SHeejin Ahn   }
1614cd3f4b3SHeejin Ahn }
1624cd3f4b3SHeejin Ahn 
1639e4eadebSHeejin Ahn // Hoist catch instructions to the beginning of their matching EH pad BBs in
1649e4eadebSHeejin Ahn // case,
1659e4eadebSHeejin Ahn // (1) catch instruction is not the first instruction in EH pad.
1669e4eadebSHeejin Ahn // ehpad:
1679e4eadebSHeejin Ahn //   some_other_instruction
1689e4eadebSHeejin Ahn //   ...
1699e4eadebSHeejin Ahn //   %exn = catch 0
1709e4eadebSHeejin Ahn // (2) catch instruction is in a non-EH pad BB. For example,
1719e4eadebSHeejin Ahn // ehpad:
1729e4eadebSHeejin Ahn //   br bb0
1739e4eadebSHeejin Ahn // bb0:
1749e4eadebSHeejin Ahn //   %exn = catch 0
hoistCatches(MachineFunction & MF)1759e4eadebSHeejin Ahn bool WebAssemblyLateEHPrepare::hoistCatches(MachineFunction &MF) {
1769e4eadebSHeejin Ahn   bool Changed = false;
1779e4eadebSHeejin Ahn   SmallVector<MachineInstr *, 16> Catches;
1789e4eadebSHeejin Ahn   for (auto &MBB : MF)
1799e4eadebSHeejin Ahn     for (auto &MI : MBB)
1809e4eadebSHeejin Ahn       if (WebAssembly::isCatch(MI.getOpcode()))
1819e4eadebSHeejin Ahn         Catches.push_back(&MI);
1829e4eadebSHeejin Ahn 
1839e4eadebSHeejin Ahn   for (auto *Catch : Catches) {
1849e4eadebSHeejin Ahn     MachineBasicBlock *EHPad = getMatchingEHPad(Catch);
1859e4eadebSHeejin Ahn     assert(EHPad && "No matching EH pad for catch");
1869e4eadebSHeejin Ahn     auto InsertPos = EHPad->begin();
1879e4eadebSHeejin Ahn     // Skip EH_LABELs in the beginning of an EH pad if present. We don't use
1889e4eadebSHeejin Ahn     // these labels at the moment, but other targets also seem to have an
1899e4eadebSHeejin Ahn     // EH_LABEL instruction in the beginning of an EH pad.
1909e4eadebSHeejin Ahn     while (InsertPos != EHPad->end() && InsertPos->isEHLabel())
1919e4eadebSHeejin Ahn       InsertPos++;
1929e4eadebSHeejin Ahn     if (InsertPos == Catch)
1939e4eadebSHeejin Ahn       continue;
1949e4eadebSHeejin Ahn     Changed = true;
1959e4eadebSHeejin Ahn     EHPad->insert(InsertPos, Catch->removeFromParent());
1969e4eadebSHeejin Ahn   }
1979e4eadebSHeejin Ahn   return Changed;
1989e4eadebSHeejin Ahn }
1999e4eadebSHeejin Ahn 
2009e4eadebSHeejin Ahn // Add catch_all to beginning of cleanup pads.
addCatchAlls(MachineFunction & MF)2019e4eadebSHeejin Ahn bool WebAssemblyLateEHPrepare::addCatchAlls(MachineFunction &MF) {
202095796a3SHeejin Ahn   bool Changed = false;
203b47a18cdSHeejin Ahn   const auto &TII = *MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo();
2049e4eadebSHeejin Ahn 
205095796a3SHeejin Ahn   for (auto &MBB : MF) {
2069e4eadebSHeejin Ahn     if (!MBB.isEHPad())
2079e4eadebSHeejin Ahn       continue;
208b47a18cdSHeejin Ahn     auto InsertPos = MBB.begin();
2099e4eadebSHeejin Ahn     // Skip EH_LABELs in the beginning of an EH pad if present.
2109e4eadebSHeejin Ahn     while (InsertPos != MBB.end() && InsertPos->isEHLabel())
2119e4eadebSHeejin Ahn       InsertPos++;
2129e4eadebSHeejin Ahn     // This runs after hoistCatches(), so we assume that if there is a catch,
2136f2999b3SHeejin Ahn     // that should be the first non-EH-label instruction in an EH pad.
2149e4eadebSHeejin Ahn     if (InsertPos == MBB.end() ||
2159e4eadebSHeejin Ahn         !WebAssembly::isCatch(InsertPos->getOpcode())) {
2169e4eadebSHeejin Ahn       Changed = true;
217dcfec279SHeejin Ahn       BuildMI(MBB, InsertPos,
218dcfec279SHeejin Ahn               InsertPos == MBB.end() ? DebugLoc() : InsertPos->getDebugLoc(),
2199e4eadebSHeejin Ahn               TII.get(WebAssembly::CATCH_ALL));
220095796a3SHeejin Ahn     }
221095796a3SHeejin Ahn   }
222095796a3SHeejin Ahn   return Changed;
223095796a3SHeejin Ahn }
224095796a3SHeejin Ahn 
2254e4df1e3SHeejin Ahn // Replace pseudo-instructions catchret and cleanupret with br and rethrow
2264e4df1e3SHeejin Ahn // respectively.
replaceFuncletReturns(MachineFunction & MF)2274934f76bSHeejin Ahn bool WebAssemblyLateEHPrepare::replaceFuncletReturns(MachineFunction &MF) {
2284934f76bSHeejin Ahn   bool Changed = false;
2294934f76bSHeejin Ahn   const auto &TII = *MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo();
2304934f76bSHeejin Ahn 
2314934f76bSHeejin Ahn   for (auto &MBB : MF) {
2324934f76bSHeejin Ahn     auto Pos = MBB.getFirstTerminator();
2334934f76bSHeejin Ahn     if (Pos == MBB.end())
2344934f76bSHeejin Ahn       continue;
2354934f76bSHeejin Ahn     MachineInstr *TI = &*Pos;
2364934f76bSHeejin Ahn 
2374934f76bSHeejin Ahn     switch (TI->getOpcode()) {
2384934f76bSHeejin Ahn     case WebAssembly::CATCHRET: {
2394934f76bSHeejin Ahn       // Replace a catchret with a branch
2404934f76bSHeejin Ahn       MachineBasicBlock *TBB = TI->getOperand(0).getMBB();
2414934f76bSHeejin Ahn       if (!MBB.isLayoutSuccessor(TBB))
2424934f76bSHeejin Ahn         BuildMI(MBB, TI, TI->getDebugLoc(), TII.get(WebAssembly::BR))
2434934f76bSHeejin Ahn             .addMBB(TBB);
2444934f76bSHeejin Ahn       TI->eraseFromParent();
2454934f76bSHeejin Ahn       Changed = true;
2464934f76bSHeejin Ahn       break;
2474934f76bSHeejin Ahn     }
2489e4eadebSHeejin Ahn     case WebAssembly::CLEANUPRET: {
2499e4eadebSHeejin Ahn       // Replace a cleanupret with a rethrow. For C++ support, currently
2509e4eadebSHeejin Ahn       // rethrow's immediate argument is always 0 (= the latest exception).
25166ce4194SHeejin Ahn       BuildMI(MBB, TI, TI->getDebugLoc(), TII.get(WebAssembly::RETHROW))
2529e4eadebSHeejin Ahn           .addImm(0);
2534934f76bSHeejin Ahn       TI->eraseFromParent();
2544934f76bSHeejin Ahn       Changed = true;
2554934f76bSHeejin Ahn       break;
2564934f76bSHeejin Ahn     }
2574934f76bSHeejin Ahn     }
2584934f76bSHeejin Ahn   }
2594934f76bSHeejin Ahn   return Changed;
2604934f76bSHeejin Ahn }
2614934f76bSHeejin Ahn 
2624e4df1e3SHeejin Ahn // Remove unnecessary unreachables after a throw or rethrow.
removeUnnecessaryUnreachables(MachineFunction & MF)263b47a18cdSHeejin Ahn bool WebAssemblyLateEHPrepare::removeUnnecessaryUnreachables(
264b47a18cdSHeejin Ahn     MachineFunction &MF) {
2654934f76bSHeejin Ahn   bool Changed = false;
2664934f76bSHeejin Ahn   for (auto &MBB : MF) {
267b47a18cdSHeejin Ahn     for (auto &MI : MBB) {
268b47a18cdSHeejin Ahn       if (MI.getOpcode() != WebAssembly::THROW &&
269b47a18cdSHeejin Ahn           MI.getOpcode() != WebAssembly::RETHROW)
270b47a18cdSHeejin Ahn         continue;
2714934f76bSHeejin Ahn       Changed = true;
272b47a18cdSHeejin Ahn 
273b47a18cdSHeejin Ahn       // The instruction after the throw should be an unreachable or a branch to
274b47a18cdSHeejin Ahn       // another BB that should eventually lead to an unreachable. Delete it
275b47a18cdSHeejin Ahn       // because throw itself is a terminator, and also delete successors if
276b47a18cdSHeejin Ahn       // any.
277b47a18cdSHeejin Ahn       MBB.erase(std::next(MI.getIterator()), MBB.end());
2780e219b64SKazu Hirata       SmallVector<MachineBasicBlock *, 8> Succs(MBB.successors());
279b47a18cdSHeejin Ahn       for (auto *Succ : Succs)
28066ce4194SHeejin Ahn         if (!Succ->isEHPad())
281b47a18cdSHeejin Ahn           MBB.removeSuccessor(Succ);
282b47a18cdSHeejin Ahn       eraseDeadBBsAndChildren(Succs);
2834934f76bSHeejin Ahn     }
2844934f76bSHeejin Ahn   }
285b47a18cdSHeejin Ahn 
2864934f76bSHeejin Ahn   return Changed;
2874934f76bSHeejin Ahn }
2884934f76bSHeejin Ahn 
2890bb98650SHeejin Ahn // After the stack is unwound due to a thrown exception, the __stack_pointer
2900bb98650SHeejin Ahn // global can point to an invalid address. This inserts instructions that
2910bb98650SHeejin Ahn // restore __stack_pointer global.
restoreStackPointer(MachineFunction & MF)2920bb98650SHeejin Ahn bool WebAssemblyLateEHPrepare::restoreStackPointer(MachineFunction &MF) {
2930bb98650SHeejin Ahn   const auto *FrameLowering = static_cast<const WebAssemblyFrameLowering *>(
2940bb98650SHeejin Ahn       MF.getSubtarget().getFrameLowering());
2950bb98650SHeejin Ahn   if (!FrameLowering->needsPrologForEH(MF))
2960bb98650SHeejin Ahn     return false;
2970bb98650SHeejin Ahn   bool Changed = false;
2980bb98650SHeejin Ahn 
2990bb98650SHeejin Ahn   for (auto &MBB : MF) {
3000bb98650SHeejin Ahn     if (!MBB.isEHPad())
3010bb98650SHeejin Ahn       continue;
3020bb98650SHeejin Ahn     Changed = true;
3030bb98650SHeejin Ahn 
3040bb98650SHeejin Ahn     // Insert __stack_pointer restoring instructions at the beginning of each EH
3050bb98650SHeejin Ahn     // pad, after the catch instruction. Here it is safe to assume that SP32
3060bb98650SHeejin Ahn     // holds the latest value of __stack_pointer, because the only exception for
3070bb98650SHeejin Ahn     // this case is when a function uses the red zone, but that only happens
3080bb98650SHeejin Ahn     // with leaf functions, and we don't restore __stack_pointer in leaf
3090bb98650SHeejin Ahn     // functions anyway.
3100bb98650SHeejin Ahn     auto InsertPos = MBB.begin();
3116f2999b3SHeejin Ahn     // Skip EH_LABELs in the beginning of an EH pad if present.
3126f2999b3SHeejin Ahn     while (InsertPos != MBB.end() && InsertPos->isEHLabel())
3136f2999b3SHeejin Ahn       InsertPos++;
3146f2999b3SHeejin Ahn     assert(InsertPos != MBB.end() &&
3156f2999b3SHeejin Ahn            WebAssembly::isCatch(InsertPos->getOpcode()) &&
3166f2999b3SHeejin Ahn            "catch/catch_all should be present in every EH pad at this point");
3176f2999b3SHeejin Ahn     ++InsertPos; // Skip the catch instruction
318b9a539c0SWouter van Oortmerssen     FrameLowering->writeSPToGlobal(FrameLowering->getSPReg(MF), MF, MBB,
319b9a539c0SWouter van Oortmerssen                                    InsertPos, MBB.begin()->getDebugLoc());
3200bb98650SHeejin Ahn   }
3210bb98650SHeejin Ahn   return Changed;
3220bb98650SHeejin Ahn }
323