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 (ehpad): 641 // catch 642 // ... 643 // bb2: <- Continuation BB 644 // end 645 // 646 // A more involved case: When the BB where 'end' is located is an another EH 647 // pad, the Cont (= continuation) BB is that EH pad's 'end' BB. For example, 648 // bb0: 649 // try 650 // try 651 // ... 652 // br bb3 <- Not necessary 653 // bb1 (ehpad): 654 // catch 655 // bb2 (ehpad): 656 // end 657 // catch 658 // ... 659 // bb3: <- Continuation BB 660 // end 661 // 662 // When the EH pad at hand is bb1, its matching end_try is in bb2. But it is 663 // another EH pad, so bb0's continuation BB becomes bb3. So 'br bb3' in the 664 // code can be deleted. This is why we run 'while' until 'Cont' is not an EH 665 // pad. 666 for (auto &MBB : MF) { 667 if (!MBB.isEHPad()) 668 continue; 669 670 MachineBasicBlock *TBB = nullptr, *FBB = nullptr; 671 SmallVector<MachineOperand, 4> Cond; 672 MachineBasicBlock *EHPadLayoutPred = MBB.getPrevNode(); 673 674 MachineBasicBlock *Cont = &MBB; 675 while (Cont->isEHPad()) { 676 MachineInstr *Try = EHPadToTry[Cont]; 677 MachineInstr *EndTry = BeginToEnd[Try]; 678 Cont = EndTry->getParent(); 679 } 680 681 bool Analyzable = !TII.analyzeBranch(*EHPadLayoutPred, TBB, FBB, Cond); 682 // This condition means either 683 // 1. This BB ends with a single unconditional branch whose destinaion is 684 // Cont. 685 // 2. This BB ends with a conditional branch followed by an unconditional 686 // branch, and the unconditional branch's destination is Cont. 687 // In both cases, we want to remove the last (= unconditional) branch. 688 if (Analyzable && ((Cond.empty() && TBB && TBB == Cont) || 689 (!Cond.empty() && FBB && FBB == Cont))) { 690 bool ErasedUncondBr = false; 691 (void)ErasedUncondBr; 692 for (auto I = EHPadLayoutPred->end(), E = EHPadLayoutPred->begin(); 693 I != E; --I) { 694 auto PrevI = std::prev(I); 695 if (PrevI->isTerminator()) { 696 assert(PrevI->getOpcode() == WebAssembly::BR); 697 PrevI->eraseFromParent(); 698 ErasedUncondBr = true; 699 break; 700 } 701 } 702 assert(ErasedUncondBr && "Unconditional branch not erased!"); 703 } 704 } 705 706 // When there are block / end_block markers that overlap with try / end_try 707 // markers, and the block and try markers' return types are the same, the 708 // block /end_block markers are not necessary, because try / end_try markers 709 // also can serve as boundaries for branches. 710 // block <- Not necessary 711 // try 712 // ... 713 // catch 714 // ... 715 // end 716 // end <- Not necessary 717 SmallVector<MachineInstr *, 32> ToDelete; 718 for (auto &MBB : MF) { 719 for (auto &MI : MBB) { 720 if (MI.getOpcode() != WebAssembly::TRY) 721 continue; 722 723 MachineInstr *Try = &MI, *EndTry = BeginToEnd[Try]; 724 MachineBasicBlock *TryBB = Try->getParent(); 725 MachineBasicBlock *Cont = EndTry->getParent(); 726 int64_t RetType = Try->getOperand(0).getImm(); 727 for (auto B = Try->getIterator(), E = std::next(EndTry->getIterator()); 728 B != TryBB->begin() && E != Cont->end() && 729 std::prev(B)->getOpcode() == WebAssembly::BLOCK && 730 E->getOpcode() == WebAssembly::END_BLOCK && 731 std::prev(B)->getOperand(0).getImm() == RetType; 732 --B, ++E) { 733 ToDelete.push_back(&*std::prev(B)); 734 ToDelete.push_back(&*E); 735 } 736 } 737 } 738 for (auto *MI : ToDelete) { 739 if (MI->getOpcode() == WebAssembly::BLOCK) 740 unregisterScope(MI); 741 MI->eraseFromParent(); 742 } 743 } 744 745 // Get the appropriate copy opcode for the given register class. 746 static unsigned getCopyOpcode(const TargetRegisterClass *RC) { 747 if (RC == &WebAssembly::I32RegClass) 748 return WebAssembly::COPY_I32; 749 if (RC == &WebAssembly::I64RegClass) 750 return WebAssembly::COPY_I64; 751 if (RC == &WebAssembly::F32RegClass) 752 return WebAssembly::COPY_F32; 753 if (RC == &WebAssembly::F64RegClass) 754 return WebAssembly::COPY_F64; 755 if (RC == &WebAssembly::V128RegClass) 756 return WebAssembly::COPY_V128; 757 if (RC == &WebAssembly::FUNCREFRegClass) 758 return WebAssembly::COPY_FUNCREF; 759 if (RC == &WebAssembly::EXTERNREFRegClass) 760 return WebAssembly::COPY_EXTERNREF; 761 llvm_unreachable("Unexpected register class"); 762 } 763 764 // When MBB is split into MBB and Split, we should unstackify defs in MBB that 765 // have their uses in Split. 766 // FIXME This function will be used when fixing unwind mismatches, but the old 767 // version of that function was removed for the moment and the new version has 768 // not yet been added. So 'LLVM_ATTRIBUTE_UNUSED' is added to suppress the 769 // warning. Remove the attribute after the new functionality is added. 770 LLVM_ATTRIBUTE_UNUSED static void 771 unstackifyVRegsUsedInSplitBB(MachineBasicBlock &MBB, MachineBasicBlock &Split) { 772 MachineFunction &MF = *MBB.getParent(); 773 const auto &TII = *MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo(); 774 auto &MFI = *MF.getInfo<WebAssemblyFunctionInfo>(); 775 auto &MRI = MF.getRegInfo(); 776 777 for (auto &MI : Split) { 778 for (auto &MO : MI.explicit_uses()) { 779 if (!MO.isReg() || Register::isPhysicalRegister(MO.getReg())) 780 continue; 781 if (MachineInstr *Def = MRI.getUniqueVRegDef(MO.getReg())) 782 if (Def->getParent() == &MBB) 783 MFI.unstackifyVReg(MO.getReg()); 784 } 785 } 786 787 // In RegStackify, when a register definition is used multiple times, 788 // Reg = INST ... 789 // INST ..., Reg, ... 790 // INST ..., Reg, ... 791 // INST ..., Reg, ... 792 // 793 // we introduce a TEE, which has the following form: 794 // DefReg = INST ... 795 // TeeReg, Reg = TEE_... DefReg 796 // INST ..., TeeReg, ... 797 // INST ..., Reg, ... 798 // INST ..., Reg, ... 799 // with DefReg and TeeReg stackified but Reg not stackified. 800 // 801 // But the invariant that TeeReg should be stackified can be violated while we 802 // unstackify registers in the split BB above. In this case, we convert TEEs 803 // into two COPYs. This COPY will be eventually eliminated in ExplicitLocals. 804 // DefReg = INST ... 805 // TeeReg = COPY DefReg 806 // Reg = COPY DefReg 807 // INST ..., TeeReg, ... 808 // INST ..., Reg, ... 809 // INST ..., Reg, ... 810 for (auto I = MBB.begin(), E = MBB.end(); I != E;) { 811 MachineInstr &MI = *I++; 812 if (!WebAssembly::isTee(MI.getOpcode())) 813 continue; 814 Register TeeReg = MI.getOperand(0).getReg(); 815 Register Reg = MI.getOperand(1).getReg(); 816 Register DefReg = MI.getOperand(2).getReg(); 817 if (!MFI.isVRegStackified(TeeReg)) { 818 // Now we are not using TEE anymore, so unstackify DefReg too 819 MFI.unstackifyVReg(DefReg); 820 unsigned CopyOpc = getCopyOpcode(MRI.getRegClass(DefReg)); 821 BuildMI(MBB, &MI, MI.getDebugLoc(), TII.get(CopyOpc), TeeReg) 822 .addReg(DefReg); 823 BuildMI(MBB, &MI, MI.getDebugLoc(), TII.get(CopyOpc), Reg).addReg(DefReg); 824 MI.eraseFromParent(); 825 } 826 } 827 } 828 829 bool WebAssemblyCFGStackify::fixUnwindMismatches(MachineFunction &MF) { 830 // TODO Implement this 831 return false; 832 } 833 834 static unsigned 835 getDepth(const SmallVectorImpl<const MachineBasicBlock *> &Stack, 836 const MachineBasicBlock *MBB) { 837 unsigned Depth = 0; 838 for (auto X : reverse(Stack)) { 839 if (X == MBB) 840 break; 841 ++Depth; 842 } 843 assert(Depth < Stack.size() && "Branch destination should be in scope"); 844 return Depth; 845 } 846 847 /// In normal assembly languages, when the end of a function is unreachable, 848 /// because the function ends in an infinite loop or a noreturn call or similar, 849 /// it isn't necessary to worry about the function return type at the end of 850 /// the function, because it's never reached. However, in WebAssembly, blocks 851 /// that end at the function end need to have a return type signature that 852 /// matches the function signature, even though it's unreachable. This function 853 /// checks for such cases and fixes up the signatures. 854 void WebAssemblyCFGStackify::fixEndsAtEndOfFunction(MachineFunction &MF) { 855 const auto &MFI = *MF.getInfo<WebAssemblyFunctionInfo>(); 856 857 if (MFI.getResults().empty()) 858 return; 859 860 // MCInstLower will add the proper types to multivalue signatures based on the 861 // function return type 862 WebAssembly::BlockType RetType = 863 MFI.getResults().size() > 1 864 ? WebAssembly::BlockType::Multivalue 865 : WebAssembly::BlockType( 866 WebAssembly::toValType(MFI.getResults().front())); 867 868 SmallVector<MachineBasicBlock::reverse_iterator, 4> Worklist; 869 Worklist.push_back(MF.rbegin()->rbegin()); 870 871 auto Process = [&](MachineBasicBlock::reverse_iterator It) { 872 auto *MBB = It->getParent(); 873 while (It != MBB->rend()) { 874 MachineInstr &MI = *It++; 875 if (MI.isPosition() || MI.isDebugInstr()) 876 continue; 877 switch (MI.getOpcode()) { 878 case WebAssembly::END_TRY: { 879 // If a 'try''s return type is fixed, both its try body and catch body 880 // should satisfy the return type, so we need to search 'end' 881 // instructions before its corresponding 'catch' too. 882 auto *EHPad = TryToEHPad.lookup(EndToBegin[&MI]); 883 assert(EHPad); 884 auto NextIt = 885 std::next(WebAssembly::findCatch(EHPad)->getReverseIterator()); 886 if (NextIt != EHPad->rend()) 887 Worklist.push_back(NextIt); 888 LLVM_FALLTHROUGH; 889 } 890 case WebAssembly::END_BLOCK: 891 case WebAssembly::END_LOOP: 892 EndToBegin[&MI]->getOperand(0).setImm(int32_t(RetType)); 893 continue; 894 default: 895 // Something other than an `end`. We're done for this BB. 896 return; 897 } 898 } 899 // We've reached the beginning of a BB. Continue the search in the previous 900 // BB. 901 Worklist.push_back(MBB->getPrevNode()->rbegin()); 902 }; 903 904 while (!Worklist.empty()) 905 Process(Worklist.pop_back_val()); 906 } 907 908 // WebAssembly functions end with an end instruction, as if the function body 909 // were a block. 910 static void appendEndToFunction(MachineFunction &MF, 911 const WebAssemblyInstrInfo &TII) { 912 BuildMI(MF.back(), MF.back().end(), 913 MF.back().findPrevDebugLoc(MF.back().end()), 914 TII.get(WebAssembly::END_FUNCTION)); 915 } 916 917 /// Insert LOOP/TRY/BLOCK markers at appropriate places. 918 void WebAssemblyCFGStackify::placeMarkers(MachineFunction &MF) { 919 // We allocate one more than the number of blocks in the function to 920 // accommodate for the possible fake block we may insert at the end. 921 ScopeTops.resize(MF.getNumBlockIDs() + 1); 922 // Place the LOOP for MBB if MBB is the header of a loop. 923 for (auto &MBB : MF) 924 placeLoopMarker(MBB); 925 926 const MCAsmInfo *MCAI = MF.getTarget().getMCAsmInfo(); 927 for (auto &MBB : MF) { 928 if (MBB.isEHPad()) { 929 // Place the TRY for MBB if MBB is the EH pad of an exception. 930 if (MCAI->getExceptionHandlingType() == ExceptionHandling::Wasm && 931 MF.getFunction().hasPersonalityFn()) 932 placeTryMarker(MBB); 933 } else { 934 // Place the BLOCK for MBB if MBB is branched to from above. 935 placeBlockMarker(MBB); 936 } 937 } 938 // Fix mismatches in unwind destinations induced by linearizing the code. 939 if (MCAI->getExceptionHandlingType() == ExceptionHandling::Wasm && 940 MF.getFunction().hasPersonalityFn()) 941 fixUnwindMismatches(MF); 942 } 943 944 void WebAssemblyCFGStackify::rewriteDepthImmediates(MachineFunction &MF) { 945 // Now rewrite references to basic blocks to be depth immediates. 946 SmallVector<const MachineBasicBlock *, 8> Stack; 947 for (auto &MBB : reverse(MF)) { 948 for (auto I = MBB.rbegin(), E = MBB.rend(); I != E; ++I) { 949 MachineInstr &MI = *I; 950 switch (MI.getOpcode()) { 951 case WebAssembly::BLOCK: 952 case WebAssembly::TRY: 953 assert(ScopeTops[Stack.back()->getNumber()]->getNumber() <= 954 MBB.getNumber() && 955 "Block/try marker should be balanced"); 956 Stack.pop_back(); 957 break; 958 959 case WebAssembly::LOOP: 960 assert(Stack.back() == &MBB && "Loop top should be balanced"); 961 Stack.pop_back(); 962 break; 963 964 case WebAssembly::END_BLOCK: 965 case WebAssembly::END_TRY: 966 Stack.push_back(&MBB); 967 break; 968 969 case WebAssembly::END_LOOP: 970 Stack.push_back(EndToBegin[&MI]->getParent()); 971 break; 972 973 default: 974 if (MI.isTerminator()) { 975 // Rewrite MBB operands to be depth immediates. 976 SmallVector<MachineOperand, 4> Ops(MI.operands()); 977 while (MI.getNumOperands() > 0) 978 MI.RemoveOperand(MI.getNumOperands() - 1); 979 for (auto MO : Ops) { 980 if (MO.isMBB()) 981 MO = MachineOperand::CreateImm(getDepth(Stack, MO.getMBB())); 982 MI.addOperand(MF, MO); 983 } 984 } 985 break; 986 } 987 } 988 } 989 assert(Stack.empty() && "Control flow should be balanced"); 990 } 991 992 void WebAssemblyCFGStackify::releaseMemory() { 993 ScopeTops.clear(); 994 BeginToEnd.clear(); 995 EndToBegin.clear(); 996 TryToEHPad.clear(); 997 EHPadToTry.clear(); 998 AppendixBB = nullptr; 999 } 1000 1001 bool WebAssemblyCFGStackify::runOnMachineFunction(MachineFunction &MF) { 1002 LLVM_DEBUG(dbgs() << "********** CFG Stackifying **********\n" 1003 "********** Function: " 1004 << MF.getName() << '\n'); 1005 const MCAsmInfo *MCAI = MF.getTarget().getMCAsmInfo(); 1006 1007 releaseMemory(); 1008 1009 // Liveness is not tracked for VALUE_STACK physreg. 1010 MF.getRegInfo().invalidateLiveness(); 1011 1012 // Place the BLOCK/LOOP/TRY markers to indicate the beginnings of scopes. 1013 placeMarkers(MF); 1014 1015 // Remove unnecessary instructions possibly introduced by try/end_trys. 1016 if (MCAI->getExceptionHandlingType() == ExceptionHandling::Wasm && 1017 MF.getFunction().hasPersonalityFn()) 1018 removeUnnecessaryInstrs(MF); 1019 1020 // Convert MBB operands in terminators to relative depth immediates. 1021 rewriteDepthImmediates(MF); 1022 1023 // Fix up block/loop/try signatures at the end of the function to conform to 1024 // WebAssembly's rules. 1025 fixEndsAtEndOfFunction(MF); 1026 1027 // Add an end instruction at the end of the function body. 1028 const auto &TII = *MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo(); 1029 if (!MF.getSubtarget<WebAssemblySubtarget>() 1030 .getTargetTriple() 1031 .isOSBinFormatELF()) 1032 appendEndToFunction(MF, TII); 1033 1034 MF.getInfo<WebAssemblyFunctionInfo>()->setCFGStackified(); 1035 return true; 1036 } 1037