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