1 //===-- WebAssemblyCFGStackify.cpp - CFG Stackification -------------------===//
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
7 //===----------------------------------------------------------------------===//
10 /// This file implements a CFG stacking pass.
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
16 /// This is sufficient to convert arbitrary CFGs into a form that works on
17 /// WebAssembly, provided that all loops are single-entry.
19 /// In case we use exceptions, this pass also fixes mismatches in unwind
20 /// destinations created during transforming CFG into wasm structured format.
22 //===----------------------------------------------------------------------===//
24 #include "Utils/WebAssemblyTypeUtilities.h"
25 #include "WebAssembly.h"
26 #include "WebAssemblyExceptionInfo.h"
27 #include "WebAssemblyMachineFunctionInfo.h"
28 #include "WebAssemblySortRegion.h"
29 #include "WebAssemblySubtarget.h"
30 #include "WebAssemblyUtilities.h"
31 #include "llvm/ADT/Statistic.h"
32 #include "llvm/CodeGen/MachineDominators.h"
33 #include "llvm/CodeGen/MachineInstrBuilder.h"
34 #include "llvm/CodeGen/MachineLoopInfo.h"
35 #include "llvm/CodeGen/WasmEHFuncInfo.h"
36 #include "llvm/MC/MCAsmInfo.h"
37 #include "llvm/Target/TargetMachine.h"
39 using WebAssembly::SortRegionInfo
;
41 #define DEBUG_TYPE "wasm-cfg-stackify"
43 STATISTIC(NumCallUnwindMismatches
, "Number of call unwind mismatches found");
44 STATISTIC(NumCatchUnwindMismatches
, "Number of catch unwind mismatches found");
47 class WebAssemblyCFGStackify final
: public MachineFunctionPass
{
48 StringRef
getPassName() const override
{ return "WebAssembly CFG Stackify"; }
50 void getAnalysisUsage(AnalysisUsage
&AU
) const override
{
51 AU
.addRequired
<MachineDominatorTree
>();
52 AU
.addRequired
<MachineLoopInfo
>();
53 AU
.addRequired
<WebAssemblyExceptionInfo
>();
54 MachineFunctionPass::getAnalysisUsage(AU
);
57 bool runOnMachineFunction(MachineFunction
&MF
) override
;
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.
62 SmallVector
<MachineBasicBlock
*, 8> ScopeTops
;
63 void updateScopeTops(MachineBasicBlock
*Begin
, MachineBasicBlock
*End
) {
64 int EndNo
= End
->getNumber();
65 if (!ScopeTops
[EndNo
] || ScopeTops
[EndNo
]->getNumber() > Begin
->getNumber())
66 ScopeTops
[EndNo
] = Begin
;
70 void placeMarkers(MachineFunction
&MF
);
71 void placeBlockMarker(MachineBasicBlock
&MBB
);
72 void placeLoopMarker(MachineBasicBlock
&MBB
);
73 void placeTryMarker(MachineBasicBlock
&MBB
);
75 // Exception handling related functions
76 bool fixCallUnwindMismatches(MachineFunction
&MF
);
77 bool fixCatchUnwindMismatches(MachineFunction
&MF
);
78 void addTryDelegate(MachineInstr
*RangeBegin
, MachineInstr
*RangeEnd
,
79 MachineBasicBlock
*DelegateDest
);
80 void recalculateScopeTops(MachineFunction
&MF
);
81 void removeUnnecessaryInstrs(MachineFunction
&MF
);
85 std::pair
<const MachineBasicBlock
*, const MachineInstr
*>;
86 unsigned getBranchDepth(const SmallVectorImpl
<EndMarkerInfo
> &Stack
,
87 const MachineBasicBlock
*MBB
);
88 unsigned getDelegateDepth(const SmallVectorImpl
<EndMarkerInfo
> &Stack
,
89 const MachineBasicBlock
*MBB
);
91 getRethrowDepth(const SmallVectorImpl
<EndMarkerInfo
> &Stack
,
92 const SmallVectorImpl
<const MachineBasicBlock
*> &EHPadStack
);
93 void rewriteDepthImmediates(MachineFunction
&MF
);
94 void fixEndsAtEndOfFunction(MachineFunction
&MF
);
95 void cleanupFunctionData(MachineFunction
&MF
);
97 // For each BLOCK|LOOP|TRY, the corresponding END_(BLOCK|LOOP|TRY) or DELEGATE
99 DenseMap
<const MachineInstr
*, MachineInstr
*> BeginToEnd
;
100 // For each END_(BLOCK|LOOP|TRY) or DELEGATE, the corresponding
102 DenseMap
<const MachineInstr
*, MachineInstr
*> EndToBegin
;
103 // <TRY marker, EH pad> map
104 DenseMap
<const MachineInstr
*, MachineBasicBlock
*> TryToEHPad
;
105 // <EH pad, TRY marker> map
106 DenseMap
<const MachineBasicBlock
*, MachineInstr
*> EHPadToTry
;
108 // We need an appendix block to place 'end_loop' or 'end_try' marker when the
109 // loop / exception bottom block is the last block in a function
110 MachineBasicBlock
*AppendixBB
= nullptr;
111 MachineBasicBlock
*getAppendixBlock(MachineFunction
&MF
) {
113 AppendixBB
= MF
.CreateMachineBasicBlock();
114 // Give it a fake predecessor so that AsmPrinter prints its label.
115 AppendixBB
->addSuccessor(AppendixBB
);
116 MF
.push_back(AppendixBB
);
121 // Before running rewriteDepthImmediates function, 'delegate' has a BB as its
122 // destination operand. getFakeCallerBlock() returns a fake BB that will be
123 // used for the operand when 'delegate' needs to rethrow to the caller. This
124 // will be rewritten as an immediate value that is the number of block depths
125 // + 1 in rewriteDepthImmediates, and this fake BB will be removed at the end
127 MachineBasicBlock
*FakeCallerBB
= nullptr;
128 MachineBasicBlock
*getFakeCallerBlock(MachineFunction
&MF
) {
130 FakeCallerBB
= MF
.CreateMachineBasicBlock();
134 // Helper functions to register / unregister scope information created by
135 // marker instructions.
136 void registerScope(MachineInstr
*Begin
, MachineInstr
*End
);
137 void registerTryScope(MachineInstr
*Begin
, MachineInstr
*End
,
138 MachineBasicBlock
*EHPad
);
139 void unregisterScope(MachineInstr
*Begin
);
142 static char ID
; // Pass identification, replacement for typeid
143 WebAssemblyCFGStackify() : MachineFunctionPass(ID
) {}
144 ~WebAssemblyCFGStackify() override
{ releaseMemory(); }
145 void releaseMemory() override
;
147 } // end anonymous namespace
149 char WebAssemblyCFGStackify::ID
= 0;
150 INITIALIZE_PASS(WebAssemblyCFGStackify
, DEBUG_TYPE
,
151 "Insert BLOCK/LOOP/TRY markers for WebAssembly scopes", false,
154 FunctionPass
*llvm::createWebAssemblyCFGStackify() {
155 return new WebAssemblyCFGStackify();
158 /// Test whether Pred has any terminators explicitly branching to MBB, as
159 /// opposed to falling through. Note that it's possible (eg. in unoptimized
160 /// code) for a branch instruction to both branch to a block and fallthrough
161 /// to it, so we check the actual branch operands to see if there are any
162 /// explicit mentions.
163 static bool explicitlyBranchesTo(MachineBasicBlock
*Pred
,
164 MachineBasicBlock
*MBB
) {
165 for (MachineInstr
&MI
: Pred
->terminators())
166 for (MachineOperand
&MO
: MI
.explicit_operands())
167 if (MO
.isMBB() && MO
.getMBB() == MBB
)
172 // Returns an iterator to the earliest position possible within the MBB,
173 // satisfying the restrictions given by BeforeSet and AfterSet. BeforeSet
174 // contains instructions that should go before the marker, and AfterSet contains
175 // ones that should go after the marker. In this function, AfterSet is only
176 // used for validation checking.
177 template <typename Container
>
178 static MachineBasicBlock::iterator
179 getEarliestInsertPos(MachineBasicBlock
*MBB
, const Container
&BeforeSet
,
180 const Container
&AfterSet
) {
181 auto InsertPos
= MBB
->end();
182 while (InsertPos
!= MBB
->begin()) {
183 if (BeforeSet
.count(&*std::prev(InsertPos
))) {
186 for (auto Pos
= InsertPos
, E
= MBB
->begin(); Pos
!= E
; --Pos
)
187 assert(!AfterSet
.count(&*std::prev(Pos
)));
196 // Returns an iterator to the latest position possible within the MBB,
197 // satisfying the restrictions given by BeforeSet and AfterSet. BeforeSet
198 // contains instructions that should go before the marker, and AfterSet contains
199 // ones that should go after the marker. In this function, BeforeSet is only
200 // used for validation checking.
201 template <typename Container
>
202 static MachineBasicBlock::iterator
203 getLatestInsertPos(MachineBasicBlock
*MBB
, const Container
&BeforeSet
,
204 const Container
&AfterSet
) {
205 auto InsertPos
= MBB
->begin();
206 while (InsertPos
!= MBB
->end()) {
207 if (AfterSet
.count(&*InsertPos
)) {
210 for (auto Pos
= InsertPos
, E
= MBB
->end(); Pos
!= E
; ++Pos
)
211 assert(!BeforeSet
.count(&*Pos
));
220 void WebAssemblyCFGStackify::registerScope(MachineInstr
*Begin
,
222 BeginToEnd
[Begin
] = End
;
223 EndToBegin
[End
] = Begin
;
226 // When 'End' is not an 'end_try' but 'delegate, EHPad is nullptr.
227 void WebAssemblyCFGStackify::registerTryScope(MachineInstr
*Begin
,
229 MachineBasicBlock
*EHPad
) {
230 registerScope(Begin
, End
);
231 TryToEHPad
[Begin
] = EHPad
;
232 EHPadToTry
[EHPad
] = Begin
;
235 void WebAssemblyCFGStackify::unregisterScope(MachineInstr
*Begin
) {
236 assert(BeginToEnd
.count(Begin
));
237 MachineInstr
*End
= BeginToEnd
[Begin
];
238 assert(EndToBegin
.count(End
));
239 BeginToEnd
.erase(Begin
);
240 EndToBegin
.erase(End
);
241 MachineBasicBlock
*EHPad
= TryToEHPad
.lookup(Begin
);
243 assert(EHPadToTry
.count(EHPad
));
244 TryToEHPad
.erase(Begin
);
245 EHPadToTry
.erase(EHPad
);
249 /// Insert a BLOCK marker for branches to MBB (if needed).
250 // TODO Consider a more generalized way of handling block (and also loop and
251 // try) signatures when we implement the multi-value proposal later.
252 void WebAssemblyCFGStackify::placeBlockMarker(MachineBasicBlock
&MBB
) {
253 assert(!MBB
.isEHPad());
254 MachineFunction
&MF
= *MBB
.getParent();
255 auto &MDT
= getAnalysis
<MachineDominatorTree
>();
256 const auto &TII
= *MF
.getSubtarget
<WebAssemblySubtarget
>().getInstrInfo();
257 const auto &MFI
= *MF
.getInfo
<WebAssemblyFunctionInfo
>();
259 // First compute the nearest common dominator of all forward non-fallthrough
260 // predecessors so that we minimize the time that the BLOCK is on the stack,
261 // which reduces overall stack height.
262 MachineBasicBlock
*Header
= nullptr;
263 bool IsBranchedTo
= false;
264 int MBBNumber
= MBB
.getNumber();
265 for (MachineBasicBlock
*Pred
: MBB
.predecessors()) {
266 if (Pred
->getNumber() < MBBNumber
) {
267 Header
= Header
? MDT
.findNearestCommonDominator(Header
, Pred
) : Pred
;
268 if (explicitlyBranchesTo(Pred
, &MBB
))
277 assert(&MBB
!= &MF
.front() && "Header blocks shouldn't have predecessors");
278 MachineBasicBlock
*LayoutPred
= MBB
.getPrevNode();
280 // If the nearest common dominator is inside a more deeply nested context,
281 // walk out to the nearest scope which isn't more deeply nested.
282 for (MachineFunction::iterator
I(LayoutPred
), E(Header
); I
!= E
; --I
) {
283 if (MachineBasicBlock
*ScopeTop
= ScopeTops
[I
->getNumber()]) {
284 if (ScopeTop
->getNumber() > Header
->getNumber()) {
285 // Skip over an intervening scope.
286 I
= std::next(ScopeTop
->getIterator());
288 // We found a scope level at an appropriate depth.
295 // Decide where in Header to put the BLOCK.
297 // Instructions that should go before the BLOCK.
298 SmallPtrSet
<const MachineInstr
*, 4> BeforeSet
;
299 // Instructions that should go after the BLOCK.
300 SmallPtrSet
<const MachineInstr
*, 4> AfterSet
;
301 for (const auto &MI
: *Header
) {
302 // If there is a previously placed LOOP marker and the bottom block of the
303 // loop is above MBB, it should be after the BLOCK, because the loop is
304 // nested in this BLOCK. Otherwise it should be before the BLOCK.
305 if (MI
.getOpcode() == WebAssembly::LOOP
) {
306 auto *LoopBottom
= BeginToEnd
[&MI
]->getParent()->getPrevNode();
307 if (MBB
.getNumber() > LoopBottom
->getNumber())
308 AfterSet
.insert(&MI
);
311 BeforeSet
.insert(&MI
);
315 // If there is a previously placed BLOCK/TRY marker and its corresponding
316 // END marker is before the current BLOCK's END marker, that should be
317 // placed after this BLOCK. Otherwise it should be placed before this BLOCK
319 if (MI
.getOpcode() == WebAssembly::BLOCK
||
320 MI
.getOpcode() == WebAssembly::TRY
) {
321 if (BeginToEnd
[&MI
]->getParent()->getNumber() <= MBB
.getNumber())
322 AfterSet
.insert(&MI
);
325 BeforeSet
.insert(&MI
);
330 // All END_(BLOCK|LOOP|TRY) markers should be before the BLOCK.
331 if (MI
.getOpcode() == WebAssembly::END_BLOCK
||
332 MI
.getOpcode() == WebAssembly::END_LOOP
||
333 MI
.getOpcode() == WebAssembly::END_TRY
)
334 BeforeSet
.insert(&MI
);
337 // Terminators should go after the BLOCK.
338 if (MI
.isTerminator())
339 AfterSet
.insert(&MI
);
342 // Local expression tree should go after the BLOCK.
343 for (auto I
= Header
->getFirstTerminator(), E
= Header
->begin(); I
!= E
;
345 if (std::prev(I
)->isDebugInstr() || std::prev(I
)->isPosition())
347 if (WebAssembly::isChild(*std::prev(I
), MFI
))
348 AfterSet
.insert(&*std::prev(I
));
354 WebAssembly::BlockType ReturnType
= WebAssembly::BlockType::Void
;
355 auto InsertPos
= getLatestInsertPos(Header
, BeforeSet
, AfterSet
);
356 MachineInstr
*Begin
=
357 BuildMI(*Header
, InsertPos
, Header
->findDebugLoc(InsertPos
),
358 TII
.get(WebAssembly::BLOCK
))
359 .addImm(int64_t(ReturnType
));
361 // Decide where in Header to put the END_BLOCK.
364 for (auto &MI
: MBB
) {
366 // END_BLOCK should precede existing LOOP and TRY markers.
367 if (MI
.getOpcode() == WebAssembly::LOOP
||
368 MI
.getOpcode() == WebAssembly::TRY
)
369 AfterSet
.insert(&MI
);
372 // If there is a previously placed END_LOOP marker and the header of the
373 // loop is above this block's header, the END_LOOP should be placed after
374 // the BLOCK, because the loop contains this block. Otherwise the END_LOOP
375 // should be placed before the BLOCK. The same for END_TRY.
376 if (MI
.getOpcode() == WebAssembly::END_LOOP
||
377 MI
.getOpcode() == WebAssembly::END_TRY
) {
378 if (EndToBegin
[&MI
]->getParent()->getNumber() >= Header
->getNumber())
379 BeforeSet
.insert(&MI
);
382 AfterSet
.insert(&MI
);
387 // Mark the end of the block.
388 InsertPos
= getEarliestInsertPos(&MBB
, BeforeSet
, AfterSet
);
389 MachineInstr
*End
= BuildMI(MBB
, InsertPos
, MBB
.findPrevDebugLoc(InsertPos
),
390 TII
.get(WebAssembly::END_BLOCK
));
391 registerScope(Begin
, End
);
393 // Track the farthest-spanning scope that ends at this point.
394 updateScopeTops(Header
, &MBB
);
397 /// Insert a LOOP marker for a loop starting at MBB (if it's a loop header).
398 void WebAssemblyCFGStackify::placeLoopMarker(MachineBasicBlock
&MBB
) {
399 MachineFunction
&MF
= *MBB
.getParent();
400 const auto &MLI
= getAnalysis
<MachineLoopInfo
>();
401 const auto &WEI
= getAnalysis
<WebAssemblyExceptionInfo
>();
402 SortRegionInfo
SRI(MLI
, WEI
);
403 const auto &TII
= *MF
.getSubtarget
<WebAssemblySubtarget
>().getInstrInfo();
405 MachineLoop
*Loop
= MLI
.getLoopFor(&MBB
);
406 if (!Loop
|| Loop
->getHeader() != &MBB
)
409 // The operand of a LOOP is the first block after the loop. If the loop is the
410 // bottom of the function, insert a dummy block at the end.
411 MachineBasicBlock
*Bottom
= SRI
.getBottom(Loop
);
412 auto Iter
= std::next(Bottom
->getIterator());
413 if (Iter
== MF
.end()) {
414 getAppendixBlock(MF
);
415 Iter
= std::next(Bottom
->getIterator());
417 MachineBasicBlock
*AfterLoop
= &*Iter
;
419 // Decide where in Header to put the LOOP.
420 SmallPtrSet
<const MachineInstr
*, 4> BeforeSet
;
421 SmallPtrSet
<const MachineInstr
*, 4> AfterSet
;
422 for (const auto &MI
: MBB
) {
423 // LOOP marker should be after any existing loop that ends here. Otherwise
424 // we assume the instruction belongs to the loop.
425 if (MI
.getOpcode() == WebAssembly::END_LOOP
)
426 BeforeSet
.insert(&MI
);
429 AfterSet
.insert(&MI
);
433 // Mark the beginning of the loop.
434 auto InsertPos
= getEarliestInsertPos(&MBB
, BeforeSet
, AfterSet
);
435 MachineInstr
*Begin
= BuildMI(MBB
, InsertPos
, MBB
.findDebugLoc(InsertPos
),
436 TII
.get(WebAssembly::LOOP
))
437 .addImm(int64_t(WebAssembly::BlockType::Void
));
439 // Decide where in Header to put the END_LOOP.
443 for (const auto &MI
: MBB
)
444 // Existing END_LOOP markers belong to parent loops of this loop
445 if (MI
.getOpcode() == WebAssembly::END_LOOP
)
446 AfterSet
.insert(&MI
);
449 // Mark the end of the loop (using arbitrary debug location that branched to
450 // the loop end as its location).
451 InsertPos
= getEarliestInsertPos(AfterLoop
, BeforeSet
, AfterSet
);
452 DebugLoc EndDL
= AfterLoop
->pred_empty()
454 : (*AfterLoop
->pred_rbegin())->findBranchDebugLoc();
456 BuildMI(*AfterLoop
, InsertPos
, EndDL
, TII
.get(WebAssembly::END_LOOP
));
457 registerScope(Begin
, End
);
459 assert((!ScopeTops
[AfterLoop
->getNumber()] ||
460 ScopeTops
[AfterLoop
->getNumber()]->getNumber() < MBB
.getNumber()) &&
461 "With block sorting the outermost loop for a block should be first.");
462 updateScopeTops(&MBB
, AfterLoop
);
465 void WebAssemblyCFGStackify::placeTryMarker(MachineBasicBlock
&MBB
) {
466 assert(MBB
.isEHPad());
467 MachineFunction
&MF
= *MBB
.getParent();
468 auto &MDT
= getAnalysis
<MachineDominatorTree
>();
469 const auto &TII
= *MF
.getSubtarget
<WebAssemblySubtarget
>().getInstrInfo();
470 const auto &MLI
= getAnalysis
<MachineLoopInfo
>();
471 const auto &WEI
= getAnalysis
<WebAssemblyExceptionInfo
>();
472 SortRegionInfo
SRI(MLI
, WEI
);
473 const auto &MFI
= *MF
.getInfo
<WebAssemblyFunctionInfo
>();
475 // Compute the nearest common dominator of all unwind predecessors
476 MachineBasicBlock
*Header
= nullptr;
477 int MBBNumber
= MBB
.getNumber();
478 for (auto *Pred
: MBB
.predecessors()) {
479 if (Pred
->getNumber() < MBBNumber
) {
480 Header
= Header
? MDT
.findNearestCommonDominator(Header
, Pred
) : Pred
;
481 assert(!explicitlyBranchesTo(Pred
, &MBB
) &&
482 "Explicit branch to an EH pad!");
488 // If this try is at the bottom of the function, insert a dummy block at the
490 WebAssemblyException
*WE
= WEI
.getExceptionFor(&MBB
);
492 MachineBasicBlock
*Bottom
= SRI
.getBottom(WE
);
494 auto Iter
= std::next(Bottom
->getIterator());
495 if (Iter
== MF
.end()) {
496 getAppendixBlock(MF
);
497 Iter
= std::next(Bottom
->getIterator());
499 MachineBasicBlock
*Cont
= &*Iter
;
501 assert(Cont
!= &MF
.front());
502 MachineBasicBlock
*LayoutPred
= Cont
->getPrevNode();
504 // If the nearest common dominator is inside a more deeply nested context,
505 // walk out to the nearest scope which isn't more deeply nested.
506 for (MachineFunction::iterator
I(LayoutPred
), E(Header
); I
!= E
; --I
) {
507 if (MachineBasicBlock
*ScopeTop
= ScopeTops
[I
->getNumber()]) {
508 if (ScopeTop
->getNumber() > Header
->getNumber()) {
509 // Skip over an intervening scope.
510 I
= std::next(ScopeTop
->getIterator());
512 // We found a scope level at an appropriate depth.
519 // Decide where in Header to put the TRY.
521 // Instructions that should go before the TRY.
522 SmallPtrSet
<const MachineInstr
*, 4> BeforeSet
;
523 // Instructions that should go after the TRY.
524 SmallPtrSet
<const MachineInstr
*, 4> AfterSet
;
525 for (const auto &MI
: *Header
) {
526 // If there is a previously placed LOOP marker and the bottom block of the
527 // loop is above MBB, it should be after the TRY, because the loop is nested
528 // in this TRY. Otherwise it should be before the TRY.
529 if (MI
.getOpcode() == WebAssembly::LOOP
) {
530 auto *LoopBottom
= BeginToEnd
[&MI
]->getParent()->getPrevNode();
531 if (MBB
.getNumber() > LoopBottom
->getNumber())
532 AfterSet
.insert(&MI
);
535 BeforeSet
.insert(&MI
);
539 // All previously inserted BLOCK/TRY markers should be after the TRY because
540 // they are all nested trys.
541 if (MI
.getOpcode() == WebAssembly::BLOCK
||
542 MI
.getOpcode() == WebAssembly::TRY
)
543 AfterSet
.insert(&MI
);
546 // All END_(BLOCK/LOOP/TRY) markers should be before the TRY.
547 if (MI
.getOpcode() == WebAssembly::END_BLOCK
||
548 MI
.getOpcode() == WebAssembly::END_LOOP
||
549 MI
.getOpcode() == WebAssembly::END_TRY
)
550 BeforeSet
.insert(&MI
);
553 // Terminators should go after the TRY.
554 if (MI
.isTerminator())
555 AfterSet
.insert(&MI
);
558 // If Header unwinds to MBB (= Header contains 'invoke'), the try block should
559 // contain the call within it. So the call should go after the TRY. The
560 // exception is when the header's terminator is a rethrow instruction, in
561 // which case that instruction, not a call instruction before it, is gonna
563 MachineInstr
*ThrowingCall
= nullptr;
564 if (MBB
.isPredecessor(Header
)) {
565 auto TermPos
= Header
->getFirstTerminator();
566 if (TermPos
== Header
->end() ||
567 TermPos
->getOpcode() != WebAssembly::RETHROW
) {
568 for (auto &MI
: reverse(*Header
)) {
570 AfterSet
.insert(&MI
);
572 // Possibly throwing calls are usually wrapped by EH_LABEL
573 // instructions. We don't want to split them and the call.
574 if (MI
.getIterator() != Header
->begin() &&
575 std::prev(MI
.getIterator())->isEHLabel()) {
576 AfterSet
.insert(&*std::prev(MI
.getIterator()));
577 ThrowingCall
= &*std::prev(MI
.getIterator());
585 // Local expression tree should go after the TRY.
586 // For BLOCK placement, we start the search from the previous instruction of a
587 // BB's terminator, but in TRY's case, we should start from the previous
588 // instruction of a call that can throw, or a EH_LABEL that precedes the call,
589 // because the return values of the call's previous instructions can be
590 // stackified and consumed by the throwing call.
591 auto SearchStartPt
= ThrowingCall
? MachineBasicBlock::iterator(ThrowingCall
)
592 : Header
->getFirstTerminator();
593 for (auto I
= SearchStartPt
, E
= Header
->begin(); I
!= E
; --I
) {
594 if (std::prev(I
)->isDebugInstr() || std::prev(I
)->isPosition())
596 if (WebAssembly::isChild(*std::prev(I
), MFI
))
597 AfterSet
.insert(&*std::prev(I
));
603 auto InsertPos
= getLatestInsertPos(Header
, BeforeSet
, AfterSet
);
604 MachineInstr
*Begin
=
605 BuildMI(*Header
, InsertPos
, Header
->findDebugLoc(InsertPos
),
606 TII
.get(WebAssembly::TRY
))
607 .addImm(int64_t(WebAssembly::BlockType::Void
));
609 // Decide where in Header to put the END_TRY.
612 for (const auto &MI
: *Cont
) {
614 // END_TRY should precede existing LOOP and BLOCK markers.
615 if (MI
.getOpcode() == WebAssembly::LOOP
||
616 MI
.getOpcode() == WebAssembly::BLOCK
)
617 AfterSet
.insert(&MI
);
619 // All END_TRY markers placed earlier belong to exceptions that contains
621 if (MI
.getOpcode() == WebAssembly::END_TRY
)
622 AfterSet
.insert(&MI
);
625 // If there is a previously placed END_LOOP marker and its header is after
626 // where TRY marker is, this loop is contained within the 'catch' part, so
627 // the END_TRY marker should go after that. Otherwise, the whole try-catch
628 // is contained within this loop, so the END_TRY should go before that.
629 if (MI
.getOpcode() == WebAssembly::END_LOOP
) {
630 // For a LOOP to be after TRY, LOOP's BB should be after TRY's BB; if they
631 // are in the same BB, LOOP is always before TRY.
632 if (EndToBegin
[&MI
]->getParent()->getNumber() > Header
->getNumber())
633 BeforeSet
.insert(&MI
);
636 AfterSet
.insert(&MI
);
640 // It is not possible for an END_BLOCK to be already in this block.
643 // Mark the end of the TRY.
644 InsertPos
= getEarliestInsertPos(Cont
, BeforeSet
, AfterSet
);
646 BuildMI(*Cont
, InsertPos
, Bottom
->findBranchDebugLoc(),
647 TII
.get(WebAssembly::END_TRY
));
648 registerTryScope(Begin
, End
, &MBB
);
650 // Track the farthest-spanning scope that ends at this point. We create two
651 // mappings: (BB with 'end_try' -> BB with 'try') and (BB with 'catch' -> BB
652 // with 'try'). We need to create 'catch' -> 'try' mapping here too because
653 // markers should not span across 'catch'. For example, this should not
661 for (auto *End
: {&MBB
, Cont
})
662 updateScopeTops(Header
, End
);
665 void WebAssemblyCFGStackify::removeUnnecessaryInstrs(MachineFunction
&MF
) {
666 const auto &TII
= *MF
.getSubtarget
<WebAssemblySubtarget
>().getInstrInfo();
668 // When there is an unconditional branch right before a catch instruction and
669 // it branches to the end of end_try marker, we don't need the branch, because
670 // if there is no exception, the control flow transfers to that point anyway.
674 // br bb2 <- Not necessary
678 // bb2: <- Continuation BB
681 // A more involved case: When the BB where 'end' is located is an another EH
682 // pad, the Cont (= continuation) BB is that EH pad's 'end' BB. For example,
687 // br bb3 <- Not necessary
694 // bb3: <- Continuation BB
697 // When the EH pad at hand is bb1, its matching end_try is in bb2. But it is
698 // another EH pad, so bb0's continuation BB becomes bb3. So 'br bb3' in the
699 // code can be deleted. This is why we run 'while' until 'Cont' is not an EH
701 for (auto &MBB
: MF
) {
705 MachineBasicBlock
*TBB
= nullptr, *FBB
= nullptr;
706 SmallVector
<MachineOperand
, 4> Cond
;
707 MachineBasicBlock
*EHPadLayoutPred
= MBB
.getPrevNode();
709 MachineBasicBlock
*Cont
= &MBB
;
710 while (Cont
->isEHPad()) {
711 MachineInstr
*Try
= EHPadToTry
[Cont
];
712 MachineInstr
*EndTry
= BeginToEnd
[Try
];
713 // We started from an EH pad, so the end marker cannot be a delegate
714 assert(EndTry
->getOpcode() != WebAssembly::DELEGATE
);
715 Cont
= EndTry
->getParent();
718 bool Analyzable
= !TII
.analyzeBranch(*EHPadLayoutPred
, TBB
, FBB
, Cond
);
719 // This condition means either
720 // 1. This BB ends with a single unconditional branch whose destinaion is
722 // 2. This BB ends with a conditional branch followed by an unconditional
723 // branch, and the unconditional branch's destination is Cont.
724 // In both cases, we want to remove the last (= unconditional) branch.
725 if (Analyzable
&& ((Cond
.empty() && TBB
&& TBB
== Cont
) ||
726 (!Cond
.empty() && FBB
&& FBB
== Cont
))) {
727 bool ErasedUncondBr
= false;
728 (void)ErasedUncondBr
;
729 for (auto I
= EHPadLayoutPred
->end(), E
= EHPadLayoutPred
->begin();
731 auto PrevI
= std::prev(I
);
732 if (PrevI
->isTerminator()) {
733 assert(PrevI
->getOpcode() == WebAssembly::BR
);
734 PrevI
->eraseFromParent();
735 ErasedUncondBr
= true;
739 assert(ErasedUncondBr
&& "Unconditional branch not erased!");
743 // When there are block / end_block markers that overlap with try / end_try
744 // markers, and the block and try markers' return types are the same, the
745 // block /end_block markers are not necessary, because try / end_try markers
746 // also can serve as boundaries for branches.
747 // block <- Not necessary
753 // end <- Not necessary
754 SmallVector
<MachineInstr
*, 32> ToDelete
;
755 for (auto &MBB
: MF
) {
756 for (auto &MI
: MBB
) {
757 if (MI
.getOpcode() != WebAssembly::TRY
)
759 MachineInstr
*Try
= &MI
, *EndTry
= BeginToEnd
[Try
];
760 if (EndTry
->getOpcode() == WebAssembly::DELEGATE
)
763 MachineBasicBlock
*TryBB
= Try
->getParent();
764 MachineBasicBlock
*Cont
= EndTry
->getParent();
765 int64_t RetType
= Try
->getOperand(0).getImm();
766 for (auto B
= Try
->getIterator(), E
= std::next(EndTry
->getIterator());
767 B
!= TryBB
->begin() && E
!= Cont
->end() &&
768 std::prev(B
)->getOpcode() == WebAssembly::BLOCK
&&
769 E
->getOpcode() == WebAssembly::END_BLOCK
&&
770 std::prev(B
)->getOperand(0).getImm() == RetType
;
772 ToDelete
.push_back(&*std::prev(B
));
773 ToDelete
.push_back(&*E
);
777 for (auto *MI
: ToDelete
) {
778 if (MI
->getOpcode() == WebAssembly::BLOCK
)
780 MI
->eraseFromParent();
784 // When MBB is split into MBB and Split, we should unstackify defs in MBB that
785 // have their uses in Split.
786 static void unstackifyVRegsUsedInSplitBB(MachineBasicBlock
&MBB
,
787 MachineBasicBlock
&Split
) {
788 MachineFunction
&MF
= *MBB
.getParent();
789 const auto &TII
= *MF
.getSubtarget
<WebAssemblySubtarget
>().getInstrInfo();
790 auto &MFI
= *MF
.getInfo
<WebAssemblyFunctionInfo
>();
791 auto &MRI
= MF
.getRegInfo();
793 for (auto &MI
: Split
) {
794 for (auto &MO
: MI
.explicit_uses()) {
795 if (!MO
.isReg() || MO
.getReg().isPhysical())
797 if (MachineInstr
*Def
= MRI
.getUniqueVRegDef(MO
.getReg()))
798 if (Def
->getParent() == &MBB
)
799 MFI
.unstackifyVReg(MO
.getReg());
803 // In RegStackify, when a register definition is used multiple times,
805 // INST ..., Reg, ...
806 // INST ..., Reg, ...
807 // INST ..., Reg, ...
809 // we introduce a TEE, which has the following form:
811 // TeeReg, Reg = TEE_... DefReg
812 // INST ..., TeeReg, ...
813 // INST ..., Reg, ...
814 // INST ..., Reg, ...
815 // with DefReg and TeeReg stackified but Reg not stackified.
817 // But the invariant that TeeReg should be stackified can be violated while we
818 // unstackify registers in the split BB above. In this case, we convert TEEs
819 // into two COPYs. This COPY will be eventually eliminated in ExplicitLocals.
821 // TeeReg = COPY DefReg
823 // INST ..., TeeReg, ...
824 // INST ..., Reg, ...
825 // INST ..., Reg, ...
826 for (MachineInstr
&MI
: llvm::make_early_inc_range(MBB
)) {
827 if (!WebAssembly::isTee(MI
.getOpcode()))
829 Register TeeReg
= MI
.getOperand(0).getReg();
830 Register Reg
= MI
.getOperand(1).getReg();
831 Register DefReg
= MI
.getOperand(2).getReg();
832 if (!MFI
.isVRegStackified(TeeReg
)) {
833 // Now we are not using TEE anymore, so unstackify DefReg too
834 MFI
.unstackifyVReg(DefReg
);
836 WebAssembly::getCopyOpcodeForRegClass(MRI
.getRegClass(DefReg
));
837 BuildMI(MBB
, &MI
, MI
.getDebugLoc(), TII
.get(CopyOpc
), TeeReg
)
839 BuildMI(MBB
, &MI
, MI
.getDebugLoc(), TII
.get(CopyOpc
), Reg
).addReg(DefReg
);
840 MI
.eraseFromParent();
845 // Wrap the given range of instruction with try-delegate. RangeBegin and
846 // RangeEnd are inclusive.
847 void WebAssemblyCFGStackify::addTryDelegate(MachineInstr
*RangeBegin
,
848 MachineInstr
*RangeEnd
,
849 MachineBasicBlock
*DelegateDest
) {
850 auto *BeginBB
= RangeBegin
->getParent();
851 auto *EndBB
= RangeEnd
->getParent();
852 MachineFunction
&MF
= *BeginBB
->getParent();
853 const auto &MFI
= *MF
.getInfo
<WebAssemblyFunctionInfo
>();
854 const auto &TII
= *MF
.getSubtarget
<WebAssemblySubtarget
>().getInstrInfo();
856 // Local expression tree before the first call of this range should go
857 // after the nested TRY.
858 SmallPtrSet
<const MachineInstr
*, 4> AfterSet
;
859 AfterSet
.insert(RangeBegin
);
860 for (auto I
= MachineBasicBlock::iterator(RangeBegin
), E
= BeginBB
->begin();
862 if (std::prev(I
)->isDebugInstr() || std::prev(I
)->isPosition())
864 if (WebAssembly::isChild(*std::prev(I
), MFI
))
865 AfterSet
.insert(&*std::prev(I
));
870 // Create the nested try instruction.
871 auto TryPos
= getLatestInsertPos(
872 BeginBB
, SmallPtrSet
<const MachineInstr
*, 4>(), AfterSet
);
873 MachineInstr
*Try
= BuildMI(*BeginBB
, TryPos
, RangeBegin
->getDebugLoc(),
874 TII
.get(WebAssembly::TRY
))
875 .addImm(int64_t(WebAssembly::BlockType::Void
));
877 // Create a BB to insert the 'delegate' instruction.
878 MachineBasicBlock
*DelegateBB
= MF
.CreateMachineBasicBlock();
879 // If the destination of 'delegate' is not the caller, adds the destination to
880 // the BB's successors.
881 if (DelegateDest
!= FakeCallerBB
)
882 DelegateBB
->addSuccessor(DelegateDest
);
884 auto SplitPos
= std::next(RangeEnd
->getIterator());
885 if (SplitPos
== EndBB
->end()) {
886 // If the range's end instruction is at the end of the BB, insert the new
887 // delegate BB after the current BB.
888 MF
.insert(std::next(EndBB
->getIterator()), DelegateBB
);
889 EndBB
->addSuccessor(DelegateBB
);
892 // When the split pos is in the middle of a BB, we split the BB into two and
893 // put the 'delegate' BB in between. We normally create a split BB and make
894 // it a successor of the original BB (PostSplit == true), but in case the BB
895 // is an EH pad and the split pos is before 'catch', we should preserve the
896 // BB's property, including that it is an EH pad, in the later part of the
897 // BB, where 'catch' is. In this case we set PostSplit to false.
898 bool PostSplit
= true;
899 if (EndBB
->isEHPad()) {
900 for (auto I
= MachineBasicBlock::iterator(SplitPos
), E
= EndBB
->end();
902 if (WebAssembly::isCatch(I
->getOpcode())) {
909 MachineBasicBlock
*PreBB
= nullptr, *PostBB
= nullptr;
911 // If the range's end instruction is in the middle of the BB, we split the
912 // BB into two and insert the delegate BB in between.
919 // pre_bb: (previous 'bb')
921 // delegate_bb: (new)
926 PostBB
= MF
.CreateMachineBasicBlock();
927 MF
.insert(std::next(PreBB
->getIterator()), PostBB
);
928 MF
.insert(std::next(PreBB
->getIterator()), DelegateBB
);
929 PostBB
->splice(PostBB
->end(), PreBB
, SplitPos
, PreBB
->end());
930 PostBB
->transferSuccessors(PreBB
);
941 // delegate_bb: (new)
943 // post_bb: (previous 'ehpad')
946 assert(EndBB
->isEHPad());
947 PreBB
= MF
.CreateMachineBasicBlock();
949 MF
.insert(PostBB
->getIterator(), PreBB
);
950 MF
.insert(PostBB
->getIterator(), DelegateBB
);
951 PreBB
->splice(PreBB
->end(), PostBB
, PostBB
->begin(), SplitPos
);
952 // We don't need to transfer predecessors of the EH pad to 'PreBB',
953 // because an EH pad's predecessors are all through unwind edges and they
954 // should still unwind to the EH pad, not PreBB.
956 unstackifyVRegsUsedInSplitBB(*PreBB
, *PostBB
);
957 PreBB
->addSuccessor(DelegateBB
);
958 PreBB
->addSuccessor(PostBB
);
961 // Add 'delegate' instruction in the delegate BB created above.
962 MachineInstr
*Delegate
= BuildMI(DelegateBB
, RangeEnd
->getDebugLoc(),
963 TII
.get(WebAssembly::DELEGATE
))
964 .addMBB(DelegateDest
);
965 registerTryScope(Try
, Delegate
, nullptr);
968 bool WebAssemblyCFGStackify::fixCallUnwindMismatches(MachineFunction
&MF
) {
969 // Linearizing the control flow by placing TRY / END_TRY markers can create
970 // mismatches in unwind destinations for throwing instructions, such as calls.
972 // We use the 'delegate' instruction to fix the unwind mismatches. 'delegate'
973 // instruction delegates an exception to an outer 'catch'. It can target not
974 // only 'catch' but all block-like structures including another 'delegate',
975 // but with slightly different semantics than branches. When it targets a
976 // 'catch', it will delegate the exception to that catch. It is being
977 // discussed how to define the semantics when 'delegate''s target is a non-try
978 // block: it will either be a validation failure or it will target the next
979 // outer try-catch. But anyway our LLVM backend currently does not generate
980 // such code. The example below illustrates where the 'delegate' instruction
981 // in the middle will delegate the exception to, depending on the value of N.
988 // delegate N ;; Where will this delegate to?
991 // end ;; N == 1 (invalid; will not be generated)
992 // delegate ;; N == 2
995 // ;; N == 4 (to caller)
997 // 1. When an instruction may throw, but the EH pad it will unwind to can be
998 // different from the original CFG.
1000 // Example: we have the following CFG:
1002 // call @foo ; if it throws, unwind to bb2
1004 // call @bar ; if it throws, unwind to bb3
1012 // And the CFG is sorted in this order. Then after placing TRY markers, it
1013 // will look like: (BB markers are omitted)
1017 // call @bar ;; if it throws, unwind to bb3
1018 // catch ;; ehpad (bb2)
1021 // catch ;; ehpad (bb3)
1025 // Now if bar() throws, it is going to end up ip in bb2, not bb3, where it
1026 // is supposed to end up. We solve this problem by wrapping the mismatching
1027 // call with an inner try-delegate that rethrows the exception to the right
1035 // delegate 1 (bb3) ;; (new)
1036 // catch ;; ehpad (bb2)
1039 // catch ;; ehpad (bb3)
1044 // 2. The same as 1, but in this case an instruction unwinds to a caller
1045 // function and not another EH pad.
1047 // Example: we have the following CFG:
1049 // call @foo ; if it throws, unwind to bb2
1051 // call @bar ; if it throws, unwind to caller
1056 // And the CFG is sorted in this order. Then after placing TRY markers, it
1060 // call @bar ;; if it throws, unwind to caller
1061 // catch ;; ehpad (bb2)
1065 // Now if bar() throws, it is going to end up ip in bb2, when it is supposed
1066 // throw up to the caller. We solve this problem in the same way, but in this
1067 // case 'delegate's immediate argument is the number of block depths + 1,
1068 // which means it rethrows to the caller.
1073 // delegate 1 (caller) ;; (new)
1074 // catch ;; ehpad (bb2)
1078 // Before rewriteDepthImmediates, delegate's argument is a BB. In case of the
1079 // caller, it will take a fake BB generated by getFakeCallerBlock(), which
1080 // will be converted to a correct immediate argument later.
1082 // In case there are multiple calls in a BB that may throw to the caller, they
1083 // can be wrapped together in one nested try-delegate scope. (In 1, this
1084 // couldn't happen, because may-throwing instruction there had an unwind
1085 // destination, i.e., it was an invoke before, and there could be only one
1086 // invoke within a BB.)
1088 SmallVector
<const MachineBasicBlock
*, 8> EHPadStack
;
1089 // Range of intructions to be wrapped in a new nested try/catch. A range
1090 // exists in a single BB and does not span multiple BBs.
1091 using TryRange
= std::pair
<MachineInstr
*, MachineInstr
*>;
1092 // In original CFG, <unwind destination BB, a vector of try ranges>
1093 DenseMap
<MachineBasicBlock
*, SmallVector
<TryRange
, 4>> UnwindDestToTryRanges
;
1095 // Gather possibly throwing calls (i.e., previously invokes) whose current
1096 // unwind destination is not the same as the original CFG. (Case 1)
1098 for (auto &MBB
: reverse(MF
)) {
1099 bool SeenThrowableInstInBB
= false;
1100 for (auto &MI
: reverse(MBB
)) {
1101 if (MI
.getOpcode() == WebAssembly::TRY
)
1102 EHPadStack
.pop_back();
1103 else if (WebAssembly::isCatch(MI
.getOpcode()))
1104 EHPadStack
.push_back(MI
.getParent());
1106 // In this loop we only gather calls that have an EH pad to unwind. So
1107 // there will be at most 1 such call (= invoke) in a BB, so after we've
1108 // seen one, we can skip the rest of BB. Also if MBB has no EH pad
1109 // successor or MI does not throw, this is not an invoke.
1110 if (SeenThrowableInstInBB
|| !MBB
.hasEHPadSuccessor() ||
1111 !WebAssembly::mayThrow(MI
))
1113 SeenThrowableInstInBB
= true;
1115 // If the EH pad on the stack top is where this instruction should unwind
1116 // next, we're good.
1117 MachineBasicBlock
*UnwindDest
= getFakeCallerBlock(MF
);
1118 for (auto *Succ
: MBB
.successors()) {
1119 // Even though semantically a BB can have multiple successors in case an
1120 // exception is not caught by a catchpad, in our backend implementation
1121 // it is guaranteed that a BB can have at most one EH pad successor. For
1122 // details, refer to comments in findWasmUnwindDestinations function in
1123 // SelectionDAGBuilder.cpp.
1124 if (Succ
->isEHPad()) {
1129 if (EHPadStack
.back() == UnwindDest
)
1132 // Include EH_LABELs in the range before and afer the invoke
1133 MachineInstr
*RangeBegin
= &MI
, *RangeEnd
= &MI
;
1134 if (RangeBegin
->getIterator() != MBB
.begin() &&
1135 std::prev(RangeBegin
->getIterator())->isEHLabel())
1136 RangeBegin
= &*std::prev(RangeBegin
->getIterator());
1137 if (std::next(RangeEnd
->getIterator()) != MBB
.end() &&
1138 std::next(RangeEnd
->getIterator())->isEHLabel())
1139 RangeEnd
= &*std::next(RangeEnd
->getIterator());
1141 // If not, record the range.
1142 UnwindDestToTryRanges
[UnwindDest
].push_back(
1143 TryRange(RangeBegin
, RangeEnd
));
1144 LLVM_DEBUG(dbgs() << "- Call unwind mismatch: MBB = " << MBB
.getName()
1145 << "\nCall = " << MI
1146 << "\nOriginal dest = " << UnwindDest
->getName()
1147 << " Current dest = " << EHPadStack
.back()->getName()
1152 assert(EHPadStack
.empty());
1154 // Gather possibly throwing calls that are supposed to unwind up to the caller
1155 // if they throw, but currently unwind to an incorrect destination. Unlike the
1156 // loop above, there can be multiple calls within a BB that unwind to the
1157 // caller, which we should group together in a range. (Case 2)
1159 MachineInstr
*RangeBegin
= nullptr, *RangeEnd
= nullptr; // inclusive
1161 // Record the range.
1162 auto RecordCallerMismatchRange
= [&](const MachineBasicBlock
*CurrentDest
) {
1163 UnwindDestToTryRanges
[getFakeCallerBlock(MF
)].push_back(
1164 TryRange(RangeBegin
, RangeEnd
));
1165 LLVM_DEBUG(dbgs() << "- Call unwind mismatch: MBB = "
1166 << RangeBegin
->getParent()->getName()
1167 << "\nRange begin = " << *RangeBegin
1168 << "Range end = " << *RangeEnd
1169 << "\nOriginal dest = caller Current dest = "
1170 << CurrentDest
->getName() << "\n\n");
1171 RangeBegin
= RangeEnd
= nullptr; // Reset range pointers
1174 for (auto &MBB
: reverse(MF
)) {
1175 bool SeenThrowableInstInBB
= false;
1176 for (auto &MI
: reverse(MBB
)) {
1177 bool MayThrow
= WebAssembly::mayThrow(MI
);
1179 // If MBB has an EH pad successor and this is the last instruction that
1180 // may throw, this instruction unwinds to the EH pad and not to the
1182 if (MBB
.hasEHPadSuccessor() && MayThrow
&& !SeenThrowableInstInBB
)
1183 SeenThrowableInstInBB
= true;
1185 // We wrap up the current range when we see a marker even if we haven't
1187 else if (RangeEnd
&& WebAssembly::isMarker(MI
.getOpcode()))
1188 RecordCallerMismatchRange(EHPadStack
.back());
1190 // If EHPadStack is empty, that means it correctly unwinds to the caller
1191 // if it throws, so we're good. If MI does not throw, we're good too.
1192 else if (EHPadStack
.empty() || !MayThrow
) {
1195 // We found an instruction that unwinds to the caller but currently has an
1196 // incorrect unwind destination. Create a new range or increment the
1197 // currently existing range.
1200 RangeBegin
= RangeEnd
= &MI
;
1205 // Update EHPadStack.
1206 if (MI
.getOpcode() == WebAssembly::TRY
)
1207 EHPadStack
.pop_back();
1208 else if (WebAssembly::isCatch(MI
.getOpcode()))
1209 EHPadStack
.push_back(MI
.getParent());
1213 RecordCallerMismatchRange(EHPadStack
.back());
1216 assert(EHPadStack
.empty());
1218 // We don't have any unwind destination mismatches to resolve.
1219 if (UnwindDestToTryRanges
.empty())
1222 // Now we fix the mismatches by wrapping calls with inner try-delegates.
1223 for (auto &P
: UnwindDestToTryRanges
) {
1224 NumCallUnwindMismatches
+= P
.second
.size();
1225 MachineBasicBlock
*UnwindDest
= P
.first
;
1226 auto &TryRanges
= P
.second
;
1228 for (auto Range
: TryRanges
) {
1229 MachineInstr
*RangeBegin
= nullptr, *RangeEnd
= nullptr;
1230 std::tie(RangeBegin
, RangeEnd
) = Range
;
1231 auto *MBB
= RangeBegin
->getParent();
1233 // If this BB has an EH pad successor, i.e., ends with an 'invoke', now we
1234 // are going to wrap the invoke with try-delegate, making the 'delegate'
1235 // BB the new successor instead, so remove the EH pad succesor here. The
1236 // BB may not have an EH pad successor if calls in this BB throw to the
1238 MachineBasicBlock
*EHPad
= nullptr;
1239 for (auto *Succ
: MBB
->successors()) {
1240 if (Succ
->isEHPad()) {
1246 MBB
->removeSuccessor(EHPad
);
1248 addTryDelegate(RangeBegin
, RangeEnd
, UnwindDest
);
1255 bool WebAssemblyCFGStackify::fixCatchUnwindMismatches(MachineFunction
&MF
) {
1256 // There is another kind of unwind destination mismatches besides call unwind
1257 // mismatches, which we will call "catch unwind mismatches". See this example
1258 // after the marker placement:
1262 // catch __cpp_exception ;; ehpad A (next unwind dest: caller)
1265 // catch_all ;; ehpad B
1269 // 'call @foo's unwind destination is the ehpad A. But suppose 'call @foo'
1270 // throws a foreign exception that is not caught by ehpad A, and its next
1271 // destination should be the caller. But after control flow linearization,
1272 // another EH pad can be placed in between (e.g. ehpad B here), making the
1273 // next unwind destination incorrect. In this case, the foreign exception
1274 // will instead go to ehpad B and will be caught there instead. In this
1275 // example the correct next unwind destination is the caller, but it can be
1276 // another outer catch in other cases.
1278 // There is no specific 'call' or 'throw' instruction to wrap with a
1279 // try-delegate, so we wrap the whole try-catch-end with a try-delegate and
1280 // make it rethrow to the right destination, as in the example below:
1285 // catch __cpp_exception ;; ehpad A (next unwind dest: caller)
1288 // delegate 1 (caller) ;; (new)
1289 // catch_all ;; ehpad B
1293 const auto *EHInfo
= MF
.getWasmEHFuncInfo();
1295 SmallVector
<const MachineBasicBlock
*, 8> EHPadStack
;
1296 // For EH pads that have catch unwind mismatches, a map of <EH pad, its
1297 // correct unwind destination>.
1298 DenseMap
<MachineBasicBlock
*, MachineBasicBlock
*> EHPadToUnwindDest
;
1300 for (auto &MBB
: reverse(MF
)) {
1301 for (auto &MI
: reverse(MBB
)) {
1302 if (MI
.getOpcode() == WebAssembly::TRY
)
1303 EHPadStack
.pop_back();
1304 else if (MI
.getOpcode() == WebAssembly::DELEGATE
)
1305 EHPadStack
.push_back(&MBB
);
1306 else if (WebAssembly::isCatch(MI
.getOpcode())) {
1309 // catch_all always catches an exception, so we don't need to do
1311 if (MI
.getOpcode() == WebAssembly::CATCH_ALL
) {
1314 // This can happen when the unwind dest was removed during the
1315 // optimization, e.g. because it was unreachable.
1316 else if (EHPadStack
.empty() && EHInfo
->hasUnwindDest(EHPad
)) {
1317 LLVM_DEBUG(dbgs() << "EHPad (" << EHPad
->getName()
1318 << "'s unwind destination does not exist anymore"
1322 // The EHPad's next unwind destination is the caller, but we incorrectly
1323 // unwind to another EH pad.
1324 else if (!EHPadStack
.empty() && !EHInfo
->hasUnwindDest(EHPad
)) {
1325 EHPadToUnwindDest
[EHPad
] = getFakeCallerBlock(MF
);
1327 << "- Catch unwind mismatch:\nEHPad = " << EHPad
->getName()
1328 << " Original dest = caller Current dest = "
1329 << EHPadStack
.back()->getName() << "\n\n");
1332 // The EHPad's next unwind destination is an EH pad, whereas we
1333 // incorrectly unwind to another EH pad.
1334 else if (!EHPadStack
.empty() && EHInfo
->hasUnwindDest(EHPad
)) {
1335 auto *UnwindDest
= EHInfo
->getUnwindDest(EHPad
);
1336 if (EHPadStack
.back() != UnwindDest
) {
1337 EHPadToUnwindDest
[EHPad
] = UnwindDest
;
1338 LLVM_DEBUG(dbgs() << "- Catch unwind mismatch:\nEHPad = "
1339 << EHPad
->getName() << " Original dest = "
1340 << UnwindDest
->getName() << " Current dest = "
1341 << EHPadStack
.back()->getName() << "\n\n");
1345 EHPadStack
.push_back(EHPad
);
1350 assert(EHPadStack
.empty());
1351 if (EHPadToUnwindDest
.empty())
1353 NumCatchUnwindMismatches
+= EHPadToUnwindDest
.size();
1354 SmallPtrSet
<MachineBasicBlock
*, 4> NewEndTryBBs
;
1356 for (auto &P
: EHPadToUnwindDest
) {
1357 MachineBasicBlock
*EHPad
= P
.first
;
1358 MachineBasicBlock
*UnwindDest
= P
.second
;
1359 MachineInstr
*Try
= EHPadToTry
[EHPad
];
1360 MachineInstr
*EndTry
= BeginToEnd
[Try
];
1361 addTryDelegate(Try
, EndTry
, UnwindDest
);
1362 NewEndTryBBs
.insert(EndTry
->getParent());
1365 // Adding a try-delegate wrapping an existing try-catch-end can make existing
1366 // branch destination BBs invalid. For example,
1379 // end_block ;; 'br bb3' targets here
1381 // Suppose this try-catch-end has a catch unwind mismatch, so we need to wrap
1382 // this with a try-delegate. Then this becomes:
1387 // br bb3 ;; invalid destination!
1389 // try ;; (new instruction)
1395 // end_try ;; 'br bb3' still incorrectly targets here!
1396 // delegate_bb: ;; (new BB)
1397 // delegate ;; (new instruction)
1398 // split_bb: ;; (new BB)
1401 // Now 'br bb3' incorrectly branches to an inner scope.
1403 // As we can see in this case, when branches target a BB that has both
1404 // 'end_try' and 'end_block' and the BB is split to insert a 'delegate', we
1405 // have to remap existing branch destinations so that they target not the
1406 // 'end_try' BB but the new 'end_block' BB. There can be multiple 'delegate's
1407 // in between, so we try to find the next BB with 'end_block' instruction. In
1408 // this example, the 'br bb3' instruction should be remapped to 'br split_bb'.
1409 for (auto &MBB
: MF
) {
1410 for (auto &MI
: MBB
) {
1411 if (MI
.isTerminator()) {
1412 for (auto &MO
: MI
.operands()) {
1413 if (MO
.isMBB() && NewEndTryBBs
.count(MO
.getMBB())) {
1414 auto *BrDest
= MO
.getMBB();
1415 bool FoundEndBlock
= false;
1416 for (; std::next(BrDest
->getIterator()) != MF
.end();
1417 BrDest
= BrDest
->getNextNode()) {
1418 for (const auto &MI
: *BrDest
) {
1419 if (MI
.getOpcode() == WebAssembly::END_BLOCK
) {
1420 FoundEndBlock
= true;
1427 assert(FoundEndBlock
);
1438 void WebAssemblyCFGStackify::recalculateScopeTops(MachineFunction
&MF
) {
1439 // Renumber BBs and recalculate ScopeTop info because new BBs might have been
1440 // created and inserted during fixing unwind mismatches.
1441 MF
.RenumberBlocks();
1443 ScopeTops
.resize(MF
.getNumBlockIDs());
1444 for (auto &MBB
: reverse(MF
)) {
1445 for (auto &MI
: reverse(MBB
)) {
1446 if (ScopeTops
[MBB
.getNumber()])
1448 switch (MI
.getOpcode()) {
1449 case WebAssembly::END_BLOCK
:
1450 case WebAssembly::END_LOOP
:
1451 case WebAssembly::END_TRY
:
1452 case WebAssembly::DELEGATE
:
1453 updateScopeTops(EndToBegin
[&MI
]->getParent(), &MBB
);
1455 case WebAssembly::CATCH
:
1456 case WebAssembly::CATCH_ALL
:
1457 updateScopeTops(EHPadToTry
[&MBB
]->getParent(), &MBB
);
1464 /// In normal assembly languages, when the end of a function is unreachable,
1465 /// because the function ends in an infinite loop or a noreturn call or similar,
1466 /// it isn't necessary to worry about the function return type at the end of
1467 /// the function, because it's never reached. However, in WebAssembly, blocks
1468 /// that end at the function end need to have a return type signature that
1469 /// matches the function signature, even though it's unreachable. This function
1470 /// checks for such cases and fixes up the signatures.
1471 void WebAssemblyCFGStackify::fixEndsAtEndOfFunction(MachineFunction
&MF
) {
1472 const auto &MFI
= *MF
.getInfo
<WebAssemblyFunctionInfo
>();
1474 if (MFI
.getResults().empty())
1477 // MCInstLower will add the proper types to multivalue signatures based on the
1478 // function return type
1479 WebAssembly::BlockType RetType
=
1480 MFI
.getResults().size() > 1
1481 ? WebAssembly::BlockType::Multivalue
1482 : WebAssembly::BlockType(
1483 WebAssembly::toValType(MFI
.getResults().front()));
1485 SmallVector
<MachineBasicBlock::reverse_iterator
, 4> Worklist
;
1486 Worklist
.push_back(MF
.rbegin()->rbegin());
1488 auto Process
= [&](MachineBasicBlock::reverse_iterator It
) {
1489 auto *MBB
= It
->getParent();
1490 while (It
!= MBB
->rend()) {
1491 MachineInstr
&MI
= *It
++;
1492 if (MI
.isPosition() || MI
.isDebugInstr())
1494 switch (MI
.getOpcode()) {
1495 case WebAssembly::END_TRY
: {
1496 // If a 'try''s return type is fixed, both its try body and catch body
1497 // should satisfy the return type, so we need to search 'end'
1498 // instructions before its corresponding 'catch' too.
1499 auto *EHPad
= TryToEHPad
.lookup(EndToBegin
[&MI
]);
1502 std::next(WebAssembly::findCatch(EHPad
)->getReverseIterator());
1503 if (NextIt
!= EHPad
->rend())
1504 Worklist
.push_back(NextIt
);
1507 case WebAssembly::END_BLOCK
:
1508 case WebAssembly::END_LOOP
:
1509 case WebAssembly::DELEGATE
:
1510 EndToBegin
[&MI
]->getOperand(0).setImm(int32_t(RetType
));
1513 // Something other than an `end`. We're done for this BB.
1517 // We've reached the beginning of a BB. Continue the search in the previous
1519 Worklist
.push_back(MBB
->getPrevNode()->rbegin());
1522 while (!Worklist
.empty())
1523 Process(Worklist
.pop_back_val());
1526 // WebAssembly functions end with an end instruction, as if the function body
1528 static void appendEndToFunction(MachineFunction
&MF
,
1529 const WebAssemblyInstrInfo
&TII
) {
1530 BuildMI(MF
.back(), MF
.back().end(),
1531 MF
.back().findPrevDebugLoc(MF
.back().end()),
1532 TII
.get(WebAssembly::END_FUNCTION
));
1535 /// Insert LOOP/TRY/BLOCK markers at appropriate places.
1536 void WebAssemblyCFGStackify::placeMarkers(MachineFunction
&MF
) {
1537 // We allocate one more than the number of blocks in the function to
1538 // accommodate for the possible fake block we may insert at the end.
1539 ScopeTops
.resize(MF
.getNumBlockIDs() + 1);
1540 // Place the LOOP for MBB if MBB is the header of a loop.
1541 for (auto &MBB
: MF
)
1542 placeLoopMarker(MBB
);
1544 const MCAsmInfo
*MCAI
= MF
.getTarget().getMCAsmInfo();
1545 for (auto &MBB
: MF
) {
1546 if (MBB
.isEHPad()) {
1547 // Place the TRY for MBB if MBB is the EH pad of an exception.
1548 if (MCAI
->getExceptionHandlingType() == ExceptionHandling::Wasm
&&
1549 MF
.getFunction().hasPersonalityFn())
1550 placeTryMarker(MBB
);
1552 // Place the BLOCK for MBB if MBB is branched to from above.
1553 placeBlockMarker(MBB
);
1556 // Fix mismatches in unwind destinations induced by linearizing the code.
1557 if (MCAI
->getExceptionHandlingType() == ExceptionHandling::Wasm
&&
1558 MF
.getFunction().hasPersonalityFn()) {
1559 bool Changed
= fixCallUnwindMismatches(MF
);
1560 Changed
|= fixCatchUnwindMismatches(MF
);
1562 recalculateScopeTops(MF
);
1566 unsigned WebAssemblyCFGStackify::getBranchDepth(
1567 const SmallVectorImpl
<EndMarkerInfo
> &Stack
, const MachineBasicBlock
*MBB
) {
1569 for (auto X
: reverse(Stack
)) {
1574 assert(Depth
< Stack
.size() && "Branch destination should be in scope");
1578 unsigned WebAssemblyCFGStackify::getDelegateDepth(
1579 const SmallVectorImpl
<EndMarkerInfo
> &Stack
, const MachineBasicBlock
*MBB
) {
1580 if (MBB
== FakeCallerBB
)
1581 return Stack
.size();
1582 // Delegate's destination is either a catch or a another delegate BB. When the
1583 // destination is another delegate, we can compute the argument in the same
1584 // way as branches, because the target delegate BB only contains the single
1585 // delegate instruction.
1586 if (!MBB
->isEHPad()) // Target is a delegate BB
1587 return getBranchDepth(Stack
, MBB
);
1589 // When the delegate's destination is a catch BB, we need to use its
1590 // corresponding try's end_try BB because Stack contains each marker's end BB.
1591 // Also we need to check if the end marker instruction matches, because a
1592 // single BB can contain multiple end markers, like this:
1600 // In case of branches getting the immediate that targets any of these is
1601 // fine, but delegate has to exactly target the correct try.
1603 const MachineInstr
*EndTry
= BeginToEnd
[EHPadToTry
[MBB
]];
1604 for (auto X
: reverse(Stack
)) {
1605 if (X
.first
== EndTry
->getParent() && X
.second
== EndTry
)
1609 assert(Depth
< Stack
.size() && "Delegate destination should be in scope");
1613 unsigned WebAssemblyCFGStackify::getRethrowDepth(
1614 const SmallVectorImpl
<EndMarkerInfo
> &Stack
,
1615 const SmallVectorImpl
<const MachineBasicBlock
*> &EHPadStack
) {
1617 // In our current implementation, rethrows always rethrow the exception caught
1618 // by the innermost enclosing catch. This means while traversing Stack in the
1619 // reverse direction, when we encounter END_TRY, we should check if the
1620 // END_TRY corresponds to the current innermost EH pad. For example:
1631 // When we are at 'rethrow' (d), while reversely traversing Stack the first
1632 // 'end' we encounter is the 'end' (e), which corresponds to the 'catch' (c).
1633 // And 'rethrow' (d) rethrows the exception caught by 'catch' (c), so we stop
1634 // there and the depth should be 0. But when we are at 'rethrow' (b), it
1635 // rethrows the exception caught by 'catch' (a), so when traversing Stack
1636 // reversely, we should skip the 'end' (e) and choose 'end' (f), which
1637 // corresponds to 'catch' (a).
1638 for (auto X
: reverse(Stack
)) {
1639 const MachineInstr
*End
= X
.second
;
1640 if (End
->getOpcode() == WebAssembly::END_TRY
) {
1641 auto *EHPad
= TryToEHPad
[EndToBegin
[End
]];
1642 if (EHPadStack
.back() == EHPad
)
1647 assert(Depth
< Stack
.size() && "Rethrow destination should be in scope");
1651 void WebAssemblyCFGStackify::rewriteDepthImmediates(MachineFunction
&MF
) {
1652 // Now rewrite references to basic blocks to be depth immediates.
1653 SmallVector
<EndMarkerInfo
, 8> Stack
;
1654 SmallVector
<const MachineBasicBlock
*, 8> EHPadStack
;
1655 for (auto &MBB
: reverse(MF
)) {
1656 for (MachineInstr
&MI
: llvm::reverse(MBB
)) {
1657 switch (MI
.getOpcode()) {
1658 case WebAssembly::BLOCK
:
1659 case WebAssembly::TRY
:
1660 assert(ScopeTops
[Stack
.back().first
->getNumber()]->getNumber() <=
1662 "Block/try marker should be balanced");
1666 case WebAssembly::LOOP
:
1667 assert(Stack
.back().first
== &MBB
&& "Loop top should be balanced");
1671 case WebAssembly::END_BLOCK
:
1672 Stack
.push_back(std::make_pair(&MBB
, &MI
));
1675 case WebAssembly::END_TRY
: {
1676 // We handle DELEGATE in the default level, because DELEGATE has
1677 // immediate operands to rewrite.
1678 Stack
.push_back(std::make_pair(&MBB
, &MI
));
1679 auto *EHPad
= TryToEHPad
[EndToBegin
[&MI
]];
1680 EHPadStack
.push_back(EHPad
);
1684 case WebAssembly::END_LOOP
:
1685 Stack
.push_back(std::make_pair(EndToBegin
[&MI
]->getParent(), &MI
));
1688 case WebAssembly::CATCH
:
1689 case WebAssembly::CATCH_ALL
:
1690 EHPadStack
.pop_back();
1693 case WebAssembly::RETHROW
:
1694 MI
.getOperand(0).setImm(getRethrowDepth(Stack
, EHPadStack
));
1698 if (MI
.isTerminator()) {
1699 // Rewrite MBB operands to be depth immediates.
1700 SmallVector
<MachineOperand
, 4> Ops(MI
.operands());
1701 while (MI
.getNumOperands() > 0)
1702 MI
.removeOperand(MI
.getNumOperands() - 1);
1703 for (auto MO
: Ops
) {
1705 if (MI
.getOpcode() == WebAssembly::DELEGATE
)
1706 MO
= MachineOperand::CreateImm(
1707 getDelegateDepth(Stack
, MO
.getMBB()));
1709 MO
= MachineOperand::CreateImm(
1710 getBranchDepth(Stack
, MO
.getMBB()));
1712 MI
.addOperand(MF
, MO
);
1716 if (MI
.getOpcode() == WebAssembly::DELEGATE
)
1717 Stack
.push_back(std::make_pair(&MBB
, &MI
));
1722 assert(Stack
.empty() && "Control flow should be balanced");
1725 void WebAssemblyCFGStackify::cleanupFunctionData(MachineFunction
&MF
) {
1727 MF
.deleteMachineBasicBlock(FakeCallerBB
);
1728 AppendixBB
= FakeCallerBB
= nullptr;
1731 void WebAssemblyCFGStackify::releaseMemory() {
1739 bool WebAssemblyCFGStackify::runOnMachineFunction(MachineFunction
&MF
) {
1740 LLVM_DEBUG(dbgs() << "********** CFG Stackifying **********\n"
1741 "********** Function: "
1742 << MF
.getName() << '\n');
1743 const MCAsmInfo
*MCAI
= MF
.getTarget().getMCAsmInfo();
1747 // Liveness is not tracked for VALUE_STACK physreg.
1748 MF
.getRegInfo().invalidateLiveness();
1750 // Place the BLOCK/LOOP/TRY markers to indicate the beginnings of scopes.
1753 // Remove unnecessary instructions possibly introduced by try/end_trys.
1754 if (MCAI
->getExceptionHandlingType() == ExceptionHandling::Wasm
&&
1755 MF
.getFunction().hasPersonalityFn())
1756 removeUnnecessaryInstrs(MF
);
1758 // Convert MBB operands in terminators to relative depth immediates.
1759 rewriteDepthImmediates(MF
);
1761 // Fix up block/loop/try signatures at the end of the function to conform to
1762 // WebAssembly's rules.
1763 fixEndsAtEndOfFunction(MF
);
1765 // Add an end instruction at the end of the function body.
1766 const auto &TII
= *MF
.getSubtarget
<WebAssemblySubtarget
>().getInstrInfo();
1767 if (!MF
.getSubtarget
<WebAssemblySubtarget
>()
1769 .isOSBinFormatELF())
1770 appendEndToFunction(MF
, TII
);
1772 cleanupFunctionData(MF
);
1774 MF
.getInfo
<WebAssemblyFunctionInfo
>()->setCFGStackified();