1 //===-- WebAssemblyCFGStackify.cpp - CFG Stackification -------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 /// 10 /// \file 11 /// \brief This file implements a CFG stacking pass. 12 /// 13 /// This pass reorders the blocks in a function to put them into topological 14 /// order, ignoring loop backedges, and without any loop being interrupted 15 /// by a block not dominated by the loop header, with special care to keep the 16 /// order as similar as possible to the original order. 17 /// 18 /// Then, it inserts BLOCK and LOOP markers to mark the start of scopes, since 19 /// scope boundaries serve as the labels for WebAssembly's control transfers. 20 /// 21 /// This is sufficient to convert arbitrary CFGs into a form that works on 22 /// WebAssembly, provided that all loops are single-entry. 23 /// 24 //===----------------------------------------------------------------------===// 25 26 #include "WebAssembly.h" 27 #include "MCTargetDesc/WebAssemblyMCTargetDesc.h" 28 #include "WebAssemblyMachineFunctionInfo.h" 29 #include "WebAssemblySubtarget.h" 30 #include "WebAssemblyUtilities.h" 31 #include "llvm/ADT/PriorityQueue.h" 32 #include "llvm/ADT/SetVector.h" 33 #include "llvm/CodeGen/MachineDominators.h" 34 #include "llvm/CodeGen/MachineFunction.h" 35 #include "llvm/CodeGen/MachineInstrBuilder.h" 36 #include "llvm/CodeGen/MachineLoopInfo.h" 37 #include "llvm/CodeGen/MachineRegisterInfo.h" 38 #include "llvm/CodeGen/Passes.h" 39 #include "llvm/Support/Debug.h" 40 #include "llvm/Support/raw_ostream.h" 41 using namespace llvm; 42 43 #define DEBUG_TYPE "wasm-cfg-stackify" 44 45 namespace { 46 class WebAssemblyCFGStackify final : public MachineFunctionPass { 47 StringRef getPassName() const override { return "WebAssembly CFG Stackify"; } 48 49 void getAnalysisUsage(AnalysisUsage &AU) const override { 50 AU.setPreservesCFG(); 51 AU.addRequired<MachineDominatorTree>(); 52 AU.addPreserved<MachineDominatorTree>(); 53 AU.addRequired<MachineLoopInfo>(); 54 AU.addPreserved<MachineLoopInfo>(); 55 MachineFunctionPass::getAnalysisUsage(AU); 56 } 57 58 bool runOnMachineFunction(MachineFunction &MF) override; 59 60 public: 61 static char ID; // Pass identification, replacement for typeid 62 WebAssemblyCFGStackify() : MachineFunctionPass(ID) {} 63 }; 64 } // end anonymous namespace 65 66 char WebAssemblyCFGStackify::ID = 0; 67 FunctionPass *llvm::createWebAssemblyCFGStackify() { 68 return new WebAssemblyCFGStackify(); 69 } 70 71 /// Return the "bottom" block of a loop. This differs from 72 /// MachineLoop::getBottomBlock in that it works even if the loop is 73 /// discontiguous. 74 static MachineBasicBlock *LoopBottom(const MachineLoop *Loop) { 75 MachineBasicBlock *Bottom = Loop->getHeader(); 76 for (MachineBasicBlock *MBB : Loop->blocks()) 77 if (MBB->getNumber() > Bottom->getNumber()) 78 Bottom = MBB; 79 return Bottom; 80 } 81 82 static void MaybeUpdateTerminator(MachineBasicBlock *MBB) { 83 #ifndef NDEBUG 84 bool AnyBarrier = false; 85 #endif 86 bool AllAnalyzable = true; 87 for (const MachineInstr &Term : MBB->terminators()) { 88 #ifndef NDEBUG 89 AnyBarrier |= Term.isBarrier(); 90 #endif 91 AllAnalyzable &= Term.isBranch() && !Term.isIndirectBranch(); 92 } 93 assert((AnyBarrier || AllAnalyzable) && 94 "AnalyzeBranch needs to analyze any block with a fallthrough"); 95 if (AllAnalyzable) 96 MBB->updateTerminator(); 97 } 98 99 namespace { 100 /// Sort blocks by their number. 101 struct CompareBlockNumbers { 102 bool operator()(const MachineBasicBlock *A, 103 const MachineBasicBlock *B) const { 104 return A->getNumber() > B->getNumber(); 105 } 106 }; 107 /// Sort blocks by their number in the opposite order.. 108 struct CompareBlockNumbersBackwards { 109 bool operator()(const MachineBasicBlock *A, 110 const MachineBasicBlock *B) const { 111 return A->getNumber() < B->getNumber(); 112 } 113 }; 114 /// Bookkeeping for a loop to help ensure that we don't mix blocks not dominated 115 /// by the loop header among the loop's blocks. 116 struct Entry { 117 const MachineLoop *Loop; 118 unsigned NumBlocksLeft; 119 120 /// List of blocks not dominated by Loop's header that are deferred until 121 /// after all of Loop's blocks have been seen. 122 std::vector<MachineBasicBlock *> Deferred; 123 124 explicit Entry(const MachineLoop *L) 125 : Loop(L), NumBlocksLeft(L->getNumBlocks()) {} 126 }; 127 } 128 129 /// Sort the blocks, taking special care to make sure that loops are not 130 /// interrupted by blocks not dominated by their header. 131 /// TODO: There are many opportunities for improving the heuristics here. 132 /// Explore them. 133 static void SortBlocks(MachineFunction &MF, const MachineLoopInfo &MLI, 134 const MachineDominatorTree &MDT) { 135 // Prepare for a topological sort: Record the number of predecessors each 136 // block has, ignoring loop backedges. 137 MF.RenumberBlocks(); 138 SmallVector<unsigned, 16> NumPredsLeft(MF.getNumBlockIDs(), 0); 139 for (MachineBasicBlock &MBB : MF) { 140 unsigned N = MBB.pred_size(); 141 if (MachineLoop *L = MLI.getLoopFor(&MBB)) 142 if (L->getHeader() == &MBB) 143 for (const MachineBasicBlock *Pred : MBB.predecessors()) 144 if (L->contains(Pred)) 145 --N; 146 NumPredsLeft[MBB.getNumber()] = N; 147 } 148 149 // Topological sort the CFG, with additional constraints: 150 // - Between a loop header and the last block in the loop, there can be 151 // no blocks not dominated by the loop header. 152 // - It's desirable to preserve the original block order when possible. 153 // We use two ready lists; Preferred and Ready. Preferred has recently 154 // processed sucessors, to help preserve block sequences from the original 155 // order. Ready has the remaining ready blocks. 156 PriorityQueue<MachineBasicBlock *, std::vector<MachineBasicBlock *>, 157 CompareBlockNumbers> 158 Preferred; 159 PriorityQueue<MachineBasicBlock *, std::vector<MachineBasicBlock *>, 160 CompareBlockNumbersBackwards> 161 Ready; 162 SmallVector<Entry, 4> Loops; 163 for (MachineBasicBlock *MBB = &MF.front();;) { 164 const MachineLoop *L = MLI.getLoopFor(MBB); 165 if (L) { 166 // If MBB is a loop header, add it to the active loop list. We can't put 167 // any blocks that it doesn't dominate until we see the end of the loop. 168 if (L->getHeader() == MBB) 169 Loops.push_back(Entry(L)); 170 // For each active loop the block is in, decrement the count. If MBB is 171 // the last block in an active loop, take it off the list and pick up any 172 // blocks deferred because the header didn't dominate them. 173 for (Entry &E : Loops) 174 if (E.Loop->contains(MBB) && --E.NumBlocksLeft == 0) 175 for (auto DeferredBlock : E.Deferred) 176 Ready.push(DeferredBlock); 177 while (!Loops.empty() && Loops.back().NumBlocksLeft == 0) 178 Loops.pop_back(); 179 } 180 // The main topological sort logic. 181 for (MachineBasicBlock *Succ : MBB->successors()) { 182 // Ignore backedges. 183 if (MachineLoop *SuccL = MLI.getLoopFor(Succ)) 184 if (SuccL->getHeader() == Succ && SuccL->contains(MBB)) 185 continue; 186 // Decrement the predecessor count. If it's now zero, it's ready. 187 if (--NumPredsLeft[Succ->getNumber()] == 0) 188 Preferred.push(Succ); 189 } 190 // Determine the block to follow MBB. First try to find a preferred block, 191 // to preserve the original block order when possible. 192 MachineBasicBlock *Next = nullptr; 193 while (!Preferred.empty()) { 194 Next = Preferred.top(); 195 Preferred.pop(); 196 // If X isn't dominated by the top active loop header, defer it until that 197 // loop is done. 198 if (!Loops.empty() && 199 !MDT.dominates(Loops.back().Loop->getHeader(), Next)) { 200 Loops.back().Deferred.push_back(Next); 201 Next = nullptr; 202 continue; 203 } 204 // If Next was originally ordered before MBB, and it isn't because it was 205 // loop-rotated above the header, it's not preferred. 206 if (Next->getNumber() < MBB->getNumber() && 207 (!L || !L->contains(Next) || 208 L->getHeader()->getNumber() < Next->getNumber())) { 209 Ready.push(Next); 210 Next = nullptr; 211 continue; 212 } 213 break; 214 } 215 // If we didn't find a suitable block in the Preferred list, check the 216 // general Ready list. 217 if (!Next) { 218 // If there are no more blocks to process, we're done. 219 if (Ready.empty()) { 220 MaybeUpdateTerminator(MBB); 221 break; 222 } 223 for (;;) { 224 Next = Ready.top(); 225 Ready.pop(); 226 // If Next isn't dominated by the top active loop header, defer it until 227 // that loop is done. 228 if (!Loops.empty() && 229 !MDT.dominates(Loops.back().Loop->getHeader(), Next)) { 230 Loops.back().Deferred.push_back(Next); 231 continue; 232 } 233 break; 234 } 235 } 236 // Move the next block into place and iterate. 237 Next->moveAfter(MBB); 238 MaybeUpdateTerminator(MBB); 239 MBB = Next; 240 } 241 assert(Loops.empty() && "Active loop list not finished"); 242 MF.RenumberBlocks(); 243 244 #ifndef NDEBUG 245 SmallSetVector<MachineLoop *, 8> OnStack; 246 247 // Insert a sentinel representing the degenerate loop that starts at the 248 // function entry block and includes the entire function as a "loop" that 249 // executes once. 250 OnStack.insert(nullptr); 251 252 for (auto &MBB : MF) { 253 assert(MBB.getNumber() >= 0 && "Renumbered blocks should be non-negative."); 254 255 MachineLoop *Loop = MLI.getLoopFor(&MBB); 256 if (Loop && &MBB == Loop->getHeader()) { 257 // Loop header. The loop predecessor should be sorted above, and the other 258 // predecessors should be backedges below. 259 for (auto Pred : MBB.predecessors()) 260 assert( 261 (Pred->getNumber() < MBB.getNumber() || Loop->contains(Pred)) && 262 "Loop header predecessors must be loop predecessors or backedges"); 263 assert(OnStack.insert(Loop) && "Loops should be declared at most once."); 264 } else { 265 // Not a loop header. All predecessors should be sorted above. 266 for (auto Pred : MBB.predecessors()) 267 assert(Pred->getNumber() < MBB.getNumber() && 268 "Non-loop-header predecessors should be topologically sorted"); 269 assert(OnStack.count(MLI.getLoopFor(&MBB)) && 270 "Blocks must be nested in their loops"); 271 } 272 while (OnStack.size() > 1 && &MBB == LoopBottom(OnStack.back())) 273 OnStack.pop_back(); 274 } 275 assert(OnStack.pop_back_val() == nullptr && 276 "The function entry block shouldn't actually be a loop header"); 277 assert(OnStack.empty() && 278 "Control flow stack pushes and pops should be balanced."); 279 #endif 280 } 281 282 /// Test whether Pred has any terminators explicitly branching to MBB, as 283 /// opposed to falling through. Note that it's possible (eg. in unoptimized 284 /// code) for a branch instruction to both branch to a block and fallthrough 285 /// to it, so we check the actual branch operands to see if there are any 286 /// explicit mentions. 287 static bool ExplicitlyBranchesTo(MachineBasicBlock *Pred, 288 MachineBasicBlock *MBB) { 289 for (MachineInstr &MI : Pred->terminators()) 290 for (MachineOperand &MO : MI.explicit_operands()) 291 if (MO.isMBB() && MO.getMBB() == MBB) 292 return true; 293 return false; 294 } 295 296 /// Insert a BLOCK marker for branches to MBB (if needed). 297 static void PlaceBlockMarker( 298 MachineBasicBlock &MBB, MachineFunction &MF, 299 SmallVectorImpl<MachineBasicBlock *> &ScopeTops, 300 DenseMap<const MachineInstr *, MachineInstr *> &BlockTops, 301 DenseMap<const MachineInstr *, MachineInstr *> &LoopTops, 302 const WebAssemblyInstrInfo &TII, 303 const MachineLoopInfo &MLI, 304 MachineDominatorTree &MDT, 305 WebAssemblyFunctionInfo &MFI) { 306 // First compute the nearest common dominator of all forward non-fallthrough 307 // predecessors so that we minimize the time that the BLOCK is on the stack, 308 // which reduces overall stack height. 309 MachineBasicBlock *Header = nullptr; 310 bool IsBranchedTo = false; 311 int MBBNumber = MBB.getNumber(); 312 for (MachineBasicBlock *Pred : MBB.predecessors()) 313 if (Pred->getNumber() < MBBNumber) { 314 Header = Header ? MDT.findNearestCommonDominator(Header, Pred) : Pred; 315 if (ExplicitlyBranchesTo(Pred, &MBB)) 316 IsBranchedTo = true; 317 } 318 if (!Header) 319 return; 320 if (!IsBranchedTo) 321 return; 322 323 assert(&MBB != &MF.front() && "Header blocks shouldn't have predecessors"); 324 MachineBasicBlock *LayoutPred = &*std::prev(MachineFunction::iterator(&MBB)); 325 326 // If the nearest common dominator is inside a more deeply nested context, 327 // walk out to the nearest scope which isn't more deeply nested. 328 for (MachineFunction::iterator I(LayoutPred), E(Header); I != E; --I) { 329 if (MachineBasicBlock *ScopeTop = ScopeTops[I->getNumber()]) { 330 if (ScopeTop->getNumber() > Header->getNumber()) { 331 // Skip over an intervening scope. 332 I = std::next(MachineFunction::iterator(ScopeTop)); 333 } else { 334 // We found a scope level at an appropriate depth. 335 Header = ScopeTop; 336 break; 337 } 338 } 339 } 340 341 // Decide where in Header to put the BLOCK. 342 MachineBasicBlock::iterator InsertPos; 343 MachineLoop *HeaderLoop = MLI.getLoopFor(Header); 344 if (HeaderLoop && MBB.getNumber() > LoopBottom(HeaderLoop)->getNumber()) { 345 // Header is the header of a loop that does not lexically contain MBB, so 346 // the BLOCK needs to be above the LOOP, after any END constructs. 347 InsertPos = Header->begin(); 348 while (InsertPos->getOpcode() == WebAssembly::END_BLOCK || 349 InsertPos->getOpcode() == WebAssembly::END_LOOP) 350 ++InsertPos; 351 } else { 352 // Otherwise, insert the BLOCK as late in Header as we can, but before the 353 // beginning of the local expression tree and any nested BLOCKs. 354 InsertPos = Header->getFirstTerminator(); 355 while (InsertPos != Header->begin() && 356 WebAssembly::isChild(*std::prev(InsertPos), MFI) && 357 std::prev(InsertPos)->getOpcode() != WebAssembly::LOOP && 358 std::prev(InsertPos)->getOpcode() != WebAssembly::END_BLOCK && 359 std::prev(InsertPos)->getOpcode() != WebAssembly::END_LOOP) 360 --InsertPos; 361 } 362 363 // Add the BLOCK. 364 MachineInstr *Begin = BuildMI(*Header, InsertPos, DebugLoc(), 365 TII.get(WebAssembly::BLOCK)) 366 .addImm(int64_t(WebAssembly::ExprType::Void)); 367 368 // Mark the end of the block. 369 InsertPos = MBB.begin(); 370 while (InsertPos != MBB.end() && 371 InsertPos->getOpcode() == WebAssembly::END_LOOP && 372 LoopTops[&*InsertPos]->getParent()->getNumber() >= Header->getNumber()) 373 ++InsertPos; 374 MachineInstr *End = BuildMI(MBB, InsertPos, DebugLoc(), 375 TII.get(WebAssembly::END_BLOCK)); 376 BlockTops[End] = Begin; 377 378 // Track the farthest-spanning scope that ends at this point. 379 int Number = MBB.getNumber(); 380 if (!ScopeTops[Number] || 381 ScopeTops[Number]->getNumber() > Header->getNumber()) 382 ScopeTops[Number] = Header; 383 } 384 385 /// Insert a LOOP marker for a loop starting at MBB (if it's a loop header). 386 static void PlaceLoopMarker( 387 MachineBasicBlock &MBB, MachineFunction &MF, 388 SmallVectorImpl<MachineBasicBlock *> &ScopeTops, 389 DenseMap<const MachineInstr *, MachineInstr *> &LoopTops, 390 const WebAssemblyInstrInfo &TII, const MachineLoopInfo &MLI) { 391 MachineLoop *Loop = MLI.getLoopFor(&MBB); 392 if (!Loop || Loop->getHeader() != &MBB) 393 return; 394 395 // The operand of a LOOP is the first block after the loop. If the loop is the 396 // bottom of the function, insert a dummy block at the end. 397 MachineBasicBlock *Bottom = LoopBottom(Loop); 398 auto Iter = std::next(MachineFunction::iterator(Bottom)); 399 if (Iter == MF.end()) { 400 MachineBasicBlock *Label = MF.CreateMachineBasicBlock(); 401 // Give it a fake predecessor so that AsmPrinter prints its label. 402 Label->addSuccessor(Label); 403 MF.push_back(Label); 404 Iter = std::next(MachineFunction::iterator(Bottom)); 405 } 406 MachineBasicBlock *AfterLoop = &*Iter; 407 408 // Mark the beginning of the loop (after the end of any existing loop that 409 // ends here). 410 auto InsertPos = MBB.begin(); 411 while (InsertPos != MBB.end() && 412 InsertPos->getOpcode() == WebAssembly::END_LOOP) 413 ++InsertPos; 414 MachineInstr *Begin = BuildMI(MBB, InsertPos, DebugLoc(), 415 TII.get(WebAssembly::LOOP)) 416 .addImm(int64_t(WebAssembly::ExprType::Void)); 417 418 // Mark the end of the loop. 419 MachineInstr *End = BuildMI(*AfterLoop, AfterLoop->begin(), DebugLoc(), 420 TII.get(WebAssembly::END_LOOP)); 421 LoopTops[End] = Begin; 422 423 assert((!ScopeTops[AfterLoop->getNumber()] || 424 ScopeTops[AfterLoop->getNumber()]->getNumber() < MBB.getNumber()) && 425 "With block sorting the outermost loop for a block should be first."); 426 if (!ScopeTops[AfterLoop->getNumber()]) 427 ScopeTops[AfterLoop->getNumber()] = &MBB; 428 } 429 430 static unsigned 431 GetDepth(const SmallVectorImpl<const MachineBasicBlock *> &Stack, 432 const MachineBasicBlock *MBB) { 433 unsigned Depth = 0; 434 for (auto X : reverse(Stack)) { 435 if (X == MBB) 436 break; 437 ++Depth; 438 } 439 assert(Depth < Stack.size() && "Branch destination should be in scope"); 440 return Depth; 441 } 442 443 /// In normal assembly languages, when the end of a function is unreachable, 444 /// because the function ends in an infinite loop or a noreturn call or similar, 445 /// it isn't necessary to worry about the function return type at the end of 446 /// the function, because it's never reached. However, in WebAssembly, blocks 447 /// that end at the function end need to have a return type signature that 448 /// matches the function signature, even though it's unreachable. This function 449 /// checks for such cases and fixes up the signatures. 450 static void FixEndsAtEndOfFunction( 451 MachineFunction &MF, 452 const WebAssemblyFunctionInfo &MFI, 453 DenseMap<const MachineInstr *, MachineInstr *> &BlockTops, 454 DenseMap<const MachineInstr *, MachineInstr *> &LoopTops) { 455 assert(MFI.getResults().size() <= 1); 456 457 if (MFI.getResults().empty()) 458 return; 459 460 WebAssembly::ExprType retType; 461 switch (MFI.getResults().front().SimpleTy) { 462 case MVT::i32: retType = WebAssembly::ExprType::I32; break; 463 case MVT::i64: retType = WebAssembly::ExprType::I64; break; 464 case MVT::f32: retType = WebAssembly::ExprType::F32; break; 465 case MVT::f64: retType = WebAssembly::ExprType::F64; break; 466 case MVT::v16i8: retType = WebAssembly::ExprType::I8x16; break; 467 case MVT::v8i16: retType = WebAssembly::ExprType::I16x8; break; 468 case MVT::v4i32: retType = WebAssembly::ExprType::I32x4; break; 469 case MVT::v2i64: retType = WebAssembly::ExprType::I64x2; break; 470 case MVT::v4f32: retType = WebAssembly::ExprType::F32x4; break; 471 case MVT::v2f64: retType = WebAssembly::ExprType::F64x2; break; 472 default: llvm_unreachable("unexpected return type"); 473 } 474 475 for (MachineBasicBlock &MBB : reverse(MF)) { 476 for (MachineInstr &MI : reverse(MBB)) { 477 if (MI.isPosition() || MI.isDebugValue()) 478 continue; 479 if (MI.getOpcode() == WebAssembly::END_BLOCK) { 480 BlockTops[&MI]->getOperand(0).setImm(int32_t(retType)); 481 continue; 482 } 483 if (MI.getOpcode() == WebAssembly::END_LOOP) { 484 LoopTops[&MI]->getOperand(0).setImm(int32_t(retType)); 485 continue; 486 } 487 // Something other than an `end`. We're done. 488 return; 489 } 490 } 491 } 492 493 /// Insert LOOP and BLOCK markers at appropriate places. 494 static void PlaceMarkers(MachineFunction &MF, const MachineLoopInfo &MLI, 495 const WebAssemblyInstrInfo &TII, 496 MachineDominatorTree &MDT, 497 WebAssemblyFunctionInfo &MFI) { 498 // For each block whose label represents the end of a scope, record the block 499 // which holds the beginning of the scope. This will allow us to quickly skip 500 // over scoped regions when walking blocks. We allocate one more than the 501 // number of blocks in the function to accommodate for the possible fake block 502 // we may insert at the end. 503 SmallVector<MachineBasicBlock *, 8> ScopeTops(MF.getNumBlockIDs() + 1); 504 505 // For each LOOP_END, the corresponding LOOP. 506 DenseMap<const MachineInstr *, MachineInstr *> LoopTops; 507 508 // For each END_BLOCK, the corresponding BLOCK. 509 DenseMap<const MachineInstr *, MachineInstr *> BlockTops; 510 511 for (auto &MBB : MF) { 512 // Place the LOOP for MBB if MBB is the header of a loop. 513 PlaceLoopMarker(MBB, MF, ScopeTops, LoopTops, TII, MLI); 514 515 // Place the BLOCK for MBB if MBB is branched to from above. 516 PlaceBlockMarker(MBB, MF, ScopeTops, BlockTops, LoopTops, TII, MLI, MDT, MFI); 517 } 518 519 // Now rewrite references to basic blocks to be depth immediates. 520 SmallVector<const MachineBasicBlock *, 8> Stack; 521 for (auto &MBB : reverse(MF)) { 522 for (auto &MI : reverse(MBB)) { 523 switch (MI.getOpcode()) { 524 case WebAssembly::BLOCK: 525 assert(ScopeTops[Stack.back()->getNumber()]->getNumber() <= MBB.getNumber() && 526 "Block should be balanced"); 527 Stack.pop_back(); 528 break; 529 case WebAssembly::LOOP: 530 assert(Stack.back() == &MBB && "Loop top should be balanced"); 531 Stack.pop_back(); 532 break; 533 case WebAssembly::END_BLOCK: 534 Stack.push_back(&MBB); 535 break; 536 case WebAssembly::END_LOOP: 537 Stack.push_back(LoopTops[&MI]->getParent()); 538 break; 539 default: 540 if (MI.isTerminator()) { 541 // Rewrite MBB operands to be depth immediates. 542 SmallVector<MachineOperand, 4> Ops(MI.operands()); 543 while (MI.getNumOperands() > 0) 544 MI.RemoveOperand(MI.getNumOperands() - 1); 545 for (auto MO : Ops) { 546 if (MO.isMBB()) 547 MO = MachineOperand::CreateImm(GetDepth(Stack, MO.getMBB())); 548 MI.addOperand(MF, MO); 549 } 550 } 551 break; 552 } 553 } 554 } 555 assert(Stack.empty() && "Control flow should be balanced"); 556 557 // Fix up block/loop signatures at the end of the function to conform to 558 // WebAssembly's rules. 559 FixEndsAtEndOfFunction(MF, MFI, BlockTops, LoopTops); 560 } 561 562 bool WebAssemblyCFGStackify::runOnMachineFunction(MachineFunction &MF) { 563 DEBUG(dbgs() << "********** CFG Stackifying **********\n" 564 "********** Function: " 565 << MF.getName() << '\n'); 566 567 const auto &MLI = getAnalysis<MachineLoopInfo>(); 568 auto &MDT = getAnalysis<MachineDominatorTree>(); 569 // Liveness is not tracked for VALUE_STACK physreg. 570 const auto &TII = *MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo(); 571 WebAssemblyFunctionInfo &MFI = *MF.getInfo<WebAssemblyFunctionInfo>(); 572 MF.getRegInfo().invalidateLiveness(); 573 574 // Sort the blocks, with contiguous loops. 575 SortBlocks(MF, MLI, MDT); 576 577 // Place the BLOCK and LOOP markers to indicate the beginnings of scopes. 578 PlaceMarkers(MF, MLI, TII, MDT, MFI); 579 580 return true; 581 } 582