24 #define DEBUG_TYPE "wasm-exception-prepare" 29 return "WebAssembly Prepare Exception";
51 "WebAssembly Late Exception Preparation",
false,
false)
54 return new WebAssemblyLateEHPrepare();
71 if (Visited.
count(MBB))
75 if (EHPad && EHPad != MBB)
80 if (MBB == &MF->
front())
89 template <
typename Container>
99 for (
auto *Succ : Succs)
105 bool WebAssemblyLateEHPrepare::runOnMachineFunction(
MachineFunction &MF) {
107 "********** Function: " 114 bool Changed =
false;
115 Changed |= removeUnnecessaryUnreachables(MF);
116 Changed |= addRethrows(MF);
119 Changed |= replaceFuncletReturns(MF);
120 Changed |= hoistCatches(MF);
121 Changed |= addCatchAlls(MF);
122 Changed |= ensureSingleBBTermPads(MF);
123 Changed |= mergeTerminatePads(MF);
124 Changed |= addCatchAllTerminatePads(MF);
128 bool WebAssemblyLateEHPrepare::removeUnnecessaryUnreachables(
130 bool Changed =
false;
131 for (
auto &MBB : MF) {
132 for (
auto &
MI : MBB) {
144 for (
auto *Succ : Succs)
145 MBB.removeSuccessor(Succ);
153 bool WebAssemblyLateEHPrepare::replaceFuncletReturns(
MachineFunction &MF) {
154 bool Changed =
false;
158 for (
auto &MBB : MF) {
159 auto Pos = MBB.getFirstTerminator();
160 if (Pos == MBB.end())
168 if (!MBB.isLayoutSuccessor(TBB))
177 if (EHInfo->hasThrowUnwindDest(&MBB))
179 .addMBB(EHInfo->getThrowUnwindDest(&MBB));
182 TII.get(WebAssembly::RETHROW_TO_CALLER));
206 bool Changed =
false;
213 for (
auto *
Catch : Catches) {
215 assert(EHPad &&
"No matching EH pad for catch");
226 bool Changed =
false;
229 for (
auto &MBB : MF) {
236 BuildMI(MBB, MBB.begin(), MBB.begin()->getDebugLoc(),
237 TII.get(WebAssembly::CATCH_ALL));
245 bool Changed =
false;
250 for (
auto &
MI : MBB) {
262 while (InsertPt != MBB.end() && InsertPt->isLabel())
265 if (EHInfo->hasThrowUnwindDest(&MBB))
266 Rethrow =
BuildMI(MBB, InsertPt,
MI.getDebugLoc(),
267 TII.get(WebAssembly::RETHROW))
268 .addMBB(EHInfo->getThrowUnwindDest(&MBB));
270 Rethrow =
BuildMI(MBB, InsertPt,
MI.getDebugLoc(),
271 TII.get(WebAssembly::RETHROW_TO_CALLER));
279 for (
auto *Succ : MBB.successors())
280 if (!Succ->isEHPad())
282 for (
auto *Succ : NonPadSuccessors)
283 MBB.removeSuccessor(Succ);
300 bool WebAssemblyLateEHPrepare::ensureSingleBBTermPads(
MachineFunction &MF) {
314 bool Changed =
false;
315 for (
auto *Call : ClangCallTerminateCalls) {
317 assert(EHPad &&
"No matching EH pad for catch");
320 if (Call->getParent() == EHPad &&
321 Call->getNextNode()->getOpcode() == WebAssembly::UNREACHABLE)
337 EHPad->
insert(InsertPos, Call->removeFromParent());
338 BuildMI(*EHPad, InsertPos, Call->getDebugLoc(),
339 TII.get(WebAssembly::UNREACHABLE));
340 EHPad->
erase(InsertPos, EHPad->
end());
343 for (
auto *Succ : Succs)
356 bool WebAssemblyLateEHPrepare::mergeTerminatePads(
MachineFunction &MF) {
361 if (TermPads.
empty())
368 TermPad->pred_end());
369 for (
auto *Pred : Preds)
370 Pred->replaceSuccessor(TermPad, UniqueTermPad);
371 TermPad->eraseFromParent();
391 bool WebAssemblyLateEHPrepare::addCatchAllTerminatePads(
MachineFunction &MF) {
397 if (TermPads.
empty())
402 assert(StdTerminateFn &&
"There is no std::terminate() function");
403 for (
auto *CatchTermPad : TermPads) {
404 DebugLoc DL = CatchTermPad->findDebugLoc(CatchTermPad->begin());
405 auto *CatchAllTermPad = MF.CreateMachineBasicBlock();
408 CatchAllTermPad->setIsEHPad();
409 BuildMI(CatchAllTermPad, DL,
TII.get(WebAssembly::CATCH_ALL));
410 BuildMI(CatchAllTermPad, DL,
TII.get(WebAssembly::CALL_VOID))
411 .addGlobalAddress(StdTerminateFn);
412 BuildMI(CatchAllTermPad, DL,
TII.get(WebAssembly::UNREACHABLE));
419 CatchTermPad->addSuccessor(CatchAllTermPad);
MachineBasicBlock * getMBB() const
This class represents lattice values for constants.
void push_back(const T &Elt)
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
unsigned getReg() const
getReg - Returns the register number.
This file contains the entry points for global functions defined in the LLVM WebAssembly back-end...
CLEANUPRET - Represents a return from a cleanup block funclet.
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.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
const HexagonInstrInfo * TII
void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
static void eraseDeadBBsAndChildren(const Container &MBBs)
const char *const StdTerminateFn
bool hasPersonalityFn() const
Check whether this function has a personality function.
bool isThrow(const MachineInstr &MI)
instr_iterator insert(instr_iterator I, MachineInstr *M)
Insert MI into the instruction list before I, possibly inside a bundle.
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
Windows Exception Handling.
This file contains the declaration of the WebAssembly-specific utility functions. ...
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
Control flow instructions. These all have token chains.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator begin()
const GlobalValue * getGlobal() const
const MCAsmInfo * getMCAsmInfo() const
Return target specific asm information.
This file provides WebAssembly-specific target descriptions.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
const char *const CxaRethrowFn
FunctionPass class - This class is used to implement most global optimizations.
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
succ_iterator succ_begin()
const MachineBasicBlock & front() const
pred_iterator pred_begin()
INITIALIZE_PASS(WebAssemblyLateEHPrepare, DEBUG_TYPE, "WebAssembly Late Exception Preparation", false, false) FunctionPass *llvm
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
This file declares the WebAssembly-specific subclass of TargetSubtarget.
Iterator for intrusive lists based on ilist_node.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements...
bool isGlobal() const
isGlobal - Tests if this is a MO_GlobalAddress operand.
const char *const ClangCallTerminateFn
MachineOperand class - Representation of each machine instruction operand.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
bool isCatchTerminatePad(const MachineBasicBlock &MBB)
Returns if the given BB is a single BB terminate pad which starts with a 'catch' instruction.
LLVM_NODISCARD T pop_back_val()
const Function & getFunction() const
Return the LLVM function that this machine code represents.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
static MachineBasicBlock * getMatchingEHPad(MachineInstr *MI)
void append(in_iter in_start, in_iter in_end)
Add the specified range to the end of the SmallVector.
CATCHRET - Represents a return from a catch block funclet.
const MachineBasicBlock * getParent() const
const WasmEHFuncInfo * getWasmEHFuncInfo() const
getWasmEHFuncInfo - Return information about how the current function uses Wasm exception handling...
Representation of each machine instruction.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator end()
bool isEHPad() const
Returns true if the block is a landing pad.
LLVM_NODISCARD bool empty() const
FunctionPass * createWebAssemblyLateEHPrepare()
StringRef getName() const
Return a constant reference to the value's name.
const LLVMTargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
bool isCatch(const MachineInstr &MI)
void removeSuccessor(MachineBasicBlock *Succ, bool NormalizeSuccProbs=false)
Remove successor from the successors list of this MachineBasicBlock.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
ExceptionHandling getExceptionHandlingType() const
StringRef - Represent a constant reference to a string, i.e.
const MachineOperand & getOperand(unsigned i) const