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