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