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/CodeGen/WasmEHFuncInfo.h" 35 #include "llvm/MC/MCAsmInfo.h" 36 #include "llvm/Target/TargetMachine.h" 37 using namespace llvm; 38 using WebAssembly::SortRegionInfo; 39 40 #define DEBUG_TYPE "wasm-cfg-stackify" 41 42 STATISTIC(NumCallUnwindMismatches, "Number of call unwind mismatches found"); 43 STATISTIC(NumCatchUnwindMismatches, "Number of catch unwind mismatches found"); 44 45 namespace { 46 class WebAssemblyCFGStackify final : public MachineFunctionPass { 47 StringRef getPassName() const override { return "WebAssembly CFG Stackify"; } 48 49 void getAnalysisUsage(AnalysisUsage &AU) const override { 50 AU.addRequired<MachineDominatorTree>(); 51 AU.addRequired<MachineLoopInfo>(); 52 AU.addRequired<WebAssemblyExceptionInfo>(); 53 MachineFunctionPass::getAnalysisUsage(AU); 54 } 55 56 bool runOnMachineFunction(MachineFunction &MF) override; 57 58 // For each block whose label represents the end of a scope, record the block 59 // which holds the beginning of the scope. This will allow us to quickly skip 60 // over scoped regions when walking blocks. 61 SmallVector<MachineBasicBlock *, 8> ScopeTops; 62 void updateScopeTops(MachineBasicBlock *Begin, MachineBasicBlock *End) { 63 int EndNo = End->getNumber(); 64 if (!ScopeTops[EndNo] || ScopeTops[EndNo]->getNumber() > Begin->getNumber()) 65 ScopeTops[EndNo] = Begin; 66 } 67 68 // Placing markers. 69 void placeMarkers(MachineFunction &MF); 70 void placeBlockMarker(MachineBasicBlock &MBB); 71 void placeLoopMarker(MachineBasicBlock &MBB); 72 void placeTryMarker(MachineBasicBlock &MBB); 73 74 // Exception handling related functions 75 bool fixCallUnwindMismatches(MachineFunction &MF); 76 bool fixCatchUnwindMismatches(MachineFunction &MF); 77 void addTryDelegate(MachineInstr *RangeBegin, MachineInstr *RangeEnd, 78 MachineBasicBlock *DelegateDest); 79 void recalculateScopeTops(MachineFunction &MF); 80 void removeUnnecessaryInstrs(MachineFunction &MF); 81 82 // Wrap-up 83 using EndMarkerInfo = 84 std::pair<const MachineBasicBlock *, const MachineInstr *>; 85 unsigned getBranchDepth(const SmallVectorImpl<EndMarkerInfo> &Stack, 86 const MachineBasicBlock *MBB); 87 unsigned getDelegateDepth(const SmallVectorImpl<EndMarkerInfo> &Stack, 88 const MachineBasicBlock *MBB); 89 void rewriteDepthImmediates(MachineFunction &MF); 90 void fixEndsAtEndOfFunction(MachineFunction &MF); 91 void cleanupFunctionData(MachineFunction &MF); 92 93 // For each BLOCK|LOOP|TRY, the corresponding END_(BLOCK|LOOP|TRY) or DELEGATE 94 // (in case of TRY). 95 DenseMap<const MachineInstr *, MachineInstr *> BeginToEnd; 96 // For each END_(BLOCK|LOOP|TRY) or DELEGATE, the corresponding 97 // BLOCK|LOOP|TRY. 98 DenseMap<const MachineInstr *, MachineInstr *> EndToBegin; 99 // <TRY marker, EH pad> map 100 DenseMap<const MachineInstr *, MachineBasicBlock *> TryToEHPad; 101 // <EH pad, TRY marker> map 102 DenseMap<const MachineBasicBlock *, MachineInstr *> EHPadToTry; 103 104 // We need an appendix block to place 'end_loop' or 'end_try' marker when the 105 // loop / exception bottom block is the last block in a function 106 MachineBasicBlock *AppendixBB = nullptr; 107 MachineBasicBlock *getAppendixBlock(MachineFunction &MF) { 108 if (!AppendixBB) { 109 AppendixBB = MF.CreateMachineBasicBlock(); 110 // Give it a fake predecessor so that AsmPrinter prints its label. 111 AppendixBB->addSuccessor(AppendixBB); 112 MF.push_back(AppendixBB); 113 } 114 return AppendixBB; 115 } 116 117 // Before running rewriteDepthImmediates function, 'delegate' has a BB as its 118 // destination operand. getFakeCallerBlock() returns a fake BB that will be 119 // used for the operand when 'delegate' needs to rethrow to the caller. This 120 // will be rewritten as an immediate value that is the number of block depths 121 // + 1 in rewriteDepthImmediates, and this fake BB will be removed at the end 122 // of the pass. 123 MachineBasicBlock *FakeCallerBB = nullptr; 124 MachineBasicBlock *getFakeCallerBlock(MachineFunction &MF) { 125 if (!FakeCallerBB) 126 FakeCallerBB = MF.CreateMachineBasicBlock(); 127 return FakeCallerBB; 128 } 129 130 // Helper functions to register / unregister scope information created by 131 // marker instructions. 132 void registerScope(MachineInstr *Begin, MachineInstr *End); 133 void registerTryScope(MachineInstr *Begin, MachineInstr *End, 134 MachineBasicBlock *EHPad); 135 void unregisterScope(MachineInstr *Begin); 136 137 public: 138 static char ID; // Pass identification, replacement for typeid 139 WebAssemblyCFGStackify() : MachineFunctionPass(ID) {} 140 ~WebAssemblyCFGStackify() override { releaseMemory(); } 141 void releaseMemory() override; 142 }; 143 } // end anonymous namespace 144 145 char WebAssemblyCFGStackify::ID = 0; 146 INITIALIZE_PASS(WebAssemblyCFGStackify, DEBUG_TYPE, 147 "Insert BLOCK/LOOP/TRY markers for WebAssembly scopes", false, 148 false) 149 150 FunctionPass *llvm::createWebAssemblyCFGStackify() { 151 return new WebAssemblyCFGStackify(); 152 } 153 154 /// Test whether Pred has any terminators explicitly branching to MBB, as 155 /// opposed to falling through. Note that it's possible (eg. in unoptimized 156 /// code) for a branch instruction to both branch to a block and fallthrough 157 /// to it, so we check the actual branch operands to see if there are any 158 /// explicit mentions. 159 static bool explicitlyBranchesTo(MachineBasicBlock *Pred, 160 MachineBasicBlock *MBB) { 161 for (MachineInstr &MI : Pred->terminators()) 162 for (MachineOperand &MO : MI.explicit_operands()) 163 if (MO.isMBB() && MO.getMBB() == MBB) 164 return true; 165 return false; 166 } 167 168 // Returns an iterator to the earliest position possible within the MBB, 169 // satisfying the restrictions given by BeforeSet and AfterSet. BeforeSet 170 // contains instructions that should go before the marker, and AfterSet contains 171 // ones that should go after the marker. In this function, AfterSet is only 172 // used for sanity checking. 173 template <typename Container> 174 static MachineBasicBlock::iterator 175 getEarliestInsertPos(MachineBasicBlock *MBB, const Container &BeforeSet, 176 const Container &AfterSet) { 177 auto InsertPos = MBB->end(); 178 while (InsertPos != MBB->begin()) { 179 if (BeforeSet.count(&*std::prev(InsertPos))) { 180 #ifndef NDEBUG 181 // Sanity check 182 for (auto Pos = InsertPos, E = MBB->begin(); Pos != E; --Pos) 183 assert(!AfterSet.count(&*std::prev(Pos))); 184 #endif 185 break; 186 } 187 --InsertPos; 188 } 189 return InsertPos; 190 } 191 192 // Returns an iterator to the latest position possible within the MBB, 193 // satisfying the restrictions given by BeforeSet and AfterSet. BeforeSet 194 // contains instructions that should go before the marker, and AfterSet contains 195 // ones that should go after the marker. In this function, BeforeSet is only 196 // used for sanity checking. 197 template <typename Container> 198 static MachineBasicBlock::iterator 199 getLatestInsertPos(MachineBasicBlock *MBB, const Container &BeforeSet, 200 const Container &AfterSet) { 201 auto InsertPos = MBB->begin(); 202 while (InsertPos != MBB->end()) { 203 if (AfterSet.count(&*InsertPos)) { 204 #ifndef NDEBUG 205 // Sanity check 206 for (auto Pos = InsertPos, E = MBB->end(); Pos != E; ++Pos) 207 assert(!BeforeSet.count(&*Pos)); 208 #endif 209 break; 210 } 211 ++InsertPos; 212 } 213 return InsertPos; 214 } 215 216 void WebAssemblyCFGStackify::registerScope(MachineInstr *Begin, 217 MachineInstr *End) { 218 BeginToEnd[Begin] = End; 219 EndToBegin[End] = Begin; 220 } 221 222 // When 'End' is not an 'end_try' but 'delegate, EHPad is nullptr. 223 void WebAssemblyCFGStackify::registerTryScope(MachineInstr *Begin, 224 MachineInstr *End, 225 MachineBasicBlock *EHPad) { 226 registerScope(Begin, End); 227 TryToEHPad[Begin] = EHPad; 228 EHPadToTry[EHPad] = Begin; 229 } 230 231 void WebAssemblyCFGStackify::unregisterScope(MachineInstr *Begin) { 232 assert(BeginToEnd.count(Begin)); 233 MachineInstr *End = BeginToEnd[Begin]; 234 assert(EndToBegin.count(End)); 235 BeginToEnd.erase(Begin); 236 EndToBegin.erase(End); 237 MachineBasicBlock *EHPad = TryToEHPad.lookup(Begin); 238 if (EHPad) { 239 assert(EHPadToTry.count(EHPad)); 240 TryToEHPad.erase(Begin); 241 EHPadToTry.erase(EHPad); 242 } 243 } 244 245 /// Insert a BLOCK marker for branches to MBB (if needed). 246 // TODO Consider a more generalized way of handling block (and also loop and 247 // try) signatures when we implement the multi-value proposal later. 248 void WebAssemblyCFGStackify::placeBlockMarker(MachineBasicBlock &MBB) { 249 assert(!MBB.isEHPad()); 250 MachineFunction &MF = *MBB.getParent(); 251 auto &MDT = getAnalysis<MachineDominatorTree>(); 252 const auto &TII = *MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo(); 253 const auto &MFI = *MF.getInfo<WebAssemblyFunctionInfo>(); 254 255 // First compute the nearest common dominator of all forward non-fallthrough 256 // predecessors so that we minimize the time that the BLOCK is on the stack, 257 // which reduces overall stack height. 258 MachineBasicBlock *Header = nullptr; 259 bool IsBranchedTo = false; 260 int MBBNumber = MBB.getNumber(); 261 for (MachineBasicBlock *Pred : MBB.predecessors()) { 262 if (Pred->getNumber() < MBBNumber) { 263 Header = Header ? MDT.findNearestCommonDominator(Header, Pred) : Pred; 264 if (explicitlyBranchesTo(Pred, &MBB)) 265 IsBranchedTo = true; 266 } 267 } 268 if (!Header) 269 return; 270 if (!IsBranchedTo) 271 return; 272 273 assert(&MBB != &MF.front() && "Header blocks shouldn't have predecessors"); 274 MachineBasicBlock *LayoutPred = MBB.getPrevNode(); 275 276 // If the nearest common dominator is inside a more deeply nested context, 277 // walk out to the nearest scope which isn't more deeply nested. 278 for (MachineFunction::iterator I(LayoutPred), E(Header); I != E; --I) { 279 if (MachineBasicBlock *ScopeTop = ScopeTops[I->getNumber()]) { 280 if (ScopeTop->getNumber() > Header->getNumber()) { 281 // Skip over an intervening scope. 282 I = std::next(ScopeTop->getIterator()); 283 } else { 284 // We found a scope level at an appropriate depth. 285 Header = ScopeTop; 286 break; 287 } 288 } 289 } 290 291 // Decide where in Header to put the BLOCK. 292 293 // Instructions that should go before the BLOCK. 294 SmallPtrSet<const MachineInstr *, 4> BeforeSet; 295 // Instructions that should go after the BLOCK. 296 SmallPtrSet<const MachineInstr *, 4> AfterSet; 297 for (const auto &MI : *Header) { 298 // If there is a previously placed LOOP marker and the bottom block of the 299 // loop is above MBB, it should be after the BLOCK, because the loop is 300 // nested in this BLOCK. Otherwise it should be before the BLOCK. 301 if (MI.getOpcode() == WebAssembly::LOOP) { 302 auto *LoopBottom = BeginToEnd[&MI]->getParent()->getPrevNode(); 303 if (MBB.getNumber() > LoopBottom->getNumber()) 304 AfterSet.insert(&MI); 305 #ifndef NDEBUG 306 else 307 BeforeSet.insert(&MI); 308 #endif 309 } 310 311 // If there is a previously placed BLOCK/TRY marker and its corresponding 312 // END marker is before the current BLOCK's END marker, that should be 313 // placed after this BLOCK. Otherwise it should be placed before this BLOCK 314 // marker. 315 if (MI.getOpcode() == WebAssembly::BLOCK || 316 MI.getOpcode() == WebAssembly::TRY) { 317 if (BeginToEnd[&MI]->getParent()->getNumber() <= MBB.getNumber()) 318 AfterSet.insert(&MI); 319 #ifndef NDEBUG 320 else 321 BeforeSet.insert(&MI); 322 #endif 323 } 324 325 #ifndef NDEBUG 326 // All END_(BLOCK|LOOP|TRY) markers should be before the BLOCK. 327 if (MI.getOpcode() == WebAssembly::END_BLOCK || 328 MI.getOpcode() == WebAssembly::END_LOOP || 329 MI.getOpcode() == WebAssembly::END_TRY) 330 BeforeSet.insert(&MI); 331 #endif 332 333 // Terminators should go after the BLOCK. 334 if (MI.isTerminator()) 335 AfterSet.insert(&MI); 336 } 337 338 // Local expression tree should go after the BLOCK. 339 for (auto I = Header->getFirstTerminator(), E = Header->begin(); I != E; 340 --I) { 341 if (std::prev(I)->isDebugInstr() || std::prev(I)->isPosition()) 342 continue; 343 if (WebAssembly::isChild(*std::prev(I), MFI)) 344 AfterSet.insert(&*std::prev(I)); 345 else 346 break; 347 } 348 349 // Add the BLOCK. 350 WebAssembly::BlockType ReturnType = WebAssembly::BlockType::Void; 351 auto InsertPos = getLatestInsertPos(Header, BeforeSet, AfterSet); 352 MachineInstr *Begin = 353 BuildMI(*Header, InsertPos, Header->findDebugLoc(InsertPos), 354 TII.get(WebAssembly::BLOCK)) 355 .addImm(int64_t(ReturnType)); 356 357 // Decide where in Header to put the END_BLOCK. 358 BeforeSet.clear(); 359 AfterSet.clear(); 360 for (auto &MI : MBB) { 361 #ifndef NDEBUG 362 // END_BLOCK should precede existing LOOP and TRY markers. 363 if (MI.getOpcode() == WebAssembly::LOOP || 364 MI.getOpcode() == WebAssembly::TRY) 365 AfterSet.insert(&MI); 366 #endif 367 368 // If there is a previously placed END_LOOP marker and the header of the 369 // loop is above this block's header, the END_LOOP should be placed after 370 // the BLOCK, because the loop contains this block. Otherwise the END_LOOP 371 // should be placed before the BLOCK. The same for END_TRY. 372 if (MI.getOpcode() == WebAssembly::END_LOOP || 373 MI.getOpcode() == WebAssembly::END_TRY) { 374 if (EndToBegin[&MI]->getParent()->getNumber() >= Header->getNumber()) 375 BeforeSet.insert(&MI); 376 #ifndef NDEBUG 377 else 378 AfterSet.insert(&MI); 379 #endif 380 } 381 } 382 383 // Mark the end of the block. 384 InsertPos = getEarliestInsertPos(&MBB, BeforeSet, AfterSet); 385 MachineInstr *End = BuildMI(MBB, InsertPos, MBB.findPrevDebugLoc(InsertPos), 386 TII.get(WebAssembly::END_BLOCK)); 387 registerScope(Begin, End); 388 389 // Track the farthest-spanning scope that ends at this point. 390 updateScopeTops(Header, &MBB); 391 } 392 393 /// Insert a LOOP marker for a loop starting at MBB (if it's a loop header). 394 void WebAssemblyCFGStackify::placeLoopMarker(MachineBasicBlock &MBB) { 395 MachineFunction &MF = *MBB.getParent(); 396 const auto &MLI = getAnalysis<MachineLoopInfo>(); 397 const auto &WEI = getAnalysis<WebAssemblyExceptionInfo>(); 398 SortRegionInfo SRI(MLI, WEI); 399 const auto &TII = *MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo(); 400 401 MachineLoop *Loop = MLI.getLoopFor(&MBB); 402 if (!Loop || Loop->getHeader() != &MBB) 403 return; 404 405 // The operand of a LOOP is the first block after the loop. If the loop is the 406 // bottom of the function, insert a dummy block at the end. 407 MachineBasicBlock *Bottom = SRI.getBottom(Loop); 408 auto Iter = std::next(Bottom->getIterator()); 409 if (Iter == MF.end()) { 410 getAppendixBlock(MF); 411 Iter = std::next(Bottom->getIterator()); 412 } 413 MachineBasicBlock *AfterLoop = &*Iter; 414 415 // Decide where in Header to put the LOOP. 416 SmallPtrSet<const MachineInstr *, 4> BeforeSet; 417 SmallPtrSet<const MachineInstr *, 4> AfterSet; 418 for (const auto &MI : MBB) { 419 // LOOP marker should be after any existing loop that ends here. Otherwise 420 // we assume the instruction belongs to the loop. 421 if (MI.getOpcode() == WebAssembly::END_LOOP) 422 BeforeSet.insert(&MI); 423 #ifndef NDEBUG 424 else 425 AfterSet.insert(&MI); 426 #endif 427 } 428 429 // Mark the beginning of the loop. 430 auto InsertPos = getEarliestInsertPos(&MBB, BeforeSet, AfterSet); 431 MachineInstr *Begin = BuildMI(MBB, InsertPos, MBB.findDebugLoc(InsertPos), 432 TII.get(WebAssembly::LOOP)) 433 .addImm(int64_t(WebAssembly::BlockType::Void)); 434 435 // Decide where in Header to put the END_LOOP. 436 BeforeSet.clear(); 437 AfterSet.clear(); 438 #ifndef NDEBUG 439 for (const auto &MI : MBB) 440 // Existing END_LOOP markers belong to parent loops of this loop 441 if (MI.getOpcode() == WebAssembly::END_LOOP) 442 AfterSet.insert(&MI); 443 #endif 444 445 // Mark the end of the loop (using arbitrary debug location that branched to 446 // the loop end as its location). 447 InsertPos = getEarliestInsertPos(AfterLoop, BeforeSet, AfterSet); 448 DebugLoc EndDL = AfterLoop->pred_empty() 449 ? DebugLoc() 450 : (*AfterLoop->pred_rbegin())->findBranchDebugLoc(); 451 MachineInstr *End = 452 BuildMI(*AfterLoop, InsertPos, EndDL, TII.get(WebAssembly::END_LOOP)); 453 registerScope(Begin, End); 454 455 assert((!ScopeTops[AfterLoop->getNumber()] || 456 ScopeTops[AfterLoop->getNumber()]->getNumber() < MBB.getNumber()) && 457 "With block sorting the outermost loop for a block should be first."); 458 updateScopeTops(&MBB, AfterLoop); 459 } 460 461 void WebAssemblyCFGStackify::placeTryMarker(MachineBasicBlock &MBB) { 462 assert(MBB.isEHPad()); 463 MachineFunction &MF = *MBB.getParent(); 464 auto &MDT = getAnalysis<MachineDominatorTree>(); 465 const auto &TII = *MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo(); 466 const auto &MLI = getAnalysis<MachineLoopInfo>(); 467 const auto &WEI = getAnalysis<WebAssemblyExceptionInfo>(); 468 SortRegionInfo SRI(MLI, WEI); 469 const auto &MFI = *MF.getInfo<WebAssemblyFunctionInfo>(); 470 471 // Compute the nearest common dominator of all unwind predecessors 472 MachineBasicBlock *Header = nullptr; 473 int MBBNumber = MBB.getNumber(); 474 for (auto *Pred : MBB.predecessors()) { 475 if (Pred->getNumber() < MBBNumber) { 476 Header = Header ? MDT.findNearestCommonDominator(Header, Pred) : Pred; 477 assert(!explicitlyBranchesTo(Pred, &MBB) && 478 "Explicit branch to an EH pad!"); 479 } 480 } 481 if (!Header) 482 return; 483 484 // If this try is at the bottom of the function, insert a dummy block at the 485 // end. 486 WebAssemblyException *WE = WEI.getExceptionFor(&MBB); 487 assert(WE); 488 MachineBasicBlock *Bottom = SRI.getBottom(WE); 489 490 auto Iter = std::next(Bottom->getIterator()); 491 if (Iter == MF.end()) { 492 getAppendixBlock(MF); 493 Iter = std::next(Bottom->getIterator()); 494 } 495 MachineBasicBlock *Cont = &*Iter; 496 497 assert(Cont != &MF.front()); 498 MachineBasicBlock *LayoutPred = Cont->getPrevNode(); 499 500 // If the nearest common dominator is inside a more deeply nested context, 501 // walk out to the nearest scope which isn't more deeply nested. 502 for (MachineFunction::iterator I(LayoutPred), E(Header); I != E; --I) { 503 if (MachineBasicBlock *ScopeTop = ScopeTops[I->getNumber()]) { 504 if (ScopeTop->getNumber() > Header->getNumber()) { 505 // Skip over an intervening scope. 506 I = std::next(ScopeTop->getIterator()); 507 } else { 508 // We found a scope level at an appropriate depth. 509 Header = ScopeTop; 510 break; 511 } 512 } 513 } 514 515 // Decide where in Header to put the TRY. 516 517 // Instructions that should go before the TRY. 518 SmallPtrSet<const MachineInstr *, 4> BeforeSet; 519 // Instructions that should go after the TRY. 520 SmallPtrSet<const MachineInstr *, 4> AfterSet; 521 for (const auto &MI : *Header) { 522 // If there is a previously placed LOOP marker and the bottom block of the 523 // loop is above MBB, it should be after the TRY, because the loop is nested 524 // in this TRY. Otherwise it should be before the TRY. 525 if (MI.getOpcode() == WebAssembly::LOOP) { 526 auto *LoopBottom = BeginToEnd[&MI]->getParent()->getPrevNode(); 527 if (MBB.getNumber() > LoopBottom->getNumber()) 528 AfterSet.insert(&MI); 529 #ifndef NDEBUG 530 else 531 BeforeSet.insert(&MI); 532 #endif 533 } 534 535 // All previously inserted BLOCK/TRY markers should be after the TRY because 536 // they are all nested trys. 537 if (MI.getOpcode() == WebAssembly::BLOCK || 538 MI.getOpcode() == WebAssembly::TRY) 539 AfterSet.insert(&MI); 540 541 #ifndef NDEBUG 542 // All END_(BLOCK/LOOP/TRY) markers should be before the TRY. 543 if (MI.getOpcode() == WebAssembly::END_BLOCK || 544 MI.getOpcode() == WebAssembly::END_LOOP || 545 MI.getOpcode() == WebAssembly::END_TRY) 546 BeforeSet.insert(&MI); 547 #endif 548 549 // Terminators should go after the TRY. 550 if (MI.isTerminator()) 551 AfterSet.insert(&MI); 552 } 553 554 // If Header unwinds to MBB (= Header contains 'invoke'), the try block should 555 // contain the call within it. So the call should go after the TRY. The 556 // exception is when the header's terminator is a rethrow instruction, in 557 // which case that instruction, not a call instruction before it, is gonna 558 // throw. 559 MachineInstr *ThrowingCall = nullptr; 560 if (MBB.isPredecessor(Header)) { 561 auto TermPos = Header->getFirstTerminator(); 562 if (TermPos == Header->end() || 563 TermPos->getOpcode() != WebAssembly::RETHROW) { 564 for (auto &MI : reverse(*Header)) { 565 if (MI.isCall()) { 566 AfterSet.insert(&MI); 567 ThrowingCall = &MI; 568 // Possibly throwing calls are usually wrapped by EH_LABEL 569 // instructions. We don't want to split them and the call. 570 if (MI.getIterator() != Header->begin() && 571 std::prev(MI.getIterator())->isEHLabel()) { 572 AfterSet.insert(&*std::prev(MI.getIterator())); 573 ThrowingCall = &*std::prev(MI.getIterator()); 574 } 575 break; 576 } 577 } 578 } 579 } 580 581 // Local expression tree should go after the TRY. 582 // For BLOCK placement, we start the search from the previous instruction of a 583 // BB's terminator, but in TRY's case, we should start from the previous 584 // instruction of a call that can throw, or a EH_LABEL that precedes the call, 585 // because the return values of the call's previous instructions can be 586 // stackified and consumed by the throwing call. 587 auto SearchStartPt = ThrowingCall ? MachineBasicBlock::iterator(ThrowingCall) 588 : Header->getFirstTerminator(); 589 for (auto I = SearchStartPt, E = Header->begin(); I != E; --I) { 590 if (std::prev(I)->isDebugInstr() || std::prev(I)->isPosition()) 591 continue; 592 if (WebAssembly::isChild(*std::prev(I), MFI)) 593 AfterSet.insert(&*std::prev(I)); 594 else 595 break; 596 } 597 598 // Add the TRY. 599 auto InsertPos = getLatestInsertPos(Header, BeforeSet, AfterSet); 600 MachineInstr *Begin = 601 BuildMI(*Header, InsertPos, Header->findDebugLoc(InsertPos), 602 TII.get(WebAssembly::TRY)) 603 .addImm(int64_t(WebAssembly::BlockType::Void)); 604 605 // Decide where in Header to put the END_TRY. 606 BeforeSet.clear(); 607 AfterSet.clear(); 608 for (const auto &MI : *Cont) { 609 #ifndef NDEBUG 610 // END_TRY should precede existing LOOP and BLOCK markers. 611 if (MI.getOpcode() == WebAssembly::LOOP || 612 MI.getOpcode() == WebAssembly::BLOCK) 613 AfterSet.insert(&MI); 614 615 // All END_TRY markers placed earlier belong to exceptions that contains 616 // this one. 617 if (MI.getOpcode() == WebAssembly::END_TRY) 618 AfterSet.insert(&MI); 619 #endif 620 621 // If there is a previously placed END_LOOP marker and its header is after 622 // where TRY marker is, this loop is contained within the 'catch' part, so 623 // the END_TRY marker should go after that. Otherwise, the whole try-catch 624 // is contained within this loop, so the END_TRY should go before that. 625 if (MI.getOpcode() == WebAssembly::END_LOOP) { 626 // For a LOOP to be after TRY, LOOP's BB should be after TRY's BB; if they 627 // are in the same BB, LOOP is always before TRY. 628 if (EndToBegin[&MI]->getParent()->getNumber() > Header->getNumber()) 629 BeforeSet.insert(&MI); 630 #ifndef NDEBUG 631 else 632 AfterSet.insert(&MI); 633 #endif 634 } 635 636 // It is not possible for an END_BLOCK to be already in this block. 637 } 638 639 // Mark the end of the TRY. 640 InsertPos = getEarliestInsertPos(Cont, BeforeSet, AfterSet); 641 MachineInstr *End = 642 BuildMI(*Cont, InsertPos, Bottom->findBranchDebugLoc(), 643 TII.get(WebAssembly::END_TRY)); 644 registerTryScope(Begin, End, &MBB); 645 646 // Track the farthest-spanning scope that ends at this point. We create two 647 // mappings: (BB with 'end_try' -> BB with 'try') and (BB with 'catch' -> BB 648 // with 'try'). We need to create 'catch' -> 'try' mapping here too because 649 // markers should not span across 'catch'. For example, this should not 650 // happen: 651 // 652 // try 653 // block --| (X) 654 // catch | 655 // end_block --| 656 // end_try 657 for (auto *End : {&MBB, Cont}) 658 updateScopeTops(Header, End); 659 } 660 661 void WebAssemblyCFGStackify::removeUnnecessaryInstrs(MachineFunction &MF) { 662 const auto &TII = *MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo(); 663 664 // When there is an unconditional branch right before a catch instruction and 665 // it branches to the end of end_try marker, we don't need the branch, because 666 // it there is no exception, the control flow transfers to that point anyway. 667 // bb0: 668 // try 669 // ... 670 // br bb2 <- Not necessary 671 // bb1 (ehpad): 672 // catch 673 // ... 674 // bb2: <- Continuation BB 675 // end 676 // 677 // A more involved case: When the BB where 'end' is located is an another EH 678 // pad, the Cont (= continuation) BB is that EH pad's 'end' BB. For example, 679 // bb0: 680 // try 681 // try 682 // ... 683 // br bb3 <- Not necessary 684 // bb1 (ehpad): 685 // catch 686 // bb2 (ehpad): 687 // end 688 // catch 689 // ... 690 // bb3: <- Continuation BB 691 // end 692 // 693 // When the EH pad at hand is bb1, its matching end_try is in bb2. But it is 694 // another EH pad, so bb0's continuation BB becomes bb3. So 'br bb3' in the 695 // code can be deleted. This is why we run 'while' until 'Cont' is not an EH 696 // pad. 697 for (auto &MBB : MF) { 698 if (!MBB.isEHPad()) 699 continue; 700 701 MachineBasicBlock *TBB = nullptr, *FBB = nullptr; 702 SmallVector<MachineOperand, 4> Cond; 703 MachineBasicBlock *EHPadLayoutPred = MBB.getPrevNode(); 704 705 MachineBasicBlock *Cont = &MBB; 706 while (Cont->isEHPad()) { 707 MachineInstr *Try = EHPadToTry[Cont]; 708 MachineInstr *EndTry = BeginToEnd[Try]; 709 // We started from an EH pad, so the end marker cannot be a delegate 710 assert(EndTry->getOpcode() != WebAssembly::DELEGATE); 711 Cont = EndTry->getParent(); 712 } 713 714 bool Analyzable = !TII.analyzeBranch(*EHPadLayoutPred, TBB, FBB, Cond); 715 // This condition means either 716 // 1. This BB ends with a single unconditional branch whose destinaion is 717 // Cont. 718 // 2. This BB ends with a conditional branch followed by an unconditional 719 // branch, and the unconditional branch's destination is Cont. 720 // In both cases, we want to remove the last (= unconditional) branch. 721 if (Analyzable && ((Cond.empty() && TBB && TBB == Cont) || 722 (!Cond.empty() && FBB && FBB == Cont))) { 723 bool ErasedUncondBr = false; 724 (void)ErasedUncondBr; 725 for (auto I = EHPadLayoutPred->end(), E = EHPadLayoutPred->begin(); 726 I != E; --I) { 727 auto PrevI = std::prev(I); 728 if (PrevI->isTerminator()) { 729 assert(PrevI->getOpcode() == WebAssembly::BR); 730 PrevI->eraseFromParent(); 731 ErasedUncondBr = true; 732 break; 733 } 734 } 735 assert(ErasedUncondBr && "Unconditional branch not erased!"); 736 } 737 } 738 739 // When there are block / end_block markers that overlap with try / end_try 740 // markers, and the block and try markers' return types are the same, the 741 // block /end_block markers are not necessary, because try / end_try markers 742 // also can serve as boundaries for branches. 743 // block <- Not necessary 744 // try 745 // ... 746 // catch 747 // ... 748 // end 749 // end <- Not necessary 750 SmallVector<MachineInstr *, 32> ToDelete; 751 for (auto &MBB : MF) { 752 for (auto &MI : MBB) { 753 if (MI.getOpcode() != WebAssembly::TRY) 754 continue; 755 MachineInstr *Try = &MI, *EndTry = BeginToEnd[Try]; 756 if (EndTry->getOpcode() == WebAssembly::DELEGATE) 757 continue; 758 759 MachineBasicBlock *TryBB = Try->getParent(); 760 MachineBasicBlock *Cont = EndTry->getParent(); 761 int64_t RetType = Try->getOperand(0).getImm(); 762 for (auto B = Try->getIterator(), E = std::next(EndTry->getIterator()); 763 B != TryBB->begin() && E != Cont->end() && 764 std::prev(B)->getOpcode() == WebAssembly::BLOCK && 765 E->getOpcode() == WebAssembly::END_BLOCK && 766 std::prev(B)->getOperand(0).getImm() == RetType; 767 --B, ++E) { 768 ToDelete.push_back(&*std::prev(B)); 769 ToDelete.push_back(&*E); 770 } 771 } 772 } 773 for (auto *MI : ToDelete) { 774 if (MI->getOpcode() == WebAssembly::BLOCK) 775 unregisterScope(MI); 776 MI->eraseFromParent(); 777 } 778 } 779 780 // Get the appropriate copy opcode for the given register class. 781 static unsigned getCopyOpcode(const TargetRegisterClass *RC) { 782 if (RC == &WebAssembly::I32RegClass) 783 return WebAssembly::COPY_I32; 784 if (RC == &WebAssembly::I64RegClass) 785 return WebAssembly::COPY_I64; 786 if (RC == &WebAssembly::F32RegClass) 787 return WebAssembly::COPY_F32; 788 if (RC == &WebAssembly::F64RegClass) 789 return WebAssembly::COPY_F64; 790 if (RC == &WebAssembly::V128RegClass) 791 return WebAssembly::COPY_V128; 792 if (RC == &WebAssembly::FUNCREFRegClass) 793 return WebAssembly::COPY_FUNCREF; 794 if (RC == &WebAssembly::EXTERNREFRegClass) 795 return WebAssembly::COPY_EXTERNREF; 796 llvm_unreachable("Unexpected register class"); 797 } 798 799 // When MBB is split into MBB and Split, we should unstackify defs in MBB that 800 // have their uses in Split. 801 static void unstackifyVRegsUsedInSplitBB(MachineBasicBlock &MBB, 802 MachineBasicBlock &Split) { 803 MachineFunction &MF = *MBB.getParent(); 804 const auto &TII = *MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo(); 805 auto &MFI = *MF.getInfo<WebAssemblyFunctionInfo>(); 806 auto &MRI = MF.getRegInfo(); 807 808 for (auto &MI : Split) { 809 for (auto &MO : MI.explicit_uses()) { 810 if (!MO.isReg() || Register::isPhysicalRegister(MO.getReg())) 811 continue; 812 if (MachineInstr *Def = MRI.getUniqueVRegDef(MO.getReg())) 813 if (Def->getParent() == &MBB) 814 MFI.unstackifyVReg(MO.getReg()); 815 } 816 } 817 818 // In RegStackify, when a register definition is used multiple times, 819 // Reg = INST ... 820 // INST ..., Reg, ... 821 // INST ..., Reg, ... 822 // INST ..., Reg, ... 823 // 824 // we introduce a TEE, which has the following form: 825 // DefReg = INST ... 826 // TeeReg, Reg = TEE_... DefReg 827 // INST ..., TeeReg, ... 828 // INST ..., Reg, ... 829 // INST ..., Reg, ... 830 // with DefReg and TeeReg stackified but Reg not stackified. 831 // 832 // But the invariant that TeeReg should be stackified can be violated while we 833 // unstackify registers in the split BB above. In this case, we convert TEEs 834 // into two COPYs. This COPY will be eventually eliminated in ExplicitLocals. 835 // DefReg = INST ... 836 // TeeReg = COPY DefReg 837 // Reg = COPY DefReg 838 // INST ..., TeeReg, ... 839 // INST ..., Reg, ... 840 // INST ..., Reg, ... 841 for (auto I = MBB.begin(), E = MBB.end(); I != E;) { 842 MachineInstr &MI = *I++; 843 if (!WebAssembly::isTee(MI.getOpcode())) 844 continue; 845 Register TeeReg = MI.getOperand(0).getReg(); 846 Register Reg = MI.getOperand(1).getReg(); 847 Register DefReg = MI.getOperand(2).getReg(); 848 if (!MFI.isVRegStackified(TeeReg)) { 849 // Now we are not using TEE anymore, so unstackify DefReg too 850 MFI.unstackifyVReg(DefReg); 851 unsigned CopyOpc = getCopyOpcode(MRI.getRegClass(DefReg)); 852 BuildMI(MBB, &MI, MI.getDebugLoc(), TII.get(CopyOpc), TeeReg) 853 .addReg(DefReg); 854 BuildMI(MBB, &MI, MI.getDebugLoc(), TII.get(CopyOpc), Reg).addReg(DefReg); 855 MI.eraseFromParent(); 856 } 857 } 858 } 859 860 // Wrap the given range of instruction with try-delegate. RangeBegin and 861 // RangeEnd are inclusive. 862 void WebAssemblyCFGStackify::addTryDelegate(MachineInstr *RangeBegin, 863 MachineInstr *RangeEnd, 864 MachineBasicBlock *DelegateDest) { 865 auto *BeginBB = RangeBegin->getParent(); 866 auto *EndBB = RangeEnd->getParent(); 867 MachineFunction &MF = *BeginBB->getParent(); 868 const auto &MFI = *MF.getInfo<WebAssemblyFunctionInfo>(); 869 const auto &TII = *MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo(); 870 871 // Local expression tree before the first call of this range should go 872 // after the nested TRY. 873 SmallPtrSet<const MachineInstr *, 4> AfterSet; 874 AfterSet.insert(RangeBegin); 875 for (auto I = MachineBasicBlock::iterator(RangeBegin), E = BeginBB->begin(); 876 I != E; --I) { 877 if (std::prev(I)->isDebugInstr() || std::prev(I)->isPosition()) 878 continue; 879 if (WebAssembly::isChild(*std::prev(I), MFI)) 880 AfterSet.insert(&*std::prev(I)); 881 else 882 break; 883 } 884 885 // Create the nested try instruction. 886 auto TryPos = getLatestInsertPos( 887 BeginBB, SmallPtrSet<const MachineInstr *, 4>(), AfterSet); 888 MachineInstr *Try = BuildMI(*BeginBB, TryPos, RangeBegin->getDebugLoc(), 889 TII.get(WebAssembly::TRY)) 890 .addImm(int64_t(WebAssembly::BlockType::Void)); 891 892 // Create a BB to insert the 'delegate' instruction. 893 MachineBasicBlock *DelegateBB = MF.CreateMachineBasicBlock(); 894 // If the destination of 'delegate' is not the caller, adds the destination to 895 // the BB's successors. 896 if (DelegateDest != FakeCallerBB) 897 DelegateBB->addSuccessor(DelegateDest); 898 899 auto SplitPos = std::next(RangeEnd->getIterator()); 900 if (SplitPos == EndBB->end()) { 901 // If the range's end instruction is at the end of the BB, insert the new 902 // delegate BB after the current BB. 903 MF.insert(std::next(EndBB->getIterator()), DelegateBB); 904 EndBB->addSuccessor(DelegateBB); 905 906 } else { 907 // When the split pos is in the middle of a BB, we split the BB into two and 908 // put the 'delegate' BB in between. We normally create a split BB and make 909 // it a successor of the original BB (PostSplit == true), but in case the BB 910 // is an EH pad and the split pos is before 'catch', we should preserve the 911 // BB's property, including that it is an EH pad, in the later part of the 912 // BB, where 'catch' is. In this case we set PostSplit to false. 913 bool PostSplit = true; 914 if (EndBB->isEHPad()) { 915 for (auto I = MachineBasicBlock::iterator(SplitPos), E = EndBB->end(); 916 I != E; ++I) { 917 if (WebAssembly::isCatch(I->getOpcode())) { 918 PostSplit = false; 919 break; 920 } 921 } 922 } 923 924 MachineBasicBlock *PreBB = nullptr, *PostBB = nullptr; 925 if (PostSplit) { 926 // If the range's end instruction is in the middle of the BB, we split the 927 // BB into two and insert the delegate BB in between. 928 // - Before: 929 // bb: 930 // range_end 931 // other_insts 932 // 933 // - After: 934 // pre_bb: (previous 'bb') 935 // range_end 936 // delegate_bb: (new) 937 // delegate 938 // post_bb: (new) 939 // other_insts 940 PreBB = EndBB; 941 PostBB = MF.CreateMachineBasicBlock(); 942 MF.insert(std::next(PreBB->getIterator()), PostBB); 943 MF.insert(std::next(PreBB->getIterator()), DelegateBB); 944 PostBB->splice(PostBB->end(), PreBB, SplitPos, PreBB->end()); 945 PostBB->transferSuccessors(PreBB); 946 } else { 947 // - Before: 948 // ehpad: 949 // range_end 950 // catch 951 // ... 952 // 953 // - After: 954 // pre_bb: (new) 955 // range_end 956 // delegate_bb: (new) 957 // delegate 958 // post_bb: (previous 'ehpad') 959 // catch 960 // ... 961 assert(EndBB->isEHPad()); 962 PreBB = MF.CreateMachineBasicBlock(); 963 PostBB = EndBB; 964 MF.insert(PostBB->getIterator(), PreBB); 965 MF.insert(PostBB->getIterator(), DelegateBB); 966 PreBB->splice(PreBB->end(), PostBB, PostBB->begin(), SplitPos); 967 // We don't need to transfer predecessors of the EH pad to 'PreBB', 968 // because an EH pad's predecessors are all through unwind edges and they 969 // should still unwind to the EH pad, not PreBB. 970 } 971 unstackifyVRegsUsedInSplitBB(*PreBB, *PostBB); 972 PreBB->addSuccessor(DelegateBB); 973 PreBB->addSuccessor(PostBB); 974 } 975 976 // Add 'delegate' instruction in the delegate BB created above. 977 MachineInstr *Delegate = BuildMI(DelegateBB, RangeEnd->getDebugLoc(), 978 TII.get(WebAssembly::DELEGATE)) 979 .addMBB(DelegateDest); 980 registerTryScope(Try, Delegate, nullptr); 981 } 982 983 bool WebAssemblyCFGStackify::fixCallUnwindMismatches(MachineFunction &MF) { 984 // Linearizing the control flow by placing TRY / END_TRY markers can create 985 // mismatches in unwind destinations for throwing instructions, such as calls. 986 // 987 // We use the 'delegate' instruction to fix the unwind mismatches. 'delegate' 988 // instruction delegates an exception to an outer 'catch'. It can target not 989 // only 'catch' but all block-like structures including another 'delegate', 990 // but with slightly different semantics than branches. When it targets a 991 // 'catch', it will delegate the exception to that catch. It is being 992 // discussed how to define the semantics when 'delegate''s target is a non-try 993 // block: it will either be a validation failure or it will target the next 994 // outer try-catch. But anyway our LLVM backend currently does not generate 995 // such code. The example below illustrates where the 'delegate' instruction 996 // in the middle will delegate the exception to, depending on the value of N. 997 // try 998 // try 999 // block 1000 // try 1001 // try 1002 // call @foo 1003 // delegate N ;; Where will this delegate to? 1004 // catch ;; N == 0 1005 // end 1006 // end ;; N == 1 (invalid; will not be generated) 1007 // delegate ;; N == 2 1008 // catch ;; N == 3 1009 // end 1010 // ;; N == 4 (to caller) 1011 1012 // 1. When an instruction may throw, but the EH pad it will unwind to can be 1013 // different from the original CFG. 1014 // 1015 // Example: we have the following CFG: 1016 // bb0: 1017 // call @foo ; if it throws, unwind to bb2 1018 // bb1: 1019 // call @bar ; if it throws, unwind to bb3 1020 // bb2 (ehpad): 1021 // catch 1022 // ... 1023 // bb3 (ehpad) 1024 // catch 1025 // ... 1026 // 1027 // And the CFG is sorted in this order. Then after placing TRY markers, it 1028 // will look like: (BB markers are omitted) 1029 // try 1030 // try 1031 // call @foo 1032 // call @bar ;; if it throws, unwind to bb3 1033 // catch ;; ehpad (bb2) 1034 // ... 1035 // end_try 1036 // catch ;; ehpad (bb3) 1037 // ... 1038 // end_try 1039 // 1040 // Now if bar() throws, it is going to end up ip in bb2, not bb3, where it 1041 // is supposed to end up. We solve this problem by wrapping the mismatching 1042 // call with an inner try-delegate that rethrows the exception to the right 1043 // 'catch'. 1044 // 1045 // try 1046 // try 1047 // call @foo 1048 // try ;; (new) 1049 // call @bar 1050 // delegate 1 (bb3) ;; (new) 1051 // catch ;; ehpad (bb2) 1052 // ... 1053 // end_try 1054 // catch ;; ehpad (bb3) 1055 // ... 1056 // end_try 1057 // 1058 // --- 1059 // 2. The same as 1, but in this case an instruction unwinds to a caller 1060 // function and not another EH pad. 1061 // 1062 // Example: we have the following CFG: 1063 // bb0: 1064 // call @foo ; if it throws, unwind to bb2 1065 // bb1: 1066 // call @bar ; if it throws, unwind to caller 1067 // bb2 (ehpad): 1068 // catch 1069 // ... 1070 // 1071 // And the CFG is sorted in this order. Then after placing TRY markers, it 1072 // will look like: 1073 // try 1074 // call @foo 1075 // call @bar ;; if it throws, unwind to caller 1076 // catch ;; ehpad (bb2) 1077 // ... 1078 // end_try 1079 // 1080 // Now if bar() throws, it is going to end up ip in bb2, when it is supposed 1081 // throw up to the caller. We solve this problem in the same way, but in this 1082 // case 'delegate's immediate argument is the number of block depths + 1, 1083 // which means it rethrows to the caller. 1084 // try 1085 // call @foo 1086 // try ;; (new) 1087 // call @bar 1088 // delegate 1 (caller) ;; (new) 1089 // catch ;; ehpad (bb2) 1090 // ... 1091 // end_try 1092 // 1093 // Before rewriteDepthImmediates, delegate's argument is a BB. In case of the 1094 // caller, it will take a fake BB generated by getFakeCallerBlock(), which 1095 // will be converted to a correct immediate argument later. 1096 // 1097 // In case there are multiple calls in a BB that may throw to the caller, they 1098 // can be wrapped together in one nested try-delegate scope. (In 1, this 1099 // couldn't happen, because may-throwing instruction there had an unwind 1100 // destination, i.e., it was an invoke before, and there could be only one 1101 // invoke within a BB.) 1102 1103 SmallVector<const MachineBasicBlock *, 8> EHPadStack; 1104 // Range of intructions to be wrapped in a new nested try/catch. A range 1105 // exists in a single BB and does not span multiple BBs. 1106 using TryRange = std::pair<MachineInstr *, MachineInstr *>; 1107 // In original CFG, <unwind destination BB, a vector of try ranges> 1108 DenseMap<MachineBasicBlock *, SmallVector<TryRange, 4>> UnwindDestToTryRanges; 1109 1110 // Gather possibly throwing calls (i.e., previously invokes) whose current 1111 // unwind destination is not the same as the original CFG. (Case 1) 1112 1113 for (auto &MBB : reverse(MF)) { 1114 bool SeenThrowableInstInBB = false; 1115 for (auto &MI : reverse(MBB)) { 1116 if (MI.getOpcode() == WebAssembly::TRY) 1117 EHPadStack.pop_back(); 1118 else if (WebAssembly::isCatch(MI.getOpcode())) 1119 EHPadStack.push_back(MI.getParent()); 1120 1121 // In this loop we only gather calls that have an EH pad to unwind. So 1122 // there will be at most 1 such call (= invoke) in a BB, so after we've 1123 // seen one, we can skip the rest of BB. Also if MBB has no EH pad 1124 // successor or MI does not throw, this is not an invoke. 1125 if (SeenThrowableInstInBB || !MBB.hasEHPadSuccessor() || 1126 !WebAssembly::mayThrow(MI)) 1127 continue; 1128 SeenThrowableInstInBB = true; 1129 1130 // If the EH pad on the stack top is where this instruction should unwind 1131 // next, we're good. 1132 MachineBasicBlock *UnwindDest = getFakeCallerBlock(MF); 1133 for (auto *Succ : MBB.successors()) { 1134 // Even though semantically a BB can have multiple successors in case an 1135 // exception is not caught by a catchpad, in our backend implementation 1136 // it is guaranteed that a BB can have at most one EH pad successor. For 1137 // details, refer to comments in findWasmUnwindDestinations function in 1138 // SelectionDAGBuilder.cpp. 1139 if (Succ->isEHPad()) { 1140 UnwindDest = Succ; 1141 break; 1142 } 1143 } 1144 if (EHPadStack.back() == UnwindDest) 1145 continue; 1146 1147 // Include EH_LABELs in the range before and afer the invoke 1148 MachineInstr *RangeBegin = &MI, *RangeEnd = &MI; 1149 if (RangeBegin->getIterator() != MBB.begin() && 1150 std::prev(RangeBegin->getIterator())->isEHLabel()) 1151 RangeBegin = &*std::prev(RangeBegin->getIterator()); 1152 if (std::next(RangeEnd->getIterator()) != MBB.end() && 1153 std::next(RangeEnd->getIterator())->isEHLabel()) 1154 RangeEnd = &*std::next(RangeEnd->getIterator()); 1155 1156 // If not, record the range. 1157 UnwindDestToTryRanges[UnwindDest].push_back( 1158 TryRange(RangeBegin, RangeEnd)); 1159 LLVM_DEBUG(dbgs() << "- Call unwind mismatch: MBB = " << MBB.getName() 1160 << "\nCall = " << MI 1161 << "\nOriginal dest = " << UnwindDest->getName() 1162 << " Current dest = " << EHPadStack.back()->getName() 1163 << "\n\n"); 1164 } 1165 } 1166 1167 assert(EHPadStack.empty()); 1168 1169 // Gather possibly throwing calls that are supposed to unwind up to the caller 1170 // if they throw, but currently unwind to an incorrect destination. Unlike the 1171 // loop above, there can be multiple calls within a BB that unwind to the 1172 // caller, which we should group together in a range. (Case 2) 1173 1174 MachineInstr *RangeBegin = nullptr, *RangeEnd = nullptr; // inclusive 1175 1176 // Record the range. 1177 auto RecordCallerMismatchRange = [&](const MachineBasicBlock *CurrentDest) { 1178 UnwindDestToTryRanges[getFakeCallerBlock(MF)].push_back( 1179 TryRange(RangeBegin, RangeEnd)); 1180 LLVM_DEBUG(dbgs() << "- Call unwind mismatch: MBB = " 1181 << RangeBegin->getParent()->getName() 1182 << "\nRange begin = " << *RangeBegin 1183 << "Range end = " << *RangeEnd 1184 << "\nOriginal dest = caller Current dest = " 1185 << CurrentDest->getName() << "\n\n"); 1186 RangeBegin = RangeEnd = nullptr; // Reset range pointers 1187 }; 1188 1189 for (auto &MBB : reverse(MF)) { 1190 bool SeenThrowableInstInBB = false; 1191 for (auto &MI : reverse(MBB)) { 1192 if (MI.getOpcode() == WebAssembly::TRY) 1193 EHPadStack.pop_back(); 1194 else if (WebAssembly::isCatch(MI.getOpcode())) 1195 EHPadStack.push_back(MI.getParent()); 1196 bool MayThrow = WebAssembly::mayThrow(MI); 1197 1198 // If MBB has an EH pad successor and this is the last instruction that 1199 // may throw, this instruction unwinds to the EH pad and not to the 1200 // caller. 1201 if (MBB.hasEHPadSuccessor() && MayThrow && !SeenThrowableInstInBB) { 1202 SeenThrowableInstInBB = true; 1203 continue; 1204 } 1205 1206 // We wrap up the current range when we see a marker even if we haven't 1207 // finished a BB. 1208 if (RangeEnd && WebAssembly::isMarker(MI.getOpcode())) { 1209 RecordCallerMismatchRange(EHPadStack.back()); 1210 continue; 1211 } 1212 1213 // If EHPadStack is empty, that means it correctly unwinds to the caller 1214 // if it throws, so we're good. If MI does not throw, we're good too. 1215 if (EHPadStack.empty() || !MayThrow) 1216 continue; 1217 1218 // We found an instruction that unwinds to the caller but currently has an 1219 // incorrect unwind destination. Create a new range or increment the 1220 // currently existing range. 1221 if (!RangeEnd) 1222 RangeBegin = RangeEnd = &MI; 1223 else 1224 RangeBegin = &MI; 1225 } 1226 1227 if (RangeEnd) 1228 RecordCallerMismatchRange(EHPadStack.back()); 1229 } 1230 1231 assert(EHPadStack.empty()); 1232 1233 // We don't have any unwind destination mismatches to resolve. 1234 if (UnwindDestToTryRanges.empty()) 1235 return false; 1236 1237 // Now we fix the mismatches by wrapping calls with inner try-delegates. 1238 for (auto &P : UnwindDestToTryRanges) { 1239 NumCallUnwindMismatches += P.second.size(); 1240 MachineBasicBlock *UnwindDest = P.first; 1241 auto &TryRanges = P.second; 1242 1243 for (auto Range : TryRanges) { 1244 MachineInstr *RangeBegin = nullptr, *RangeEnd = nullptr; 1245 std::tie(RangeBegin, RangeEnd) = Range; 1246 auto *MBB = RangeBegin->getParent(); 1247 1248 // If this BB has an EH pad successor, i.e., ends with an 'invoke', now we 1249 // are going to wrap the invoke with try-delegate, making the 'delegate' 1250 // BB the new successor instead, so remove the EH pad succesor here. The 1251 // BB may not have an EH pad successor if calls in this BB throw to the 1252 // caller. 1253 MachineBasicBlock *EHPad = nullptr; 1254 for (auto *Succ : MBB->successors()) { 1255 if (Succ->isEHPad()) { 1256 EHPad = Succ; 1257 break; 1258 } 1259 } 1260 if (EHPad) 1261 MBB->removeSuccessor(EHPad); 1262 1263 addTryDelegate(RangeBegin, RangeEnd, UnwindDest); 1264 } 1265 } 1266 1267 return true; 1268 } 1269 1270 bool WebAssemblyCFGStackify::fixCatchUnwindMismatches(MachineFunction &MF) { 1271 // There is another kind of unwind destination mismatches besides call unwind 1272 // mismatches, which we will call "catch unwind mismatches". See this example 1273 // after the marker placement: 1274 // try 1275 // try 1276 // call @foo 1277 // catch __cpp_exception ;; ehpad A (next unwind dest: caller) 1278 // ... 1279 // end_try 1280 // catch_all ;; ehpad B 1281 // ... 1282 // end_try 1283 // 1284 // 'call @foo's unwind destination is the ehpad A. But suppose 'call @foo' 1285 // throws a foreign exception that is not caught by ehpad A, and its next 1286 // destination should be the caller. But after control flow linearization, 1287 // another EH pad can be placed in between (e.g. ehpad B here), making the 1288 // next unwind destination incorrect. In this case, the foreign exception 1289 // will instead go to ehpad B and will be caught there instead. In this 1290 // example the correct next unwind destination is the caller, but it can be 1291 // another outer catch in other cases. 1292 // 1293 // There is no specific 'call' or 'throw' instruction to wrap with a 1294 // try-delegate, so we wrap the whole try-catch-end with a try-delegate and 1295 // make it rethrow to the right destination, as in the example below: 1296 // try 1297 // try ;; (new) 1298 // try 1299 // call @foo 1300 // catch __cpp_exception ;; ehpad A (next unwind dest: caller) 1301 // ... 1302 // end_try 1303 // delegate 1 (caller) ;; (new) 1304 // catch_all ;; ehpad B 1305 // ... 1306 // end_try 1307 1308 const auto *EHInfo = MF.getWasmEHFuncInfo(); 1309 SmallVector<const MachineBasicBlock *, 8> EHPadStack; 1310 // For EH pads that have catch unwind mismatches, a map of <EH pad, its 1311 // correct unwind destination>. 1312 DenseMap<MachineBasicBlock *, MachineBasicBlock *> EHPadToUnwindDest; 1313 1314 for (auto &MBB : reverse(MF)) { 1315 for (auto &MI : reverse(MBB)) { 1316 if (MI.getOpcode() == WebAssembly::TRY) 1317 EHPadStack.pop_back(); 1318 else if (MI.getOpcode() == WebAssembly::DELEGATE) 1319 EHPadStack.push_back(&MBB); 1320 else if (WebAssembly::isCatch(MI.getOpcode())) { 1321 auto *EHPad = &MBB; 1322 1323 // catch_all always catches an exception, so we don't need to do 1324 // anything 1325 if (MI.getOpcode() == WebAssembly::CATCH_ALL) { 1326 } 1327 1328 // This can happen when the unwind dest was removed during the 1329 // optimization, e.g. because it was unreachable. 1330 else if (EHPadStack.empty() && EHInfo->hasEHPadUnwindDest(EHPad)) { 1331 LLVM_DEBUG(dbgs() << "EHPad (" << EHPad->getName() 1332 << "'s unwind destination does not exist anymore" 1333 << "\n\n"); 1334 } 1335 1336 // The EHPad's next unwind destination is the caller, but we incorrectly 1337 // unwind to another EH pad. 1338 else if (!EHPadStack.empty() && !EHInfo->hasEHPadUnwindDest(EHPad)) { 1339 EHPadToUnwindDest[EHPad] = getFakeCallerBlock(MF); 1340 LLVM_DEBUG(dbgs() 1341 << "- Catch unwind mismatch:\nEHPad = " << EHPad->getName() 1342 << " Original dest = caller Current dest = " 1343 << EHPadStack.back()->getName() << "\n\n"); 1344 } 1345 1346 // The EHPad's next unwind destination is an EH pad, whereas we 1347 // incorrectly unwind to another EH pad. 1348 else if (!EHPadStack.empty() && EHInfo->hasEHPadUnwindDest(EHPad)) { 1349 auto *UnwindDest = EHInfo->getEHPadUnwindDest(EHPad); 1350 if (EHPadStack.back() != UnwindDest) { 1351 EHPadToUnwindDest[EHPad] = UnwindDest; 1352 LLVM_DEBUG(dbgs() << "- Catch unwind mismatch:\nEHPad = " 1353 << EHPad->getName() << " Original dest = " 1354 << UnwindDest->getName() << " Current dest = " 1355 << EHPadStack.back()->getName() << "\n\n"); 1356 } 1357 } 1358 1359 EHPadStack.push_back(EHPad); 1360 } 1361 } 1362 } 1363 1364 assert(EHPadStack.empty()); 1365 if (EHPadToUnwindDest.empty()) 1366 return false; 1367 NumCatchUnwindMismatches += EHPadToUnwindDest.size(); 1368 1369 for (auto &P : EHPadToUnwindDest) { 1370 MachineBasicBlock *EHPad = P.first; 1371 MachineBasicBlock *UnwindDest = P.second; 1372 MachineInstr *Try = EHPadToTry[EHPad]; 1373 MachineInstr *EndTry = BeginToEnd[Try]; 1374 addTryDelegate(Try, EndTry, UnwindDest); 1375 } 1376 1377 return true; 1378 } 1379 1380 void WebAssemblyCFGStackify::recalculateScopeTops(MachineFunction &MF) { 1381 // Renumber BBs and recalculate ScopeTop info because new BBs might have been 1382 // created and inserted during fixing unwind mismatches. 1383 MF.RenumberBlocks(); 1384 ScopeTops.clear(); 1385 ScopeTops.resize(MF.getNumBlockIDs()); 1386 for (auto &MBB : reverse(MF)) { 1387 for (auto &MI : reverse(MBB)) { 1388 if (ScopeTops[MBB.getNumber()]) 1389 break; 1390 switch (MI.getOpcode()) { 1391 case WebAssembly::END_BLOCK: 1392 case WebAssembly::END_LOOP: 1393 case WebAssembly::END_TRY: 1394 case WebAssembly::DELEGATE: 1395 updateScopeTops(EndToBegin[&MI]->getParent(), &MBB); 1396 break; 1397 case WebAssembly::CATCH: 1398 case WebAssembly::CATCH_ALL: 1399 updateScopeTops(EHPadToTry[&MBB]->getParent(), &MBB); 1400 break; 1401 } 1402 } 1403 } 1404 } 1405 1406 /// In normal assembly languages, when the end of a function is unreachable, 1407 /// because the function ends in an infinite loop or a noreturn call or similar, 1408 /// it isn't necessary to worry about the function return type at the end of 1409 /// the function, because it's never reached. However, in WebAssembly, blocks 1410 /// that end at the function end need to have a return type signature that 1411 /// matches the function signature, even though it's unreachable. This function 1412 /// checks for such cases and fixes up the signatures. 1413 void WebAssemblyCFGStackify::fixEndsAtEndOfFunction(MachineFunction &MF) { 1414 const auto &MFI = *MF.getInfo<WebAssemblyFunctionInfo>(); 1415 1416 if (MFI.getResults().empty()) 1417 return; 1418 1419 // MCInstLower will add the proper types to multivalue signatures based on the 1420 // function return type 1421 WebAssembly::BlockType RetType = 1422 MFI.getResults().size() > 1 1423 ? WebAssembly::BlockType::Multivalue 1424 : WebAssembly::BlockType( 1425 WebAssembly::toValType(MFI.getResults().front())); 1426 1427 SmallVector<MachineBasicBlock::reverse_iterator, 4> Worklist; 1428 Worklist.push_back(MF.rbegin()->rbegin()); 1429 1430 auto Process = [&](MachineBasicBlock::reverse_iterator It) { 1431 auto *MBB = It->getParent(); 1432 while (It != MBB->rend()) { 1433 MachineInstr &MI = *It++; 1434 if (MI.isPosition() || MI.isDebugInstr()) 1435 continue; 1436 switch (MI.getOpcode()) { 1437 case WebAssembly::END_TRY: { 1438 // If a 'try''s return type is fixed, both its try body and catch body 1439 // should satisfy the return type, so we need to search 'end' 1440 // instructions before its corresponding 'catch' too. 1441 auto *EHPad = TryToEHPad.lookup(EndToBegin[&MI]); 1442 assert(EHPad); 1443 auto NextIt = 1444 std::next(WebAssembly::findCatch(EHPad)->getReverseIterator()); 1445 if (NextIt != EHPad->rend()) 1446 Worklist.push_back(NextIt); 1447 LLVM_FALLTHROUGH; 1448 } 1449 case WebAssembly::END_BLOCK: 1450 case WebAssembly::END_LOOP: 1451 EndToBegin[&MI]->getOperand(0).setImm(int32_t(RetType)); 1452 continue; 1453 default: 1454 // Something other than an `end`. We're done for this BB. 1455 return; 1456 } 1457 } 1458 // We've reached the beginning of a BB. Continue the search in the previous 1459 // BB. 1460 Worklist.push_back(MBB->getPrevNode()->rbegin()); 1461 }; 1462 1463 while (!Worklist.empty()) 1464 Process(Worklist.pop_back_val()); 1465 } 1466 1467 // WebAssembly functions end with an end instruction, as if the function body 1468 // were a block. 1469 static void appendEndToFunction(MachineFunction &MF, 1470 const WebAssemblyInstrInfo &TII) { 1471 BuildMI(MF.back(), MF.back().end(), 1472 MF.back().findPrevDebugLoc(MF.back().end()), 1473 TII.get(WebAssembly::END_FUNCTION)); 1474 } 1475 1476 /// Insert LOOP/TRY/BLOCK markers at appropriate places. 1477 void WebAssemblyCFGStackify::placeMarkers(MachineFunction &MF) { 1478 // We allocate one more than the number of blocks in the function to 1479 // accommodate for the possible fake block we may insert at the end. 1480 ScopeTops.resize(MF.getNumBlockIDs() + 1); 1481 // Place the LOOP for MBB if MBB is the header of a loop. 1482 for (auto &MBB : MF) 1483 placeLoopMarker(MBB); 1484 1485 const MCAsmInfo *MCAI = MF.getTarget().getMCAsmInfo(); 1486 for (auto &MBB : MF) { 1487 if (MBB.isEHPad()) { 1488 // Place the TRY for MBB if MBB is the EH pad of an exception. 1489 if (MCAI->getExceptionHandlingType() == ExceptionHandling::Wasm && 1490 MF.getFunction().hasPersonalityFn()) 1491 placeTryMarker(MBB); 1492 } else { 1493 // Place the BLOCK for MBB if MBB is branched to from above. 1494 placeBlockMarker(MBB); 1495 } 1496 } 1497 // Fix mismatches in unwind destinations induced by linearizing the code. 1498 if (MCAI->getExceptionHandlingType() == ExceptionHandling::Wasm && 1499 MF.getFunction().hasPersonalityFn()) { 1500 bool Changed = fixCallUnwindMismatches(MF); 1501 Changed |= fixCatchUnwindMismatches(MF); 1502 if (Changed) 1503 recalculateScopeTops(MF); 1504 } 1505 } 1506 1507 unsigned WebAssemblyCFGStackify::getBranchDepth( 1508 const SmallVectorImpl<EndMarkerInfo> &Stack, const MachineBasicBlock *MBB) { 1509 unsigned Depth = 0; 1510 for (auto X : reverse(Stack)) { 1511 if (X.first == MBB) 1512 break; 1513 ++Depth; 1514 } 1515 assert(Depth < Stack.size() && "Branch destination should be in scope"); 1516 return Depth; 1517 } 1518 1519 unsigned WebAssemblyCFGStackify::getDelegateDepth( 1520 const SmallVectorImpl<EndMarkerInfo> &Stack, const MachineBasicBlock *MBB) { 1521 if (MBB == FakeCallerBB) 1522 return Stack.size(); 1523 // Delegate's destination is either a catch or a another delegate BB. When the 1524 // destination is another delegate, we can compute the argument in the same 1525 // way as branches, because the target delegate BB only contains the single 1526 // delegate instruction. 1527 if (!MBB->isEHPad()) // Target is a delegate BB 1528 return getBranchDepth(Stack, MBB); 1529 1530 // When the delegate's destination is a catch BB, we need to use its 1531 // corresponding try's end_try BB because Stack contains each marker's end BB. 1532 // Also we need to check if the end marker instruction matches, because a 1533 // single BB can contain multiple end markers, like this: 1534 // bb: 1535 // END_BLOCK 1536 // END_TRY 1537 // END_BLOCK 1538 // END_TRY 1539 // ... 1540 // 1541 // In case of branches getting the immediate that targets any of these is 1542 // fine, but delegate has to exactly target the correct try. 1543 unsigned Depth = 0; 1544 const MachineInstr *EndTry = BeginToEnd[EHPadToTry[MBB]]; 1545 for (auto X : reverse(Stack)) { 1546 if (X.first == EndTry->getParent() && X.second == EndTry) 1547 break; 1548 ++Depth; 1549 } 1550 assert(Depth < Stack.size() && "Delegate destination should be in scope"); 1551 return Depth; 1552 } 1553 1554 void WebAssemblyCFGStackify::rewriteDepthImmediates(MachineFunction &MF) { 1555 // Now rewrite references to basic blocks to be depth immediates. 1556 SmallVector<EndMarkerInfo, 8> Stack; 1557 for (auto &MBB : reverse(MF)) { 1558 for (auto I = MBB.rbegin(), E = MBB.rend(); I != E; ++I) { 1559 MachineInstr &MI = *I; 1560 switch (MI.getOpcode()) { 1561 case WebAssembly::BLOCK: 1562 case WebAssembly::TRY: 1563 assert(ScopeTops[Stack.back().first->getNumber()]->getNumber() <= 1564 MBB.getNumber() && 1565 "Block/try marker should be balanced"); 1566 Stack.pop_back(); 1567 break; 1568 1569 case WebAssembly::LOOP: 1570 assert(Stack.back().first == &MBB && "Loop top should be balanced"); 1571 Stack.pop_back(); 1572 break; 1573 1574 case WebAssembly::END_BLOCK: 1575 Stack.push_back(std::make_pair(&MBB, &MI)); 1576 break; 1577 1578 case WebAssembly::END_TRY: 1579 // We handle DELEGATE in the default level, because DELEGATE has 1580 // immediate operands to rewrite. 1581 Stack.push_back(std::make_pair(&MBB, &MI)); 1582 break; 1583 1584 case WebAssembly::END_LOOP: 1585 Stack.push_back(std::make_pair(EndToBegin[&MI]->getParent(), &MI)); 1586 break; 1587 1588 default: 1589 if (MI.isTerminator()) { 1590 // Rewrite MBB operands to be depth immediates. 1591 SmallVector<MachineOperand, 4> Ops(MI.operands()); 1592 while (MI.getNumOperands() > 0) 1593 MI.RemoveOperand(MI.getNumOperands() - 1); 1594 for (auto MO : Ops) { 1595 if (MO.isMBB()) { 1596 if (MI.getOpcode() == WebAssembly::DELEGATE) 1597 MO = MachineOperand::CreateImm( 1598 getDelegateDepth(Stack, MO.getMBB())); 1599 else 1600 MO = MachineOperand::CreateImm( 1601 getBranchDepth(Stack, MO.getMBB())); 1602 } 1603 MI.addOperand(MF, MO); 1604 } 1605 } 1606 1607 if (MI.getOpcode() == WebAssembly::DELEGATE) 1608 Stack.push_back(std::make_pair(&MBB, &MI)); 1609 break; 1610 } 1611 } 1612 } 1613 assert(Stack.empty() && "Control flow should be balanced"); 1614 } 1615 1616 void WebAssemblyCFGStackify::cleanupFunctionData(MachineFunction &MF) { 1617 if (FakeCallerBB) 1618 MF.DeleteMachineBasicBlock(FakeCallerBB); 1619 AppendixBB = FakeCallerBB = nullptr; 1620 } 1621 1622 void WebAssemblyCFGStackify::releaseMemory() { 1623 ScopeTops.clear(); 1624 BeginToEnd.clear(); 1625 EndToBegin.clear(); 1626 TryToEHPad.clear(); 1627 EHPadToTry.clear(); 1628 } 1629 1630 bool WebAssemblyCFGStackify::runOnMachineFunction(MachineFunction &MF) { 1631 LLVM_DEBUG(dbgs() << "********** CFG Stackifying **********\n" 1632 "********** Function: " 1633 << MF.getName() << '\n'); 1634 const MCAsmInfo *MCAI = MF.getTarget().getMCAsmInfo(); 1635 1636 releaseMemory(); 1637 1638 // Liveness is not tracked for VALUE_STACK physreg. 1639 MF.getRegInfo().invalidateLiveness(); 1640 1641 // Place the BLOCK/LOOP/TRY markers to indicate the beginnings of scopes. 1642 placeMarkers(MF); 1643 1644 // Remove unnecessary instructions possibly introduced by try/end_trys. 1645 if (MCAI->getExceptionHandlingType() == ExceptionHandling::Wasm && 1646 MF.getFunction().hasPersonalityFn()) 1647 removeUnnecessaryInstrs(MF); 1648 1649 // Convert MBB operands in terminators to relative depth immediates. 1650 rewriteDepthImmediates(MF); 1651 1652 // Fix up block/loop/try signatures at the end of the function to conform to 1653 // WebAssembly's rules. 1654 fixEndsAtEndOfFunction(MF); 1655 1656 // Add an end instruction at the end of the function body. 1657 const auto &TII = *MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo(); 1658 if (!MF.getSubtarget<WebAssemblySubtarget>() 1659 .getTargetTriple() 1660 .isOSBinFormatELF()) 1661 appendEndToFunction(MF, TII); 1662 1663 cleanupFunctionData(MF); 1664 1665 MF.getInfo<WebAssemblyFunctionInfo>()->setCFGStackified(); 1666 return true; 1667 } 1668