27#define DEBUG_TYPE "wasm-late-eh-prepare"
32 return "WebAssembly Late Prepare Exception";
54char WebAssemblyLateEHPrepare::ID = 0;
56 "WebAssembly Late Exception Preparation",
false,
false)
59 return new WebAssemblyLateEHPrepare();
80 if (EHPad && EHPad !=
MBB)
88 if (!CatchRetBBs.count(Pred))
96template <
typename Container>
100 while (!WL.
empty()) {
106 for (
auto *Succ : Succs)
115bool WebAssemblyLateEHPrepare::runOnMachineFunction(
MachineFunction &MF) {
117 "********** Function: "
121 ExceptionHandling::Wasm)
124 bool Changed =
false;
126 Changed |= removeUnreachableEHPads(MF);
127 recordCatchRetBBs(MF);
128 Changed |= hoistCatches(MF);
129 Changed |= addCatchAlls(MF);
130 Changed |= replaceFuncletReturns(MF);
132 Changed |= addCatchRefsAndThrowRefs(MF);
134 Changed |= removeUnnecessaryUnreachables(MF);
136 Changed |= restoreStackPointer(MF);
142bool WebAssemblyLateEHPrepare::removeUnreachableEHPads(
MachineFunction &MF) {
148 return !ToDelete.
empty();
156 for (
auto &
MBB : MF) {
161 if (TI->
getOpcode() == WebAssembly::CATCHRET)
179 bool Changed =
false;
186 for (
auto *
Catch : Catches) {
188 assert(EHPad &&
"No matching EH pad for catch");
189 auto InsertPos = EHPad->
begin();
193 while (InsertPos != EHPad->
end() && InsertPos->isEHLabel())
195 if (InsertPos ==
Catch)
198 EHPad->
insert(InsertPos,
Catch->removeFromParent());
205 bool Changed =
false;
208 for (
auto &
MBB : MF) {
213 while (InsertPos !=
MBB.
end() && InsertPos->isEHLabel())
217 if (InsertPos ==
MBB.
end() ||
221 ? WebAssembly::CATCH_ALL
222 : WebAssembly::CATCH_ALL_LEGACY;
225 TII.get(CatchAllOpcode));
233bool WebAssemblyLateEHPrepare::replaceFuncletReturns(
MachineFunction &MF) {
234 bool Changed =
false;
237 for (
auto &
MBB : MF) {
244 case WebAssembly::CATCHRET: {
254 case WebAssembly::RETHROW:
277 case WebAssembly::CLEANUPRET: {
298bool WebAssemblyLateEHPrepare::addCatchRefsAndThrowRefs(
MachineFunction &MF) {
306 if (
MI.getOpcode() == WebAssembly::RETHROW)
307 EHPadToRethrows[
MI.getOperand(0).getMBB()].push_back(&
MI);
308 if (EHPadToRethrows.
empty())
313 for (
auto &[EHPad, Rethrows] : EHPadToRethrows) {
315 auto *InsertPos =
Catch->getIterator()->getNextNode();
316 auto ExnReg =
MRI.createVirtualRegister(&WebAssembly::EXNREFRegClass);
317 if (
Catch->getOpcode() == WebAssembly::CATCH) {
319 TII.get(WebAssembly::CATCH_REF));
321 for (
const auto &Def :
Catch->defs())
326 for (
const auto &
Use :
Catch->uses()) {
330 }
else if (
Catch->getOpcode() == WebAssembly::CATCH_ALL) {
332 TII.get(WebAssembly::CATCH_ALL_REF))
337 Catch->eraseFromParent();
339 for (
auto *Rethrow : Rethrows) {
340 auto InsertPos = std::next(Rethrow->getIterator());
341 BuildMI(*Rethrow->getParent(), InsertPos, Rethrow->getDebugLoc(),
342 TII.get(WebAssembly::THROW_REF))
352bool WebAssemblyLateEHPrepare::removeUnnecessaryUnreachables(
354 bool Changed =
false;
355 for (
auto &
MBB : MF) {
356 for (
auto &
MI :
MBB) {
357 if (
MI.getOpcode() != WebAssembly::THROW &&
358 MI.getOpcode() != WebAssembly::RETHROW &&
359 MI.getOpcode() != WebAssembly::THROW_REF)
369 for (
auto *Succ : Succs)
370 if (!Succ->isEHPad())
382bool WebAssemblyLateEHPrepare::restoreStackPointer(
MachineFunction &MF) {
385 if (!FrameLowering->needsPrologForEH(MF))
387 bool Changed =
false;
389 for (
auto &
MBB : MF) {
402 while (InsertPos !=
MBB.
end() && InsertPos->isEHLabel())
406 "catch/catch_all should be present in every EH pad at this point");
408 FrameLowering->writeSPToGlobal(FrameLowering->getSPReg(MF), MF,
MBB,
409 InsertPos,
MBB.
begin()->getDebugLoc());
unsigned const MachineRegisterInfo * MRI
const HexagonInstrInfo * TII
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
const SmallVectorImpl< MachineOperand > MachineBasicBlock * TBB
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallPtrSet class.
static void eraseDeadBBsAndChildren(const Container &MBBs)
This file provides WebAssembly-specific target descriptions.
This file declares the WebAssembly-specific subclass of TargetSubtarget.
This file contains the declaration of the WebAssembly-specific utility functions.
This file contains the entry points for global functions defined in the LLVM WebAssembly back-end.
FunctionPass class - This class is used to implement most global optimizations.
bool hasPersonalityFn() const
Check whether this function has a personality function.
ExceptionHandling getExceptionHandlingType() const
bool isEHPad() const
Returns true if the block is a landing pad.
instr_iterator insert(instr_iterator I, MachineInstr *M)
Insert MI into the instruction list before I, possibly inside a bundle.
succ_iterator succ_begin()
iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
void removeSuccessor(MachineBasicBlock *Succ, bool NormalizeSuccProbs=false)
Remove successor from the successors list of this MachineBasicBlock.
bool isLayoutSuccessor(const MachineBasicBlock *MBB) const
Return true if the specified MBB will be emitted immediately after this block, such that if this bloc...
void eraseFromParent()
This method unlinks 'this' from the containing function and deletes it.
instr_iterator erase(instr_iterator I)
Remove an instruction from the instruction list and delete it.
iterator_range< succ_iterator > successors()
iterator_range< pred_iterator > predecessors()
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
virtual bool runOnMachineFunction(MachineFunction &MF)=0
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
const MachineBasicBlock & front() const
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
const MachineInstrBuilder & addExternalSymbol(const char *FnName, unsigned TargetFlags=0) const
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & addDef(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register definition operand.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
void addOperand(MachineFunction &MF, const MachineOperand &Op)
Add the specified operand to the instruction.
void insert(mop_iterator InsertBefore, ArrayRef< MachineOperand > Ops)
Inserts Ops BEFORE It. Can untie/retie tied operands.
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
void removeOperand(unsigned OpNo)
Erase an operand from an instruction, leaving it with one fewer operand than it started with.
const MachineOperand & getOperand(unsigned i) const
MachineBasicBlock * getMBB() const
static MachineOperand CreateMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0)
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
const MCAsmInfo * getMCAsmInfo() const
Return target specific asm information.
virtual const TargetFrameLowering * getFrameLowering() const
A Use represents the edge between a Value definition and its users.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
MachineInstr * findCatch(MachineBasicBlock *EHPad)
Find a catch instruction from an EH pad.
bool isCatch(unsigned Opc)
cl::opt< bool > WasmEnableExnref
NodeAddr< DefNode * > Def
This is an optimization pass for GlobalISel generic memory operations.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
FunctionPass * createWebAssemblyLateEHPrepare()
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.