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