1 //===-- WebAssemblyCFGStackify.cpp - CFG Stackification -------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 /// 9 /// \file 10 /// This file implements a CFG stacking pass. 11 /// 12 /// This pass inserts BLOCK, LOOP, and TRY markers to mark the start of scopes, 13 /// since scope boundaries serve as the labels for WebAssembly's control 14 /// transfers. 15 /// 16 /// This is sufficient to convert arbitrary CFGs into a form that works on 17 /// WebAssembly, provided that all loops are single-entry. 18 /// 19 /// In case we use exceptions, this pass also fixes mismatches in unwind 20 /// destinations created during transforming CFG into wasm structured format. 21 /// 22 //===----------------------------------------------------------------------===// 23 24 #include "WebAssembly.h" 25 #include "WebAssemblyExceptionInfo.h" 26 #include "WebAssemblyMachineFunctionInfo.h" 27 #include "WebAssemblySortRegion.h" 28 #include "WebAssemblySubtarget.h" 29 #include "WebAssemblyUtilities.h" 30 #include "llvm/ADT/Statistic.h" 31 #include "llvm/CodeGen/MachineDominators.h" 32 #include "llvm/CodeGen/MachineInstrBuilder.h" 33 #include "llvm/CodeGen/MachineLoopInfo.h" 34 #include "llvm/MC/MCAsmInfo.h" 35 #include "llvm/Target/TargetMachine.h" 36 using namespace llvm; 37 using WebAssembly::SortRegionInfo; 38 39 #define DEBUG_TYPE "wasm-cfg-stackify" 40 41 STATISTIC(NumUnwindMismatches, "Number of EH pad unwind mismatches found"); 42 43 namespace { 44 class WebAssemblyCFGStackify final : public MachineFunctionPass { 45 StringRef getPassName() const override { return "WebAssembly CFG Stackify"; } 46 47 void getAnalysisUsage(AnalysisUsage &AU) const override { 48 AU.addRequired<MachineDominatorTree>(); 49 AU.addRequired<MachineLoopInfo>(); 50 AU.addRequired<WebAssemblyExceptionInfo>(); 51 MachineFunctionPass::getAnalysisUsage(AU); 52 } 53 54 bool runOnMachineFunction(MachineFunction &MF) override; 55 56 // For each block whose label represents the end of a scope, record the block 57 // which holds the beginning of the scope. This will allow us to quickly skip 58 // over scoped regions when walking blocks. 59 SmallVector<MachineBasicBlock *, 8> ScopeTops; 60 61 // Placing markers. 62 void placeMarkers(MachineFunction &MF); 63 void placeBlockMarker(MachineBasicBlock &MBB); 64 void placeLoopMarker(MachineBasicBlock &MBB); 65 void placeTryMarker(MachineBasicBlock &MBB); 66 void removeUnnecessaryInstrs(MachineFunction &MF); 67 bool fixUnwindMismatches(MachineFunction &MF); 68 void rewriteDepthImmediates(MachineFunction &MF); 69 void fixEndsAtEndOfFunction(MachineFunction &MF); 70 71 // For each BLOCK|LOOP|TRY, the corresponding END_(BLOCK|LOOP|TRY). 72 DenseMap<const MachineInstr *, MachineInstr *> BeginToEnd; 73 // For each END_(BLOCK|LOOP|TRY), the corresponding BLOCK|LOOP|TRY. 74 DenseMap<const MachineInstr *, MachineInstr *> EndToBegin; 75 // <TRY marker, EH pad> map 76 DenseMap<const MachineInstr *, MachineBasicBlock *> TryToEHPad; 77 // <EH pad, TRY marker> map 78 DenseMap<const MachineBasicBlock *, MachineInstr *> EHPadToTry; 79 80 // There can be an appendix block at the end of each function, shared for: 81 // - creating a correct signature for fallthrough returns 82 // - target for rethrows that need to unwind to the caller, but are trapped 83 // inside another try/catch 84 MachineBasicBlock *AppendixBB = nullptr; 85 MachineBasicBlock *getAppendixBlock(MachineFunction &MF) { 86 if (!AppendixBB) { 87 AppendixBB = MF.CreateMachineBasicBlock(); 88 // Give it a fake predecessor so that AsmPrinter prints its label. 89 AppendixBB->addSuccessor(AppendixBB); 90 MF.push_back(AppendixBB); 91 } 92 return AppendixBB; 93 } 94 95 // Helper functions to register / unregister scope information created by 96 // marker instructions. 97 void registerScope(MachineInstr *Begin, MachineInstr *End); 98 void registerTryScope(MachineInstr *Begin, MachineInstr *End, 99 MachineBasicBlock *EHPad); 100 void unregisterScope(MachineInstr *Begin); 101 102 public: 103 static char ID; // Pass identification, replacement for typeid 104 WebAssemblyCFGStackify() : MachineFunctionPass(ID) {} 105 ~WebAssemblyCFGStackify() override { releaseMemory(); } 106 void releaseMemory() override; 107 }; 108 } // end anonymous namespace 109 110 char WebAssemblyCFGStackify::ID = 0; 111 INITIALIZE_PASS(WebAssemblyCFGStackify, DEBUG_TYPE, 112 "Insert BLOCK/LOOP/TRY markers for WebAssembly scopes", false, 113 false) 114 115 FunctionPass *llvm::createWebAssemblyCFGStackify() { 116 return new WebAssemblyCFGStackify(); 117 } 118 119 /// Test whether Pred has any terminators explicitly branching to MBB, as 120 /// opposed to falling through. Note that it's possible (eg. in unoptimized 121 /// code) for a branch instruction to both branch to a block and fallthrough 122 /// to it, so we check the actual branch operands to see if there are any 123 /// explicit mentions. 124 static bool explicitlyBranchesTo(MachineBasicBlock *Pred, 125 MachineBasicBlock *MBB) { 126 for (MachineInstr &MI : Pred->terminators()) 127 for (MachineOperand &MO : MI.explicit_operands()) 128 if (MO.isMBB() && MO.getMBB() == MBB) 129 return true; 130 return false; 131 } 132 133 // Returns an iterator to the earliest position possible within the MBB, 134 // satisfying the restrictions given by BeforeSet and AfterSet. BeforeSet 135 // contains instructions that should go before the marker, and AfterSet contains 136 // ones that should go after the marker. In this function, AfterSet is only 137 // used for sanity checking. 138 static MachineBasicBlock::iterator 139 getEarliestInsertPos(MachineBasicBlock *MBB, 140 const SmallPtrSet<const MachineInstr *, 4> &BeforeSet, 141 const SmallPtrSet<const MachineInstr *, 4> &AfterSet) { 142 auto InsertPos = MBB->end(); 143 while (InsertPos != MBB->begin()) { 144 if (BeforeSet.count(&*std::prev(InsertPos))) { 145 #ifndef NDEBUG 146 // Sanity check 147 for (auto Pos = InsertPos, E = MBB->begin(); Pos != E; --Pos) 148 assert(!AfterSet.count(&*std::prev(Pos))); 149 #endif 150 break; 151 } 152 --InsertPos; 153 } 154 return InsertPos; 155 } 156 157 // Returns an iterator to the latest position possible within the MBB, 158 // satisfying the restrictions given by BeforeSet and AfterSet. BeforeSet 159 // contains instructions that should go before the marker, and AfterSet contains 160 // ones that should go after the marker. In this function, BeforeSet is only 161 // used for sanity checking. 162 static MachineBasicBlock::iterator 163 getLatestInsertPos(MachineBasicBlock *MBB, 164 const SmallPtrSet<const MachineInstr *, 4> &BeforeSet, 165 const SmallPtrSet<const MachineInstr *, 4> &AfterSet) { 166 auto InsertPos = MBB->begin(); 167 while (InsertPos != MBB->end()) { 168 if (AfterSet.count(&*InsertPos)) { 169 #ifndef NDEBUG 170 // Sanity check 171 for (auto Pos = InsertPos, E = MBB->end(); Pos != E; ++Pos) 172 assert(!BeforeSet.count(&*Pos)); 173 #endif 174 break; 175 } 176 ++InsertPos; 177 } 178 return InsertPos; 179 } 180 181 // Find a catch instruction and its destination register within an EH pad. 182 static MachineInstr *findCatch(MachineBasicBlock *EHPad, Register &ExnReg) { 183 assert(EHPad->isEHPad()); 184 MachineInstr *Catch = nullptr; 185 for (auto &MI : *EHPad) { 186 if (WebAssembly::isCatch(MI.getOpcode())) { 187 Catch = &MI; 188 ExnReg = Catch->getOperand(0).getReg(); 189 break; 190 } 191 } 192 assert(Catch && "EH pad does not have a catch"); 193 assert(ExnReg != 0 && "Invalid register"); 194 return Catch; 195 } 196 197 static MachineInstr *findCatch(MachineBasicBlock *EHPad) { 198 Register Dummy; 199 return findCatch(EHPad, Dummy); 200 } 201 202 void WebAssemblyCFGStackify::registerScope(MachineInstr *Begin, 203 MachineInstr *End) { 204 BeginToEnd[Begin] = End; 205 EndToBegin[End] = Begin; 206 } 207 208 void WebAssemblyCFGStackify::registerTryScope(MachineInstr *Begin, 209 MachineInstr *End, 210 MachineBasicBlock *EHPad) { 211 registerScope(Begin, End); 212 TryToEHPad[Begin] = EHPad; 213 EHPadToTry[EHPad] = Begin; 214 } 215 216 void WebAssemblyCFGStackify::unregisterScope(MachineInstr *Begin) { 217 assert(BeginToEnd.count(Begin)); 218 MachineInstr *End = BeginToEnd[Begin]; 219 assert(EndToBegin.count(End)); 220 BeginToEnd.erase(Begin); 221 EndToBegin.erase(End); 222 MachineBasicBlock *EHPad = TryToEHPad.lookup(Begin); 223 if (EHPad) { 224 assert(EHPadToTry.count(EHPad)); 225 TryToEHPad.erase(Begin); 226 EHPadToTry.erase(EHPad); 227 } 228 } 229 230 /// Insert a BLOCK marker for branches to MBB (if needed). 231 // TODO Consider a more generalized way of handling block (and also loop and 232 // try) signatures when we implement the multi-value proposal later. 233 void WebAssemblyCFGStackify::placeBlockMarker(MachineBasicBlock &MBB) { 234 assert(!MBB.isEHPad()); 235 MachineFunction &MF = *MBB.getParent(); 236 auto &MDT = getAnalysis<MachineDominatorTree>(); 237 const auto &TII = *MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo(); 238 const auto &MFI = *MF.getInfo<WebAssemblyFunctionInfo>(); 239 240 // First compute the nearest common dominator of all forward non-fallthrough 241 // predecessors so that we minimize the time that the BLOCK is on the stack, 242 // which reduces overall stack height. 243 MachineBasicBlock *Header = nullptr; 244 bool IsBranchedTo = false; 245 int MBBNumber = MBB.getNumber(); 246 for (MachineBasicBlock *Pred : MBB.predecessors()) { 247 if (Pred->getNumber() < MBBNumber) { 248 Header = Header ? MDT.findNearestCommonDominator(Header, Pred) : Pred; 249 if (explicitlyBranchesTo(Pred, &MBB)) 250 IsBranchedTo = true; 251 } 252 } 253 if (!Header) 254 return; 255 if (!IsBranchedTo) 256 return; 257 258 assert(&MBB != &MF.front() && "Header blocks shouldn't have predecessors"); 259 MachineBasicBlock *LayoutPred = MBB.getPrevNode(); 260 261 // If the nearest common dominator is inside a more deeply nested context, 262 // walk out to the nearest scope which isn't more deeply nested. 263 for (MachineFunction::iterator I(LayoutPred), E(Header); I != E; --I) { 264 if (MachineBasicBlock *ScopeTop = ScopeTops[I->getNumber()]) { 265 if (ScopeTop->getNumber() > Header->getNumber()) { 266 // Skip over an intervening scope. 267 I = std::next(ScopeTop->getIterator()); 268 } else { 269 // We found a scope level at an appropriate depth. 270 Header = ScopeTop; 271 break; 272 } 273 } 274 } 275 276 // Decide where in Header to put the BLOCK. 277 278 // Instructions that should go before the BLOCK. 279 SmallPtrSet<const MachineInstr *, 4> BeforeSet; 280 // Instructions that should go after the BLOCK. 281 SmallPtrSet<const MachineInstr *, 4> AfterSet; 282 for (const auto &MI : *Header) { 283 // If there is a previously placed LOOP marker and the bottom block of the 284 // loop is above MBB, it should be after the BLOCK, because the loop is 285 // nested in this BLOCK. Otherwise it should be before the BLOCK. 286 if (MI.getOpcode() == WebAssembly::LOOP) { 287 auto *LoopBottom = BeginToEnd[&MI]->getParent()->getPrevNode(); 288 if (MBB.getNumber() > LoopBottom->getNumber()) 289 AfterSet.insert(&MI); 290 #ifndef NDEBUG 291 else 292 BeforeSet.insert(&MI); 293 #endif 294 } 295 296 // If there is a previously placed BLOCK/TRY marker and its corresponding 297 // END marker is before the current BLOCK's END marker, that should be 298 // placed after this BLOCK. Otherwise it should be placed before this BLOCK 299 // marker. 300 if (MI.getOpcode() == WebAssembly::BLOCK || 301 MI.getOpcode() == WebAssembly::TRY) { 302 if (BeginToEnd[&MI]->getParent()->getNumber() <= MBB.getNumber()) 303 AfterSet.insert(&MI); 304 #ifndef NDEBUG 305 else 306 BeforeSet.insert(&MI); 307 #endif 308 } 309 310 #ifndef NDEBUG 311 // All END_(BLOCK|LOOP|TRY) markers should be before the BLOCK. 312 if (MI.getOpcode() == WebAssembly::END_BLOCK || 313 MI.getOpcode() == WebAssembly::END_LOOP || 314 MI.getOpcode() == WebAssembly::END_TRY) 315 BeforeSet.insert(&MI); 316 #endif 317 318 // Terminators should go after the BLOCK. 319 if (MI.isTerminator()) 320 AfterSet.insert(&MI); 321 } 322 323 // Local expression tree should go after the BLOCK. 324 for (auto I = Header->getFirstTerminator(), E = Header->begin(); I != E; 325 --I) { 326 if (std::prev(I)->isDebugInstr() || std::prev(I)->isPosition()) 327 continue; 328 if (WebAssembly::isChild(*std::prev(I), MFI)) 329 AfterSet.insert(&*std::prev(I)); 330 else 331 break; 332 } 333 334 // Add the BLOCK. 335 WebAssembly::BlockType ReturnType = WebAssembly::BlockType::Void; 336 auto InsertPos = getLatestInsertPos(Header, BeforeSet, AfterSet); 337 MachineInstr *Begin = 338 BuildMI(*Header, InsertPos, Header->findDebugLoc(InsertPos), 339 TII.get(WebAssembly::BLOCK)) 340 .addImm(int64_t(ReturnType)); 341 342 // Decide where in Header to put the END_BLOCK. 343 BeforeSet.clear(); 344 AfterSet.clear(); 345 for (auto &MI : MBB) { 346 #ifndef NDEBUG 347 // END_BLOCK should precede existing LOOP and TRY markers. 348 if (MI.getOpcode() == WebAssembly::LOOP || 349 MI.getOpcode() == WebAssembly::TRY) 350 AfterSet.insert(&MI); 351 #endif 352 353 // If there is a previously placed END_LOOP marker and the header of the 354 // loop is above this block's header, the END_LOOP should be placed after 355 // the BLOCK, because the loop contains this block. Otherwise the END_LOOP 356 // should be placed before the BLOCK. The same for END_TRY. 357 if (MI.getOpcode() == WebAssembly::END_LOOP || 358 MI.getOpcode() == WebAssembly::END_TRY) { 359 if (EndToBegin[&MI]->getParent()->getNumber() >= Header->getNumber()) 360 BeforeSet.insert(&MI); 361 #ifndef NDEBUG 362 else 363 AfterSet.insert(&MI); 364 #endif 365 } 366 } 367 368 // Mark the end of the block. 369 InsertPos = getEarliestInsertPos(&MBB, BeforeSet, AfterSet); 370 MachineInstr *End = BuildMI(MBB, InsertPos, MBB.findPrevDebugLoc(InsertPos), 371 TII.get(WebAssembly::END_BLOCK)); 372 registerScope(Begin, End); 373 374 // Track the farthest-spanning scope that ends at this point. 375 int Number = MBB.getNumber(); 376 if (!ScopeTops[Number] || 377 ScopeTops[Number]->getNumber() > Header->getNumber()) 378 ScopeTops[Number] = Header; 379 } 380 381 /// Insert a LOOP marker for a loop starting at MBB (if it's a loop header). 382 void WebAssemblyCFGStackify::placeLoopMarker(MachineBasicBlock &MBB) { 383 MachineFunction &MF = *MBB.getParent(); 384 const auto &MLI = getAnalysis<MachineLoopInfo>(); 385 const auto &WEI = getAnalysis<WebAssemblyExceptionInfo>(); 386 SortRegionInfo SRI(MLI, WEI); 387 const auto &TII = *MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo(); 388 389 MachineLoop *Loop = MLI.getLoopFor(&MBB); 390 if (!Loop || Loop->getHeader() != &MBB) 391 return; 392 393 // The operand of a LOOP is the first block after the loop. If the loop is the 394 // bottom of the function, insert a dummy block at the end. 395 MachineBasicBlock *Bottom = SRI.getBottom(Loop); 396 auto Iter = std::next(Bottom->getIterator()); 397 if (Iter == MF.end()) { 398 getAppendixBlock(MF); 399 Iter = std::next(Bottom->getIterator()); 400 } 401 MachineBasicBlock *AfterLoop = &*Iter; 402 403 // Decide where in Header to put the LOOP. 404 SmallPtrSet<const MachineInstr *, 4> BeforeSet; 405 SmallPtrSet<const MachineInstr *, 4> AfterSet; 406 for (const auto &MI : MBB) { 407 // LOOP marker should be after any existing loop that ends here. Otherwise 408 // we assume the instruction belongs to the loop. 409 if (MI.getOpcode() == WebAssembly::END_LOOP) 410 BeforeSet.insert(&MI); 411 #ifndef NDEBUG 412 else 413 AfterSet.insert(&MI); 414 #endif 415 } 416 417 // Mark the beginning of the loop. 418 auto InsertPos = getEarliestInsertPos(&MBB, BeforeSet, AfterSet); 419 MachineInstr *Begin = BuildMI(MBB, InsertPos, MBB.findDebugLoc(InsertPos), 420 TII.get(WebAssembly::LOOP)) 421 .addImm(int64_t(WebAssembly::BlockType::Void)); 422 423 // Decide where in Header to put the END_LOOP. 424 BeforeSet.clear(); 425 AfterSet.clear(); 426 #ifndef NDEBUG 427 for (const auto &MI : MBB) 428 // Existing END_LOOP markers belong to parent loops of this loop 429 if (MI.getOpcode() == WebAssembly::END_LOOP) 430 AfterSet.insert(&MI); 431 #endif 432 433 // Mark the end of the loop (using arbitrary debug location that branched to 434 // the loop end as its location). 435 InsertPos = getEarliestInsertPos(AfterLoop, BeforeSet, AfterSet); 436 DebugLoc EndDL = AfterLoop->pred_empty() 437 ? DebugLoc() 438 : (*AfterLoop->pred_rbegin())->findBranchDebugLoc(); 439 MachineInstr *End = 440 BuildMI(*AfterLoop, InsertPos, EndDL, TII.get(WebAssembly::END_LOOP)); 441 registerScope(Begin, End); 442 443 assert((!ScopeTops[AfterLoop->getNumber()] || 444 ScopeTops[AfterLoop->getNumber()]->getNumber() < MBB.getNumber()) && 445 "With block sorting the outermost loop for a block should be first."); 446 if (!ScopeTops[AfterLoop->getNumber()]) 447 ScopeTops[AfterLoop->getNumber()] = &MBB; 448 } 449 450 void WebAssemblyCFGStackify::placeTryMarker(MachineBasicBlock &MBB) { 451 assert(MBB.isEHPad()); 452 MachineFunction &MF = *MBB.getParent(); 453 auto &MDT = getAnalysis<MachineDominatorTree>(); 454 const auto &TII = *MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo(); 455 const auto &MLI = getAnalysis<MachineLoopInfo>(); 456 const auto &WEI = getAnalysis<WebAssemblyExceptionInfo>(); 457 SortRegionInfo SRI(MLI, WEI); 458 const auto &MFI = *MF.getInfo<WebAssemblyFunctionInfo>(); 459 460 // Compute the nearest common dominator of all unwind predecessors 461 MachineBasicBlock *Header = nullptr; 462 int MBBNumber = MBB.getNumber(); 463 for (auto *Pred : MBB.predecessors()) { 464 if (Pred->getNumber() < MBBNumber) { 465 Header = Header ? MDT.findNearestCommonDominator(Header, Pred) : Pred; 466 assert(!explicitlyBranchesTo(Pred, &MBB) && 467 "Explicit branch to an EH pad!"); 468 } 469 } 470 if (!Header) 471 return; 472 473 // If this try is at the bottom of the function, insert a dummy block at the 474 // end. 475 WebAssemblyException *WE = WEI.getExceptionFor(&MBB); 476 assert(WE); 477 MachineBasicBlock *Bottom = SRI.getBottom(WE); 478 479 auto Iter = std::next(Bottom->getIterator()); 480 if (Iter == MF.end()) { 481 getAppendixBlock(MF); 482 Iter = std::next(Bottom->getIterator()); 483 } 484 MachineBasicBlock *Cont = &*Iter; 485 486 assert(Cont != &MF.front()); 487 MachineBasicBlock *LayoutPred = Cont->getPrevNode(); 488 489 // If the nearest common dominator is inside a more deeply nested context, 490 // walk out to the nearest scope which isn't more deeply nested. 491 for (MachineFunction::iterator I(LayoutPred), E(Header); I != E; --I) { 492 if (MachineBasicBlock *ScopeTop = ScopeTops[I->getNumber()]) { 493 if (ScopeTop->getNumber() > Header->getNumber()) { 494 // Skip over an intervening scope. 495 I = std::next(ScopeTop->getIterator()); 496 } else { 497 // We found a scope level at an appropriate depth. 498 Header = ScopeTop; 499 break; 500 } 501 } 502 } 503 504 // Decide where in Header to put the TRY. 505 506 // Instructions that should go before the TRY. 507 SmallPtrSet<const MachineInstr *, 4> BeforeSet; 508 // Instructions that should go after the TRY. 509 SmallPtrSet<const MachineInstr *, 4> AfterSet; 510 for (const auto &MI : *Header) { 511 // If there is a previously placed LOOP marker and the bottom block of the 512 // loop is above MBB, it should be after the TRY, because the loop is nested 513 // in this TRY. Otherwise it should be before the TRY. 514 if (MI.getOpcode() == WebAssembly::LOOP) { 515 auto *LoopBottom = BeginToEnd[&MI]->getParent()->getPrevNode(); 516 if (MBB.getNumber() > LoopBottom->getNumber()) 517 AfterSet.insert(&MI); 518 #ifndef NDEBUG 519 else 520 BeforeSet.insert(&MI); 521 #endif 522 } 523 524 // All previously inserted BLOCK/TRY markers should be after the TRY because 525 // they are all nested trys. 526 if (MI.getOpcode() == WebAssembly::BLOCK || 527 MI.getOpcode() == WebAssembly::TRY) 528 AfterSet.insert(&MI); 529 530 #ifndef NDEBUG 531 // All END_(BLOCK/LOOP/TRY) markers should be before the TRY. 532 if (MI.getOpcode() == WebAssembly::END_BLOCK || 533 MI.getOpcode() == WebAssembly::END_LOOP || 534 MI.getOpcode() == WebAssembly::END_TRY) 535 BeforeSet.insert(&MI); 536 #endif 537 538 // Terminators should go after the TRY. 539 if (MI.isTerminator()) 540 AfterSet.insert(&MI); 541 } 542 543 // If Header unwinds to MBB (= Header contains 'invoke'), the try block should 544 // contain the call within it. So the call should go after the TRY. The 545 // exception is when the header's terminator is a rethrow instruction, in 546 // which case that instruction, not a call instruction before it, is gonna 547 // throw. 548 MachineInstr *ThrowingCall = nullptr; 549 if (MBB.isPredecessor(Header)) { 550 auto TermPos = Header->getFirstTerminator(); 551 if (TermPos == Header->end() || 552 TermPos->getOpcode() != WebAssembly::RETHROW) { 553 for (auto &MI : reverse(*Header)) { 554 if (MI.isCall()) { 555 AfterSet.insert(&MI); 556 ThrowingCall = &MI; 557 // Possibly throwing calls are usually wrapped by EH_LABEL 558 // instructions. We don't want to split them and the call. 559 if (MI.getIterator() != Header->begin() && 560 std::prev(MI.getIterator())->isEHLabel()) { 561 AfterSet.insert(&*std::prev(MI.getIterator())); 562 ThrowingCall = &*std::prev(MI.getIterator()); 563 } 564 break; 565 } 566 } 567 } 568 } 569 570 // Local expression tree should go after the TRY. 571 // For BLOCK placement, we start the search from the previous instruction of a 572 // BB's terminator, but in TRY's case, we should start from the previous 573 // instruction of a call that can throw, or a EH_LABEL that precedes the call, 574 // because the return values of the call's previous instructions can be 575 // stackified and consumed by the throwing call. 576 auto SearchStartPt = ThrowingCall ? MachineBasicBlock::iterator(ThrowingCall) 577 : Header->getFirstTerminator(); 578 for (auto I = SearchStartPt, E = Header->begin(); I != E; --I) { 579 if (std::prev(I)->isDebugInstr() || std::prev(I)->isPosition()) 580 continue; 581 if (WebAssembly::isChild(*std::prev(I), MFI)) 582 AfterSet.insert(&*std::prev(I)); 583 else 584 break; 585 } 586 587 // Add the TRY. 588 auto InsertPos = getLatestInsertPos(Header, BeforeSet, AfterSet); 589 MachineInstr *Begin = 590 BuildMI(*Header, InsertPos, Header->findDebugLoc(InsertPos), 591 TII.get(WebAssembly::TRY)) 592 .addImm(int64_t(WebAssembly::BlockType::Void)); 593 594 // Decide where in Header to put the END_TRY. 595 BeforeSet.clear(); 596 AfterSet.clear(); 597 for (const auto &MI : *Cont) { 598 #ifndef NDEBUG 599 // END_TRY should precede existing LOOP and BLOCK markers. 600 if (MI.getOpcode() == WebAssembly::LOOP || 601 MI.getOpcode() == WebAssembly::BLOCK) 602 AfterSet.insert(&MI); 603 604 // All END_TRY markers placed earlier belong to exceptions that contains 605 // this one. 606 if (MI.getOpcode() == WebAssembly::END_TRY) 607 AfterSet.insert(&MI); 608 #endif 609 610 // If there is a previously placed END_LOOP marker and its header is after 611 // where TRY marker is, this loop is contained within the 'catch' part, so 612 // the END_TRY marker should go after that. Otherwise, the whole try-catch 613 // is contained within this loop, so the END_TRY should go before that. 614 if (MI.getOpcode() == WebAssembly::END_LOOP) { 615 // For a LOOP to be after TRY, LOOP's BB should be after TRY's BB; if they 616 // are in the same BB, LOOP is always before TRY. 617 if (EndToBegin[&MI]->getParent()->getNumber() > Header->getNumber()) 618 BeforeSet.insert(&MI); 619 #ifndef NDEBUG 620 else 621 AfterSet.insert(&MI); 622 #endif 623 } 624 625 // It is not possible for an END_BLOCK to be already in this block. 626 } 627 628 // Mark the end of the TRY. 629 InsertPos = getEarliestInsertPos(Cont, BeforeSet, AfterSet); 630 MachineInstr *End = 631 BuildMI(*Cont, InsertPos, Bottom->findBranchDebugLoc(), 632 TII.get(WebAssembly::END_TRY)); 633 registerTryScope(Begin, End, &MBB); 634 635 // Track the farthest-spanning scope that ends at this point. We create two 636 // mappings: (BB with 'end_try' -> BB with 'try') and (BB with 'catch' -> BB 637 // with 'try'). We need to create 'catch' -> 'try' mapping here too because 638 // markers should not span across 'catch'. For example, this should not 639 // happen: 640 // 641 // try 642 // block --| (X) 643 // catch | 644 // end_block --| 645 // end_try 646 for (int Number : {Cont->getNumber(), MBB.getNumber()}) { 647 if (!ScopeTops[Number] || 648 ScopeTops[Number]->getNumber() > Header->getNumber()) 649 ScopeTops[Number] = Header; 650 } 651 } 652 653 void WebAssemblyCFGStackify::removeUnnecessaryInstrs(MachineFunction &MF) { 654 const auto &TII = *MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo(); 655 656 // When there is an unconditional branch right before a catch instruction and 657 // it branches to the end of end_try marker, we don't need the branch, because 658 // it there is no exception, the control flow transfers to that point anyway. 659 // bb0: 660 // try 661 // ... 662 // br bb2 <- Not necessary 663 // bb1: 664 // catch 665 // ... 666 // bb2: 667 // end 668 for (auto &MBB : MF) { 669 if (!MBB.isEHPad()) 670 continue; 671 672 MachineBasicBlock *TBB = nullptr, *FBB = nullptr; 673 SmallVector<MachineOperand, 4> Cond; 674 MachineBasicBlock *EHPadLayoutPred = MBB.getPrevNode(); 675 MachineBasicBlock *Cont = BeginToEnd[EHPadToTry[&MBB]]->getParent(); 676 bool Analyzable = !TII.analyzeBranch(*EHPadLayoutPred, TBB, FBB, Cond); 677 // This condition means either 678 // 1. This BB ends with a single unconditional branch whose destinaion is 679 // Cont. 680 // 2. This BB ends with a conditional branch followed by an unconditional 681 // branch, and the unconditional branch's destination is Cont. 682 // In both cases, we want to remove the last (= unconditional) branch. 683 if (Analyzable && ((Cond.empty() && TBB && TBB == Cont) || 684 (!Cond.empty() && FBB && FBB == Cont))) { 685 bool ErasedUncondBr = false; 686 (void)ErasedUncondBr; 687 for (auto I = EHPadLayoutPred->end(), E = EHPadLayoutPred->begin(); 688 I != E; --I) { 689 auto PrevI = std::prev(I); 690 if (PrevI->isTerminator()) { 691 assert(PrevI->getOpcode() == WebAssembly::BR); 692 PrevI->eraseFromParent(); 693 ErasedUncondBr = true; 694 break; 695 } 696 } 697 assert(ErasedUncondBr && "Unconditional branch not erased!"); 698 } 699 } 700 701 // When there are block / end_block markers that overlap with try / end_try 702 // markers, and the block and try markers' return types are the same, the 703 // block /end_block markers are not necessary, because try / end_try markers 704 // also can serve as boundaries for branches. 705 // block <- Not necessary 706 // try 707 // ... 708 // catch 709 // ... 710 // end 711 // end <- Not necessary 712 SmallVector<MachineInstr *, 32> ToDelete; 713 for (auto &MBB : MF) { 714 for (auto &MI : MBB) { 715 if (MI.getOpcode() != WebAssembly::TRY) 716 continue; 717 718 MachineInstr *Try = &MI, *EndTry = BeginToEnd[Try]; 719 MachineBasicBlock *TryBB = Try->getParent(); 720 MachineBasicBlock *Cont = EndTry->getParent(); 721 int64_t RetType = Try->getOperand(0).getImm(); 722 for (auto B = Try->getIterator(), E = std::next(EndTry->getIterator()); 723 B != TryBB->begin() && E != Cont->end() && 724 std::prev(B)->getOpcode() == WebAssembly::BLOCK && 725 E->getOpcode() == WebAssembly::END_BLOCK && 726 std::prev(B)->getOperand(0).getImm() == RetType; 727 --B, ++E) { 728 ToDelete.push_back(&*std::prev(B)); 729 ToDelete.push_back(&*E); 730 } 731 } 732 } 733 for (auto *MI : ToDelete) { 734 if (MI->getOpcode() == WebAssembly::BLOCK) 735 unregisterScope(MI); 736 MI->eraseFromParent(); 737 } 738 } 739 740 // Get the appropriate copy opcode for the given register class. 741 static unsigned getCopyOpcode(const TargetRegisterClass *RC) { 742 if (RC == &WebAssembly::I32RegClass) 743 return WebAssembly::COPY_I32; 744 if (RC == &WebAssembly::I64RegClass) 745 return WebAssembly::COPY_I64; 746 if (RC == &WebAssembly::F32RegClass) 747 return WebAssembly::COPY_F32; 748 if (RC == &WebAssembly::F64RegClass) 749 return WebAssembly::COPY_F64; 750 if (RC == &WebAssembly::V128RegClass) 751 return WebAssembly::COPY_V128; 752 if (RC == &WebAssembly::FUNCREFRegClass) 753 return WebAssembly::COPY_FUNCREF; 754 if (RC == &WebAssembly::EXTERNREFRegClass) 755 return WebAssembly::COPY_EXTERNREF; 756 llvm_unreachable("Unexpected register class"); 757 } 758 759 // When MBB is split into MBB and Split, we should unstackify defs in MBB that 760 // have their uses in Split. 761 // FIXME This function will be used when fixing unwind mismatches, but the old 762 // version of that function was removed for the moment and the new version has 763 // not yet been added. So 'LLVM_ATTRIBUTE_UNUSED' is added to suppress the 764 // warning. Remove the attribute after the new functionality is added. 765 LLVM_ATTRIBUTE_UNUSED static void 766 unstackifyVRegsUsedInSplitBB(MachineBasicBlock &MBB, MachineBasicBlock &Split, 767 WebAssemblyFunctionInfo &MFI, 768 MachineRegisterInfo &MRI, 769 const WebAssemblyInstrInfo &TII) { 770 for (auto &MI : Split) { 771 for (auto &MO : MI.explicit_uses()) { 772 if (!MO.isReg() || Register::isPhysicalRegister(MO.getReg())) 773 continue; 774 if (MachineInstr *Def = MRI.getUniqueVRegDef(MO.getReg())) 775 if (Def->getParent() == &MBB) 776 MFI.unstackifyVReg(MO.getReg()); 777 } 778 } 779 780 // In RegStackify, when a register definition is used multiple times, 781 // Reg = INST ... 782 // INST ..., Reg, ... 783 // INST ..., Reg, ... 784 // INST ..., Reg, ... 785 // 786 // we introduce a TEE, which has the following form: 787 // DefReg = INST ... 788 // TeeReg, Reg = TEE_... DefReg 789 // INST ..., TeeReg, ... 790 // INST ..., Reg, ... 791 // INST ..., Reg, ... 792 // with DefReg and TeeReg stackified but Reg not stackified. 793 // 794 // But the invariant that TeeReg should be stackified can be violated while we 795 // unstackify registers in the split BB above. In this case, we convert TEEs 796 // into two COPYs. This COPY will be eventually eliminated in ExplicitLocals. 797 // DefReg = INST ... 798 // TeeReg = COPY DefReg 799 // Reg = COPY DefReg 800 // INST ..., TeeReg, ... 801 // INST ..., Reg, ... 802 // INST ..., Reg, ... 803 for (auto I = MBB.begin(), E = MBB.end(); I != E;) { 804 MachineInstr &MI = *I++; 805 if (!WebAssembly::isTee(MI.getOpcode())) 806 continue; 807 Register TeeReg = MI.getOperand(0).getReg(); 808 Register Reg = MI.getOperand(1).getReg(); 809 Register DefReg = MI.getOperand(2).getReg(); 810 if (!MFI.isVRegStackified(TeeReg)) { 811 // Now we are not using TEE anymore, so unstackify DefReg too 812 MFI.unstackifyVReg(DefReg); 813 unsigned CopyOpc = getCopyOpcode(MRI.getRegClass(DefReg)); 814 BuildMI(MBB, &MI, MI.getDebugLoc(), TII.get(CopyOpc), TeeReg) 815 .addReg(DefReg); 816 BuildMI(MBB, &MI, MI.getDebugLoc(), TII.get(CopyOpc), Reg).addReg(DefReg); 817 MI.eraseFromParent(); 818 } 819 } 820 } 821 822 bool WebAssemblyCFGStackify::fixUnwindMismatches(MachineFunction &MF) { 823 // TODO Implement this 824 return false; 825 } 826 827 static unsigned 828 getDepth(const SmallVectorImpl<const MachineBasicBlock *> &Stack, 829 const MachineBasicBlock *MBB) { 830 unsigned Depth = 0; 831 for (auto X : reverse(Stack)) { 832 if (X == MBB) 833 break; 834 ++Depth; 835 } 836 assert(Depth < Stack.size() && "Branch destination should be in scope"); 837 return Depth; 838 } 839 840 /// In normal assembly languages, when the end of a function is unreachable, 841 /// because the function ends in an infinite loop or a noreturn call or similar, 842 /// it isn't necessary to worry about the function return type at the end of 843 /// the function, because it's never reached. However, in WebAssembly, blocks 844 /// that end at the function end need to have a return type signature that 845 /// matches the function signature, even though it's unreachable. This function 846 /// checks for such cases and fixes up the signatures. 847 void WebAssemblyCFGStackify::fixEndsAtEndOfFunction(MachineFunction &MF) { 848 const auto &MFI = *MF.getInfo<WebAssemblyFunctionInfo>(); 849 850 if (MFI.getResults().empty()) 851 return; 852 853 // MCInstLower will add the proper types to multivalue signatures based on the 854 // function return type 855 WebAssembly::BlockType RetType = 856 MFI.getResults().size() > 1 857 ? WebAssembly::BlockType::Multivalue 858 : WebAssembly::BlockType( 859 WebAssembly::toValType(MFI.getResults().front())); 860 861 SmallVector<MachineBasicBlock::reverse_iterator, 4> Worklist; 862 Worklist.push_back(MF.rbegin()->rbegin()); 863 864 auto Process = [&](MachineBasicBlock::reverse_iterator It) { 865 auto *MBB = It->getParent(); 866 while (It != MBB->rend()) { 867 MachineInstr &MI = *It++; 868 if (MI.isPosition() || MI.isDebugInstr()) 869 continue; 870 switch (MI.getOpcode()) { 871 case WebAssembly::END_TRY: { 872 // If a 'try''s return type is fixed, both its try body and catch body 873 // should satisfy the return type, so we need to search 'end' 874 // instructions before its corresponding 'catch' too. 875 auto *EHPad = TryToEHPad.lookup(EndToBegin[&MI]); 876 assert(EHPad); 877 Worklist.push_back(std::next(findCatch(EHPad)->getReverseIterator())); 878 LLVM_FALLTHROUGH; 879 } 880 case WebAssembly::END_BLOCK: 881 case WebAssembly::END_LOOP: 882 EndToBegin[&MI]->getOperand(0).setImm(int32_t(RetType)); 883 continue; 884 default: 885 // Something other than an `end`. We're done for this BB. 886 return; 887 } 888 } 889 // We've reached the beginning of a BB. Continue the search in the previous 890 // BB. 891 Worklist.push_back(MBB->getPrevNode()->rbegin()); 892 }; 893 894 while (!Worklist.empty()) 895 Process(Worklist.pop_back_val()); 896 } 897 898 // WebAssembly functions end with an end instruction, as if the function body 899 // were a block. 900 static void appendEndToFunction(MachineFunction &MF, 901 const WebAssemblyInstrInfo &TII) { 902 BuildMI(MF.back(), MF.back().end(), 903 MF.back().findPrevDebugLoc(MF.back().end()), 904 TII.get(WebAssembly::END_FUNCTION)); 905 } 906 907 /// Insert LOOP/TRY/BLOCK markers at appropriate places. 908 void WebAssemblyCFGStackify::placeMarkers(MachineFunction &MF) { 909 // We allocate one more than the number of blocks in the function to 910 // accommodate for the possible fake block we may insert at the end. 911 ScopeTops.resize(MF.getNumBlockIDs() + 1); 912 // Place the LOOP for MBB if MBB is the header of a loop. 913 for (auto &MBB : MF) 914 placeLoopMarker(MBB); 915 916 const MCAsmInfo *MCAI = MF.getTarget().getMCAsmInfo(); 917 for (auto &MBB : MF) { 918 if (MBB.isEHPad()) { 919 // Place the TRY for MBB if MBB is the EH pad of an exception. 920 if (MCAI->getExceptionHandlingType() == ExceptionHandling::Wasm && 921 MF.getFunction().hasPersonalityFn()) 922 placeTryMarker(MBB); 923 } else { 924 // Place the BLOCK for MBB if MBB is branched to from above. 925 placeBlockMarker(MBB); 926 } 927 } 928 // Fix mismatches in unwind destinations induced by linearizing the code. 929 if (MCAI->getExceptionHandlingType() == ExceptionHandling::Wasm && 930 MF.getFunction().hasPersonalityFn()) 931 fixUnwindMismatches(MF); 932 } 933 934 void WebAssemblyCFGStackify::rewriteDepthImmediates(MachineFunction &MF) { 935 // Now rewrite references to basic blocks to be depth immediates. 936 SmallVector<const MachineBasicBlock *, 8> Stack; 937 for (auto &MBB : reverse(MF)) { 938 for (auto I = MBB.rbegin(), E = MBB.rend(); I != E; ++I) { 939 MachineInstr &MI = *I; 940 switch (MI.getOpcode()) { 941 case WebAssembly::BLOCK: 942 case WebAssembly::TRY: 943 assert(ScopeTops[Stack.back()->getNumber()]->getNumber() <= 944 MBB.getNumber() && 945 "Block/try marker should be balanced"); 946 Stack.pop_back(); 947 break; 948 949 case WebAssembly::LOOP: 950 assert(Stack.back() == &MBB && "Loop top should be balanced"); 951 Stack.pop_back(); 952 break; 953 954 case WebAssembly::END_BLOCK: 955 case WebAssembly::END_TRY: 956 Stack.push_back(&MBB); 957 break; 958 959 case WebAssembly::END_LOOP: 960 Stack.push_back(EndToBegin[&MI]->getParent()); 961 break; 962 963 default: 964 if (MI.isTerminator()) { 965 // Rewrite MBB operands to be depth immediates. 966 SmallVector<MachineOperand, 4> Ops(MI.operands()); 967 while (MI.getNumOperands() > 0) 968 MI.RemoveOperand(MI.getNumOperands() - 1); 969 for (auto MO : Ops) { 970 if (MO.isMBB()) 971 MO = MachineOperand::CreateImm(getDepth(Stack, MO.getMBB())); 972 MI.addOperand(MF, MO); 973 } 974 } 975 break; 976 } 977 } 978 } 979 assert(Stack.empty() && "Control flow should be balanced"); 980 } 981 982 void WebAssemblyCFGStackify::releaseMemory() { 983 ScopeTops.clear(); 984 BeginToEnd.clear(); 985 EndToBegin.clear(); 986 TryToEHPad.clear(); 987 EHPadToTry.clear(); 988 AppendixBB = nullptr; 989 } 990 991 bool WebAssemblyCFGStackify::runOnMachineFunction(MachineFunction &MF) { 992 LLVM_DEBUG(dbgs() << "********** CFG Stackifying **********\n" 993 "********** Function: " 994 << MF.getName() << '\n'); 995 const MCAsmInfo *MCAI = MF.getTarget().getMCAsmInfo(); 996 997 releaseMemory(); 998 999 // Liveness is not tracked for VALUE_STACK physreg. 1000 MF.getRegInfo().invalidateLiveness(); 1001 1002 // Place the BLOCK/LOOP/TRY markers to indicate the beginnings of scopes. 1003 placeMarkers(MF); 1004 1005 // Remove unnecessary instructions possibly introduced by try/end_trys. 1006 if (MCAI->getExceptionHandlingType() == ExceptionHandling::Wasm && 1007 MF.getFunction().hasPersonalityFn()) 1008 removeUnnecessaryInstrs(MF); 1009 1010 // Convert MBB operands in terminators to relative depth immediates. 1011 rewriteDepthImmediates(MF); 1012 1013 // Fix up block/loop/try signatures at the end of the function to conform to 1014 // WebAssembly's rules. 1015 fixEndsAtEndOfFunction(MF); 1016 1017 // Add an end instruction at the end of the function body. 1018 const auto &TII = *MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo(); 1019 if (!MF.getSubtarget<WebAssemblySubtarget>() 1020 .getTargetTriple() 1021 .isOSBinFormatELF()) 1022 appendEndToFunction(MF, TII); 1023 1024 MF.getInfo<WebAssemblyFunctionInfo>()->setCFGStackified(); 1025 return true; 1026 } 1027