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