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