43 #define DEBUG_TYPE "wasm-cfg-stackify" 47 StringRef getPassName()
const override {
return "WebAssembly CFG Stackify"; }
92 ~WebAssemblyCFGStackify()
override { releaseMemory(); }
93 void releaseMemory()
override;
99 "Insert BLOCK and LOOP markers for WebAssembly scopes",
false,
103 return new WebAssemblyCFGStackify();
117 if (MO.isMBB() && MO.getMBB() == MBB)
131 auto InsertPos = MBB->
end();
132 while (InsertPos != MBB->
begin()) {
133 if (BeforeSet.
count(&*std::prev(InsertPos))) {
136 for (
auto Pos = InsertPos,
E = MBB->
begin(); Pos !=
E; --Pos)
155 auto InsertPos = MBB->
begin();
156 while (InsertPos != MBB->
end()) {
157 if (AfterSet.
count(&*InsertPos)) {
160 for (
auto Pos = InsertPos,
E = MBB->
end(); Pos !=
E; ++Pos)
170 void WebAssemblyCFGStackify::registerScope(
MachineInstr *Begin,
172 BeginToEnd[Begin] = End;
173 EndToBegin[End] = Begin;
176 void WebAssemblyCFGStackify::registerTryScope(
MachineInstr *Begin,
179 registerScope(Begin, End);
180 TryToEHPad[Begin] = EHPad;
181 EHPadToTry[EHPad] = Begin;
188 const auto &MLI = getAnalysis<MachineLoopInfo>();
189 const auto &WEI = getAnalysis<WebAssemblyExceptionInfo>();
190 if (BeginToBottom.count(Begin))
191 return BeginToBottom[Begin];
196 }
else if (Begin->
getOpcode() == WebAssembly::TRY) {
202 return BeginToBottom[Begin];
212 auto &MDT = getAnalysis<MachineDominatorTree>();
220 bool IsBranchedTo =
false;
223 if (Pred->getNumber() < MBBNumber) {
224 Header = Header ? MDT.findNearestCommonDominator(Header, Pred) : Pred;
234 assert(&MBB != &MF.
front() &&
"Header blocks shouldn't have predecessors");
241 if (ScopeTop->getNumber() > Header->getNumber()) {
258 for (
const auto &
MI : *Header) {
264 MI.getOpcode() == WebAssembly::TRY) {
275 if (
MI.getOpcode() == WebAssembly::BLOCK)
281 MI.getOpcode() == WebAssembly::END_LOOP ||
282 MI.getOpcode() == WebAssembly::END_TRY)
287 if (
MI.isTerminator())
292 for (
auto I = Header->getFirstTerminator(),
E = Header->begin();
I !=
E;
294 if (std::prev(
I)->isDebugInstr() || std::prev(
I)->isPosition())
297 AfterSet.
insert(&*std::prev(
I));
305 BuildMI(*Header, InsertPos, Header->findDebugLoc(InsertPos),
306 TII.get(WebAssembly::BLOCK))
312 for (
auto &
MI : MBB) {
316 MI.getOpcode() == WebAssembly::TRY)
324 if (
MI.getOpcode() == WebAssembly::END_LOOP ||
325 MI.getOpcode() == WebAssembly::END_TRY) {
326 if (EndToBegin[&
MI]->
getParent()->getNumber() >= Header->getNumber())
339 registerScope(Begin, End);
342 int Number = MBB.getNumber();
343 if (!ScopeTops[Number] ||
344 ScopeTops[Number]->getNumber() > Header->getNumber())
345 ScopeTops[Number] = Header;
351 const auto &MLI = getAnalysis<MachineLoopInfo>();
362 if (Iter == MF.
end()) {
374 for (
const auto &
MI : MBB) {
377 if (
MI.getOpcode() == WebAssembly::END_LOOP)
395 for (
const auto &
MI : MBB)
397 if (
MI.getOpcode() == WebAssembly::END_LOOP)
406 BuildMI(*AfterLoop, InsertPos, EndDL, TII.
get(WebAssembly::END_LOOP));
407 registerScope(Begin, End);
410 ScopeTops[AfterLoop->
getNumber()]->getNumber() < MBB.getNumber()) &&
411 "With block sorting the outermost loop for a block should be first.");
413 ScopeTops[AfterLoop->
getNumber()] = &MBB;
426 auto &MDT = getAnalysis<MachineDominatorTree>();
428 const auto &WEI = getAnalysis<WebAssemblyExceptionInfo>();
435 if (Pred->getNumber() < MBBNumber) {
436 Header = Header ? MDT.findNearestCommonDominator(Header, Pred) : Pred;
438 "Explicit branch to an EH pad!");
451 if (Iter == MF.
end()) {
468 if (ScopeTop->getNumber() > Header->getNumber()) {
485 for (
const auto &
MI : *Header) {
500 if (
MI.getOpcode() == WebAssembly::TRY)
505 if (
MI.getOpcode() == WebAssembly::END_LOOP ||
506 MI.getOpcode() == WebAssembly::END_TRY)
511 if (
MI.isTerminator())
516 for (
auto I = Header->getFirstTerminator(),
E = Header->begin();
I !=
E;
518 if (std::prev(
I)->isDebugInstr() || std::prev(
I)->isPosition())
521 AfterSet.
insert(&*std::prev(
I));
532 auto TermPos = Header->getFirstTerminator();
534 for (
const auto &
MI :
reverse(*Header)) {
546 BuildMI(*Header, InsertPos, Header->findDebugLoc(InsertPos),
547 TII.get(WebAssembly::TRY))
553 for (
const auto &
MI : *AfterTry) {
561 if (
MI.getOpcode() == WebAssembly::END_TRY)
569 if (
MI.getOpcode() == WebAssembly::END_LOOP) {
570 if (EndToBegin[&
MI]->
getParent()->getNumber() >= Header->getNumber())
583 TII.
get(WebAssembly::END_TRY));
584 registerTryScope(Begin, End, &MBB);
587 int Number = AfterTry->getNumber();
588 if (!ScopeTops[Number] ||
589 ScopeTops[Number]->getNumber() > Header->getNumber())
590 ScopeTops[Number] = Header;
602 assert(Depth < Stack.
size() &&
"Branch destination should be in scope");
613 void WebAssemblyCFGStackify::fixEndsAtEndOfFunction(
MachineFunction &MF) {
615 assert(MFI.getResults().size() <= 1);
617 if (MFI.getResults().empty())
621 switch (MFI.getResults().front().SimpleTy) {
651 if (
MI.isPosition() ||
MI.isDebugInstr())
654 EndToBegin[&
MI]->getOperand(0).setImm(int32_t(retType));
657 if (
MI.getOpcode() == WebAssembly::END_LOOP) {
658 EndToBegin[&
MI]->getOperand(0).setImm(int32_t(retType));
673 TII.get(WebAssembly::END_FUNCTION));
684 placeLoopMarker(MBB);
687 MF.getFunction().hasPersonalityFn())
692 placeBlockMarker(MBB);
695 void WebAssemblyCFGStackify::rewriteDepthImmediates(
MachineFunction &MF) {
702 for (
auto &MBB :
reverse(MF)) {
706 case WebAssembly::BLOCK:
709 "Block/try should be balanced");
713 case WebAssembly::TRY:
716 "Block/try marker should be balanced");
721 case WebAssembly::CATCH_I32:
722 case WebAssembly::CATCH_I64:
723 case WebAssembly::CATCH_ALL:
741 assert(Stack.
back() == &MBB &&
"Loop top should be balanced");
746 case WebAssembly::END_TRY:
750 case WebAssembly::END_LOOP:
754 case WebAssembly::RETHROW: {
762 case WebAssembly::RETHROW_TO_CALLER: {
765 .addImm(EHPadStack.
size());
777 for (
auto MO : Ops) {
787 assert(Stack.
empty() &&
"Control flow should be balanced");
790 void WebAssemblyCFGStackify::releaseMemory() {
796 BeginToBottom.clear();
799 bool WebAssemblyCFGStackify::runOnMachineFunction(
MachineFunction &MF) {
801 "********** Function: " 813 rewriteDepthImmediates(MF);
817 fixEndsAtEndOfFunction(MF);
pred_reverse_iterator pred_rbegin()
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
DILocation * get() const
Get the underlying DILocation.
MachineBasicBlock * getMBB() const
This class represents lattice values for constants.
bool isOSBinFormatELF() const
Tests whether the OS uses the ELF binary format.
unsigned getNumBlockIDs() const
getNumBlockIDs - Return the number of MBB ID's allocated.
void push_back(const T &Elt)
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
iterator_range< mop_iterator > operands()
This file contains the entry points for global functions defined in the LLVM WebAssembly back-end...
static bool ExplicitlyBranchesTo(MachineBasicBlock *Pred, MachineBasicBlock *MBB)
Test whether Pred has any terminators explicitly branching to MBB, as opposed to falling through...
AnalysisUsage & addRequired()
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
const HexagonInstrInfo * TII
unsigned getNumOperands() const
Retuns the total number of operands.
INITIALIZE_PASS(WebAssemblyCFGStackify, DEBUG_TYPE, "Insert BLOCK and LOOP markers for WebAssembly scopes", false, false) FunctionPass *llvm
static unsigned GetDepth(const SmallVectorImpl< const MachineBasicBlock *> &Stack, const MachineBasicBlock *MBB)
MachineBasicBlock iterator that automatically skips over MIs that are inside bundles (i...
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
bool isTerminator(QueryType Type=AnyInBundle) const
Returns true if this instruction part of the terminator for a basic block.
iterator_range< iterator > terminators()
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
BlockT * getHeader() const
auto reverse(ContainerTy &&C, typename std::enable_if< has_rbegin< ContainerTy >::value >::type *=nullptr) -> decltype(make_range(C.rbegin(), C.rend()))
DebugLoc findPrevDebugLoc(instr_iterator MBBI)
Find the previous valid DebugLoc preceding MBBI, skipping and DBG_VALUE instructions.
MachineInstrBundleIterator< MachineInstr, true > reverse_iterator
int getNumber() const
MachineBasicBlocks are uniquely numbered at the function level, unless they're not in a MachineFuncti...
This file implements WebAssemblyException information analysis.
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *bb=nullptr)
CreateMachineBasicBlock - Allocate a new MachineBasicBlock.
reverse_iterator rbegin()
static void AppendEndToFunction(MachineFunction &MF, const WebAssemblyInstrInfo &TII)
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
Windows Exception Handling.
This class is intended to be used as a base class for asm properties and features specific to the tar...
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.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
const Triple & getTargetTriple() const
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
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.
bool isPredecessor(const MachineBasicBlock *MBB) const
Return true if the specified MBB is a predecessor of this block.
Represent the analysis usage information of a pass.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
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.
bool isRethrow(const MachineInstr &MI)
iterator_range< pred_iterator > predecessors()
const MachineBasicBlock & front() const
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
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...
void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
void addOperand(MachineFunction &MF, const MachineOperand &Op)
Add the specified operand to the instruction.
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...
ExprType
This is used to indicate block signatures.
void invalidateLiveness()
invalidateLiveness - Indicates that register liveness is no longer being tracked accurately.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
DebugLoc findBranchDebugLoc()
Find and return the merged DebugLoc of the branch instructions of the block.
const MachineBasicBlock * getParent() const
Representation of each machine instruction.
This class is derived from MachineFunctionInfo and contains private WebAssembly-specific information ...
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
bool isEHPad() const
Returns true if the block is a landing pad.
LLVM_NODISCARD bool empty() const
Represents a single loop in the control flow graph.
static MachineOperand CreateImm(int64_t Val)
This file declares WebAssembly-specific per-machine-function information.
const MachineBasicBlock & back() const
const LLVMTargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
FunctionPass * createWebAssemblyCFGStackify()
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
MachineBasicBlock * getBottom(const T *Unit)
Return the "bottom" block of an entity, which can be either a MachineLoop or WebAssemblyException.
void push_back(MachineBasicBlock *MBB)
static const Function * getParent(const Value *V)
ExceptionHandling getExceptionHandlingType() const
StringRef - Represent a constant reference to a string, i.e.
void RemoveOperand(unsigned OpNo)
Erase an operand from an instruction, leaving it with one fewer operand than it started with...
static MachineBasicBlock::iterator GetEarliestInsertPos(MachineBasicBlock *MBB, const SmallPtrSet< const MachineInstr *, 4 > &BeforeSet, const SmallPtrSet< const MachineInstr *, 4 > &AfterSet)
bool isChild(const MachineInstr &MI, const WebAssemblyFunctionInfo &MFI)
Test whether MI is a child of some other node in an expression tree.
const MachineOperand & getOperand(unsigned i) const
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...
static MachineBasicBlock::iterator GetLatestInsertPos(MachineBasicBlock *MBB, const SmallPtrSet< const MachineInstr *, 4 > &BeforeSet, const SmallPtrSet< const MachineInstr *, 4 > &AfterSet)
bool isCatchAllTerminatePad(const MachineBasicBlock &MBB)
Returns if the given BB is a single BB terminate pad which starts with a 'catch_all' insrtruction...