LLVM 24.0.0git
WebAssemblyCFGStackify.cpp
Go to the documentation of this file.
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
25#include "WebAssembly.h"
32#include "llvm/ADT/MapVector.h"
33#include "llvm/ADT/Statistic.h"
41#include "llvm/IR/Analysis.h"
42#include "llvm/MC/MCAsmInfo.h"
44using namespace llvm;
46
47#define DEBUG_TYPE "wasm-cfg-stackify"
48
49STATISTIC(NumCallUnwindMismatches, "Number of call unwind mismatches found");
50STATISTIC(NumCatchUnwindMismatches, "Number of catch unwind mismatches found");
51
52namespace {
53class WebAssemblyCFGStackifyImpl {
55 MachineLoopInfo &MLI;
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.
62 void updateScopeTops(MachineBasicBlock *Begin, MachineBasicBlock *End) {
63 int BeginNo = Begin->getNumber();
64 int EndNo = End->getNumber();
65 if (!ScopeTops[EndNo] || ScopeTops[EndNo]->getNumber() > BeginNo)
66 ScopeTops[EndNo] = Begin;
67 }
68
69 // Placing markers.
70 void placeMarkers(MachineFunction &MF);
71 void placeBlockMarker(MachineBasicBlock &MBB);
72 void placeLoopMarker(MachineBasicBlock &MBB);
73 void placeTryMarker(MachineBasicBlock &MBB);
74 void placeTryTableMarker(MachineBasicBlock &MBB);
75
76 // Unwind mismatch fixing for exception handling
77 // - Common functions
78 bool fixCallUnwindMismatches(MachineFunction &MF);
79 bool fixCatchUnwindMismatches(MachineFunction &MF);
80 void recalculateScopeTops(MachineFunction &MF);
81 // - Legacy EH
82 void addNestedTryDelegate(MachineInstr *RangeBegin, MachineInstr *RangeEnd,
83 MachineBasicBlock *UnwindDest);
84 void removeUnnecessaryInstrs(MachineFunction &MF);
85 // - Standard EH (exnref)
86 void addNestedTryTable(MachineInstr *RangeBegin, MachineInstr *RangeEnd,
87 MachineBasicBlock *UnwindDest);
88 MachineBasicBlock *getTrampolineBlock(MachineBasicBlock *UnwindDest);
89
90 // Wrap-up
91 using EndMarkerInfo =
92 std::pair<const MachineBasicBlock *, const MachineInstr *>;
93 unsigned getBranchDepth(const SmallVectorImpl<EndMarkerInfo> &Stack,
94 const MachineBasicBlock *MBB);
95 unsigned getDelegateDepth(const SmallVectorImpl<EndMarkerInfo> &Stack,
96 const MachineBasicBlock *MBB);
97 unsigned getRethrowDepth(const SmallVectorImpl<EndMarkerInfo> &Stack,
98 const MachineBasicBlock *EHPadToRethrow);
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 DenseMap<const MachineBasicBlock *, MachineBasicBlock *>
115 UnwindDestToTrampoline;
116
117 // We need an appendix block to place 'end_loop' or 'end_try' marker when the
118 // loop / exception bottom block is the last block in a function
119 MachineBasicBlock *AppendixBB = nullptr;
120 MachineBasicBlock *getAppendixBlock(MachineFunction &MF) {
121 if (!AppendixBB) {
122 AppendixBB = MF.CreateMachineBasicBlock();
123 // Give it a fake predecessor so that AsmPrinter prints its label.
124 AppendixBB->addSuccessor(AppendixBB);
125 // If the caller trampoline BB exists, insert the appendix BB before it.
126 // Otherwise insert it at the end of the function.
127 if (CallerTrampolineBB)
128 MF.insert(CallerTrampolineBB->getIterator(), AppendixBB);
129 else
130 MF.push_back(AppendixBB);
131 }
132 return AppendixBB;
133 }
134
135 // Create a caller-dedicated trampoline BB to be used for fixing unwind
136 // mismatches where the unwind destination is the caller.
137 MachineBasicBlock *CallerTrampolineBB = nullptr;
138 MachineBasicBlock *getCallerTrampolineBlock(MachineFunction &MF) {
139 if (!CallerTrampolineBB) {
140 CallerTrampolineBB = MF.CreateMachineBasicBlock();
141 MF.push_back(CallerTrampolineBB);
142 }
143 return CallerTrampolineBB;
144 }
145
146 // Before running rewriteDepthImmediates function, 'delegate' has a BB as its
147 // destination operand. getFakeCallerBlock() returns a fake BB that will be
148 // used for the operand when 'delegate' needs to rethrow to the caller. This
149 // will be rewritten as an immediate value that is the number of block depths
150 // + 1 in rewriteDepthImmediates, and this fake BB will be removed at the end
151 // of the pass.
152 MachineBasicBlock *FakeCallerBB = nullptr;
153 MachineBasicBlock *getFakeCallerBlock(MachineFunction &MF) {
154 if (!FakeCallerBB)
155 FakeCallerBB = MF.CreateMachineBasicBlock();
156 return FakeCallerBB;
157 }
158
159 // Helper functions to register / unregister scope information created by
160 // marker instructions.
161 void registerScope(MachineInstr *Begin, MachineInstr *End);
162 void registerTryScope(MachineInstr *Begin, MachineInstr *End,
163 MachineBasicBlock *EHPad);
164 void unregisterScope(MachineInstr *Begin);
165
166public:
167 WebAssemblyCFGStackifyImpl(MachineDominatorTree &MDT, MachineLoopInfo &MLI,
168 WebAssemblyExceptionInfo &WEI)
169 : MDT(MDT), MLI(MLI), WEI(WEI) {}
170
171 bool runOnMachineFunction(MachineFunction &MF);
172};
173
174class WebAssemblyCFGStackifyLegacy : public MachineFunctionPass {
175 StringRef getPassName() const override { return "WebAssembly CFG Stackify"; }
176
177 void getAnalysisUsage(AnalysisUsage &AU) const override {
178 AU.addRequired<MachineDominatorTreeWrapperPass>();
179 AU.addRequired<MachineLoopInfoWrapperPass>();
180 AU.addRequired<WebAssemblyExceptionInfoWrapperPass>();
182 }
183
184public:
185 bool runOnMachineFunction(MachineFunction &MF) override;
186 static char ID; // Pass identification, replacement for typeid
187 WebAssemblyCFGStackifyLegacy() : MachineFunctionPass(ID) {}
188};
189} // end anonymous namespace
190
191char WebAssemblyCFGStackifyLegacy::ID = 0;
193 WebAssemblyCFGStackifyLegacy, DEBUG_TYPE,
194 "Insert BLOCK/LOOP/TRY/TRY_TABLE markers for WebAssembly scopes", false,
195 false)
196
198 return new WebAssemblyCFGStackifyLegacy();
199}
200
201/// Test whether Pred has any terminators explicitly branching to MBB, as
202/// opposed to falling through. Note that it's possible (eg. in unoptimized
203/// code) for a branch instruction to both branch to a block and fallthrough
204/// to it, so we check the actual branch operands to see if there are any
205/// explicit mentions.
208 for (MachineInstr &MI : Pred->terminators())
209 for (MachineOperand &MO : MI.explicit_operands())
210 if (MO.isMBB() && MO.getMBB() == MBB)
211 return true;
212 return false;
213}
214
215// Returns an iterator to the earliest position possible within the MBB,
216// satisfying the restrictions given by BeforeSet and AfterSet. BeforeSet
217// contains instructions that should go before the marker, and AfterSet contains
218// ones that should go after the marker. In this function, AfterSet is only
219// used for validation checking.
220template <typename Container>
222getEarliestInsertPos(MachineBasicBlock *MBB, const Container &BeforeSet,
223 const Container &AfterSet) {
224 auto InsertPos = MBB->end();
225 while (InsertPos != MBB->begin()) {
226 if (BeforeSet.count(&*std::prev(InsertPos))) {
227#ifndef NDEBUG
228 // Validation check
229 for (auto Pos = InsertPos, E = MBB->begin(); Pos != E; --Pos)
230 assert(!AfterSet.count(&*std::prev(Pos)));
231#endif
232 break;
233 }
234 --InsertPos;
235 }
236 return InsertPos;
237}
238
239// Returns an iterator to the latest position possible within the MBB,
240// satisfying the restrictions given by BeforeSet and AfterSet. BeforeSet
241// contains instructions that should go before the marker, and AfterSet contains
242// ones that should go after the marker. In this function, BeforeSet is only
243// used for validation checking.
244template <typename Container>
246getLatestInsertPos(MachineBasicBlock *MBB, const Container &BeforeSet,
247 const Container &AfterSet) {
248 auto InsertPos = MBB->begin();
249 while (InsertPos != MBB->end()) {
250 if (AfterSet.count(&*InsertPos)) {
251#ifndef NDEBUG
252 // Validation check
253 for (auto Pos = InsertPos, E = MBB->end(); Pos != E; ++Pos)
254 assert(!BeforeSet.count(&*Pos));
255#endif
256 break;
257 }
258 ++InsertPos;
259 }
260 return InsertPos;
261}
262
263void WebAssemblyCFGStackifyImpl::registerScope(MachineInstr *Begin,
264 MachineInstr *End) {
265 BeginToEnd[Begin] = End;
266 EndToBegin[End] = Begin;
267}
268
269// When 'End' is not an 'end_try' but a 'delegate', EHPad is nullptr.
270void WebAssemblyCFGStackifyImpl::registerTryScope(MachineInstr *Begin,
271 MachineInstr *End,
272 MachineBasicBlock *EHPad) {
273 registerScope(Begin, End);
274 TryToEHPad[Begin] = EHPad;
275 EHPadToTry[EHPad] = Begin;
276}
277
278void WebAssemblyCFGStackifyImpl::unregisterScope(MachineInstr *Begin) {
279 assert(BeginToEnd.count(Begin));
280 MachineInstr *End = BeginToEnd[Begin];
281 assert(EndToBegin.count(End));
282 BeginToEnd.erase(Begin);
283 EndToBegin.erase(End);
284 MachineBasicBlock *EHPad = TryToEHPad.lookup(Begin);
285 if (EHPad) {
286 assert(EHPadToTry.count(EHPad));
287 TryToEHPad.erase(Begin);
288 EHPadToTry.erase(EHPad);
289 }
290}
291
292/// Insert a BLOCK marker for branches to MBB (if needed).
293// TODO Consider a more generalized way of handling block (and also loop and
294// try) signatures when we implement the multi-value proposal later.
295void WebAssemblyCFGStackifyImpl::placeBlockMarker(MachineBasicBlock &MBB) {
296 assert(!MBB.isEHPad());
297 MachineFunction &MF = *MBB.getParent();
298 const auto &TII = *MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo();
299 const auto &MFI = *MF.getInfo<WebAssemblyFunctionInfo>();
300
301 // First compute the nearest common dominator of all forward non-fallthrough
302 // predecessors so that we minimize the time that the BLOCK is on the stack,
303 // which reduces overall stack height.
304 MachineBasicBlock *Header = nullptr;
305 bool IsBranchedTo = false;
306 int MBBNumber = MBB.getNumber();
307 for (MachineBasicBlock *Pred : MBB.predecessors()) {
308 if (Pred->getNumber() < MBBNumber) {
309 Header = Header ? MDT.findNearestCommonDominator(Header, Pred) : Pred;
310 if (explicitlyBranchesTo(Pred, &MBB))
311 IsBranchedTo = true;
312 }
313 }
314 if (!Header)
315 return;
316 if (!IsBranchedTo)
317 return;
318
319 assert(&MBB != &MF.front() && "Header blocks shouldn't have predecessors");
320 MachineBasicBlock *LayoutPred = MBB.getPrevNode();
321
322 // If the nearest common dominator is inside a more deeply nested context,
323 // walk out to the nearest scope which isn't more deeply nested.
324 for (MachineFunction::iterator I(LayoutPred), E(Header); I != E; --I) {
325 if (MachineBasicBlock *ScopeTop = ScopeTops[I->getNumber()]) {
326 if (ScopeTop->getNumber() > Header->getNumber()) {
327 // Skip over an intervening scope.
328 I = std::next(ScopeTop->getIterator());
329 } else {
330 // We found a scope level at an appropriate depth.
331 Header = ScopeTop;
332 break;
333 }
334 }
335 }
336
337 // Decide where in MBB to put the BLOCK.
338
339 // Instructions that should go before the BLOCK.
340 SmallPtrSet<const MachineInstr *, 4> BeforeSet;
341 // Instructions that should go after the BLOCK.
342 SmallPtrSet<const MachineInstr *, 4> AfterSet;
343 for (const auto &MI : *Header) {
344 // If there is a previously placed LOOP marker and the bottom block of the
345 // loop is above MBB, it should be after the BLOCK, because the loop is
346 // nested in this BLOCK. Otherwise it should be before the BLOCK.
347 if (MI.getOpcode() == WebAssembly::LOOP) {
348 auto *LoopBottom = BeginToEnd[&MI]->getParent()->getPrevNode();
349 if (MBB.getNumber() > LoopBottom->getNumber())
350 AfterSet.insert(&MI);
351#ifndef NDEBUG
352 else
353 BeforeSet.insert(&MI);
354#endif
355 }
356
357 // If there is a previously placed BLOCK/TRY/TRY_TABLE marker and its
358 // corresponding END marker is before the current BLOCK's END marker, that
359 // should be placed after this BLOCK. Otherwise it should be placed before
360 // this BLOCK marker.
361 if (MI.getOpcode() == WebAssembly::BLOCK ||
362 MI.getOpcode() == WebAssembly::TRY ||
363 MI.getOpcode() == WebAssembly::TRY_TABLE) {
364 if (BeginToEnd[&MI]->getParent()->getNumber() <= MBB.getNumber())
365 AfterSet.insert(&MI);
366#ifndef NDEBUG
367 else
368 BeforeSet.insert(&MI);
369#endif
370 }
371
372#ifndef NDEBUG
373 // All END_(BLOCK|LOOP|TRY|TRY_TABLE) markers should be before the BLOCK.
374 if (MI.getOpcode() == WebAssembly::END_BLOCK ||
375 MI.getOpcode() == WebAssembly::END_LOOP ||
376 MI.getOpcode() == WebAssembly::END_TRY ||
377 MI.getOpcode() == WebAssembly::END_TRY_TABLE)
378 BeforeSet.insert(&MI);
379#endif
380
381 // Terminators should go after the BLOCK.
382 if (MI.isTerminator())
383 AfterSet.insert(&MI);
384 }
385
386 // Local expression tree should go after the BLOCK.
387 for (auto I = Header->getFirstTerminator(), E = Header->begin(); I != E;
388 --I) {
389 if (std::prev(I)->isDebugInstr() || std::prev(I)->isPosition())
390 continue;
391 if (WebAssembly::isChild(*std::prev(I), MFI))
392 AfterSet.insert(&*std::prev(I));
393 else
394 break;
395 }
396
397 // Add the BLOCK.
398 WebAssembly::BlockType ReturnType = WebAssembly::BlockType::Void;
399 auto InsertPos = getLatestInsertPos(Header, BeforeSet, AfterSet);
400 MachineInstr *Begin =
401 BuildMI(*Header, InsertPos, Header->findDebugLoc(InsertPos),
402 TII.get(WebAssembly::BLOCK))
403 .addImm(int64_t(ReturnType));
404
405 // Decide where in MBB to put the END_BLOCK.
406 BeforeSet.clear();
407 AfterSet.clear();
408 for (auto &MI : MBB) {
409#ifndef NDEBUG
410 // END_BLOCK should precede existing LOOP markers.
411 if (MI.getOpcode() == WebAssembly::LOOP)
412 AfterSet.insert(&MI);
413#endif
414
415 // If there is a previously placed END_LOOP marker and the header of the
416 // loop is above this block's header, the END_LOOP should be placed after
417 // the END_BLOCK, because the loop contains this block. Otherwise the
418 // END_LOOP should be placed before the END_BLOCK. The same for END_TRY.
419 //
420 // Note that while there can be existing END_TRYs, there can't be
421 // END_TRY_TABLEs; END_TRYs are placed when its corresponding EH pad is
422 // processed, so they are placed below MBB (EH pad) in placeTryMarker. But
423 // END_TRY_TABLE is placed like a END_BLOCK, so they can't be here already.
424 if (MI.getOpcode() == WebAssembly::END_LOOP ||
425 MI.getOpcode() == WebAssembly::END_TRY) {
426 if (EndToBegin[&MI]->getParent()->getNumber() >= Header->getNumber())
427 BeforeSet.insert(&MI);
428#ifndef NDEBUG
429 else
430 AfterSet.insert(&MI);
431#endif
432 }
433 }
434
435 // Mark the end of the block.
436 InsertPos = getEarliestInsertPos(&MBB, BeforeSet, AfterSet);
437 MachineInstr *End = BuildMI(MBB, InsertPos, MBB.findPrevDebugLoc(InsertPos),
438 TII.get(WebAssembly::END_BLOCK));
439 registerScope(Begin, End);
440
441 // Track the farthest-spanning scope that ends at this point.
442 updateScopeTops(Header, &MBB);
443}
444
445/// Insert a LOOP marker for a loop starting at MBB (if it's a loop header).
446void WebAssemblyCFGStackifyImpl::placeLoopMarker(MachineBasicBlock &MBB) {
447 MachineFunction &MF = *MBB.getParent();
448 SortRegionInfo SRI(MLI, WEI);
449 const auto &TII = *MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo();
450
451 MachineLoop *Loop = MLI.getLoopFor(&MBB);
452 if (!Loop || Loop->getHeader() != &MBB)
453 return;
454
455 // The operand of a LOOP is the first block after the loop. If the loop is the
456 // bottom of the function, insert a dummy block at the end.
457 MachineBasicBlock *Bottom = SRI.getBottom(Loop);
458 auto Iter = std::next(Bottom->getIterator());
459 if (Iter == MF.end()) {
460 getAppendixBlock(MF);
461 Iter = std::next(Bottom->getIterator());
462 }
463 MachineBasicBlock *AfterLoop = &*Iter;
464
465 // Decide where in Header to put the LOOP.
466 SmallPtrSet<const MachineInstr *, 4> BeforeSet;
467 SmallPtrSet<const MachineInstr *, 4> AfterSet;
468 for (const auto &MI : MBB) {
469 // LOOP marker should be after any existing loop that ends here. Otherwise
470 // we assume the instruction belongs to the loop.
471 if (MI.getOpcode() == WebAssembly::END_LOOP)
472 BeforeSet.insert(&MI);
473#ifndef NDEBUG
474 else
475 AfterSet.insert(&MI);
476#endif
477 }
478
479 // Mark the beginning of the loop.
480 auto InsertPos = getEarliestInsertPos(&MBB, BeforeSet, AfterSet);
481 MachineInstr *Begin = BuildMI(MBB, InsertPos, MBB.findDebugLoc(InsertPos),
482 TII.get(WebAssembly::LOOP))
483 .addImm(int64_t(WebAssembly::BlockType::Void));
484
485 // Decide where in MBB to put the END_LOOP.
486 BeforeSet.clear();
487 AfterSet.clear();
488#ifndef NDEBUG
489 for (const auto &MI : MBB)
490 // Existing END_LOOP markers belong to parent loops of this loop
491 if (MI.getOpcode() == WebAssembly::END_LOOP)
492 AfterSet.insert(&MI);
493#endif
494
495 // Mark the end of the loop (using arbitrary debug location that branched to
496 // the loop end as its location).
497 InsertPos = getEarliestInsertPos(AfterLoop, BeforeSet, AfterSet);
498 DebugLoc EndDL = AfterLoop->pred_empty()
499 ? DebugLoc()
500 : (*AfterLoop->pred_rbegin())->findBranchDebugLoc();
501 MachineInstr *End =
502 BuildMI(*AfterLoop, InsertPos, EndDL, TII.get(WebAssembly::END_LOOP));
503 registerScope(Begin, End);
504
505 assert((!ScopeTops[AfterLoop->getNumber()] ||
506 ScopeTops[AfterLoop->getNumber()]->getNumber() < MBB.getNumber()) &&
507 "With block sorting the outermost loop for a block should be first.");
508 updateScopeTops(&MBB, AfterLoop);
509}
510
511void WebAssemblyCFGStackifyImpl::placeTryMarker(MachineBasicBlock &MBB) {
512 assert(MBB.isEHPad());
513 MachineFunction &MF = *MBB.getParent();
514 const auto &TII = *MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo();
515 SortRegionInfo SRI(MLI, WEI);
516 const auto &MFI = *MF.getInfo<WebAssemblyFunctionInfo>();
517
518 // Compute the nearest common dominator of all unwind predecessors
519 MachineBasicBlock *Header = nullptr;
520 int MBBNumber = MBB.getNumber();
521 for (auto *Pred : MBB.predecessors()) {
522 if (Pred->getNumber() < MBBNumber) {
523 Header = Header ? MDT.findNearestCommonDominator(Header, Pred) : Pred;
525 "Explicit branch to an EH pad!");
526 }
527 }
528 if (!Header)
529 return;
530
531 // If this try is at the bottom of the function, insert a dummy block at the
532 // end.
533 WebAssemblyException *WE = WEI.getExceptionFor(&MBB);
534 assert(WE);
535 MachineBasicBlock *Bottom = SRI.getBottom(WE);
536 auto Iter = std::next(Bottom->getIterator());
537 if (Iter == MF.end()) {
538 getAppendixBlock(MF);
539 Iter = std::next(Bottom->getIterator());
540 }
541 MachineBasicBlock *Cont = &*Iter;
542
543 // If the nearest common dominator is inside a more deeply nested context,
544 // walk out to the nearest scope which isn't more deeply nested.
545 for (MachineFunction::iterator I(Bottom), E(Header); I != E; --I) {
546 if (MachineBasicBlock *ScopeTop = ScopeTops[I->getNumber()]) {
547 if (ScopeTop->getNumber() > Header->getNumber()) {
548 // Skip over an intervening scope.
549 I = std::next(ScopeTop->getIterator());
550 } else {
551 // We found a scope level at an appropriate depth.
552 Header = ScopeTop;
553 break;
554 }
555 }
556 }
557
558 // Decide where in Header to put the TRY.
559
560 // Instructions that should go before the TRY.
561 SmallPtrSet<const MachineInstr *, 4> BeforeSet;
562 // Instructions that should go after the TRY.
563 SmallPtrSet<const MachineInstr *, 4> AfterSet;
564 for (const auto &MI : *Header) {
565 // If there is a previously placed LOOP marker and the bottom block of the
566 // loop is above MBB, it should be after the TRY, because the loop is nested
567 // in this TRY. Otherwise it should be before the TRY.
568 if (MI.getOpcode() == WebAssembly::LOOP) {
569 auto *LoopBottom = BeginToEnd[&MI]->getParent()->getPrevNode();
570 if (MBB.getNumber() > LoopBottom->getNumber())
571 AfterSet.insert(&MI);
572#ifndef NDEBUG
573 else
574 BeforeSet.insert(&MI);
575#endif
576 }
577
578 // All previously inserted BLOCK/TRY markers should be after the TRY because
579 // they are all nested blocks/trys.
580 if (MI.getOpcode() == WebAssembly::BLOCK ||
581 MI.getOpcode() == WebAssembly::TRY)
582 AfterSet.insert(&MI);
583
584#ifndef NDEBUG
585 // All END_(BLOCK/LOOP/TRY) markers should be before the TRY.
586 if (MI.getOpcode() == WebAssembly::END_BLOCK ||
587 MI.getOpcode() == WebAssembly::END_LOOP ||
588 MI.getOpcode() == WebAssembly::END_TRY)
589 BeforeSet.insert(&MI);
590#endif
591
592 // Terminators should go after the TRY.
593 if (MI.isTerminator())
594 AfterSet.insert(&MI);
595 }
596
597 // If Header unwinds to MBB (= Header contains 'invoke'), the try block should
598 // contain the call within it. So the call should go after the TRY. The
599 // exception is when the header's terminator is a rethrow instruction, in
600 // which case that instruction, not a call instruction before it, is gonna
601 // throw.
602 MachineInstr *ThrowingCall = nullptr;
603 if (MBB.isPredecessor(Header)) {
604 auto TermPos = Header->getFirstTerminator();
605 if (TermPos == Header->end() ||
606 TermPos->getOpcode() != WebAssembly::RETHROW) {
607 for (auto &MI : reverse(*Header)) {
608 if (MI.isCall()) {
609 AfterSet.insert(&MI);
610 ThrowingCall = &MI;
611 // Possibly throwing calls are usually wrapped by EH_LABEL
612 // instructions. We don't want to split them and the call.
613 if (MI.getIterator() != Header->begin() &&
614 std::prev(MI.getIterator())->isEHLabel()) {
615 AfterSet.insert(&*std::prev(MI.getIterator()));
616 ThrowingCall = &*std::prev(MI.getIterator());
617 }
618 break;
619 }
620 }
621 }
622 }
623
624 // Local expression tree should go after the TRY.
625 // For BLOCK placement, we start the search from the previous instruction of a
626 // BB's terminator, but in TRY's case, we should start from the previous
627 // instruction of a call that can throw, or a EH_LABEL that precedes the call,
628 // because the return values of the call's previous instructions can be
629 // stackified and consumed by the throwing call.
630 auto SearchStartPt = ThrowingCall ? MachineBasicBlock::iterator(ThrowingCall)
631 : Header->getFirstTerminator();
632 for (auto I = SearchStartPt, E = Header->begin(); I != E; --I) {
633 if (std::prev(I)->isDebugInstr() || std::prev(I)->isPosition())
634 continue;
635 if (WebAssembly::isChild(*std::prev(I), MFI))
636 AfterSet.insert(&*std::prev(I));
637 else
638 break;
639 }
640
641 // Add the TRY.
642 auto InsertPos = getLatestInsertPos(Header, BeforeSet, AfterSet);
643 MachineInstr *Begin =
644 BuildMI(*Header, InsertPos, Header->findDebugLoc(InsertPos),
645 TII.get(WebAssembly::TRY))
646 .addImm(int64_t(WebAssembly::BlockType::Void));
647
648 // Decide where in Cont to put the END_TRY.
649 BeforeSet.clear();
650 AfterSet.clear();
651 for (const auto &MI : *Cont) {
652#ifndef NDEBUG
653 // END_TRY should precede existing LOOP markers.
654 if (MI.getOpcode() == WebAssembly::LOOP)
655 AfterSet.insert(&MI);
656
657 // All END_TRY markers placed earlier belong to exceptions that contains
658 // this one.
659 if (MI.getOpcode() == WebAssembly::END_TRY)
660 AfterSet.insert(&MI);
661#endif
662
663 // If there is a previously placed END_LOOP marker and its header is after
664 // where TRY marker is, this loop is contained within the 'catch' part, so
665 // the END_TRY marker should go after that. Otherwise, the whole try-catch
666 // is contained within this loop, so the END_TRY should go before that.
667 if (MI.getOpcode() == WebAssembly::END_LOOP) {
668 // For a LOOP to be after TRY, LOOP's BB should be after TRY's BB; if they
669 // are in the same BB, LOOP is always before TRY.
670 if (EndToBegin[&MI]->getParent()->getNumber() > Header->getNumber())
671 BeforeSet.insert(&MI);
672#ifndef NDEBUG
673 else
674 AfterSet.insert(&MI);
675#endif
676 }
677
678 // It is not possible for an END_BLOCK to be already in this block.
679 }
680
681 // Mark the end of the TRY.
682 InsertPos = getEarliestInsertPos(Cont, BeforeSet, AfterSet);
683 MachineInstr *End = BuildMI(*Cont, InsertPos, Bottom->findBranchDebugLoc(),
684 TII.get(WebAssembly::END_TRY));
685 registerTryScope(Begin, End, &MBB);
686
687 // Track the farthest-spanning scope that ends at this point. We create two
688 // mappings: (BB with 'end_try' -> BB with 'try') and (BB with 'catch' -> BB
689 // with 'try'). We need to create 'catch' -> 'try' mapping here too because
690 // markers should not span across 'catch'. For example, this should not
691 // happen:
692 //
693 // try
694 // block --| (X)
695 // catch |
696 // end_block --|
697 // end_try
698 for (auto *End : {&MBB, Cont})
699 updateScopeTops(Header, End);
700}
701
702void WebAssemblyCFGStackifyImpl::placeTryTableMarker(MachineBasicBlock &MBB) {
703 assert(MBB.isEHPad());
704 MachineFunction &MF = *MBB.getParent();
705 const auto &TII = *MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo();
706 SortRegionInfo SRI(MLI, WEI);
707 const auto &MFI = *MF.getInfo<WebAssemblyFunctionInfo>();
708
709 // Compute the nearest common dominator of all unwind predecessors
710 MachineBasicBlock *Header = nullptr;
711 int MBBNumber = MBB.getNumber();
712 for (auto *Pred : MBB.predecessors()) {
713 if (Pred->getNumber() < MBBNumber) {
714 Header = Header ? MDT.findNearestCommonDominator(Header, Pred) : Pred;
716 "Explicit branch to an EH pad!");
717 }
718 }
719 if (!Header)
720 return;
721
722 // Unlike the end_try marker, we don't place an end marker at the end of
723 // exception bottom, i.e., at the end of the old 'catch' block. But we still
724 // consider the try-catch part as a scope when computing ScopeTops.
725 WebAssemblyException *WE = WEI.getExceptionFor(&MBB);
726 assert(WE);
727 MachineBasicBlock *Bottom = SRI.getBottom(WE);
728 auto Iter = std::next(Bottom->getIterator());
729 if (Iter == MF.end())
730 Iter--;
731 MachineBasicBlock *Cont = &*Iter;
732
733 // If the nearest common dominator is inside a more deeply nested context,
734 // walk out to the nearest scope which isn't more deeply nested.
735 for (MachineFunction::iterator I(Bottom), E(Header); I != E; --I) {
736 if (MachineBasicBlock *ScopeTop = ScopeTops[I->getNumber()]) {
737 if (ScopeTop->getNumber() > Header->getNumber()) {
738 // Skip over an intervening scope.
739 I = std::next(ScopeTop->getIterator());
740 } else {
741 // We found a scope level at an appropriate depth.
742 Header = ScopeTop;
743 break;
744 }
745 }
746 }
747
748 // Decide where in Header to put the TRY_TABLE.
749
750 // Instructions that should go before the TRY_TABLE.
751 SmallPtrSet<const MachineInstr *, 4> BeforeSet;
752 // Instructions that should go after the TRY_TABLE.
753 SmallPtrSet<const MachineInstr *, 4> AfterSet;
754 for (const auto &MI : *Header) {
755 // If there is a previously placed LOOP marker and the bottom block of the
756 // loop is above MBB, it should be after the TRY_TABLE, because the loop is
757 // nested in this TRY_TABLE. Otherwise it should be before the TRY_TABLE.
758 if (MI.getOpcode() == WebAssembly::LOOP) {
759 auto *LoopBottom = BeginToEnd[&MI]->getParent()->getPrevNode();
760 if (MBB.getNumber() > LoopBottom->getNumber())
761 AfterSet.insert(&MI);
762#ifndef NDEBUG
763 else
764 BeforeSet.insert(&MI);
765#endif
766 }
767
768 // All previously inserted BLOCK/TRY_TABLE markers should be after the
769 // TRY_TABLE because they are all nested blocks/try_tables.
770 if (MI.getOpcode() == WebAssembly::BLOCK ||
771 MI.getOpcode() == WebAssembly::TRY_TABLE)
772 AfterSet.insert(&MI);
773
774#ifndef NDEBUG
775 // All END_(BLOCK/LOOP/TRY_TABLE) markers should be before the TRY_TABLE.
776 if (MI.getOpcode() == WebAssembly::END_BLOCK ||
777 MI.getOpcode() == WebAssembly::END_LOOP ||
778 MI.getOpcode() == WebAssembly::END_TRY_TABLE)
779 BeforeSet.insert(&MI);
780#endif
781
782 // Terminators should go after the TRY_TABLE.
783 if (MI.isTerminator())
784 AfterSet.insert(&MI);
785 }
786
787 // If Header unwinds to MBB (= Header contains 'invoke'), the try_table block
788 // should contain the call within it. So the call should go after the
789 // TRY_TABLE. The exception is when the header's terminator is a rethrow
790 // instruction, in which case that instruction, not a call instruction before
791 // it, is gonna throw.
792 MachineInstr *ThrowingCall = nullptr;
793 if (MBB.isPredecessor(Header)) {
794 auto TermPos = Header->getFirstTerminator();
795 if (TermPos == Header->end() ||
796 TermPos->getOpcode() != WebAssembly::RETHROW) {
797 for (auto &MI : reverse(*Header)) {
798 if (MI.isCall()) {
799 AfterSet.insert(&MI);
800 ThrowingCall = &MI;
801 // Possibly throwing calls are usually wrapped by EH_LABEL
802 // instructions. We don't want to split them and the call.
803 if (MI.getIterator() != Header->begin() &&
804 std::prev(MI.getIterator())->isEHLabel()) {
805 AfterSet.insert(&*std::prev(MI.getIterator()));
806 ThrowingCall = &*std::prev(MI.getIterator());
807 }
808 break;
809 }
810 }
811 }
812 }
813
814 // Local expression tree should go after the TRY_TABLE.
815 // For BLOCK placement, we start the search from the previous instruction of a
816 // BB's terminator, but in TRY_TABLE's case, we should start from the previous
817 // instruction of a call that can throw, or a EH_LABEL that precedes the call,
818 // because the return values of the call's previous instructions can be
819 // stackified and consumed by the throwing call.
820 auto SearchStartPt = ThrowingCall ? MachineBasicBlock::iterator(ThrowingCall)
821 : Header->getFirstTerminator();
822 for (auto I = SearchStartPt, E = Header->begin(); I != E; --I) {
823 if (std::prev(I)->isDebugInstr() || std::prev(I)->isPosition())
824 continue;
825 if (WebAssembly::isChild(*std::prev(I), MFI))
826 AfterSet.insert(&*std::prev(I));
827 else
828 break;
829 }
830
831 // Add the TRY_TABLE and a BLOCK for the catch destination. We currently
832 // generate only one CATCH clause for a TRY_TABLE, so we need one BLOCK for
833 // its destination.
834 //
835 // Header:
836 // block
837 // try_table (catch ... $MBB)
838 // ...
839 //
840 // MBB:
841 // end_try_table
842 // end_block ;; destination of (catch ...)
843 // ... catch handler body ...
844 auto InsertPos = getLatestInsertPos(Header, BeforeSet, AfterSet);
845 MachineInstrBuilder BlockMIB =
846 BuildMI(*Header, InsertPos, Header->findDebugLoc(InsertPos),
847 TII.get(WebAssembly::BLOCK));
848 auto *Block = BlockMIB.getInstr();
849 MachineInstrBuilder TryTableMIB =
850 BuildMI(*Header, InsertPos, Header->findDebugLoc(InsertPos),
851 TII.get(WebAssembly::TRY_TABLE))
852 .addImm(int64_t(WebAssembly::BlockType::Void))
853 .addImm(1); // # of catch clauses
854 auto *TryTable = TryTableMIB.getInstr();
855
856 // Add a CATCH_*** clause to the TRY_TABLE. These are pseudo instructions
857 // following the destination END_BLOCK to simulate block return values,
858 // because we currently don't support them.
859 const auto &TLI =
860 *MF.getSubtarget<WebAssemblySubtarget>().getTargetLowering();
861 WebAssembly::BlockType PtrTy =
862 TLI.getPointerTy(MF.getDataLayout()) == MVT::i32
863 ? WebAssembly::BlockType::I32
864 : WebAssembly::BlockType::I64;
865 auto *Catch = WebAssembly::findCatch(&MBB);
866 switch (Catch->getOpcode()) {
867 case WebAssembly::CATCH:
868 // CATCH's destination block's return type is the extracted value type,
869 // which is currently the thrown value's pointer type for all supported
870 // tags.
871 BlockMIB.addImm(int64_t(PtrTy));
872 TryTableMIB.addImm(wasm::WASM_OPCODE_CATCH);
873 for (const auto &Use : Catch->uses()) {
874 // The only use operand a CATCH can have is the tag symbol.
875 TryTableMIB.addExternalSymbol(Use.getSymbolName());
876 break;
877 }
878 TryTableMIB.addMBB(&MBB);
879 break;
880 case WebAssembly::CATCH_REF:
881 // CATCH_REF's destination block's return type is the extracted value type
882 // followed by an exnref, which is (i32, exnref) in our case. We assign the
883 // actual multiavlue signature in MCInstLower. MO_CATCH_BLOCK_SIG signals
884 // that this operand is used for catch_ref's multivalue destination.
885 BlockMIB.addImm(int64_t(WebAssembly::BlockType::Multivalue));
888 for (const auto &Use : Catch->uses()) {
889 TryTableMIB.addExternalSymbol(Use.getSymbolName());
890 break;
891 }
892 TryTableMIB.addMBB(&MBB);
893 break;
894 case WebAssembly::CATCH_ALL:
895 // CATCH_ALL's destination block's return type is void.
896 BlockMIB.addImm(int64_t(WebAssembly::BlockType::Void));
898 TryTableMIB.addMBB(&MBB);
899 break;
900 case WebAssembly::CATCH_ALL_REF:
901 // CATCH_ALL_REF's destination block's return type is exnref.
902 BlockMIB.addImm(int64_t(WebAssembly::BlockType::Exnref));
904 TryTableMIB.addMBB(&MBB);
905 break;
906 }
907
908 // Decide where in MBB to put the END_TRY_TABLE, and the END_BLOCK for the
909 // CATCH destination.
910 BeforeSet.clear();
911 AfterSet.clear();
912 for (const auto &MI : MBB) {
913#ifndef NDEBUG
914 // END_TRY_TABLE should precede existing LOOP markers.
915 if (MI.getOpcode() == WebAssembly::LOOP)
916 AfterSet.insert(&MI);
917#endif
918
919 // If there is a previously placed END_LOOP marker and the header of the
920 // loop is above this try_table's header, the END_LOOP should be placed
921 // after the END_TRY_TABLE, because the loop contains this block. Otherwise
922 // the END_LOOP should be placed before the END_TRY_TABLE.
923 if (MI.getOpcode() == WebAssembly::END_LOOP) {
924 if (EndToBegin[&MI]->getParent()->getNumber() >= Header->getNumber())
925 BeforeSet.insert(&MI);
926#ifndef NDEBUG
927 else
928 AfterSet.insert(&MI);
929#endif
930 }
931
932#ifndef NDEBUG
933 // CATCH, CATCH_REF, CATCH_ALL, and CATCH_ALL_REF are pseudo-instructions
934 // that simulate the block return value, so they should be placed after the
935 // END_TRY_TABLE.
936 if (WebAssembly::isCatch(MI.getOpcode()))
937 AfterSet.insert(&MI);
938#endif
939 }
940
941 // Mark the end of the TRY_TABLE and the BLOCK.
942 InsertPos = getEarliestInsertPos(&MBB, BeforeSet, AfterSet);
943 MachineInstr *EndTryTable =
944 BuildMI(MBB, InsertPos, MBB.findPrevDebugLoc(InsertPos),
945 TII.get(WebAssembly::END_TRY_TABLE));
946 registerTryScope(TryTable, EndTryTable, &MBB);
947 MachineInstr *EndBlock =
948 BuildMI(MBB, InsertPos, MBB.findPrevDebugLoc(InsertPos),
949 TII.get(WebAssembly::END_BLOCK));
950 registerScope(Block, EndBlock);
951
952 // Track the farthest-spanning scope that ends at this point.
953 // Unlike the end_try, even if we don't put a end marker at the end of catch
954 // block, we still have to create two mappings: (BB with 'end_try_table' -> BB
955 // with 'try_table') and (BB after the (conceptual) catch block -> BB with
956 // 'try_table').
957 //
958 // This is what can happen if we don't create the latter mapping:
959 //
960 // Suppoe in the legacy EH we have this code:
961 // try
962 // try
963 // code1
964 // catch (a)
965 // end_try
966 // code2
967 // catch (b)
968 // end_try
969 //
970 // If we don't create the latter mapping, try_table markers would be placed
971 // like this:
972 // try_table
973 // code1
974 // end_try_table (a)
975 // try_table
976 // code2
977 // end_try_table (b)
978 //
979 // This does not reflect the original structure, and more important problem
980 // is, in case 'code1' has an unwind mismatch and should unwind to
981 // 'end_try_table (b)' rather than 'end_try_table (a)', we don't have a way to
982 // make it jump after 'end_try_table (b)' without creating another block. So
983 // even if we don't place 'end_try' marker at the end of 'catch' block
984 // anymore, we create ScopeTops mapping the same way as the legacy exception,
985 // so the resulting code will look like:
986 // try_table
987 // try_table
988 // code1
989 // end_try_table (a)
990 // code2
991 // end_try_table (b)
992 for (auto *End : {&MBB, Cont})
993 updateScopeTops(Header, End);
994}
995
996void WebAssemblyCFGStackifyImpl::removeUnnecessaryInstrs(MachineFunction &MF) {
997 const auto &TII = *MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo();
998
999 // When there is an unconditional branch right before a catch instruction and
1000 // it branches to the end of end_try marker, we don't need the branch, because
1001 // if there is no exception, the control flow transfers to that point anyway.
1002 // bb0:
1003 // try
1004 // ...
1005 // br bb2 <- Not necessary
1006 // bb1 (ehpad):
1007 // catch
1008 // ...
1009 // bb2: <- Continuation BB
1010 // end
1011 //
1012 // A more involved case: When the BB where 'end' is located is an another EH
1013 // pad, the Cont (= continuation) BB is that EH pad's 'end' BB. For example,
1014 // bb0:
1015 // try
1016 // try
1017 // ...
1018 // br bb3 <- Not necessary
1019 // bb1 (ehpad):
1020 // catch
1021 // bb2 (ehpad):
1022 // end
1023 // catch
1024 // ...
1025 // bb3: <- Continuation BB
1026 // end
1027 //
1028 // When the EH pad at hand is bb1, its matching end_try is in bb2. But it is
1029 // another EH pad, so bb0's continuation BB becomes bb3. So 'br bb3' in the
1030 // code can be deleted. This is why we run 'while' until 'Cont' is not an EH
1031 // pad.
1032 for (auto &MBB : MF) {
1033 if (!MBB.isEHPad())
1034 continue;
1035
1036 MachineBasicBlock *TBB = nullptr, *FBB = nullptr;
1038 MachineBasicBlock *EHPadLayoutPred = MBB.getPrevNode();
1039
1040 MachineBasicBlock *Cont = &MBB;
1041 while (Cont->isEHPad()) {
1042 MachineInstr *Try = EHPadToTry[Cont];
1043 MachineInstr *EndTry = BeginToEnd[Try];
1044 // We started from an EH pad, so the end marker cannot be a delegate
1045 assert(EndTry->getOpcode() != WebAssembly::DELEGATE);
1046 Cont = EndTry->getParent();
1047 }
1048
1049 bool Analyzable = !TII.analyzeBranch(*EHPadLayoutPred, TBB, FBB, Cond);
1050 // This condition means either
1051 // 1. This BB ends with a single unconditional branch whose destinaion is
1052 // Cont.
1053 // 2. This BB ends with a conditional branch followed by an unconditional
1054 // branch, and the unconditional branch's destination is Cont.
1055 // In both cases, we want to remove the last (= unconditional) branch.
1056 if (Analyzable && ((Cond.empty() && TBB && TBB == Cont) ||
1057 (!Cond.empty() && FBB && FBB == Cont))) {
1058 bool ErasedUncondBr = false;
1059 (void)ErasedUncondBr;
1060 for (auto I = EHPadLayoutPred->end(), E = EHPadLayoutPred->begin();
1061 I != E; --I) {
1062 auto PrevI = std::prev(I);
1063 if (PrevI->isTerminator()) {
1064 assert(PrevI->getOpcode() == WebAssembly::BR);
1065 PrevI->eraseFromParent();
1066 ErasedUncondBr = true;
1067 break;
1068 }
1069 }
1070 assert(ErasedUncondBr && "Unconditional branch not erased!");
1071 }
1072 }
1073
1074 // When there are block / end_block markers that overlap with try / end_try
1075 // markers, and the block and try markers' return types are the same, the
1076 // block /end_block markers are not necessary, because try / end_try markers
1077 // also can serve as boundaries for branches.
1078 // block <- Not necessary
1079 // try
1080 // ...
1081 // catch
1082 // ...
1083 // end
1084 // end <- Not necessary
1086 for (auto &MBB : MF) {
1087 for (auto &MI : MBB) {
1088 if (MI.getOpcode() != WebAssembly::TRY)
1089 continue;
1090 MachineInstr *Try = &MI, *EndTry = BeginToEnd[Try];
1091 if (EndTry->getOpcode() == WebAssembly::DELEGATE)
1092 continue;
1093
1094 MachineBasicBlock *TryBB = Try->getParent();
1095 MachineBasicBlock *Cont = EndTry->getParent();
1096 int64_t RetType = Try->getOperand(0).getImm();
1097 for (auto B = Try->getIterator(), E = std::next(EndTry->getIterator());
1098 B != TryBB->begin() && E != Cont->end() &&
1099 std::prev(B)->getOpcode() == WebAssembly::BLOCK &&
1100 E->getOpcode() == WebAssembly::END_BLOCK &&
1101 std::prev(B)->getOperand(0).getImm() == RetType;
1102 --B, ++E) {
1103 ToDelete.push_back(&*std::prev(B));
1104 ToDelete.push_back(&*E);
1105 }
1106 }
1107 }
1108 for (auto *MI : ToDelete) {
1109 if (MI->getOpcode() == WebAssembly::BLOCK)
1110 unregisterScope(MI);
1111 MI->eraseFromParent();
1112 }
1113}
1114
1115// When MBB is split into MBB and Split, we should unstackify defs in MBB that
1116// have their uses in Split.
1118 MachineBasicBlock &Split) {
1119 MachineFunction &MF = *MBB.getParent();
1120 const auto &TII = *MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo();
1121 auto &MFI = *MF.getInfo<WebAssemblyFunctionInfo>();
1122 auto &MRI = MF.getRegInfo();
1123
1124 for (auto &MI : Split) {
1125 for (auto &MO : MI.explicit_uses()) {
1126 if (!MO.isReg() || MO.getReg().isPhysical())
1127 continue;
1128 if (MachineInstr *Def = MRI.getUniqueVRegDef(MO.getReg()))
1129 if (Def->getParent() == &MBB)
1130 MFI.unstackifyVReg(MO.getReg());
1131 }
1132 }
1133
1134 // In RegStackify, when a register definition is used multiple times,
1135 // Reg = INST ...
1136 // INST ..., Reg, ...
1137 // INST ..., Reg, ...
1138 // INST ..., Reg, ...
1139 //
1140 // we introduce a TEE, which has the following form:
1141 // DefReg = INST ...
1142 // TeeReg, Reg = TEE_... DefReg
1143 // INST ..., TeeReg, ...
1144 // INST ..., Reg, ...
1145 // INST ..., Reg, ...
1146 // with DefReg and TeeReg stackified but Reg not stackified.
1147 //
1148 // But the invariant that TeeReg should be stackified can be violated while we
1149 // unstackify registers in the split BB above. In this case, we convert TEEs
1150 // into two COPYs. This COPY will be eventually eliminated in ExplicitLocals.
1151 // DefReg = INST ...
1152 // TeeReg = COPY DefReg
1153 // Reg = COPY DefReg
1154 // INST ..., TeeReg, ...
1155 // INST ..., Reg, ...
1156 // INST ..., Reg, ...
1158 if (!WebAssembly::isTee(MI.getOpcode()))
1159 continue;
1160 Register TeeReg = MI.getOperand(0).getReg();
1161 Register Reg = MI.getOperand(1).getReg();
1162 Register DefReg = MI.getOperand(2).getReg();
1163 if (!MFI.isVRegStackified(TeeReg)) {
1164 // Now we are not using TEE anymore, so unstackify DefReg too
1165 MFI.unstackifyVReg(DefReg);
1166 unsigned CopyOpc =
1167 WebAssembly::getCopyOpcodeForRegClass(MRI.getRegClass(DefReg));
1168 BuildMI(MBB, &MI, MI.getDebugLoc(), TII.get(CopyOpc), TeeReg)
1169 .addReg(DefReg);
1170 BuildMI(MBB, &MI, MI.getDebugLoc(), TII.get(CopyOpc), Reg).addReg(DefReg);
1171 MI.eraseFromParent();
1172 }
1173 }
1174}
1175
1176// Wrap the given range of instructions with a try-delegate that targets
1177// 'UnwindDest'. RangeBegin and RangeEnd are inclusive.
1178void WebAssemblyCFGStackifyImpl::addNestedTryDelegate(
1179 MachineInstr *RangeBegin, MachineInstr *RangeEnd,
1180 MachineBasicBlock *UnwindDest) {
1181 auto *BeginBB = RangeBegin->getParent();
1182 auto *EndBB = RangeEnd->getParent();
1183 MachineFunction &MF = *BeginBB->getParent();
1184 const auto &MFI = *MF.getInfo<WebAssemblyFunctionInfo>();
1185 const auto &TII = *MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo();
1186
1187 // Local expression tree before the first call of this range should go
1188 // after the nested TRY.
1189 SmallPtrSet<const MachineInstr *, 4> AfterSet;
1190 AfterSet.insert(RangeBegin);
1191 for (auto I = MachineBasicBlock::iterator(RangeBegin), E = BeginBB->begin();
1192 I != E; --I) {
1193 if (std::prev(I)->isDebugInstr() || std::prev(I)->isPosition())
1194 continue;
1195 if (WebAssembly::isChild(*std::prev(I), MFI))
1196 AfterSet.insert(&*std::prev(I));
1197 else
1198 break;
1199 }
1200
1201 // Create the nested try instruction.
1202 auto TryPos = getLatestInsertPos(
1203 BeginBB, SmallPtrSet<const MachineInstr *, 4>(), AfterSet);
1204 MachineInstr *Try = BuildMI(*BeginBB, TryPos, RangeBegin->getDebugLoc(),
1205 TII.get(WebAssembly::TRY))
1206 .addImm(int64_t(WebAssembly::BlockType::Void));
1207
1208 // Create a BB to insert the 'delegate' instruction.
1209 MachineBasicBlock *DelegateBB = MF.CreateMachineBasicBlock();
1210 // If the destination of 'delegate' is not the caller, adds the destination to
1211 // the BB's successors.
1212 if (UnwindDest != FakeCallerBB)
1213 DelegateBB->addSuccessor(UnwindDest);
1214
1215 auto SplitPos = std::next(RangeEnd->getIterator());
1216 if (SplitPos == EndBB->end()) {
1217 // If the range's end instruction is at the end of the BB, insert the new
1218 // delegate BB after the current BB.
1219 MF.insert(std::next(EndBB->getIterator()), DelegateBB);
1220 EndBB->addSuccessor(DelegateBB);
1221
1222 } else {
1223 // When the split pos is in the middle of a BB, we split the BB into two and
1224 // put the 'delegate' BB in between. We normally create a split BB and make
1225 // it a successor of the original BB (CatchAfterSplit == false), but in case
1226 // the BB is an EH pad and there is a 'catch' after the split pos
1227 // (CatchAfterSplit == true), we should preserve the BB's property,
1228 // including that it is an EH pad, in the later part of the BB, where the
1229 // 'catch' is.
1230 bool CatchAfterSplit = false;
1231 if (EndBB->isEHPad()) {
1232 for (auto I = MachineBasicBlock::iterator(SplitPos), E = EndBB->end();
1233 I != E; ++I) {
1234 if (WebAssembly::isCatch(I->getOpcode())) {
1235 CatchAfterSplit = true;
1236 break;
1237 }
1238 }
1239 }
1240
1241 MachineBasicBlock *PreBB = nullptr, *PostBB = nullptr;
1242 if (!CatchAfterSplit) {
1243 // If the range's end instruction is in the middle of the BB, we split the
1244 // BB into two and insert the delegate BB in between.
1245 // - Before:
1246 // bb:
1247 // range_end
1248 // other_insts
1249 //
1250 // - After:
1251 // pre_bb: (previous 'bb')
1252 // range_end
1253 // delegate_bb: (new)
1254 // delegate
1255 // post_bb: (new)
1256 // other_insts
1257 PreBB = EndBB;
1258 PostBB = MF.CreateMachineBasicBlock();
1259 MF.insert(std::next(PreBB->getIterator()), PostBB);
1260 MF.insert(std::next(PreBB->getIterator()), DelegateBB);
1261 PostBB->splice(PostBB->end(), PreBB, SplitPos, PreBB->end());
1262 PostBB->transferSuccessors(PreBB);
1263 } else {
1264 // - Before:
1265 // ehpad:
1266 // range_end
1267 // catch
1268 // ...
1269 //
1270 // - After:
1271 // pre_bb: (new)
1272 // range_end
1273 // delegate_bb: (new)
1274 // delegate
1275 // post_bb: (previous 'ehpad')
1276 // catch
1277 // ...
1278 assert(EndBB->isEHPad());
1279 PreBB = MF.CreateMachineBasicBlock();
1280 PostBB = EndBB;
1281 MF.insert(PostBB->getIterator(), PreBB);
1282 MF.insert(PostBB->getIterator(), DelegateBB);
1283 PreBB->splice(PreBB->end(), PostBB, PostBB->begin(), SplitPos);
1284 // We don't need to transfer predecessors of the EH pad to 'PreBB',
1285 // because an EH pad's predecessors are all through unwind edges and they
1286 // should still unwind to the EH pad, not PreBB.
1287 }
1288 unstackifyVRegsUsedInSplitBB(*PreBB, *PostBB);
1289 PreBB->addSuccessor(DelegateBB);
1290 PreBB->addSuccessor(PostBB);
1291 }
1292
1293 // Add a 'delegate' instruction in the delegate BB created above.
1294 MachineInstr *Delegate = BuildMI(DelegateBB, RangeEnd->getDebugLoc(),
1295 TII.get(WebAssembly::DELEGATE))
1296 .addMBB(UnwindDest);
1297 registerTryScope(Try, Delegate, nullptr);
1298}
1299
1300// Given an unwind destination, return a trampoline BB. A trampoline BB is a
1301// destination of a nested try_table inserted to fix an unwind mismatch. It
1302// contains an end_block, which is the target of the try_table, and a throw_ref,
1303// to rethrow the exception to the right try_table.
1304// try_table (catch ... )
1305// block exnref
1306// ...
1307// try_table (catch_all_ref N)
1308// some code
1309// end_try_table
1310// ...
1311// unreachable
1312// end_block ;; Trampoline BB
1313// throw_ref
1314// end_try_table
1315MachineBasicBlock *
1316WebAssemblyCFGStackifyImpl::getTrampolineBlock(MachineBasicBlock *UnwindDest) {
1317 // We need one trampoline BB per unwind destination, even though there are
1318 // multiple try_tables target the same unwind destination. If we have already
1319 // created one for the given UnwindDest, return it.
1320 auto It = UnwindDestToTrampoline.find(UnwindDest);
1321 if (It != UnwindDestToTrampoline.end())
1322 return It->second;
1323
1324 auto &MF = *UnwindDest->getParent();
1325 auto &MRI = MF.getRegInfo();
1326 const auto &TII = *MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo();
1327
1328 MachineInstr *Block = nullptr;
1329 MachineBasicBlock *TrampolineBB = nullptr;
1330 DebugLoc EndDebugLoc;
1331
1332 if (UnwindDest == getFakeCallerBlock(MF)) {
1333 // If the unwind destination is the caller, create a caller-dedicated
1334 // trampoline BB at the end of the function and wrap the whole function with
1335 // a block.
1336 auto BeginPos = MF.begin()->begin();
1337 while (WebAssembly::isArgument(BeginPos->getOpcode()))
1338 BeginPos++;
1339 Block = BuildMI(*MF.begin(), BeginPos, MF.begin()->begin()->getDebugLoc(),
1340 TII.get(WebAssembly::BLOCK))
1341 .addImm(int64_t(WebAssembly::BlockType::Exnref));
1342 TrampolineBB = getCallerTrampolineBlock(MF);
1343 MachineBasicBlock *PrevBB = &*std::prev(CallerTrampolineBB->getIterator());
1344 EndDebugLoc = PrevBB->findPrevDebugLoc(PrevBB->end());
1345 } else {
1346 // If the unwind destination is another EH pad, create a trampoline BB for
1347 // the unwind dest and insert a block instruction right after the target
1348 // try_table.
1349 auto *TargetBeginTry = EHPadToTry[UnwindDest];
1350 auto *TargetEndTry = BeginToEnd[TargetBeginTry];
1351 auto *TargetBeginBB = TargetBeginTry->getParent();
1352 auto *TargetEndBB = TargetEndTry->getParent();
1353
1354 Block = BuildMI(*TargetBeginBB, std::next(TargetBeginTry->getIterator()),
1355 TargetBeginTry->getDebugLoc(), TII.get(WebAssembly::BLOCK))
1356 .addImm(int64_t(WebAssembly::BlockType::Exnref));
1357 TrampolineBB = MF.CreateMachineBasicBlock();
1358 EndDebugLoc = TargetEndTry->getDebugLoc();
1359 MF.insert(TargetEndBB->getIterator(), TrampolineBB);
1360 TrampolineBB->addSuccessor(UnwindDest);
1361 }
1362
1363 // Insert an end_block, catch_all_ref (pseudo instruction), and throw_ref
1364 // instructions in the trampoline BB.
1365 MachineInstr *EndBlock =
1366 BuildMI(TrampolineBB, EndDebugLoc, TII.get(WebAssembly::END_BLOCK));
1367 auto ExnReg = MRI.createVirtualRegister(&WebAssembly::EXNREFRegClass);
1368 BuildMI(TrampolineBB, EndDebugLoc, TII.get(WebAssembly::CATCH_ALL_REF))
1369 .addDef(ExnReg);
1370 BuildMI(TrampolineBB, EndDebugLoc, TII.get(WebAssembly::THROW_REF))
1371 .addReg(ExnReg);
1372
1373 // The trampoline BB's return type is exnref because it is a target of
1374 // catch_all_ref. But the body type of the block we just created is not. We
1375 // add an 'unreachable' right before the 'end_block' to make the code valid.
1376 MachineBasicBlock *TrampolineLayoutPred = TrampolineBB->getPrevNode();
1377 BuildMI(TrampolineLayoutPred, TrampolineLayoutPred->findBranchDebugLoc(),
1378 TII.get(WebAssembly::UNREACHABLE));
1379
1380 registerScope(Block, EndBlock);
1381 UnwindDestToTrampoline[UnwindDest] = TrampolineBB;
1382 return TrampolineBB;
1383}
1384
1385// Wrap the given range of instructions with a try_table-end_try_table that
1386// targets 'UnwindDest'. RangeBegin and RangeEnd are inclusive.
1387void WebAssemblyCFGStackifyImpl::addNestedTryTable(
1388 MachineInstr *RangeBegin, MachineInstr *RangeEnd,
1389 MachineBasicBlock *UnwindDest) {
1390 auto *BeginBB = RangeBegin->getParent();
1391 auto *EndBB = RangeEnd->getParent();
1392
1393 MachineFunction &MF = *BeginBB->getParent();
1394 const auto &MFI = *MF.getInfo<WebAssemblyFunctionInfo>();
1395 const auto &TII = *MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo();
1396
1397 // Get the trampoline BB that the new try_table will unwind to.
1398 auto *TrampolineBB = getTrampolineBlock(UnwindDest);
1399
1400 // Local expression tree before the first call of this range should go
1401 // after the nested TRY_TABLE.
1402 SmallPtrSet<const MachineInstr *, 4> AfterSet;
1403 AfterSet.insert(RangeBegin);
1404 for (auto I = MachineBasicBlock::iterator(RangeBegin), E = BeginBB->begin();
1405 I != E; --I) {
1406 if (std::prev(I)->isDebugInstr() || std::prev(I)->isPosition())
1407 continue;
1408 if (WebAssembly::isChild(*std::prev(I), MFI))
1409 AfterSet.insert(&*std::prev(I));
1410 else
1411 break;
1412 }
1413
1414 // Create the nested try_table instruction.
1415 auto TryTablePos = getLatestInsertPos(
1416 BeginBB, SmallPtrSet<const MachineInstr *, 4>(), AfterSet);
1417 MachineInstr *TryTable =
1418 BuildMI(*BeginBB, TryTablePos, RangeBegin->getDebugLoc(),
1419 TII.get(WebAssembly::TRY_TABLE))
1420 .addImm(int64_t(WebAssembly::BlockType::Void))
1421 .addImm(1) // # of catch clauses
1423 .addMBB(TrampolineBB);
1424
1425 // Create a BB to insert the 'end_try_table' instruction.
1426 MachineBasicBlock *EndTryTableBB = MF.CreateMachineBasicBlock();
1427 EndTryTableBB->addSuccessor(TrampolineBB);
1428
1429 auto SplitPos = std::next(RangeEnd->getIterator());
1430 if (SplitPos == EndBB->end()) {
1431 // If the range's end instruction is at the end of the BB, insert the new
1432 // end_try_table BB after the current BB.
1433 MF.insert(std::next(EndBB->getIterator()), EndTryTableBB);
1434 EndBB->addSuccessor(EndTryTableBB);
1435
1436 } else {
1437 // When the split pos is in the middle of a BB, we split the BB into two and
1438 // put the 'end_try_table' BB in between. We normally create a split BB and
1439 // make it a successor of the original BB (CatchAfterSplit == false), but in
1440 // case the BB is an EH pad and there is a 'catch' after split pos
1441 // (CatchAfterSplit == true), we should preserve the BB's property,
1442 // including that it is an EH pad, in the later part of the BB, where the
1443 // 'catch' is.
1444 bool CatchAfterSplit = false;
1445 if (EndBB->isEHPad()) {
1446 for (auto I = MachineBasicBlock::iterator(SplitPos), E = EndBB->end();
1447 I != E; ++I) {
1448 if (WebAssembly::isCatch(I->getOpcode())) {
1449 CatchAfterSplit = true;
1450 break;
1451 }
1452 }
1453 }
1454
1455 MachineBasicBlock *PreBB = nullptr, *PostBB = nullptr;
1456 if (!CatchAfterSplit) {
1457 // If the range's end instruction is in the middle of the BB, we split the
1458 // BB into two and insert the end_try_table BB in between.
1459 // - Before:
1460 // bb:
1461 // range_end
1462 // other_insts
1463 //
1464 // - After:
1465 // pre_bb: (previous 'bb')
1466 // range_end
1467 // end_try_table_bb: (new)
1468 // end_try_table
1469 // post_bb: (new)
1470 // other_insts
1471 PreBB = EndBB;
1472 PostBB = MF.CreateMachineBasicBlock();
1473 MF.insert(std::next(PreBB->getIterator()), PostBB);
1474 MF.insert(std::next(PreBB->getIterator()), EndTryTableBB);
1475 PostBB->splice(PostBB->end(), PreBB, SplitPos, PreBB->end());
1476 PostBB->transferSuccessors(PreBB);
1477 } else {
1478 // - Before:
1479 // ehpad:
1480 // range_end
1481 // catch
1482 // ...
1483 //
1484 // - After:
1485 // pre_bb: (new)
1486 // range_end
1487 // end_try_table_bb: (new)
1488 // end_try_table
1489 // post_bb: (previous 'ehpad')
1490 // catch
1491 // ...
1492 assert(EndBB->isEHPad());
1493 PreBB = MF.CreateMachineBasicBlock();
1494 PostBB = EndBB;
1495 MF.insert(PostBB->getIterator(), PreBB);
1496 MF.insert(PostBB->getIterator(), EndTryTableBB);
1497 PreBB->splice(PreBB->end(), PostBB, PostBB->begin(), SplitPos);
1498 // We don't need to transfer predecessors of the EH pad to 'PreBB',
1499 // because an EH pad's predecessors are all through unwind edges and they
1500 // should still unwind to the EH pad, not PreBB.
1501 }
1502 unstackifyVRegsUsedInSplitBB(*PreBB, *PostBB);
1503 PreBB->addSuccessor(EndTryTableBB);
1504 PreBB->addSuccessor(PostBB);
1505 }
1506
1507 // Add a 'end_try_table' instruction in the EndTryTable BB created above.
1508 MachineInstr *EndTryTable = BuildMI(EndTryTableBB, RangeEnd->getDebugLoc(),
1509 TII.get(WebAssembly::END_TRY_TABLE));
1510 registerTryScope(TryTable, EndTryTable, TrampolineBB);
1511}
1512
1513// In the standard (exnref) EH, we fix unwind mismatches by adding a new
1514// block~end_block inside of the unwind destination try_table~end_try_table:
1515// try_table ...
1516// block exnref ;; (new)
1517// ...
1518// try_table (catch_all_ref N) ;; (new) to trampoline BB
1519// code
1520// end_try_table ;; (new)
1521// ...
1522// end_block ;; (new) trampoline BB
1523// throw_ref ;; (new)
1524// end_try_table
1525//
1526// To do this, we will create a new BB that will contain the new 'end_block' and
1527// 'throw_ref' and insert it before the 'end_try_table' BB.
1528//
1529// But there are cases when there are 'end_loop'(s) before the 'end_try_table'
1530// in the same BB. (There can't be 'end_block' before 'end_try_table' in the
1531// same BB because EH pads can't be directly branched to.) Then after fixing
1532// unwind mismatches this will create the mismatching markers like below:
1533// bb0:
1534// try_table
1535// block exnref
1536// ...
1537// loop
1538// ...
1539// new_bb:
1540// end_block
1541// end_try_table_bb:
1542// end_loop
1543// end_try_table
1544//
1545// So if an end_try_table BB has an end_loop before the end_try_table, we split
1546// the BB with the end_loop as a separate BB before the end_try_table BB, so
1547// that after we fix the unwind mismatch, the code will be like:
1548// bb0:
1549// try_table
1550// block exnref
1551// ...
1552// loop
1553// ...
1554// end_loop_bb:
1555// end_loop
1556// new_bb:
1557// end_block
1558// end_try_table_bb:
1559// end_try_table
1560static void splitEndLoopBB(MachineBasicBlock *EndTryTableBB) {
1561 auto &MF = *EndTryTableBB->getParent();
1562 MachineInstr *EndTryTable = nullptr, *EndLoop = nullptr;
1563 for (auto &MI : reverse(*EndTryTableBB)) {
1564 if (MI.getOpcode() == WebAssembly::END_TRY_TABLE) {
1565 EndTryTable = &MI;
1566 continue;
1567 }
1568 if (EndTryTable && MI.getOpcode() == WebAssembly::END_LOOP) {
1569 EndLoop = &MI;
1570 break;
1571 }
1572 }
1573 if (!EndLoop)
1574 return;
1575
1576 auto *EndLoopBB = MF.CreateMachineBasicBlock();
1577 MF.insert(EndTryTableBB->getIterator(), EndLoopBB);
1578 auto SplitPos = std::next(EndLoop->getIterator());
1579 EndLoopBB->splice(EndLoopBB->end(), EndTryTableBB, EndTryTableBB->begin(),
1580 SplitPos);
1581 EndLoopBB->addSuccessor(EndTryTableBB);
1582}
1583
1584// Print the BB name in the form of bb.NUMBER.ORIGINAL_NAME.
1585// e.g., bb.3.catch.start
1586[[maybe_unused]] static std::string getBBName(const MachineBasicBlock *MBB) {
1587 std::string Name = "bb.";
1588 Name += Twine(MBB->getNumber()).str();
1589 if (MBB->getBasicBlock()) {
1590 Name += ".";
1591 Name += MBB->getBasicBlock()->getName();
1592 }
1593 return Name;
1594}
1595
1596bool WebAssemblyCFGStackifyImpl::fixCallUnwindMismatches(MachineFunction &MF) {
1597 // This function is used for both the legacy EH and the standard (exnref) EH,
1598 // and the reason we have unwind mismatches is the same for the both of them,
1599 // but the code examples in the comments are going to be different. To make
1600 // the description less confusing, we write the basically same comments twice,
1601 // once for the legacy EH and the standard EH.
1602 //
1603 // -- Legacy EH --------------------------------------------------------------
1604 //
1605 // Linearizing the control flow by placing TRY / END_TRY markers can create
1606 // mismatches in unwind destinations for throwing instructions, such as calls.
1607 //
1608 // We use the 'delegate' instruction to fix the unwind mismatches. 'delegate'
1609 // instruction delegates an exception to an outer 'catch'. It can target not
1610 // only 'catch' but all block-like structures including another 'delegate',
1611 // but with slightly different semantics than branches. When it targets a
1612 // 'catch', it will delegate the exception to that catch. It is being
1613 // discussed how to define the semantics when 'delegate''s target is a non-try
1614 // block: it will either be a validation failure or it will target the next
1615 // outer try-catch. But anyway our LLVM backend currently does not generate
1616 // such code. The example below illustrates where the 'delegate' instruction
1617 // in the middle will delegate the exception to, depending on the value of N.
1618 // try
1619 // try
1620 // block
1621 // try
1622 // try
1623 // call @foo
1624 // delegate N ;; Where will this delegate to?
1625 // catch ;; N == 0
1626 // end
1627 // end ;; N == 1 (invalid; will not be generated)
1628 // delegate ;; N == 2
1629 // catch ;; N == 3
1630 // end
1631 // ;; N == 4 (to caller)
1632 //
1633 // 1. When an instruction may throw, but the EH pad it will unwind to can be
1634 // different from the original CFG.
1635 //
1636 // Example: we have the following CFG:
1637 // bb0:
1638 // call @foo ; if it throws, unwind to bb2
1639 // bb1:
1640 // call @bar ; if it throws, unwind to bb3
1641 // bb2 (ehpad):
1642 // catch
1643 // ...
1644 // bb3 (ehpad)
1645 // catch
1646 // ...
1647 //
1648 // And the CFG is sorted in this order. Then after placing TRY markers, it
1649 // will look like: (BB markers are omitted)
1650 // try
1651 // try
1652 // call @foo
1653 // call @bar ;; if it throws, unwind to bb3
1654 // catch ;; ehpad (bb2)
1655 // ...
1656 // end_try
1657 // catch ;; ehpad (bb3)
1658 // ...
1659 // end_try
1660 //
1661 // Now if bar() throws, it is going to end up in bb2, not bb3, where it is
1662 // supposed to end up. We solve this problem by wrapping the mismatching call
1663 // with an inner try-delegate that rethrows the exception to the right
1664 // 'catch'.
1665 //
1666 // try
1667 // try
1668 // call @foo
1669 // try ;; (new)
1670 // call @bar
1671 // delegate 1 (bb3) ;; (new)
1672 // catch ;; ehpad (bb2)
1673 // ...
1674 // end_try
1675 // catch ;; ehpad (bb3)
1676 // ...
1677 // end_try
1678 //
1679 // ---
1680 // 2. The same as 1, but in this case an instruction unwinds to a caller
1681 // function and not another EH pad.
1682 //
1683 // Example: we have the following CFG:
1684 // bb0:
1685 // call @foo ; if it throws, unwind to bb2
1686 // bb1:
1687 // call @bar ; if it throws, unwind to caller
1688 // bb2 (ehpad):
1689 // catch
1690 // ...
1691 //
1692 // And the CFG is sorted in this order. Then after placing TRY markers, it
1693 // will look like:
1694 // try
1695 // call @foo
1696 // call @bar ;; if it throws, unwind to caller
1697 // catch ;; ehpad (bb2)
1698 // ...
1699 // end_try
1700 //
1701 // Now if bar() throws, it is going to end up in bb2, when it is supposed
1702 // throw up to the caller. We solve this problem in the same way, but in this
1703 // case 'delegate's immediate argument is the number of block depths + 1,
1704 // which means it rethrows to the caller.
1705 // try
1706 // call @foo
1707 // try ;; (new)
1708 // call @bar
1709 // delegate 1 (caller) ;; (new)
1710 // catch ;; ehpad (bb2)
1711 // ...
1712 // end_try
1713 //
1714 // Before rewriteDepthImmediates, delegate's argument is a BB. In case of the
1715 // caller, it will take a fake BB generated by getFakeCallerBlock(), which
1716 // will be converted to a correct immediate argument later.
1717 //
1718 // In case there are multiple calls in a BB that may throw to the caller, they
1719 // can be wrapped together in one nested try-delegate scope. (In 1, this
1720 // couldn't happen, because may-throwing instruction there had an unwind
1721 // destination, i.e., it was an invoke before, and there could be only one
1722 // invoke within a BB.)
1723 //
1724 // -- Standard EH ------------------------------------------------------------
1725 //
1726 // Linearizing the control flow by placing TRY / END_TRY_TABLE markers can
1727 // create mismatches in unwind destinations for throwing instructions, such as
1728 // calls.
1729 //
1730 // We use the a nested 'try_table'~'end_try_table' instruction to fix the
1731 // unwind mismatches. try_table's catch clauses take an immediate argument
1732 // that specifics which block we should branch to.
1733 //
1734 // 1. When an instruction may throw, but the EH pad it will unwind to can be
1735 // different from the original CFG.
1736 //
1737 // Example: we have the following CFG:
1738 // bb0:
1739 // call @foo ; if it throws, unwind to bb2
1740 // bb1:
1741 // call @bar ; if it throws, unwind to bb3
1742 // bb2 (ehpad):
1743 // catch
1744 // ...
1745 // bb3 (ehpad)
1746 // catch
1747 // ...
1748 //
1749 // And the CFG is sorted in this order. Then after placing TRY_TABLE markers
1750 // (and BLOCK markers for the TRY_TABLE's destinations), it will look like:
1751 // (BB markers are omitted)
1752 // block
1753 // try_table (catch ... 0)
1754 // block
1755 // try_table (catch ... 0)
1756 // call @foo
1757 // call @bar ;; if it throws, unwind to bb3
1758 // end_try_table
1759 // end_block ;; ehpad (bb2)
1760 // ...
1761 // end_try_table
1762 // end_block ;; ehpad (bb3)
1763 // ...
1764 //
1765 // Now if bar() throws, it is going to end up in bb2, not bb3, where it is
1766 // supposed to end up. We solve this problem by wrapping the mismatching call
1767 // with an inner try_table~end_try_table that sends the exception to the the
1768 // 'trampoline' block, which rethrows, or 'bounces' it to the right
1769 // end_try_table:
1770 // block
1771 // try_table (catch ... 0)
1772 // block exnref ;; (new)
1773 // block
1774 // try_table (catch ... 0)
1775 // call @foo
1776 // try_table (catch_all_ref 2) ;; (new) to trampoline BB
1777 // call @bar
1778 // end_try_table ;; (new)
1779 // end_try_table
1780 // end_block ;; ehpad (bb2)
1781 // ...
1782 // end_block ;; (new) trampoline BB
1783 // throw_ref ;; (new)
1784 // end_try_table
1785 // end_block ;; ehpad (bb3)
1786 //
1787 // ---
1788 // 2. The same as 1, but in this case an instruction unwinds to a caller
1789 // function and not another EH pad.
1790 //
1791 // Example: we have the following CFG:
1792 // bb0:
1793 // call @foo ; if it throws, unwind to bb2
1794 // bb1:
1795 // call @bar ; if it throws, unwind to caller
1796 // bb2 (ehpad):
1797 // catch
1798 // ...
1799 //
1800 // And the CFG is sorted in this order. Then after placing TRY_TABLE markers
1801 // (and BLOCK markers for the TRY_TABLE's destinations), it will look like:
1802 // block
1803 // try_table (catch ... 0)
1804 // call @foo
1805 // call @bar ;; if it throws, unwind to caller
1806 // end_try_table
1807 // end_block ;; ehpad (bb2)
1808 // ...
1809 //
1810 // Now if bar() throws, it is going to end up in bb2, when it is supposed
1811 // throw up to the caller. We solve this problem in the same way, but in this
1812 // case 'catch_all_ref's immediate argument is the number of block depths + 1,
1813 // which means it rethrows to the caller.
1814 // block exnref ;; (new)
1815 // block
1816 // try_table (catch ... 0)
1817 // call @foo
1818 // try_table (catch_all_ref 2) ;; (new) to trampoline BB
1819 // call @bar
1820 // end_try_table ;; (new)
1821 // end_try_table
1822 // end_block ;; ehpad (bb2)
1823 // ...
1824 // end_block ;; (new) caller trampoline BB
1825 // throw_ref ;; (new) throw to the caller
1826 //
1827 // Before rewriteDepthImmediates, try_table's catch clauses' argument is a
1828 // trampoline BB from which we throw_ref the exception to the right
1829 // end_try_table. In case of the caller, it will take a new caller-dedicated
1830 // trampoline BB generated by getCallerTrampolineBlock(), which throws the
1831 // exception to the caller.
1832 //
1833 // In case there are multiple calls in a BB that may throw to the caller, they
1834 // can be wrapped together in one nested try_table-end_try_table scope. (In 1,
1835 // this couldn't happen, because may-throwing instruction there had an unwind
1836 // destination, i.e., it was an invoke before, and there could be only one
1837 // invoke within a BB.)
1838
1840 // Range of intructions to be wrapped in a new nested try~delegate or
1841 // try_table~end_try_table. A range exists in a single BB and does not span
1842 // multiple BBs.
1843 using TryRange = std::pair<MachineInstr *, MachineInstr *>;
1844 // In original CFG, <unwind destination BB, a vector of try/try_table ranges>
1845 MapVector<MachineBasicBlock *, SmallVector<TryRange, 4>>
1846 UnwindDestToTryRanges;
1847
1848 // Gather possibly throwing calls (i.e., previously invokes) whose current
1849 // unwind destination is not the same as the original CFG. (Case 1)
1850
1851 for (auto &MBB : reverse(MF)) {
1852 bool SeenThrowableInstInBB = false;
1853 for (auto &MI : reverse(MBB)) {
1854 if (WebAssembly::isTry(MI.getOpcode()))
1855 EHPadStack.pop_back();
1856 else if (MI.getOpcode() == WebAssembly::DELEGATE)
1857 EHPadStack.push_back(MI.getOperand(0).getMBB());
1858 else if (WebAssembly::WasmUseLegacyEH &&
1859 WebAssembly::isCatch(MI.getOpcode()))
1860 EHPadStack.push_back(MI.getParent());
1861 else if (MI.getOpcode() == WebAssembly::END_TRY_TABLE)
1862 // In case of the legacy EH, 'catch' instruction is always an EH pad for
1863 // the 'try' body that precedes it. But in the standard EH, because
1864 // fixCatchUnwindMismatches runs before this, a new try_table's
1865 // trampoline BB will be separated from try_table ~ end_try_table body:
1866 //
1867 // bb0:
1868 // try_table (catch_all_ref %far_away_trampoline)
1869 // ...
1870 // end_try_table
1871 // ...
1872 // far_away_trampoline:
1873 // catch_all_ref
1874 // throw_ref
1875 //
1876 // And there can be multiple try_tables that target a single trampoline:
1877 //
1878 // bb0:
1879 // try_table (catch_all_ref %far_away_trampolinle_bb)
1880 // ...
1881 // end_try_table
1882 // ...
1883 // bb1:
1884 // try_table (catch_all_ref %far_away_trampolinle_bb)
1885 // ...
1886 // end_try_table
1887 // ...
1888 // far_away_trampoline:
1889 // catch_all_ref
1890 // throw_ref
1891 //
1892 // So we can't call WebAssembly::isCatch to add its parent EH pad to
1893 // EHPadStack. Now we add to EHPadStack at end_try_table marker, by
1894 // getting its matching try_table's destination. This works when the
1895 // destination EH pad is either a normal EH pad or a trampoline created
1896 // in fixCatchUnwindMismatches.
1897 //
1898 // Note that we don't need to distinguish this case in
1899 // fixCatchUnwindMismatches because it runs before
1900 // fixCallUnwindMismatches and there is no new try_tables and
1901 // trampolines when it runs.
1902 EHPadStack.push_back(TryToEHPad[EndToBegin[&MI]]);
1903
1904 // In this loop we only gather calls that have an EH pad to unwind. So
1905 // there will be at most 1 such call (= invoke) in a BB, so after we've
1906 // seen one, we can skip the rest of BB. Also if MBB has no EH pad
1907 // successor or MI does not throw, this is not an invoke.
1908 if (SeenThrowableInstInBB || !MBB.hasEHPadSuccessor() ||
1909 !WebAssembly::mayThrow(MI))
1910 continue;
1911 SeenThrowableInstInBB = true;
1912
1913 // If the EH pad on the stack top is where this instruction should unwind
1914 // next, we're good.
1915 MachineBasicBlock *UnwindDest = nullptr;
1916 for (auto *Succ : MBB.successors()) {
1917 // Even though semantically a BB can have multiple successors in case an
1918 // exception is not caught by a catchpad, the first unwind destination
1919 // should appear first in the successor list, based on the calculation
1920 // in findUnwindDestinations() in SelectionDAGBuilder.cpp.
1921 if (Succ->isEHPad()) {
1922 UnwindDest = Succ;
1923 break;
1924 }
1925 }
1926 if (EHPadStack.back() == UnwindDest)
1927 continue;
1928
1929 // Include EH_LABELs in the range before and after the invoke
1930 MachineInstr *RangeBegin = &MI, *RangeEnd = &MI;
1931 if (RangeBegin->getIterator() != MBB.begin() &&
1932 std::prev(RangeBegin->getIterator())->isEHLabel())
1933 RangeBegin = &*std::prev(RangeBegin->getIterator());
1934 if (std::next(RangeEnd->getIterator()) != MBB.end() &&
1935 std::next(RangeEnd->getIterator())->isEHLabel())
1936 RangeEnd = &*std::next(RangeEnd->getIterator());
1937
1938 // If not, record the range.
1939 UnwindDestToTryRanges[UnwindDest].push_back(
1940 TryRange(RangeBegin, RangeEnd));
1941 LLVM_DEBUG(dbgs() << "- Call unwind mismatch: MBB = " << getBBName(&MBB)
1942 << "\nCall = " << MI
1943 << "\nOriginal dest = " << getBBName(UnwindDest)
1944 << " Current dest = " << getBBName(EHPadStack.back())
1945 << "\n\n");
1946 }
1947 }
1948
1949 assert(EHPadStack.empty());
1950
1951 // Gather possibly throwing calls that are supposed to unwind up to the caller
1952 // if they throw, but currently unwind to an incorrect destination. Unlike the
1953 // loop above, there can be multiple calls within a BB that unwind to the
1954 // caller, which we should group together in a range. (Case 2)
1955
1956 MachineInstr *RangeBegin = nullptr, *RangeEnd = nullptr; // inclusive
1957
1958 // Record the range.
1959 auto RecordCallerMismatchRange = [&](const MachineBasicBlock *CurrentDest) {
1960 UnwindDestToTryRanges[getFakeCallerBlock(MF)].push_back(
1961 TryRange(RangeBegin, RangeEnd));
1962 LLVM_DEBUG(dbgs() << "- Call unwind mismatch: MBB = "
1963 << getBBName(RangeBegin->getParent())
1964 << "\nRange begin = " << *RangeBegin
1965 << "Range end = " << *RangeEnd
1966 << "\nOriginal dest = caller Current dest = "
1967 << getBBName(CurrentDest) << "\n\n");
1968 RangeBegin = RangeEnd = nullptr; // Reset range pointers
1969 };
1970
1971 for (auto &MBB : reverse(MF)) {
1972 bool SeenThrowableInstInBB = false;
1973 for (auto &MI : reverse(MBB)) {
1974 bool MayThrow = WebAssembly::mayThrow(MI);
1975
1976 // If MBB has an EH pad successor and this is the last instruction that
1977 // may throw, this instruction unwinds to the EH pad and not to the
1978 // caller.
1979 if (MBB.hasEHPadSuccessor() && MayThrow && !SeenThrowableInstInBB)
1980 SeenThrowableInstInBB = true;
1981
1982 // We wrap up the current range when we see a marker even if we haven't
1983 // finished a BB.
1984 else if (RangeEnd && WebAssembly::isMarker(MI.getOpcode()))
1985 RecordCallerMismatchRange(EHPadStack.back());
1986
1987 // If EHPadStack is empty, that means it correctly unwinds to the caller
1988 // if it throws, so we're good. A delegate targeting FakeCallerBB also
1989 // correctly unwinds to the caller. If MI does not throw, we're good too.
1990 else if (EHPadStack.empty() || EHPadStack.back() == FakeCallerBB ||
1991 !MayThrow) {
1992 }
1993
1994 // We found an instruction that unwinds to the caller but currently has an
1995 // incorrect unwind destination. Create a new range or increment the
1996 // currently existing range.
1997 else {
1998 if (!RangeEnd)
1999 RangeBegin = RangeEnd = &MI;
2000 else
2001 RangeBegin = &MI;
2002 }
2003
2004 // Update EHPadStack.
2005 if (WebAssembly::isTry(MI.getOpcode()))
2006 EHPadStack.pop_back();
2007 else if (MI.getOpcode() == WebAssembly::DELEGATE)
2008 EHPadStack.push_back(MI.getOperand(0).getMBB());
2009 else if (WebAssembly::WasmUseLegacyEH &&
2010 WebAssembly::isCatch(MI.getOpcode()))
2011 EHPadStack.push_back(MI.getParent());
2012 else if (!WebAssembly::WasmUseLegacyEH &&
2013 MI.getOpcode() == WebAssembly::END_TRY_TABLE)
2014 EHPadStack.push_back(TryToEHPad[EndToBegin[&MI]]);
2015 }
2016
2017 if (RangeEnd)
2018 RecordCallerMismatchRange(EHPadStack.back());
2019 }
2020
2021 assert(EHPadStack.empty());
2022
2023 // We don't have any unwind destination mismatches to resolve.
2024 if (UnwindDestToTryRanges.empty())
2025 return false;
2026
2027 // When end_loop is before end_try_table within the same BB in unwind
2028 // destinations, we should split the end_loop into another BB.
2029 if (!WebAssembly::WasmUseLegacyEH)
2030 for (auto &[UnwindDest, _] : UnwindDestToTryRanges) {
2031 auto It = EHPadToTry.find(UnwindDest);
2032 // If UnwindDest is the fake caller block, it will not be in EHPadToTry
2033 // map
2034 if (It != EHPadToTry.end()) {
2035 auto *TryTable = It->second;
2036 auto *EndTryTable = BeginToEnd[TryTable];
2037 splitEndLoopBB(EndTryTable->getParent());
2038 }
2039 }
2040
2041 // Now we fix the mismatches by wrapping calls with inner try-delegates.
2042 for (auto &P : UnwindDestToTryRanges) {
2043 NumCallUnwindMismatches += P.second.size();
2044 MachineBasicBlock *UnwindDest = P.first;
2045 auto &TryRanges = P.second;
2046
2047 for (auto Range : TryRanges) {
2048 MachineInstr *RangeBegin = nullptr, *RangeEnd = nullptr;
2049 std::tie(RangeBegin, RangeEnd) = Range;
2050 auto *MBB = RangeBegin->getParent();
2051
2052 // If this BB has an EH pad successor, i.e., ends with an 'invoke', and if
2053 // the current range contains the invoke, now we are going to wrap the
2054 // invoke with try-delegate or try_table-end_try_table, making the
2055 // 'delegate' or 'end_try_table' BB the new successor instead, so remove
2056 // the EH pad succesor here. The BB may not have an EH pad successor if
2057 // calls in this BB throw to the caller.
2058 if (UnwindDest != getFakeCallerBlock(MF)) {
2059 MachineBasicBlock *EHPad = nullptr;
2060 for (auto *Succ : MBB->successors()) {
2061 if (Succ->isEHPad()) {
2062 EHPad = Succ;
2063 break;
2064 }
2065 }
2066 if (EHPad)
2067 MBB->removeSuccessor(EHPad);
2068 }
2069
2070 if (WebAssembly::WasmUseLegacyEH)
2071 addNestedTryDelegate(RangeBegin, RangeEnd, UnwindDest);
2072 else
2073 addNestedTryTable(RangeBegin, RangeEnd, UnwindDest);
2074 }
2075 }
2076
2077 return true;
2078}
2079
2080bool WebAssemblyCFGStackifyImpl::fixCatchUnwindMismatches(MachineFunction &MF) {
2081 // This function is used for both the legacy EH and the standard (exnref) EH,
2082 // and the reason we have unwind mismatches is the same for the both of them,
2083 // but the code examples in the comments are going to be different. To make
2084 // the description less confusing, we write the basically same comments twice,
2085 // once for the legacy EH and the standard EH.
2086 //
2087 // -- Legacy EH --------------------------------------------------------------
2088 //
2089 // There is another kind of unwind destination mismatches besides call unwind
2090 // mismatches, which we will call "catch unwind mismatches". See this example
2091 // after the marker placement:
2092 // try
2093 // try
2094 // call @foo
2095 // catch __cpp_exception ;; ehpad A (next unwind dest: caller)
2096 // ...
2097 // end_try
2098 // catch_all ;; ehpad B
2099 // ...
2100 // end_try
2101 //
2102 // 'call @foo's unwind destination is the ehpad A. But suppose 'call @foo'
2103 // throws a foreign exception that is not caught by ehpad A, and its next
2104 // destination should be the caller. But after control flow linearization,
2105 // another EH pad can be placed in between (e.g. ehpad B here), making the
2106 // next unwind destination incorrect. In this case, the foreign exception will
2107 // instead go to ehpad B and will be caught there instead. In this example the
2108 // correct next unwind destination is the caller, but it can be another outer
2109 // catch in other cases.
2110 //
2111 // There is no specific 'call' or 'throw' instruction to wrap with a
2112 // try-delegate, so we wrap the whole try-catch-end with a try-delegate and
2113 // make it rethrow to the right destination, which is the caller in the
2114 // example below:
2115 // try
2116 // try ;; (new)
2117 // try
2118 // call @foo
2119 // catch __cpp_exception ;; ehpad A (next unwind dest: caller)
2120 // ...
2121 // end_try
2122 // delegate 1 (caller) ;; (new)
2123 // catch_all ;; ehpad B
2124 // ...
2125 // end_try
2126 //
2127 // The right destination may be another EH pad or the caller. (The example
2128 // here shows the case it is the caller.)
2129 //
2130 // -- Standard EH ------------------------------------------------------------
2131 //
2132 // There is another kind of unwind destination mismatches besides call unwind
2133 // mismatches, which we will call "catch unwind mismatches". See this example
2134 // after the marker placement:
2135 // block
2136 // try_table (catch_all_ref 0)
2137 // block
2138 // try_table (catch ... 0)
2139 // call @foo
2140 // end_try_table
2141 // end_block ;; ehpad A (next unwind dest: caller)
2142 // ...
2143 // end_try_table
2144 // end_block ;; ehpad B
2145 // ...
2146 //
2147 // 'call @foo's unwind destination is the ehpad A. But suppose 'call @foo'
2148 // throws a foreign exception that is not caught by ehpad A, and its next
2149 // destination should be the caller. But after control flow linearization,
2150 // another EH pad can be placed in between (e.g. ehpad B here), making the
2151 // next unwind destination incorrect. In this case, the foreign exception will
2152 // instead go to ehpad B and will be caught there instead. In this example the
2153 // correct next unwind destination is the caller, but it can be another outer
2154 // catch in other cases.
2155 //
2156 // There is no specific 'call' or 'throw' instruction to wrap with an inner
2157 // try_table-end_try_table, so we wrap the whole try_table-end_try_table with
2158 // an inner try_table-end_try_table that sends the exception to a trampoline
2159 // BB. We rethrow the sent exception using a throw_ref to the right
2160 // destination, which is the caller in the example below:
2161 // block exnref
2162 // block
2163 // try_table (catch_all_ref 0)
2164 // try_table (catch_all_ref 2) ;; (new) to trampoline
2165 // block
2166 // try_table (catch ... 0)
2167 // call @foo
2168 // end_try_table
2169 // end_block ;; ehpad A (next unwind dest: caller)
2170 // end_try_table ;; (new)
2171 // ...
2172 // end_try_table
2173 // end_block ;; ehpad B
2174 // ...
2175 // end_block ;; (new) caller trampoline BB
2176 // throw_ref ;; (new) throw to the caller
2177 //
2178 // The right destination may be another EH pad or the caller. (The example
2179 // here shows the case it is the caller.)
2180
2181 // Returns whether the next unwind destination exists when an exception is not
2182 // caught by the given EHPad. It is guaranteed that the next successor of the
2183 // given EHPad's predecessor is the next unwind destination, due to the order
2184 // we add successors in findUnwindDestinations in SelectionDAGBuilder.
2185 auto HasUnwindDest = [&](const MachineBasicBlock *EHPad) {
2186 assert(!EHPad->pred_empty() && "EHPad has no predecessors");
2187 auto *InvokeBB = *EHPad->pred_begin();
2188 for (auto I = InvokeBB->succ_begin(), E = InvokeBB->succ_end(); I != E; ++I)
2189 if (*I == EHPad)
2190 return std::next(I) != E;
2191 llvm_unreachable("EHPad not found in its predecessor's successors");
2192 };
2193
2194 // Returns the next unwind destination when an exception is not caught by the
2195 // given EHPad. Returns nullptr when it doesn't exist.
2196 auto GetUnwindDest = [&](const MachineBasicBlock *EHPad) {
2197 assert(!EHPad->pred_empty() && "EHPad has no predecessors");
2198 auto *InvokeBB = *EHPad->pred_begin();
2199 for (auto I = InvokeBB->succ_begin(), E = InvokeBB->succ_end(); I != E;
2200 ++I) {
2201 if (*I == EHPad) {
2202 auto *Next = std::next(I);
2203 return Next == E ? nullptr : *Next;
2204 }
2205 }
2206 llvm_unreachable("EHPad not found in its predecessor's successors");
2207 };
2208
2210 // For EH pads that have catch unwind mismatches, a map of <EH pad, its
2211 // correct unwind destination>.
2212 MapVector<MachineBasicBlock *, MachineBasicBlock *> EHPadToUnwindDest;
2213
2214 for (auto &MBB : reverse(MF)) {
2215 for (auto &MI : reverse(MBB)) {
2216 if (WebAssembly::isTry(MI.getOpcode())) {
2217 EHPadStack.pop_back();
2218 } else if (MI.getOpcode() == WebAssembly::DELEGATE) {
2219 EHPadStack.push_back(&MBB);
2220 } else if (WebAssembly::isCatch(MI.getOpcode())) {
2221 auto *EHPad = &MBB;
2222
2223 // catch_all always catches an exception, so we don't need to do
2224 // anything
2225 if (WebAssembly::isCatchAll(MI.getOpcode())) {
2226 }
2227
2228 // This can happen when the unwind dest was removed during the
2229 // optimization, e.g. because it was unreachable.
2230 else if (EHPadStack.empty() && HasUnwindDest(EHPad)) {
2231 LLVM_DEBUG(dbgs() << "EHPad (" << getBBName(EHPad)
2232 << "'s unwind destination does not exist anymore"
2233 << "\n\n");
2234 }
2235
2236 // The EHPad's next unwind destination is the caller, but we incorrectly
2237 // unwind to another EH pad.
2238 else if (!EHPadStack.empty() && EHPadStack.back() != FakeCallerBB &&
2239 !HasUnwindDest(EHPad)) {
2240 EHPadToUnwindDest[EHPad] = getFakeCallerBlock(MF);
2242 << "- Catch unwind mismatch:\nEHPad = " << getBBName(EHPad)
2243 << " Original dest = caller Current dest = "
2244 << getBBName(EHPadStack.back()) << "\n\n");
2245 }
2246
2247 // The EHPad's next unwind destination is an EH pad, whereas we
2248 // incorrectly unwind to another EH pad.
2249 else if (!EHPadStack.empty() && HasUnwindDest(EHPad)) {
2250 auto *UnwindDest = GetUnwindDest(EHPad);
2251 if (EHPadStack.back() != UnwindDest) {
2252 EHPadToUnwindDest[EHPad] = UnwindDest;
2253 LLVM_DEBUG(dbgs() << "- Catch unwind mismatch:\nEHPad = "
2254 << getBBName(EHPad) << " Original dest = "
2255 << getBBName(UnwindDest) << " Current dest = "
2256 << getBBName(EHPadStack.back()) << "\n\n");
2257 }
2258 }
2259
2260 EHPadStack.push_back(EHPad);
2261 }
2262 }
2263 }
2264
2265 assert(EHPadStack.empty());
2266 if (EHPadToUnwindDest.empty())
2267 return false;
2268
2269 // When end_loop is before end_try_table within the same BB in unwind
2270 // destinations, we should split the end_loop into another BB.
2271 for (auto &[_, UnwindDest] : EHPadToUnwindDest) {
2272 auto It = EHPadToTry.find(UnwindDest);
2273 // If UnwindDest is the fake caller block, it will not be in EHPadToTry map
2274 if (It != EHPadToTry.end()) {
2275 auto *TryTable = It->second;
2276 auto *EndTryTable = BeginToEnd[TryTable];
2277 splitEndLoopBB(EndTryTable->getParent());
2278 }
2279 }
2280
2281 NumCatchUnwindMismatches += EHPadToUnwindDest.size();
2282 SmallPtrSet<MachineBasicBlock *, 4> NewEndTryBBs;
2283
2284 for (auto &[EHPad, UnwindDest] : EHPadToUnwindDest) {
2285 MachineInstr *Try = EHPadToTry[EHPad];
2286 MachineInstr *EndTry = BeginToEnd[Try];
2287 if (WebAssembly::WasmUseLegacyEH) {
2288 addNestedTryDelegate(Try, EndTry, UnwindDest);
2289 NewEndTryBBs.insert(EndTry->getParent());
2290 } else {
2291 addNestedTryTable(Try, EndTry, UnwindDest);
2292 }
2293 }
2294
2295 if (!WebAssembly::WasmUseLegacyEH)
2296 return true;
2297
2298 // Adding a try-delegate wrapping an existing try-catch-end can make existing
2299 // branch destination BBs invalid. For example,
2300 //
2301 // - Before:
2302 // bb0:
2303 // block
2304 // br bb3
2305 // bb1:
2306 // try
2307 // ...
2308 // bb2: (ehpad)
2309 // catch
2310 // bb3:
2311 // end_try
2312 // end_block ;; 'br bb3' targets here
2313 //
2314 // Suppose this try-catch-end has a catch unwind mismatch, so we need to wrap
2315 // this with a try-delegate. Then this becomes:
2316 //
2317 // - After:
2318 // bb0:
2319 // block
2320 // br bb3 ;; invalid destination!
2321 // bb1:
2322 // try ;; (new instruction)
2323 // try
2324 // ...
2325 // bb2: (ehpad)
2326 // catch
2327 // bb3:
2328 // end_try ;; 'br bb3' still incorrectly targets here!
2329 // delegate_bb: ;; (new BB)
2330 // delegate ;; (new instruction)
2331 // split_bb: ;; (new BB)
2332 // end_block
2333 //
2334 // Now 'br bb3' incorrectly branches to an inner scope.
2335 //
2336 // As we can see in this case, when branches target a BB that has both
2337 // 'end_try' and 'end_block' and the BB is split to insert a 'delegate', we
2338 // have to remap existing branch destinations so that they target not the
2339 // 'end_try' BB but the new 'end_block' BB. There can be multiple 'delegate's
2340 // in between, so we try to find the next BB with 'end_block' instruction. In
2341 // this example, the 'br bb3' instruction should be remapped to 'br split_bb'.
2342 for (auto &MBB : MF) {
2343 for (auto &MI : MBB) {
2344 if (MI.isTerminator()) {
2345 for (auto &MO : MI.operands()) {
2346 if (MO.isMBB() && NewEndTryBBs.count(MO.getMBB())) {
2347 auto *BrDest = MO.getMBB();
2348 bool FoundEndBlock = false;
2349 for (; std::next(BrDest->getIterator()) != MF.end();
2350 BrDest = BrDest->getNextNode()) {
2351 for (const auto &MI : *BrDest) {
2352 if (MI.getOpcode() == WebAssembly::END_BLOCK) {
2353 FoundEndBlock = true;
2354 break;
2355 }
2356 }
2357 if (FoundEndBlock)
2358 break;
2359 }
2360 assert(FoundEndBlock);
2361 MO.setMBB(BrDest);
2362 }
2363 }
2364 }
2365 }
2366 }
2367
2368 return true;
2369}
2370
2371void WebAssemblyCFGStackifyImpl::recalculateScopeTops(MachineFunction &MF) {
2372 // Renumber BBs and recalculate ScopeTop info because new BBs might have been
2373 // created and inserted during fixing unwind mismatches.
2374 MF.RenumberBlocks();
2375 ScopeTops.clear();
2376 ScopeTops.resize(MF.getNumBlockIDs());
2377 for (auto &MBB : reverse(MF)) {
2378 for (auto &MI : reverse(MBB)) {
2379 if (ScopeTops[MBB.getNumber()])
2380 break;
2381 switch (MI.getOpcode()) {
2382 case WebAssembly::END_BLOCK:
2383 case WebAssembly::END_LOOP:
2384 case WebAssembly::END_TRY:
2385 case WebAssembly::END_TRY_TABLE:
2386 case WebAssembly::DELEGATE:
2387 updateScopeTops(EndToBegin[&MI]->getParent(), &MBB);
2388 break;
2389 case WebAssembly::CATCH_LEGACY:
2390 case WebAssembly::CATCH_ALL_LEGACY:
2391 updateScopeTops(EHPadToTry[&MBB]->getParent(), &MBB);
2392 break;
2393 }
2394 }
2395 }
2396}
2397
2398/// In normal assembly languages, when the end of a function is unreachable,
2399/// because the function ends in an infinite loop or a noreturn call or similar,
2400/// it isn't necessary to worry about the function return type at the end of
2401/// the function, because it's never reached. However, in WebAssembly, blocks
2402/// that end at the function end need to have a return type signature that
2403/// matches the function signature, even though it's unreachable. This function
2404/// checks for such cases and fixes up the signatures.
2405void WebAssemblyCFGStackifyImpl::fixEndsAtEndOfFunction(MachineFunction &MF) {
2406 const auto &MFI = *MF.getInfo<WebAssemblyFunctionInfo>();
2407
2408 if (MFI.getResults().empty())
2409 return;
2410
2411 // MCInstLower will add the proper types to multivalue signatures based on the
2412 // function return type
2413 WebAssembly::BlockType RetType =
2414 MFI.getResults().size() > 1
2415 ? WebAssembly::BlockType::Multivalue
2416 : WebAssembly::BlockType(
2417 WebAssembly::toValType(MFI.getResults().front()));
2418
2420 Worklist.push_back(MF.rbegin()->rbegin());
2421
2422 auto Process = [&](MachineBasicBlock::reverse_iterator It) {
2423 auto *MBB = It->getParent();
2424 while (It != MBB->rend()) {
2425 MachineInstr &MI = *It++;
2426 if (MI.isPosition() || MI.isDebugInstr())
2427 continue;
2428 switch (MI.getOpcode()) {
2429 case WebAssembly::END_TRY: {
2430 // If a 'try''s return type is fixed, both its try body and catch body
2431 // should satisfy the return type, so we need to search 'end'
2432 // instructions before its corresponding 'catch' too.
2433 auto *EHPad = TryToEHPad.lookup(EndToBegin[&MI]);
2434 assert(EHPad);
2435 auto NextIt =
2436 std::next(WebAssembly::findCatch(EHPad)->getReverseIterator());
2437 if (NextIt != EHPad->rend())
2438 Worklist.push_back(NextIt);
2439 [[fallthrough]];
2440 }
2441 case WebAssembly::END_BLOCK:
2442 case WebAssembly::END_LOOP:
2443 case WebAssembly::END_TRY_TABLE:
2444 case WebAssembly::DELEGATE:
2445 EndToBegin[&MI]->getOperand(0).setImm(int32_t(RetType));
2446 continue;
2447 default:
2448 // Something other than an `end`. We're done for this BB.
2449 return;
2450 }
2451 }
2452 // We've reached the beginning of a BB. Continue the search in the previous
2453 // BB.
2454 Worklist.push_back(MBB->getPrevNode()->rbegin());
2455 };
2456
2457 while (!Worklist.empty())
2458 Process(Worklist.pop_back_val());
2459}
2460
2461// WebAssembly functions end with an end instruction, as if the function body
2462// were a block.
2464 const WebAssemblyInstrInfo &TII) {
2465 BuildMI(MF.back(), MF.back().end(),
2466 MF.back().findPrevDebugLoc(MF.back().end()),
2467 TII.get(WebAssembly::END_FUNCTION));
2468}
2469
2470// We added block~end_block and try_table~end_try_table markers in
2471// placeTryTableMarker. But When catch clause's destination has a return type,
2472// as in the case of catch with a concrete tag, catch_ref, and catch_all_ref.
2473// For example:
2474// block exnref
2475// try_table (catch_all_ref 0)
2476// ...
2477// end_try_table
2478// end_block
2479// ... use exnref ...
2480//
2481// This code is not valid because the block's body type is not exnref. So we add
2482// an unreachable after the 'end_try_table' to make the code valid here:
2483// block exnref
2484// try_table (catch_all_ref 0)
2485// ...
2486// end_try_table
2487// unreachable (new)
2488// end_block
2489//
2490// Because 'unreachable' is a terminator we also need to split the BB.
2492 const WebAssemblyInstrInfo &TII) {
2493 std::vector<MachineInstr *> EndTryTables;
2494 for (auto &MBB : MF)
2495 for (auto &MI : MBB)
2496 if (MI.getOpcode() == WebAssembly::END_TRY_TABLE)
2497 EndTryTables.push_back(&MI);
2498
2499 for (auto *EndTryTable : EndTryTables) {
2500 auto *MBB = EndTryTable->getParent();
2501 auto *NewEndTryTableBB = MF.CreateMachineBasicBlock();
2502 MF.insert(MBB->getIterator(), NewEndTryTableBB);
2503 auto SplitPos = std::next(EndTryTable->getIterator());
2504 NewEndTryTableBB->splice(NewEndTryTableBB->end(), MBB, MBB->begin(),
2505 SplitPos);
2506 NewEndTryTableBB->addSuccessor(MBB);
2507 BuildMI(NewEndTryTableBB, EndTryTable->getDebugLoc(),
2508 TII.get(WebAssembly::UNREACHABLE));
2509 }
2510}
2511
2512/// Insert BLOCK/LOOP/TRY/TRY_TABLE markers at appropriate places.
2513void WebAssemblyCFGStackifyImpl::placeMarkers(MachineFunction &MF) {
2514 // We allocate one more than the number of blocks in the function to
2515 // accommodate for the possible fake block we may insert at the end.
2516 ScopeTops.resize(MF.getNumBlockIDs() + 1);
2517 // Place the LOOP for MBB if MBB is the header of a loop.
2518 for (auto &MBB : MF)
2519 placeLoopMarker(MBB);
2520
2521 const MCAsmInfo &MCAI = MF.getTarget().getMCAsmInfo();
2522 for (auto &MBB : MF) {
2523 if (MBB.isEHPad()) {
2524 // Place the TRY/TRY_TABLE for MBB if MBB is the EH pad of an exception.
2525 if (MCAI.getExceptionHandlingType() == ExceptionHandling::Wasm &&
2526 MF.getFunction().hasPersonalityFn()) {
2527 if (WebAssembly::WasmUseLegacyEH)
2528 placeTryMarker(MBB);
2529 else
2530 placeTryTableMarker(MBB);
2531 }
2532 } else {
2533 // Place the BLOCK for MBB if MBB is branched to from above.
2534 placeBlockMarker(MBB);
2535 }
2536 }
2537
2538 if (MCAI.getExceptionHandlingType() == ExceptionHandling::Wasm &&
2539 MF.getFunction().hasPersonalityFn()) {
2540 const auto &TII = *MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo();
2541 // Add an 'unreachable' after 'end_try_table's.
2543 // Fix mismatches in unwind destinations induced by linearizing the code.
2544 // Run fixCatchUnwindMismatches() first so that fixCallUnwindMismatches()
2545 // will see and correct any new call/rethrow unwind mismatches introduced by
2546 // fixCatchUnwindMismatches().
2547 fixCatchUnwindMismatches(MF);
2548 fixCallUnwindMismatches(MF);
2549 // addUnreachableAfterTryTables and fixUnwindMismatches create new BBs, so
2550 // we need to recalculate ScopeTops.
2551 recalculateScopeTops(MF);
2552 }
2553}
2554
2555unsigned WebAssemblyCFGStackifyImpl::getBranchDepth(
2556 const SmallVectorImpl<EndMarkerInfo> &Stack, const MachineBasicBlock *MBB) {
2557 unsigned Depth = 0;
2558 for (auto X : reverse(Stack)) {
2559 if (X.first == MBB)
2560 break;
2561 ++Depth;
2562 }
2563 assert(Depth < Stack.size() && "Branch destination should be in scope");
2564 return Depth;
2565}
2566
2567unsigned WebAssemblyCFGStackifyImpl::getDelegateDepth(
2568 const SmallVectorImpl<EndMarkerInfo> &Stack, const MachineBasicBlock *MBB) {
2569 if (MBB == FakeCallerBB)
2570 return Stack.size();
2571 // Delegate's destination is either a catch or a another delegate BB. When the
2572 // destination is another delegate, we can compute the argument in the same
2573 // way as branches, because the target delegate BB only contains the single
2574 // delegate instruction.
2575 if (!MBB->isEHPad()) // Target is a delegate BB
2576 return getBranchDepth(Stack, MBB);
2577
2578 // When the delegate's destination is a catch BB, we need to use its
2579 // corresponding try's end_try BB because Stack contains each marker's end BB.
2580 // Also we need to check if the end marker instruction matches, because a
2581 // single BB can contain multiple end markers, like this:
2582 // bb:
2583 // END_BLOCK
2584 // END_TRY
2585 // END_BLOCK
2586 // END_TRY
2587 // ...
2588 //
2589 // In case of branches getting the immediate that targets any of these is
2590 // fine, but delegate has to exactly target the correct try.
2591 unsigned Depth = 0;
2592 const MachineInstr *EndTry = BeginToEnd[EHPadToTry[MBB]];
2593 for (auto X : reverse(Stack)) {
2594 if (X.first == EndTry->getParent() && X.second == EndTry)
2595 break;
2596 ++Depth;
2597 }
2598 assert(Depth < Stack.size() && "Delegate destination should be in scope");
2599 return Depth;
2600}
2601
2602unsigned WebAssemblyCFGStackifyImpl::getRethrowDepth(
2603 const SmallVectorImpl<EndMarkerInfo> &Stack,
2604 const MachineBasicBlock *EHPadToRethrow) {
2605 unsigned Depth = 0;
2606 for (auto X : reverse(Stack)) {
2607 const MachineInstr *End = X.second;
2608 if (End->getOpcode() == WebAssembly::END_TRY) {
2609 auto *EHPad = TryToEHPad[EndToBegin[End]];
2610 if (EHPadToRethrow == EHPad)
2611 break;
2612 }
2613 ++Depth;
2614 }
2615 assert(Depth < Stack.size() && "Rethrow destination should be in scope");
2616 return Depth;
2617}
2618
2619void WebAssemblyCFGStackifyImpl::rewriteDepthImmediates(MachineFunction &MF) {
2620 // Now rewrite references to basic blocks to be depth immediates.
2622
2623 auto RewriteOperands = [&](MachineInstr &MI) {
2624 // Rewrite MBB operands to be depth immediates.
2626 while (MI.getNumOperands() > 0)
2627 MI.removeOperand(MI.getNumOperands() - 1);
2628 for (auto MO : Ops) {
2629 if (MO.isMBB()) {
2630 if (MI.getOpcode() == WebAssembly::DELEGATE)
2631 MO = MachineOperand::CreateImm(getDelegateDepth(Stack, MO.getMBB()));
2632 else if (MI.getOpcode() == WebAssembly::RETHROW)
2633 MO = MachineOperand::CreateImm(getRethrowDepth(Stack, MO.getMBB()));
2634 else
2635 MO = MachineOperand::CreateImm(getBranchDepth(Stack, MO.getMBB()));
2636 }
2637 MI.addOperand(MF, MO);
2638 }
2639 };
2640
2641 for (auto &MBB : reverse(MF)) {
2642 for (MachineInstr &MI : llvm::reverse(MBB)) {
2643 switch (MI.getOpcode()) {
2644 case WebAssembly::BLOCK:
2645 case WebAssembly::TRY:
2646 assert(ScopeTops[Stack.back().first->getNumber()]->getNumber() <=
2647 MBB.getNumber() &&
2648 "Block/try/try_table marker should be balanced");
2649 Stack.pop_back();
2650 break;
2651
2652 case WebAssembly::TRY_TABLE:
2653 assert(ScopeTops[Stack.back().first->getNumber()]->getNumber() <=
2654 MBB.getNumber() &&
2655 "Block/try/try_table marker should be balanced");
2656 Stack.pop_back();
2657 RewriteOperands(MI);
2658 break;
2659
2660 case WebAssembly::LOOP:
2661 assert(Stack.back().first == &MBB && "Loop top should be balanced");
2662 Stack.pop_back();
2663 break;
2664
2665 case WebAssembly::END_BLOCK:
2666 case WebAssembly::END_TRY:
2667 case WebAssembly::END_TRY_TABLE:
2668 Stack.push_back(std::make_pair(&MBB, &MI));
2669 break;
2670
2671 case WebAssembly::END_LOOP:
2672 Stack.push_back(std::make_pair(EndToBegin[&MI]->getParent(), &MI));
2673 break;
2674
2675 case WebAssembly::DELEGATE:
2676 RewriteOperands(MI);
2677 Stack.push_back(std::make_pair(&MBB, &MI));
2678 break;
2679
2680 default:
2681 if (MI.isTerminator())
2682 RewriteOperands(MI);
2683 break;
2684 }
2685 }
2686 }
2687 assert(Stack.empty() && "Control flow should be balanced");
2688}
2689
2690void WebAssemblyCFGStackifyImpl::cleanupFunctionData(MachineFunction &MF) {
2691 if (FakeCallerBB)
2692 MF.deleteMachineBasicBlock(FakeCallerBB);
2693 AppendixBB = FakeCallerBB = CallerTrampolineBB = nullptr;
2694}
2695
2696bool WebAssemblyCFGStackifyImpl::runOnMachineFunction(MachineFunction &MF) {
2697 LLVM_DEBUG(dbgs() << "********** CFG Stackifying **********\n"
2698 "********** Function: "
2699 << MF.getName() << '\n');
2700 const MCAsmInfo &MCAI = MF.getTarget().getMCAsmInfo();
2701
2702 // Liveness is not tracked for VALUE_STACK physreg.
2704
2705 // Place the BLOCK/LOOP/TRY/TRY_TABLE markers to indicate the beginnings of
2706 // scopes.
2707 placeMarkers(MF);
2708
2709 // Remove unnecessary instructions possibly introduced by try/end_trys.
2710 if (MCAI.getExceptionHandlingType() == ExceptionHandling::Wasm &&
2711 MF.getFunction().hasPersonalityFn() && WebAssembly::WasmUseLegacyEH)
2712 removeUnnecessaryInstrs(MF);
2713
2714 // Convert MBB operands in terminators to relative depth immediates.
2715 rewriteDepthImmediates(MF);
2716
2717 // Fix up block/loop/try/try_table signatures at the end of the function to
2718 // conform to WebAssembly's rules.
2719 fixEndsAtEndOfFunction(MF);
2720
2721 // Add an end instruction at the end of the function body.
2722 const auto &TII = *MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo();
2724
2725 cleanupFunctionData(MF);
2726
2727 MF.getInfo<WebAssemblyFunctionInfo>()->setCFGStackified();
2728 return true;
2729}
2730
2731bool WebAssemblyCFGStackifyLegacy::runOnMachineFunction(MachineFunction &MF) {
2732 MachineDominatorTree &MDT =
2733 getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
2734 MachineLoopInfo &MLI = getAnalysis<MachineLoopInfoWrapperPass>().getLI();
2735 WebAssemblyExceptionInfo &WEI =
2736 getAnalysis<WebAssemblyExceptionInfoWrapperPass>().getWEI();
2737 WebAssemblyCFGStackifyImpl Impl(MDT, MLI, WEI);
2738 return Impl.runOnMachineFunction(MF);
2739}
2740
2741PreservedAnalyses
2748 WebAssemblyCFGStackifyImpl Impl(MDT, MLI, WEI);
2749 return Impl.runOnMachineFunction(MF)
2752}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock & MBB
static const Function * getParent(const Value *V)
#define X(NUM, ENUM, NAME)
Definition ELF.h:856
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define DEBUG_TYPE
const HexagonInstrInfo * TII
#define _
IRTranslator LLVM IR MI
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
#define I(x, y, z)
Definition MD5.cpp:57
Register Reg
This file implements a map that provides insertion order iteration.
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
#define P(N)
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
const SmallVectorImpl< MachineOperand > MachineBasicBlock * TBB
const SmallVectorImpl< MachineOperand > & Cond
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
Definition Statistic.h:171
#define LLVM_DEBUG(...)
Definition Debug.h:119
static std::string getBBName(const MachineBasicBlock *MBB)
static bool explicitlyBranchesTo(MachineBasicBlock *Pred, MachineBasicBlock *MBB)
Test whether Pred has any terminators explicitly branching to MBB, as opposed to falling through.
static void addUnreachableAfterTryTables(MachineFunction &MF, const WebAssemblyInstrInfo &TII)
static MachineBasicBlock::iterator getLatestInsertPos(MachineBasicBlock *MBB, const Container &BeforeSet, const Container &AfterSet)
static void splitEndLoopBB(MachineBasicBlock *EndTryTableBB)
static void appendEndToFunction(MachineFunction &MF, const WebAssemblyInstrInfo &TII)
static void unstackifyVRegsUsedInSplitBB(MachineBasicBlock &MBB, MachineBasicBlock &Split)
static MachineBasicBlock::iterator getEarliestInsertPos(MachineBasicBlock *MBB, const Container &BeforeSet, const Container &AfterSet)
This file implements WebAssemblyException information analysis.
This file declares WebAssembly-specific per-machine-function information.
This file implements regions used in CFGSort and CFGStackify.
This file declares the WebAssembly-specific subclass of TargetSubtarget.
This file declares the WebAssembly-specific subclass of TargetMachine.
This file contains the declaration of the WebAssembly-specific type parsing utility functions.
This file contains the declaration of the WebAssembly-specific utility functions.
This file contains the entry points for global functions defined in the LLVM WebAssembly back-end.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
AnalysisUsage & addRequired()
ValueT lookup(const_arg_type_t< KeyT > Val) const
Return the entry for the specified key, or a default constructed value if no such entry exists.
Definition DenseMap.h:250
iterator find(const_arg_type_t< KeyT > Val)
Definition DenseMap.h:223
bool erase(const KeyT &Val)
Definition DenseMap.h:377
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
Definition DenseMap.h:219
iterator end()
Definition DenseMap.h:141
NodeT * findNearestCommonDominator(NodeT *A, NodeT *B) const
Find nearest common dominator basic block for basic block A and B.
FunctionPass class - This class is used to implement most global optimizations.
Definition Pass.h:314
bool hasPersonalityFn() const
Check whether this function has a personality function.
Definition Function.h:882
bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl< MachineOperand > &Cond, bool AllowModify) const override
Analyze the branching code at the end of MBB, returning true if it cannot be understood (e....
BlockT * getHeader() const
LoopT * getLoopFor(const BlockT *BB) const
Return the inner most loop that BB lives in.
ExceptionHandling getExceptionHandlingType() const
Definition MCAsmInfo.h:656
LLVM_ABI bool hasEHPadSuccessor() const
bool isEHPad() const
Returns true if the block is a landing pad.
int getNumber() const
MachineBasicBlocks are uniquely numbered at the function level, unless they're not in a MachineFuncti...
LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
LLVM_ABI void removeSuccessor(MachineBasicBlock *Succ, bool NormalizeSuccProbs=false)
Remove successor from the successors list of this MachineBasicBlock.
LLVM_ABI bool isPredecessor(const MachineBasicBlock *MBB) const
Return true if the specified MBB is a predecessor of this block.
LLVM_ABI DebugLoc findDebugLoc(instr_iterator MBBI)
Find the next valid DebugLoc starting at MBBI, skipping any debug instructions.
MachineInstrBundleIterator< MachineInstr, true > reverse_iterator
LLVM_ABI DebugLoc findPrevDebugLoc(instr_iterator MBBI)
Find the previous valid DebugLoc preceding MBBI, skipping any debug instructions.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
LLVM_ABI DebugLoc findBranchDebugLoc()
Find and return the merged DebugLoc of the branch instructions of the block.
iterator_range< succ_iterator > successors()
reverse_iterator rbegin()
iterator_range< pred_iterator > predecessors()
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
MachineInstrBundleIterator< MachineInstr > iterator
Analysis pass which computes a MachineDominatorTree.
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
void push_back(MachineBasicBlock *MBB)
reverse_iterator rbegin()
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
void deleteMachineBasicBlock(MachineBasicBlock *MBB)
DeleteMachineBasicBlock - Delete the given MachineBasicBlock.
Function & getFunction()
Return the LLVM function that this machine code represents.
unsigned getNumBlockIDs() const
getNumBlockIDs - Return the number of MBB ID's allocated.
const MachineBasicBlock & back() const
BasicBlockListType::iterator iterator
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
void RenumberBlocks(MachineBasicBlock *MBBFrom=nullptr)
RenumberBlocks - This discards all of the MachineBasicBlock numbers and recomputes them.
const MachineBasicBlock & front() const
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
void insert(iterator MBBI, MachineBasicBlock *MBB)
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
const MachineInstrBuilder & addExternalSymbol(const char *FnName, unsigned TargetFlags=0) const
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & addDef(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register definition operand.
MachineInstr * getInstr() const
If conversion operators fail, use this method to get the MachineInstr explicitly.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const MachineBasicBlock * getParent() const
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
const MachineOperand & getOperand(unsigned i) const
Analysis pass that exposes the MachineLoopInfo for a machine function.
MachineOperand class - Representation of each machine instruction operand.
int64_t getImm() const
static MachineOperand CreateImm(int64_t Val)
void setTargetFlags(unsigned F)
void invalidateLiveness()
invalidateLiveness - Indicates that register liveness is no longer being tracked accurately.
bool empty() const
Definition MapVector.h:79
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition Analysis.h:118
Wrapper class representing virtual and physical registers.
Definition Register.h:20
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
void resize(size_type N)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
const MCAsmInfo & getMCAsmInfo() const
Return target specific asm information.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
LLVM_ABI std::string str() const
Return the twine contents as a std::string.
Definition Twine.cpp:17
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
WebAssemblyException * getExceptionFor(const MachineBasicBlock *MBB) const
This class is derived from MachineFunctionInfo and contains private WebAssembly-specific information ...
self_iterator getIterator()
Definition ilist_node.h:123
Pass manager infrastructure for declaring and invalidating analyses.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned getCopyOpcodeForRegClass(const TargetRegisterClass *RC)
Returns the appropriate copy opcode for the given register class.
NodeAddr< UseNode * > Use
Definition RDFGraph.h:385
@ WASM_OPCODE_CATCH_ALL_REF
Definition Wasm.h:163
@ WASM_OPCODE_CATCH
Definition Wasm.h:160
@ WASM_OPCODE_CATCH_ALL
Definition Wasm.h:162
@ WASM_OPCODE_CATCH_REF
Definition Wasm.h:161
This is an optimization pass for GlobalISel generic memory operations.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
Definition STLExtras.h:633
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
LLVM_ABI PreservedAnalyses getMachineFunctionPassPreservedAnalyses()
Returns the minimum set of Analyses that all machine function passes must preserve.
auto reverse(ContainerTy &&C)
Definition STLExtras.h:407
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
FunctionPass * createWebAssemblyCFGStackifyLegacyPass()
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Next
Definition InstrProf.h:147