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 void WebAssemblyCFGStackify::registerScope(MachineInstr *Begin, 182 MachineInstr *End) { 183 BeginToEnd[Begin] = End; 184 EndToBegin[End] = Begin; 185 } 186 187 void WebAssemblyCFGStackify::registerTryScope(MachineInstr *Begin, 188 MachineInstr *End, 189 MachineBasicBlock *EHPad) { 190 registerScope(Begin, End); 191 TryToEHPad[Begin] = EHPad; 192 EHPadToTry[EHPad] = Begin; 193 } 194 195 void WebAssemblyCFGStackify::unregisterScope(MachineInstr *Begin) { 196 assert(BeginToEnd.count(Begin)); 197 MachineInstr *End = BeginToEnd[Begin]; 198 assert(EndToBegin.count(End)); 199 BeginToEnd.erase(Begin); 200 EndToBegin.erase(End); 201 MachineBasicBlock *EHPad = TryToEHPad.lookup(Begin); 202 if (EHPad) { 203 assert(EHPadToTry.count(EHPad)); 204 TryToEHPad.erase(Begin); 205 EHPadToTry.erase(EHPad); 206 } 207 } 208 209 /// Insert a BLOCK marker for branches to MBB (if needed). 210 // TODO Consider a more generalized way of handling block (and also loop and 211 // try) signatures when we implement the multi-value proposal later. 212 void WebAssemblyCFGStackify::placeBlockMarker(MachineBasicBlock &MBB) { 213 assert(!MBB.isEHPad()); 214 MachineFunction &MF = *MBB.getParent(); 215 auto &MDT = getAnalysis<MachineDominatorTree>(); 216 const auto &TII = *MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo(); 217 const auto &MFI = *MF.getInfo<WebAssemblyFunctionInfo>(); 218 219 // First compute the nearest common dominator of all forward non-fallthrough 220 // predecessors so that we minimize the time that the BLOCK is on the stack, 221 // which reduces overall stack height. 222 MachineBasicBlock *Header = nullptr; 223 bool IsBranchedTo = false; 224 int MBBNumber = MBB.getNumber(); 225 for (MachineBasicBlock *Pred : MBB.predecessors()) { 226 if (Pred->getNumber() < MBBNumber) { 227 Header = Header ? MDT.findNearestCommonDominator(Header, Pred) : Pred; 228 if (explicitlyBranchesTo(Pred, &MBB)) 229 IsBranchedTo = true; 230 } 231 } 232 if (!Header) 233 return; 234 if (!IsBranchedTo) 235 return; 236 237 assert(&MBB != &MF.front() && "Header blocks shouldn't have predecessors"); 238 MachineBasicBlock *LayoutPred = MBB.getPrevNode(); 239 240 // If the nearest common dominator is inside a more deeply nested context, 241 // walk out to the nearest scope which isn't more deeply nested. 242 for (MachineFunction::iterator I(LayoutPred), E(Header); I != E; --I) { 243 if (MachineBasicBlock *ScopeTop = ScopeTops[I->getNumber()]) { 244 if (ScopeTop->getNumber() > Header->getNumber()) { 245 // Skip over an intervening scope. 246 I = std::next(ScopeTop->getIterator()); 247 } else { 248 // We found a scope level at an appropriate depth. 249 Header = ScopeTop; 250 break; 251 } 252 } 253 } 254 255 // Decide where in Header to put the BLOCK. 256 257 // Instructions that should go before the BLOCK. 258 SmallPtrSet<const MachineInstr *, 4> BeforeSet; 259 // Instructions that should go after the BLOCK. 260 SmallPtrSet<const MachineInstr *, 4> AfterSet; 261 for (const auto &MI : *Header) { 262 // If there is a previously placed LOOP marker and the bottom block of the 263 // loop is above MBB, it should be after the BLOCK, because the loop is 264 // nested in this BLOCK. Otherwise it should be before the BLOCK. 265 if (MI.getOpcode() == WebAssembly::LOOP) { 266 auto *LoopBottom = BeginToEnd[&MI]->getParent()->getPrevNode(); 267 if (MBB.getNumber() > LoopBottom->getNumber()) 268 AfterSet.insert(&MI); 269 #ifndef NDEBUG 270 else 271 BeforeSet.insert(&MI); 272 #endif 273 } 274 275 // If there is a previously placed BLOCK/TRY marker and its corresponding 276 // END marker is before the current BLOCK's END marker, that should be 277 // placed after this BLOCK. Otherwise it should be placed before this BLOCK 278 // marker. 279 if (MI.getOpcode() == WebAssembly::BLOCK || 280 MI.getOpcode() == WebAssembly::TRY) { 281 if (BeginToEnd[&MI]->getParent()->getNumber() <= MBB.getNumber()) 282 AfterSet.insert(&MI); 283 #ifndef NDEBUG 284 else 285 BeforeSet.insert(&MI); 286 #endif 287 } 288 289 #ifndef NDEBUG 290 // All END_(BLOCK|LOOP|TRY) markers should be before the BLOCK. 291 if (MI.getOpcode() == WebAssembly::END_BLOCK || 292 MI.getOpcode() == WebAssembly::END_LOOP || 293 MI.getOpcode() == WebAssembly::END_TRY) 294 BeforeSet.insert(&MI); 295 #endif 296 297 // Terminators should go after the BLOCK. 298 if (MI.isTerminator()) 299 AfterSet.insert(&MI); 300 } 301 302 // Local expression tree should go after the BLOCK. 303 for (auto I = Header->getFirstTerminator(), E = Header->begin(); I != E; 304 --I) { 305 if (std::prev(I)->isDebugInstr() || std::prev(I)->isPosition()) 306 continue; 307 if (WebAssembly::isChild(*std::prev(I), MFI)) 308 AfterSet.insert(&*std::prev(I)); 309 else 310 break; 311 } 312 313 // Add the BLOCK. 314 WebAssembly::BlockType ReturnType = WebAssembly::BlockType::Void; 315 auto InsertPos = getLatestInsertPos(Header, BeforeSet, AfterSet); 316 MachineInstr *Begin = 317 BuildMI(*Header, InsertPos, Header->findDebugLoc(InsertPos), 318 TII.get(WebAssembly::BLOCK)) 319 .addImm(int64_t(ReturnType)); 320 321 // Decide where in Header to put the END_BLOCK. 322 BeforeSet.clear(); 323 AfterSet.clear(); 324 for (auto &MI : MBB) { 325 #ifndef NDEBUG 326 // END_BLOCK should precede existing LOOP and TRY markers. 327 if (MI.getOpcode() == WebAssembly::LOOP || 328 MI.getOpcode() == WebAssembly::TRY) 329 AfterSet.insert(&MI); 330 #endif 331 332 // If there is a previously placed END_LOOP marker and the header of the 333 // loop is above this block's header, the END_LOOP should be placed after 334 // the BLOCK, because the loop contains this block. Otherwise the END_LOOP 335 // should be placed before the BLOCK. The same for END_TRY. 336 if (MI.getOpcode() == WebAssembly::END_LOOP || 337 MI.getOpcode() == WebAssembly::END_TRY) { 338 if (EndToBegin[&MI]->getParent()->getNumber() >= Header->getNumber()) 339 BeforeSet.insert(&MI); 340 #ifndef NDEBUG 341 else 342 AfterSet.insert(&MI); 343 #endif 344 } 345 } 346 347 // Mark the end of the block. 348 InsertPos = getEarliestInsertPos(&MBB, BeforeSet, AfterSet); 349 MachineInstr *End = BuildMI(MBB, InsertPos, MBB.findPrevDebugLoc(InsertPos), 350 TII.get(WebAssembly::END_BLOCK)); 351 registerScope(Begin, End); 352 353 // Track the farthest-spanning scope that ends at this point. 354 int Number = MBB.getNumber(); 355 if (!ScopeTops[Number] || 356 ScopeTops[Number]->getNumber() > Header->getNumber()) 357 ScopeTops[Number] = Header; 358 } 359 360 /// Insert a LOOP marker for a loop starting at MBB (if it's a loop header). 361 void WebAssemblyCFGStackify::placeLoopMarker(MachineBasicBlock &MBB) { 362 MachineFunction &MF = *MBB.getParent(); 363 const auto &MLI = getAnalysis<MachineLoopInfo>(); 364 const auto &WEI = getAnalysis<WebAssemblyExceptionInfo>(); 365 SortRegionInfo SRI(MLI, WEI); 366 const auto &TII = *MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo(); 367 368 MachineLoop *Loop = MLI.getLoopFor(&MBB); 369 if (!Loop || Loop->getHeader() != &MBB) 370 return; 371 372 // The operand of a LOOP is the first block after the loop. If the loop is the 373 // bottom of the function, insert a dummy block at the end. 374 MachineBasicBlock *Bottom = SRI.getBottom(Loop); 375 auto Iter = std::next(Bottom->getIterator()); 376 if (Iter == MF.end()) { 377 getAppendixBlock(MF); 378 Iter = std::next(Bottom->getIterator()); 379 } 380 MachineBasicBlock *AfterLoop = &*Iter; 381 382 // Decide where in Header to put the LOOP. 383 SmallPtrSet<const MachineInstr *, 4> BeforeSet; 384 SmallPtrSet<const MachineInstr *, 4> AfterSet; 385 for (const auto &MI : MBB) { 386 // LOOP marker should be after any existing loop that ends here. Otherwise 387 // we assume the instruction belongs to the loop. 388 if (MI.getOpcode() == WebAssembly::END_LOOP) 389 BeforeSet.insert(&MI); 390 #ifndef NDEBUG 391 else 392 AfterSet.insert(&MI); 393 #endif 394 } 395 396 // Mark the beginning of the loop. 397 auto InsertPos = getEarliestInsertPos(&MBB, BeforeSet, AfterSet); 398 MachineInstr *Begin = BuildMI(MBB, InsertPos, MBB.findDebugLoc(InsertPos), 399 TII.get(WebAssembly::LOOP)) 400 .addImm(int64_t(WebAssembly::BlockType::Void)); 401 402 // Decide where in Header to put the END_LOOP. 403 BeforeSet.clear(); 404 AfterSet.clear(); 405 #ifndef NDEBUG 406 for (const auto &MI : MBB) 407 // Existing END_LOOP markers belong to parent loops of this loop 408 if (MI.getOpcode() == WebAssembly::END_LOOP) 409 AfterSet.insert(&MI); 410 #endif 411 412 // Mark the end of the loop (using arbitrary debug location that branched to 413 // the loop end as its location). 414 InsertPos = getEarliestInsertPos(AfterLoop, BeforeSet, AfterSet); 415 DebugLoc EndDL = AfterLoop->pred_empty() 416 ? DebugLoc() 417 : (*AfterLoop->pred_rbegin())->findBranchDebugLoc(); 418 MachineInstr *End = 419 BuildMI(*AfterLoop, InsertPos, EndDL, TII.get(WebAssembly::END_LOOP)); 420 registerScope(Begin, End); 421 422 assert((!ScopeTops[AfterLoop->getNumber()] || 423 ScopeTops[AfterLoop->getNumber()]->getNumber() < MBB.getNumber()) && 424 "With block sorting the outermost loop for a block should be first."); 425 if (!ScopeTops[AfterLoop->getNumber()]) 426 ScopeTops[AfterLoop->getNumber()] = &MBB; 427 } 428 429 void WebAssemblyCFGStackify::placeTryMarker(MachineBasicBlock &MBB) { 430 assert(MBB.isEHPad()); 431 MachineFunction &MF = *MBB.getParent(); 432 auto &MDT = getAnalysis<MachineDominatorTree>(); 433 const auto &TII = *MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo(); 434 const auto &MLI = getAnalysis<MachineLoopInfo>(); 435 const auto &WEI = getAnalysis<WebAssemblyExceptionInfo>(); 436 SortRegionInfo SRI(MLI, WEI); 437 const auto &MFI = *MF.getInfo<WebAssemblyFunctionInfo>(); 438 439 // Compute the nearest common dominator of all unwind predecessors 440 MachineBasicBlock *Header = nullptr; 441 int MBBNumber = MBB.getNumber(); 442 for (auto *Pred : MBB.predecessors()) { 443 if (Pred->getNumber() < MBBNumber) { 444 Header = Header ? MDT.findNearestCommonDominator(Header, Pred) : Pred; 445 assert(!explicitlyBranchesTo(Pred, &MBB) && 446 "Explicit branch to an EH pad!"); 447 } 448 } 449 if (!Header) 450 return; 451 452 // If this try is at the bottom of the function, insert a dummy block at the 453 // end. 454 WebAssemblyException *WE = WEI.getExceptionFor(&MBB); 455 assert(WE); 456 MachineBasicBlock *Bottom = SRI.getBottom(WE); 457 458 auto Iter = std::next(Bottom->getIterator()); 459 if (Iter == MF.end()) { 460 getAppendixBlock(MF); 461 Iter = std::next(Bottom->getIterator()); 462 } 463 MachineBasicBlock *Cont = &*Iter; 464 465 assert(Cont != &MF.front()); 466 MachineBasicBlock *LayoutPred = Cont->getPrevNode(); 467 468 // If the nearest common dominator is inside a more deeply nested context, 469 // walk out to the nearest scope which isn't more deeply nested. 470 for (MachineFunction::iterator I(LayoutPred), E(Header); I != E; --I) { 471 if (MachineBasicBlock *ScopeTop = ScopeTops[I->getNumber()]) { 472 if (ScopeTop->getNumber() > Header->getNumber()) { 473 // Skip over an intervening scope. 474 I = std::next(ScopeTop->getIterator()); 475 } else { 476 // We found a scope level at an appropriate depth. 477 Header = ScopeTop; 478 break; 479 } 480 } 481 } 482 483 // Decide where in Header to put the TRY. 484 485 // Instructions that should go before the TRY. 486 SmallPtrSet<const MachineInstr *, 4> BeforeSet; 487 // Instructions that should go after the TRY. 488 SmallPtrSet<const MachineInstr *, 4> AfterSet; 489 for (const auto &MI : *Header) { 490 // If there is a previously placed LOOP marker and the bottom block of the 491 // loop is above MBB, it should be after the TRY, because the loop is nested 492 // in this TRY. Otherwise it should be before the TRY. 493 if (MI.getOpcode() == WebAssembly::LOOP) { 494 auto *LoopBottom = BeginToEnd[&MI]->getParent()->getPrevNode(); 495 if (MBB.getNumber() > LoopBottom->getNumber()) 496 AfterSet.insert(&MI); 497 #ifndef NDEBUG 498 else 499 BeforeSet.insert(&MI); 500 #endif 501 } 502 503 // All previously inserted BLOCK/TRY markers should be after the TRY because 504 // they are all nested trys. 505 if (MI.getOpcode() == WebAssembly::BLOCK || 506 MI.getOpcode() == WebAssembly::TRY) 507 AfterSet.insert(&MI); 508 509 #ifndef NDEBUG 510 // All END_(BLOCK/LOOP/TRY) markers should be before the TRY. 511 if (MI.getOpcode() == WebAssembly::END_BLOCK || 512 MI.getOpcode() == WebAssembly::END_LOOP || 513 MI.getOpcode() == WebAssembly::END_TRY) 514 BeforeSet.insert(&MI); 515 #endif 516 517 // Terminators should go after the TRY. 518 if (MI.isTerminator()) 519 AfterSet.insert(&MI); 520 } 521 522 // If Header unwinds to MBB (= Header contains 'invoke'), the try block should 523 // contain the call within it. So the call should go after the TRY. The 524 // exception is when the header's terminator is a rethrow instruction, in 525 // which case that instruction, not a call instruction before it, is gonna 526 // throw. 527 MachineInstr *ThrowingCall = nullptr; 528 if (MBB.isPredecessor(Header)) { 529 auto TermPos = Header->getFirstTerminator(); 530 if (TermPos == Header->end() || 531 TermPos->getOpcode() != WebAssembly::RETHROW) { 532 for (auto &MI : reverse(*Header)) { 533 if (MI.isCall()) { 534 AfterSet.insert(&MI); 535 ThrowingCall = &MI; 536 // Possibly throwing calls are usually wrapped by EH_LABEL 537 // instructions. We don't want to split them and the call. 538 if (MI.getIterator() != Header->begin() && 539 std::prev(MI.getIterator())->isEHLabel()) { 540 AfterSet.insert(&*std::prev(MI.getIterator())); 541 ThrowingCall = &*std::prev(MI.getIterator()); 542 } 543 break; 544 } 545 } 546 } 547 } 548 549 // Local expression tree should go after the TRY. 550 // For BLOCK placement, we start the search from the previous instruction of a 551 // BB's terminator, but in TRY's case, we should start from the previous 552 // instruction of a call that can throw, or a EH_LABEL that precedes the call, 553 // because the return values of the call's previous instructions can be 554 // stackified and consumed by the throwing call. 555 auto SearchStartPt = ThrowingCall ? MachineBasicBlock::iterator(ThrowingCall) 556 : Header->getFirstTerminator(); 557 for (auto I = SearchStartPt, E = Header->begin(); I != E; --I) { 558 if (std::prev(I)->isDebugInstr() || std::prev(I)->isPosition()) 559 continue; 560 if (WebAssembly::isChild(*std::prev(I), MFI)) 561 AfterSet.insert(&*std::prev(I)); 562 else 563 break; 564 } 565 566 // Add the TRY. 567 auto InsertPos = getLatestInsertPos(Header, BeforeSet, AfterSet); 568 MachineInstr *Begin = 569 BuildMI(*Header, InsertPos, Header->findDebugLoc(InsertPos), 570 TII.get(WebAssembly::TRY)) 571 .addImm(int64_t(WebAssembly::BlockType::Void)); 572 573 // Decide where in Header to put the END_TRY. 574 BeforeSet.clear(); 575 AfterSet.clear(); 576 for (const auto &MI : *Cont) { 577 #ifndef NDEBUG 578 // END_TRY should precede existing LOOP and BLOCK markers. 579 if (MI.getOpcode() == WebAssembly::LOOP || 580 MI.getOpcode() == WebAssembly::BLOCK) 581 AfterSet.insert(&MI); 582 583 // All END_TRY markers placed earlier belong to exceptions that contains 584 // this one. 585 if (MI.getOpcode() == WebAssembly::END_TRY) 586 AfterSet.insert(&MI); 587 #endif 588 589 // If there is a previously placed END_LOOP marker and its header is after 590 // where TRY marker is, this loop is contained within the 'catch' part, so 591 // the END_TRY marker should go after that. Otherwise, the whole try-catch 592 // is contained within this loop, so the END_TRY should go before that. 593 if (MI.getOpcode() == WebAssembly::END_LOOP) { 594 // For a LOOP to be after TRY, LOOP's BB should be after TRY's BB; if they 595 // are in the same BB, LOOP is always before TRY. 596 if (EndToBegin[&MI]->getParent()->getNumber() > Header->getNumber()) 597 BeforeSet.insert(&MI); 598 #ifndef NDEBUG 599 else 600 AfterSet.insert(&MI); 601 #endif 602 } 603 604 // It is not possible for an END_BLOCK to be already in this block. 605 } 606 607 // Mark the end of the TRY. 608 InsertPos = getEarliestInsertPos(Cont, BeforeSet, AfterSet); 609 MachineInstr *End = 610 BuildMI(*Cont, InsertPos, Bottom->findBranchDebugLoc(), 611 TII.get(WebAssembly::END_TRY)); 612 registerTryScope(Begin, End, &MBB); 613 614 // Track the farthest-spanning scope that ends at this point. We create two 615 // mappings: (BB with 'end_try' -> BB with 'try') and (BB with 'catch' -> BB 616 // with 'try'). We need to create 'catch' -> 'try' mapping here too because 617 // markers should not span across 'catch'. For example, this should not 618 // happen: 619 // 620 // try 621 // block --| (X) 622 // catch | 623 // end_block --| 624 // end_try 625 for (int Number : {Cont->getNumber(), MBB.getNumber()}) { 626 if (!ScopeTops[Number] || 627 ScopeTops[Number]->getNumber() > Header->getNumber()) 628 ScopeTops[Number] = Header; 629 } 630 } 631 632 void WebAssemblyCFGStackify::removeUnnecessaryInstrs(MachineFunction &MF) { 633 const auto &TII = *MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo(); 634 635 // When there is an unconditional branch right before a catch instruction and 636 // it branches to the end of end_try marker, we don't need the branch, because 637 // it there is no exception, the control flow transfers to that point anyway. 638 // bb0: 639 // try 640 // ... 641 // br bb2 <- Not necessary 642 // bb1: 643 // catch 644 // ... 645 // bb2: 646 // end 647 for (auto &MBB : MF) { 648 if (!MBB.isEHPad()) 649 continue; 650 651 MachineBasicBlock *TBB = nullptr, *FBB = nullptr; 652 SmallVector<MachineOperand, 4> Cond; 653 MachineBasicBlock *EHPadLayoutPred = MBB.getPrevNode(); 654 MachineBasicBlock *Cont = BeginToEnd[EHPadToTry[&MBB]]->getParent(); 655 bool Analyzable = !TII.analyzeBranch(*EHPadLayoutPred, TBB, FBB, Cond); 656 // This condition means either 657 // 1. This BB ends with a single unconditional branch whose destinaion is 658 // Cont. 659 // 2. This BB ends with a conditional branch followed by an unconditional 660 // branch, and the unconditional branch's destination is Cont. 661 // In both cases, we want to remove the last (= unconditional) branch. 662 if (Analyzable && ((Cond.empty() && TBB && TBB == Cont) || 663 (!Cond.empty() && FBB && FBB == Cont))) { 664 bool ErasedUncondBr = false; 665 (void)ErasedUncondBr; 666 for (auto I = EHPadLayoutPred->end(), E = EHPadLayoutPred->begin(); 667 I != E; --I) { 668 auto PrevI = std::prev(I); 669 if (PrevI->isTerminator()) { 670 assert(PrevI->getOpcode() == WebAssembly::BR); 671 PrevI->eraseFromParent(); 672 ErasedUncondBr = true; 673 break; 674 } 675 } 676 assert(ErasedUncondBr && "Unconditional branch not erased!"); 677 } 678 } 679 680 // When there are block / end_block markers that overlap with try / end_try 681 // markers, and the block and try markers' return types are the same, the 682 // block /end_block markers are not necessary, because try / end_try markers 683 // also can serve as boundaries for branches. 684 // block <- Not necessary 685 // try 686 // ... 687 // catch 688 // ... 689 // end 690 // end <- Not necessary 691 SmallVector<MachineInstr *, 32> ToDelete; 692 for (auto &MBB : MF) { 693 for (auto &MI : MBB) { 694 if (MI.getOpcode() != WebAssembly::TRY) 695 continue; 696 697 MachineInstr *Try = &MI, *EndTry = BeginToEnd[Try]; 698 MachineBasicBlock *TryBB = Try->getParent(); 699 MachineBasicBlock *Cont = EndTry->getParent(); 700 int64_t RetType = Try->getOperand(0).getImm(); 701 for (auto B = Try->getIterator(), E = std::next(EndTry->getIterator()); 702 B != TryBB->begin() && E != Cont->end() && 703 std::prev(B)->getOpcode() == WebAssembly::BLOCK && 704 E->getOpcode() == WebAssembly::END_BLOCK && 705 std::prev(B)->getOperand(0).getImm() == RetType; 706 --B, ++E) { 707 ToDelete.push_back(&*std::prev(B)); 708 ToDelete.push_back(&*E); 709 } 710 } 711 } 712 for (auto *MI : ToDelete) { 713 if (MI->getOpcode() == WebAssembly::BLOCK) 714 unregisterScope(MI); 715 MI->eraseFromParent(); 716 } 717 } 718 719 // Get the appropriate copy opcode for the given register class. 720 static unsigned getCopyOpcode(const TargetRegisterClass *RC) { 721 if (RC == &WebAssembly::I32RegClass) 722 return WebAssembly::COPY_I32; 723 if (RC == &WebAssembly::I64RegClass) 724 return WebAssembly::COPY_I64; 725 if (RC == &WebAssembly::F32RegClass) 726 return WebAssembly::COPY_F32; 727 if (RC == &WebAssembly::F64RegClass) 728 return WebAssembly::COPY_F64; 729 if (RC == &WebAssembly::V128RegClass) 730 return WebAssembly::COPY_V128; 731 if (RC == &WebAssembly::FUNCREFRegClass) 732 return WebAssembly::COPY_FUNCREF; 733 if (RC == &WebAssembly::EXTERNREFRegClass) 734 return WebAssembly::COPY_EXTERNREF; 735 llvm_unreachable("Unexpected register class"); 736 } 737 738 // When MBB is split into MBB and Split, we should unstackify defs in MBB that 739 // have their uses in Split. 740 // FIXME This function will be used when fixing unwind mismatches, but the old 741 // version of that function was removed for the moment and the new version has 742 // not yet been added. So 'LLVM_ATTRIBUTE_UNUSED' is added to suppress the 743 // warning. Remove the attribute after the new functionality is added. 744 LLVM_ATTRIBUTE_UNUSED static void 745 unstackifyVRegsUsedInSplitBB(MachineBasicBlock &MBB, MachineBasicBlock &Split, 746 WebAssemblyFunctionInfo &MFI, 747 MachineRegisterInfo &MRI, 748 const WebAssemblyInstrInfo &TII) { 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