17d523365SDimitry Andric //===-- WebAssemblyCFGStackify.cpp - CFG Stackification -------------------===// 27d523365SDimitry Andric // 37d523365SDimitry Andric // The LLVM Compiler Infrastructure 47d523365SDimitry Andric // 57d523365SDimitry Andric // This file is distributed under the University of Illinois Open Source 67d523365SDimitry Andric // License. See LICENSE.TXT for details. 77d523365SDimitry Andric // 87d523365SDimitry Andric //===----------------------------------------------------------------------===// 97d523365SDimitry Andric /// 107d523365SDimitry Andric /// \file 117d523365SDimitry Andric /// \brief This file implements a CFG stacking pass. 127d523365SDimitry Andric /// 137a7e6055SDimitry Andric /// This pass inserts BLOCK and LOOP markers to mark the start of scopes, since 147d523365SDimitry Andric /// scope boundaries serve as the labels for WebAssembly's control transfers. 157d523365SDimitry Andric /// 167d523365SDimitry Andric /// This is sufficient to convert arbitrary CFGs into a form that works on 177d523365SDimitry Andric /// WebAssembly, provided that all loops are single-entry. 187d523365SDimitry Andric /// 197d523365SDimitry Andric //===----------------------------------------------------------------------===// 207d523365SDimitry Andric 217d523365SDimitry Andric #include "MCTargetDesc/WebAssemblyMCTargetDesc.h" 22db17bf38SDimitry Andric #include "WebAssembly.h" 233ca95b02SDimitry Andric #include "WebAssemblyMachineFunctionInfo.h" 247d523365SDimitry Andric #include "WebAssemblySubtarget.h" 25d88c1a5aSDimitry Andric #include "WebAssemblyUtilities.h" 267d523365SDimitry Andric #include "llvm/CodeGen/MachineDominators.h" 277d523365SDimitry Andric #include "llvm/CodeGen/MachineFunction.h" 287d523365SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h" 297d523365SDimitry Andric #include "llvm/CodeGen/MachineLoopInfo.h" 30444ed5c5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h" 317d523365SDimitry Andric #include "llvm/CodeGen/Passes.h" 327d523365SDimitry Andric #include "llvm/Support/Debug.h" 337d523365SDimitry Andric #include "llvm/Support/raw_ostream.h" 347d523365SDimitry Andric using namespace llvm; 357d523365SDimitry Andric 367d523365SDimitry Andric #define DEBUG_TYPE "wasm-cfg-stackify" 377d523365SDimitry Andric 387d523365SDimitry Andric namespace { 397d523365SDimitry Andric class WebAssemblyCFGStackify final : public MachineFunctionPass { 40d88c1a5aSDimitry Andric StringRef getPassName() const override { return "WebAssembly CFG Stackify"; } 417d523365SDimitry Andric 427d523365SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override { 437d523365SDimitry Andric AU.setPreservesCFG(); 447d523365SDimitry Andric AU.addRequired<MachineDominatorTree>(); 457d523365SDimitry Andric AU.addPreserved<MachineDominatorTree>(); 467d523365SDimitry Andric AU.addRequired<MachineLoopInfo>(); 477d523365SDimitry Andric AU.addPreserved<MachineLoopInfo>(); 487d523365SDimitry Andric MachineFunctionPass::getAnalysisUsage(AU); 497d523365SDimitry Andric } 507d523365SDimitry Andric 517d523365SDimitry Andric bool runOnMachineFunction(MachineFunction &MF) override; 527d523365SDimitry Andric 537d523365SDimitry Andric public: 547d523365SDimitry Andric static char ID; // Pass identification, replacement for typeid 557d523365SDimitry Andric WebAssemblyCFGStackify() : MachineFunctionPass(ID) {} 567d523365SDimitry Andric }; 577d523365SDimitry Andric } // end anonymous namespace 587d523365SDimitry Andric 597d523365SDimitry Andric char WebAssemblyCFGStackify::ID = 0; 607d523365SDimitry Andric FunctionPass *llvm::createWebAssemblyCFGStackify() { 617d523365SDimitry Andric return new WebAssemblyCFGStackify(); 627d523365SDimitry Andric } 637d523365SDimitry Andric 647d523365SDimitry Andric /// Test whether Pred has any terminators explicitly branching to MBB, as 657d523365SDimitry Andric /// opposed to falling through. Note that it's possible (eg. in unoptimized 667d523365SDimitry Andric /// code) for a branch instruction to both branch to a block and fallthrough 677d523365SDimitry Andric /// to it, so we check the actual branch operands to see if there are any 687d523365SDimitry Andric /// explicit mentions. 69444ed5c5SDimitry Andric static bool ExplicitlyBranchesTo(MachineBasicBlock *Pred, 70444ed5c5SDimitry Andric MachineBasicBlock *MBB) { 717d523365SDimitry Andric for (MachineInstr &MI : Pred->terminators()) 727d523365SDimitry Andric for (MachineOperand &MO : MI.explicit_operands()) 737d523365SDimitry Andric if (MO.isMBB() && MO.getMBB() == MBB) 747d523365SDimitry Andric return true; 757d523365SDimitry Andric return false; 767d523365SDimitry Andric } 777d523365SDimitry Andric 787d523365SDimitry Andric /// Insert a BLOCK marker for branches to MBB (if needed). 79d88c1a5aSDimitry Andric static void PlaceBlockMarker( 80d88c1a5aSDimitry Andric MachineBasicBlock &MBB, MachineFunction &MF, 817d523365SDimitry Andric SmallVectorImpl<MachineBasicBlock *> &ScopeTops, 82d88c1a5aSDimitry Andric DenseMap<const MachineInstr *, MachineInstr *> &BlockTops, 83d88c1a5aSDimitry Andric DenseMap<const MachineInstr *, MachineInstr *> &LoopTops, 847d523365SDimitry Andric const WebAssemblyInstrInfo &TII, 857d523365SDimitry Andric const MachineLoopInfo &MLI, 863ca95b02SDimitry Andric MachineDominatorTree &MDT, 873ca95b02SDimitry Andric WebAssemblyFunctionInfo &MFI) { 887d523365SDimitry Andric // First compute the nearest common dominator of all forward non-fallthrough 897d523365SDimitry Andric // predecessors so that we minimize the time that the BLOCK is on the stack, 907d523365SDimitry Andric // which reduces overall stack height. 917d523365SDimitry Andric MachineBasicBlock *Header = nullptr; 927d523365SDimitry Andric bool IsBranchedTo = false; 937d523365SDimitry Andric int MBBNumber = MBB.getNumber(); 947d523365SDimitry Andric for (MachineBasicBlock *Pred : MBB.predecessors()) 957d523365SDimitry Andric if (Pred->getNumber() < MBBNumber) { 967d523365SDimitry Andric Header = Header ? MDT.findNearestCommonDominator(Header, Pred) : Pred; 977d523365SDimitry Andric if (ExplicitlyBranchesTo(Pred, &MBB)) 987d523365SDimitry Andric IsBranchedTo = true; 997d523365SDimitry Andric } 1007d523365SDimitry Andric if (!Header) 1017d523365SDimitry Andric return; 1027d523365SDimitry Andric if (!IsBranchedTo) 1037d523365SDimitry Andric return; 1047d523365SDimitry Andric 1057d523365SDimitry Andric assert(&MBB != &MF.front() && "Header blocks shouldn't have predecessors"); 106d88c1a5aSDimitry Andric MachineBasicBlock *LayoutPred = &*std::prev(MachineFunction::iterator(&MBB)); 1077d523365SDimitry Andric 1087d523365SDimitry Andric // If the nearest common dominator is inside a more deeply nested context, 1097d523365SDimitry Andric // walk out to the nearest scope which isn't more deeply nested. 1107d523365SDimitry Andric for (MachineFunction::iterator I(LayoutPred), E(Header); I != E; --I) { 1117d523365SDimitry Andric if (MachineBasicBlock *ScopeTop = ScopeTops[I->getNumber()]) { 1127d523365SDimitry Andric if (ScopeTop->getNumber() > Header->getNumber()) { 1137d523365SDimitry Andric // Skip over an intervening scope. 114d88c1a5aSDimitry Andric I = std::next(MachineFunction::iterator(ScopeTop)); 1157d523365SDimitry Andric } else { 1167d523365SDimitry Andric // We found a scope level at an appropriate depth. 1177d523365SDimitry Andric Header = ScopeTop; 1187d523365SDimitry Andric break; 1197d523365SDimitry Andric } 1207d523365SDimitry Andric } 1217d523365SDimitry Andric } 1227d523365SDimitry Andric 1237d523365SDimitry Andric // Decide where in Header to put the BLOCK. 1247d523365SDimitry Andric MachineBasicBlock::iterator InsertPos; 1257d523365SDimitry Andric MachineLoop *HeaderLoop = MLI.getLoopFor(Header); 1267d523365SDimitry Andric if (HeaderLoop && MBB.getNumber() > LoopBottom(HeaderLoop)->getNumber()) { 1277d523365SDimitry Andric // Header is the header of a loop that does not lexically contain MBB, so 1283ca95b02SDimitry Andric // the BLOCK needs to be above the LOOP, after any END constructs. 1297d523365SDimitry Andric InsertPos = Header->begin(); 130d88c1a5aSDimitry Andric while (InsertPos->getOpcode() == WebAssembly::END_BLOCK || 131d88c1a5aSDimitry Andric InsertPos->getOpcode() == WebAssembly::END_LOOP) 1323ca95b02SDimitry Andric ++InsertPos; 1337d523365SDimitry Andric } else { 1347d523365SDimitry Andric // Otherwise, insert the BLOCK as late in Header as we can, but before the 1357d523365SDimitry Andric // beginning of the local expression tree and any nested BLOCKs. 1367d523365SDimitry Andric InsertPos = Header->getFirstTerminator(); 137d88c1a5aSDimitry Andric while (InsertPos != Header->begin() && 138d88c1a5aSDimitry Andric WebAssembly::isChild(*std::prev(InsertPos), MFI) && 139d88c1a5aSDimitry Andric std::prev(InsertPos)->getOpcode() != WebAssembly::LOOP && 140d88c1a5aSDimitry Andric std::prev(InsertPos)->getOpcode() != WebAssembly::END_BLOCK && 141d88c1a5aSDimitry Andric std::prev(InsertPos)->getOpcode() != WebAssembly::END_LOOP) 1427d523365SDimitry Andric --InsertPos; 1437d523365SDimitry Andric } 1447d523365SDimitry Andric 1457d523365SDimitry Andric // Add the BLOCK. 146d88c1a5aSDimitry Andric MachineInstr *Begin = BuildMI(*Header, InsertPos, DebugLoc(), 147d88c1a5aSDimitry Andric TII.get(WebAssembly::BLOCK)) 148d88c1a5aSDimitry Andric .addImm(int64_t(WebAssembly::ExprType::Void)); 149444ed5c5SDimitry Andric 150444ed5c5SDimitry Andric // Mark the end of the block. 151444ed5c5SDimitry Andric InsertPos = MBB.begin(); 152444ed5c5SDimitry Andric while (InsertPos != MBB.end() && 153d88c1a5aSDimitry Andric InsertPos->getOpcode() == WebAssembly::END_LOOP && 154d88c1a5aSDimitry Andric LoopTops[&*InsertPos]->getParent()->getNumber() >= Header->getNumber()) 155444ed5c5SDimitry Andric ++InsertPos; 156d88c1a5aSDimitry Andric MachineInstr *End = BuildMI(MBB, InsertPos, DebugLoc(), 157d88c1a5aSDimitry Andric TII.get(WebAssembly::END_BLOCK)); 158d88c1a5aSDimitry Andric BlockTops[End] = Begin; 1597d523365SDimitry Andric 1607d523365SDimitry Andric // Track the farthest-spanning scope that ends at this point. 1617d523365SDimitry Andric int Number = MBB.getNumber(); 1627d523365SDimitry Andric if (!ScopeTops[Number] || 1637d523365SDimitry Andric ScopeTops[Number]->getNumber() > Header->getNumber()) 1647d523365SDimitry Andric ScopeTops[Number] = Header; 1657d523365SDimitry Andric } 1667d523365SDimitry Andric 1677d523365SDimitry Andric /// Insert a LOOP marker for a loop starting at MBB (if it's a loop header). 168444ed5c5SDimitry Andric static void PlaceLoopMarker( 169444ed5c5SDimitry Andric MachineBasicBlock &MBB, MachineFunction &MF, 1707d523365SDimitry Andric SmallVectorImpl<MachineBasicBlock *> &ScopeTops, 171d88c1a5aSDimitry Andric DenseMap<const MachineInstr *, MachineInstr *> &LoopTops, 172444ed5c5SDimitry Andric const WebAssemblyInstrInfo &TII, const MachineLoopInfo &MLI) { 1737d523365SDimitry Andric MachineLoop *Loop = MLI.getLoopFor(&MBB); 1747d523365SDimitry Andric if (!Loop || Loop->getHeader() != &MBB) 1757d523365SDimitry Andric return; 1767d523365SDimitry Andric 1777d523365SDimitry Andric // The operand of a LOOP is the first block after the loop. If the loop is the 1787d523365SDimitry Andric // bottom of the function, insert a dummy block at the end. 1797d523365SDimitry Andric MachineBasicBlock *Bottom = LoopBottom(Loop); 180d88c1a5aSDimitry Andric auto Iter = std::next(MachineFunction::iterator(Bottom)); 1817d523365SDimitry Andric if (Iter == MF.end()) { 1827d523365SDimitry Andric MachineBasicBlock *Label = MF.CreateMachineBasicBlock(); 1837d523365SDimitry Andric // Give it a fake predecessor so that AsmPrinter prints its label. 1847d523365SDimitry Andric Label->addSuccessor(Label); 1857d523365SDimitry Andric MF.push_back(Label); 186d88c1a5aSDimitry Andric Iter = std::next(MachineFunction::iterator(Bottom)); 1877d523365SDimitry Andric } 1887d523365SDimitry Andric MachineBasicBlock *AfterLoop = &*Iter; 1897d523365SDimitry Andric 190444ed5c5SDimitry Andric // Mark the beginning of the loop (after the end of any existing loop that 191444ed5c5SDimitry Andric // ends here). 192444ed5c5SDimitry Andric auto InsertPos = MBB.begin(); 193444ed5c5SDimitry Andric while (InsertPos != MBB.end() && 194444ed5c5SDimitry Andric InsertPos->getOpcode() == WebAssembly::END_LOOP) 195444ed5c5SDimitry Andric ++InsertPos; 196d88c1a5aSDimitry Andric MachineInstr *Begin = BuildMI(MBB, InsertPos, DebugLoc(), 197d88c1a5aSDimitry Andric TII.get(WebAssembly::LOOP)) 198d88c1a5aSDimitry Andric .addImm(int64_t(WebAssembly::ExprType::Void)); 199444ed5c5SDimitry Andric 200444ed5c5SDimitry Andric // Mark the end of the loop. 201444ed5c5SDimitry Andric MachineInstr *End = BuildMI(*AfterLoop, AfterLoop->begin(), DebugLoc(), 202444ed5c5SDimitry Andric TII.get(WebAssembly::END_LOOP)); 203d88c1a5aSDimitry Andric LoopTops[End] = Begin; 2047d523365SDimitry Andric 2057d523365SDimitry Andric assert((!ScopeTops[AfterLoop->getNumber()] || 2067d523365SDimitry Andric ScopeTops[AfterLoop->getNumber()]->getNumber() < MBB.getNumber()) && 2073ca95b02SDimitry Andric "With block sorting the outermost loop for a block should be first."); 2087d523365SDimitry Andric if (!ScopeTops[AfterLoop->getNumber()]) 2097d523365SDimitry Andric ScopeTops[AfterLoop->getNumber()] = &MBB; 2107d523365SDimitry Andric } 2117d523365SDimitry Andric 212444ed5c5SDimitry Andric static unsigned 213444ed5c5SDimitry Andric GetDepth(const SmallVectorImpl<const MachineBasicBlock *> &Stack, 214444ed5c5SDimitry Andric const MachineBasicBlock *MBB) { 215444ed5c5SDimitry Andric unsigned Depth = 0; 216444ed5c5SDimitry Andric for (auto X : reverse(Stack)) { 217444ed5c5SDimitry Andric if (X == MBB) 218444ed5c5SDimitry Andric break; 219444ed5c5SDimitry Andric ++Depth; 220444ed5c5SDimitry Andric } 221444ed5c5SDimitry Andric assert(Depth < Stack.size() && "Branch destination should be in scope"); 222444ed5c5SDimitry Andric return Depth; 223444ed5c5SDimitry Andric } 224444ed5c5SDimitry Andric 225d88c1a5aSDimitry Andric /// In normal assembly languages, when the end of a function is unreachable, 226d88c1a5aSDimitry Andric /// because the function ends in an infinite loop or a noreturn call or similar, 227d88c1a5aSDimitry Andric /// it isn't necessary to worry about the function return type at the end of 228d88c1a5aSDimitry Andric /// the function, because it's never reached. However, in WebAssembly, blocks 229d88c1a5aSDimitry Andric /// that end at the function end need to have a return type signature that 230d88c1a5aSDimitry Andric /// matches the function signature, even though it's unreachable. This function 231d88c1a5aSDimitry Andric /// checks for such cases and fixes up the signatures. 232d88c1a5aSDimitry Andric static void FixEndsAtEndOfFunction( 233d88c1a5aSDimitry Andric MachineFunction &MF, 234d88c1a5aSDimitry Andric const WebAssemblyFunctionInfo &MFI, 235d88c1a5aSDimitry Andric DenseMap<const MachineInstr *, MachineInstr *> &BlockTops, 236d88c1a5aSDimitry Andric DenseMap<const MachineInstr *, MachineInstr *> &LoopTops) { 237d88c1a5aSDimitry Andric assert(MFI.getResults().size() <= 1); 238d88c1a5aSDimitry Andric 239d88c1a5aSDimitry Andric if (MFI.getResults().empty()) 240d88c1a5aSDimitry Andric return; 241d88c1a5aSDimitry Andric 242d88c1a5aSDimitry Andric WebAssembly::ExprType retType; 243d88c1a5aSDimitry Andric switch (MFI.getResults().front().SimpleTy) { 244d88c1a5aSDimitry Andric case MVT::i32: retType = WebAssembly::ExprType::I32; break; 245d88c1a5aSDimitry Andric case MVT::i64: retType = WebAssembly::ExprType::I64; break; 246d88c1a5aSDimitry Andric case MVT::f32: retType = WebAssembly::ExprType::F32; break; 247d88c1a5aSDimitry Andric case MVT::f64: retType = WebAssembly::ExprType::F64; break; 248d88c1a5aSDimitry Andric case MVT::v16i8: retType = WebAssembly::ExprType::I8x16; break; 249d88c1a5aSDimitry Andric case MVT::v8i16: retType = WebAssembly::ExprType::I16x8; break; 250d88c1a5aSDimitry Andric case MVT::v4i32: retType = WebAssembly::ExprType::I32x4; break; 251d88c1a5aSDimitry Andric case MVT::v4f32: retType = WebAssembly::ExprType::F32x4; break; 252d88c1a5aSDimitry Andric default: llvm_unreachable("unexpected return type"); 253d88c1a5aSDimitry Andric } 254d88c1a5aSDimitry Andric 255d88c1a5aSDimitry Andric for (MachineBasicBlock &MBB : reverse(MF)) { 256d88c1a5aSDimitry Andric for (MachineInstr &MI : reverse(MBB)) { 257d88c1a5aSDimitry Andric if (MI.isPosition() || MI.isDebugValue()) 258d88c1a5aSDimitry Andric continue; 259d88c1a5aSDimitry Andric if (MI.getOpcode() == WebAssembly::END_BLOCK) { 260d88c1a5aSDimitry Andric BlockTops[&MI]->getOperand(0).setImm(int32_t(retType)); 261d88c1a5aSDimitry Andric continue; 262d88c1a5aSDimitry Andric } 263d88c1a5aSDimitry Andric if (MI.getOpcode() == WebAssembly::END_LOOP) { 264d88c1a5aSDimitry Andric LoopTops[&MI]->getOperand(0).setImm(int32_t(retType)); 265d88c1a5aSDimitry Andric continue; 266d88c1a5aSDimitry Andric } 267d88c1a5aSDimitry Andric // Something other than an `end`. We're done. 268d88c1a5aSDimitry Andric return; 269d88c1a5aSDimitry Andric } 270d88c1a5aSDimitry Andric } 271d88c1a5aSDimitry Andric } 272d88c1a5aSDimitry Andric 2737a7e6055SDimitry Andric // WebAssembly functions end with an end instruction, as if the function body 2747a7e6055SDimitry Andric // were a block. 2757a7e6055SDimitry Andric static void AppendEndToFunction( 2767a7e6055SDimitry Andric MachineFunction &MF, 2777a7e6055SDimitry Andric const WebAssemblyInstrInfo &TII) { 2787a7e6055SDimitry Andric BuildMI(MF.back(), MF.back().end(), DebugLoc(), 2797a7e6055SDimitry Andric TII.get(WebAssembly::END_FUNCTION)); 2807a7e6055SDimitry Andric } 2817a7e6055SDimitry Andric 2827d523365SDimitry Andric /// Insert LOOP and BLOCK markers at appropriate places. 2837d523365SDimitry Andric static void PlaceMarkers(MachineFunction &MF, const MachineLoopInfo &MLI, 2847d523365SDimitry Andric const WebAssemblyInstrInfo &TII, 2853ca95b02SDimitry Andric MachineDominatorTree &MDT, 2863ca95b02SDimitry Andric WebAssemblyFunctionInfo &MFI) { 2877d523365SDimitry Andric // For each block whose label represents the end of a scope, record the block 2887d523365SDimitry Andric // which holds the beginning of the scope. This will allow us to quickly skip 2897d523365SDimitry Andric // over scoped regions when walking blocks. We allocate one more than the 2907d523365SDimitry Andric // number of blocks in the function to accommodate for the possible fake block 2917d523365SDimitry Andric // we may insert at the end. 2927d523365SDimitry Andric SmallVector<MachineBasicBlock *, 8> ScopeTops(MF.getNumBlockIDs() + 1); 2937d523365SDimitry Andric 294d88c1a5aSDimitry Andric // For each LOOP_END, the corresponding LOOP. 295d88c1a5aSDimitry Andric DenseMap<const MachineInstr *, MachineInstr *> LoopTops; 296d88c1a5aSDimitry Andric 297d88c1a5aSDimitry Andric // For each END_BLOCK, the corresponding BLOCK. 298d88c1a5aSDimitry Andric DenseMap<const MachineInstr *, MachineInstr *> BlockTops; 299444ed5c5SDimitry Andric 3007d523365SDimitry Andric for (auto &MBB : MF) { 3017d523365SDimitry Andric // Place the LOOP for MBB if MBB is the header of a loop. 302444ed5c5SDimitry Andric PlaceLoopMarker(MBB, MF, ScopeTops, LoopTops, TII, MLI); 3037d523365SDimitry Andric 3047d523365SDimitry Andric // Place the BLOCK for MBB if MBB is branched to from above. 305d88c1a5aSDimitry Andric PlaceBlockMarker(MBB, MF, ScopeTops, BlockTops, LoopTops, TII, MLI, MDT, MFI); 3067d523365SDimitry Andric } 3077d523365SDimitry Andric 308444ed5c5SDimitry Andric // Now rewrite references to basic blocks to be depth immediates. 309444ed5c5SDimitry Andric SmallVector<const MachineBasicBlock *, 8> Stack; 310444ed5c5SDimitry Andric for (auto &MBB : reverse(MF)) { 311444ed5c5SDimitry Andric for (auto &MI : reverse(MBB)) { 312444ed5c5SDimitry Andric switch (MI.getOpcode()) { 313444ed5c5SDimitry Andric case WebAssembly::BLOCK: 314d88c1a5aSDimitry Andric assert(ScopeTops[Stack.back()->getNumber()]->getNumber() <= MBB.getNumber() && 315444ed5c5SDimitry Andric "Block should be balanced"); 316444ed5c5SDimitry Andric Stack.pop_back(); 317444ed5c5SDimitry Andric break; 318444ed5c5SDimitry Andric case WebAssembly::LOOP: 319444ed5c5SDimitry Andric assert(Stack.back() == &MBB && "Loop top should be balanced"); 320444ed5c5SDimitry Andric Stack.pop_back(); 321444ed5c5SDimitry Andric break; 322444ed5c5SDimitry Andric case WebAssembly::END_BLOCK: 323444ed5c5SDimitry Andric Stack.push_back(&MBB); 324444ed5c5SDimitry Andric break; 325444ed5c5SDimitry Andric case WebAssembly::END_LOOP: 326d88c1a5aSDimitry Andric Stack.push_back(LoopTops[&MI]->getParent()); 327444ed5c5SDimitry Andric break; 328444ed5c5SDimitry Andric default: 329444ed5c5SDimitry Andric if (MI.isTerminator()) { 330444ed5c5SDimitry Andric // Rewrite MBB operands to be depth immediates. 331444ed5c5SDimitry Andric SmallVector<MachineOperand, 4> Ops(MI.operands()); 332444ed5c5SDimitry Andric while (MI.getNumOperands() > 0) 333444ed5c5SDimitry Andric MI.RemoveOperand(MI.getNumOperands() - 1); 334444ed5c5SDimitry Andric for (auto MO : Ops) { 335444ed5c5SDimitry Andric if (MO.isMBB()) 336444ed5c5SDimitry Andric MO = MachineOperand::CreateImm(GetDepth(Stack, MO.getMBB())); 337444ed5c5SDimitry Andric MI.addOperand(MF, MO); 3387d523365SDimitry Andric } 339444ed5c5SDimitry Andric } 340444ed5c5SDimitry Andric break; 341444ed5c5SDimitry Andric } 342444ed5c5SDimitry Andric } 343444ed5c5SDimitry Andric } 344444ed5c5SDimitry Andric assert(Stack.empty() && "Control flow should be balanced"); 345d88c1a5aSDimitry Andric 346d88c1a5aSDimitry Andric // Fix up block/loop signatures at the end of the function to conform to 347d88c1a5aSDimitry Andric // WebAssembly's rules. 348d88c1a5aSDimitry Andric FixEndsAtEndOfFunction(MF, MFI, BlockTops, LoopTops); 3497a7e6055SDimitry Andric 3507a7e6055SDimitry Andric // Add an end instruction at the end of the function body. 3517a7e6055SDimitry Andric if (!MF.getSubtarget<WebAssemblySubtarget>() 3527a7e6055SDimitry Andric .getTargetTriple().isOSBinFormatELF()) 3537a7e6055SDimitry Andric AppendEndToFunction(MF, TII); 354444ed5c5SDimitry Andric } 3557d523365SDimitry Andric 3567d523365SDimitry Andric bool WebAssemblyCFGStackify::runOnMachineFunction(MachineFunction &MF) { 3577d523365SDimitry Andric DEBUG(dbgs() << "********** CFG Stackifying **********\n" 3587d523365SDimitry Andric "********** Function: " 3597d523365SDimitry Andric << MF.getName() << '\n'); 3607d523365SDimitry Andric 3617d523365SDimitry Andric const auto &MLI = getAnalysis<MachineLoopInfo>(); 3627d523365SDimitry Andric auto &MDT = getAnalysis<MachineDominatorTree>(); 363d88c1a5aSDimitry Andric // Liveness is not tracked for VALUE_STACK physreg. 3647d523365SDimitry Andric const auto &TII = *MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo(); 3653ca95b02SDimitry Andric WebAssemblyFunctionInfo &MFI = *MF.getInfo<WebAssemblyFunctionInfo>(); 366444ed5c5SDimitry Andric MF.getRegInfo().invalidateLiveness(); 3677d523365SDimitry Andric 3687d523365SDimitry Andric // Place the BLOCK and LOOP markers to indicate the beginnings of scopes. 3693ca95b02SDimitry Andric PlaceMarkers(MF, MLI, TII, MDT, MFI); 3707d523365SDimitry Andric 3717d523365SDimitry Andric return true; 3727d523365SDimitry Andric } 373