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 
24 #include "WebAssembly.h"
25 #include "WebAssemblyExceptionInfo.h"
26 #include "WebAssemblyMachineFunctionInfo.h"
27 #include "WebAssemblySortRegion.h"
28 #include "WebAssemblySubtarget.h"
29 #include "WebAssemblyUtilities.h"
30 #include "llvm/ADT/Statistic.h"
31 #include "llvm/CodeGen/MachineDominators.h"
32 #include "llvm/CodeGen/MachineInstrBuilder.h"
33 #include "llvm/CodeGen/MachineLoopInfo.h"
34 #include "llvm/MC/MCAsmInfo.h"
35 #include "llvm/Target/TargetMachine.h"
36 using namespace llvm;
37 using WebAssembly::SortRegionInfo;
38 
39 #define DEBUG_TYPE "wasm-cfg-stackify"
40 
41 STATISTIC(NumUnwindMismatches, "Number of EH pad unwind mismatches found");
42 
43 namespace {
44 class WebAssemblyCFGStackify final : public MachineFunctionPass {
getPassName() const45   StringRef getPassName() const override { return "WebAssembly CFG Stackify"; }
46 
getAnalysisUsage(AnalysisUsage & AU) const47   void getAnalysisUsage(AnalysisUsage &AU) const override {
48     AU.addRequired<MachineDominatorTree>();
49     AU.addRequired<MachineLoopInfo>();
50     AU.addRequired<WebAssemblyExceptionInfo>();
51     MachineFunctionPass::getAnalysisUsage(AU);
52   }
53 
54   bool runOnMachineFunction(MachineFunction &MF) override;
55 
56   // For each block whose label represents the end of a scope, record the block
57   // which holds the beginning of the scope. This will allow us to quickly skip
58   // over scoped regions when walking blocks.
59   SmallVector<MachineBasicBlock *, 8> ScopeTops;
60 
61   // Placing markers.
62   void placeMarkers(MachineFunction &MF);
63   void placeBlockMarker(MachineBasicBlock &MBB);
64   void placeLoopMarker(MachineBasicBlock &MBB);
65   void placeTryMarker(MachineBasicBlock &MBB);
66   void removeUnnecessaryInstrs(MachineFunction &MF);
67   bool fixUnwindMismatches(MachineFunction &MF);
68   void rewriteDepthImmediates(MachineFunction &MF);
69   void fixEndsAtEndOfFunction(MachineFunction &MF);
70 
71   // For each BLOCK|LOOP|TRY, the corresponding END_(BLOCK|LOOP|TRY).
72   DenseMap<const MachineInstr *, MachineInstr *> BeginToEnd;
73   // For each END_(BLOCK|LOOP|TRY), the corresponding BLOCK|LOOP|TRY.
74   DenseMap<const MachineInstr *, MachineInstr *> EndToBegin;
75   // <TRY marker, EH pad> map
76   DenseMap<const MachineInstr *, MachineBasicBlock *> TryToEHPad;
77   // <EH pad, TRY marker> map
78   DenseMap<const MachineBasicBlock *, MachineInstr *> EHPadToTry;
79 
80   // There can be an appendix block at the end of each function, shared for:
81   // - creating a correct signature for fallthrough returns
82   // - target for rethrows that need to unwind to the caller, but are trapped
83   //   inside another try/catch
84   MachineBasicBlock *AppendixBB = nullptr;
getAppendixBlock(MachineFunction & MF)85   MachineBasicBlock *getAppendixBlock(MachineFunction &MF) {
86     if (!AppendixBB) {
87       AppendixBB = MF.CreateMachineBasicBlock();
88       // Give it a fake predecessor so that AsmPrinter prints its label.
89       AppendixBB->addSuccessor(AppendixBB);
90       MF.push_back(AppendixBB);
91     }
92     return AppendixBB;
93   }
94 
95   // Helper functions to register / unregister scope information created by
96   // marker instructions.
97   void registerScope(MachineInstr *Begin, MachineInstr *End);
98   void registerTryScope(MachineInstr *Begin, MachineInstr *End,
99                         MachineBasicBlock *EHPad);
100   void unregisterScope(MachineInstr *Begin);
101 
102 public:
103   static char ID; // Pass identification, replacement for typeid
WebAssemblyCFGStackify()104   WebAssemblyCFGStackify() : MachineFunctionPass(ID) {}
~WebAssemblyCFGStackify()105   ~WebAssemblyCFGStackify() override { releaseMemory(); }
106   void releaseMemory() override;
107 };
108 } // end anonymous namespace
109 
110 char WebAssemblyCFGStackify::ID = 0;
111 INITIALIZE_PASS(WebAssemblyCFGStackify, DEBUG_TYPE,
112                 "Insert BLOCK/LOOP/TRY markers for WebAssembly scopes", false,
113                 false)
114 
createWebAssemblyCFGStackify()115 FunctionPass *llvm::createWebAssemblyCFGStackify() {
116   return new WebAssemblyCFGStackify();
117 }
118 
119 /// Test whether Pred has any terminators explicitly branching to MBB, as
120 /// opposed to falling through. Note that it's possible (eg. in unoptimized
121 /// code) for a branch instruction to both branch to a block and fallthrough
122 /// to it, so we check the actual branch operands to see if there are any
123 /// explicit mentions.
explicitlyBranchesTo(MachineBasicBlock * Pred,MachineBasicBlock * MBB)124 static bool explicitlyBranchesTo(MachineBasicBlock *Pred,
125                                  MachineBasicBlock *MBB) {
126   for (MachineInstr &MI : Pred->terminators())
127     for (MachineOperand &MO : MI.explicit_operands())
128       if (MO.isMBB() && MO.getMBB() == MBB)
129         return true;
130   return false;
131 }
132 
133 // Returns an iterator to the earliest position possible within the MBB,
134 // satisfying the restrictions given by BeforeSet and AfterSet. BeforeSet
135 // contains instructions that should go before the marker, and AfterSet contains
136 // ones that should go after the marker. In this function, AfterSet is only
137 // used for sanity checking.
138 static MachineBasicBlock::iterator
getEarliestInsertPos(MachineBasicBlock * MBB,const SmallPtrSet<const MachineInstr *,4> & BeforeSet,const SmallPtrSet<const MachineInstr *,4> & AfterSet)139 getEarliestInsertPos(MachineBasicBlock *MBB,
140                      const SmallPtrSet<const MachineInstr *, 4> &BeforeSet,
141                      const SmallPtrSet<const MachineInstr *, 4> &AfterSet) {
142   auto InsertPos = MBB->end();
143   while (InsertPos != MBB->begin()) {
144     if (BeforeSet.count(&*std::prev(InsertPos))) {
145 #ifndef NDEBUG
146       // Sanity check
147       for (auto Pos = InsertPos, E = MBB->begin(); Pos != E; --Pos)
148         assert(!AfterSet.count(&*std::prev(Pos)));
149 #endif
150       break;
151     }
152     --InsertPos;
153   }
154   return InsertPos;
155 }
156 
157 // Returns an iterator to the latest position possible within the MBB,
158 // satisfying the restrictions given by BeforeSet and AfterSet. BeforeSet
159 // contains instructions that should go before the marker, and AfterSet contains
160 // ones that should go after the marker. In this function, BeforeSet is only
161 // used for sanity checking.
162 static MachineBasicBlock::iterator
getLatestInsertPos(MachineBasicBlock * MBB,const SmallPtrSet<const MachineInstr *,4> & BeforeSet,const SmallPtrSet<const MachineInstr *,4> & AfterSet)163 getLatestInsertPos(MachineBasicBlock *MBB,
164                    const SmallPtrSet<const MachineInstr *, 4> &BeforeSet,
165                    const SmallPtrSet<const MachineInstr *, 4> &AfterSet) {
166   auto InsertPos = MBB->begin();
167   while (InsertPos != MBB->end()) {
168     if (AfterSet.count(&*InsertPos)) {
169 #ifndef NDEBUG
170       // Sanity check
171       for (auto Pos = InsertPos, E = MBB->end(); Pos != E; ++Pos)
172         assert(!BeforeSet.count(&*Pos));
173 #endif
174       break;
175     }
176     ++InsertPos;
177   }
178   return InsertPos;
179 }
180 
181 // Find a catch instruction and its destination register within an EH pad.
findCatch(MachineBasicBlock * EHPad,Register & ExnReg)182 static MachineInstr *findCatch(MachineBasicBlock *EHPad, Register &ExnReg) {
183   assert(EHPad->isEHPad());
184   MachineInstr *Catch = nullptr;
185   for (auto &MI : *EHPad) {
186     switch (MI.getOpcode()) {
187     case WebAssembly::CATCH:
188       Catch = &MI;
189       ExnReg = Catch->getOperand(0).getReg();
190       break;
191     }
192   }
193   assert(Catch && "EH pad does not have a catch");
194   assert(ExnReg != 0 && "Invalid register");
195   return Catch;
196 }
197 
findCatch(MachineBasicBlock * EHPad)198 static MachineInstr *findCatch(MachineBasicBlock *EHPad) {
199   Register Dummy;
200   return findCatch(EHPad, Dummy);
201 }
202 
registerScope(MachineInstr * Begin,MachineInstr * End)203 void WebAssemblyCFGStackify::registerScope(MachineInstr *Begin,
204                                            MachineInstr *End) {
205   BeginToEnd[Begin] = End;
206   EndToBegin[End] = Begin;
207 }
208 
registerTryScope(MachineInstr * Begin,MachineInstr * End,MachineBasicBlock * EHPad)209 void WebAssemblyCFGStackify::registerTryScope(MachineInstr *Begin,
210                                               MachineInstr *End,
211                                               MachineBasicBlock *EHPad) {
212   registerScope(Begin, End);
213   TryToEHPad[Begin] = EHPad;
214   EHPadToTry[EHPad] = Begin;
215 }
216 
unregisterScope(MachineInstr * Begin)217 void WebAssemblyCFGStackify::unregisterScope(MachineInstr *Begin) {
218   assert(BeginToEnd.count(Begin));
219   MachineInstr *End = BeginToEnd[Begin];
220   assert(EndToBegin.count(End));
221   BeginToEnd.erase(Begin);
222   EndToBegin.erase(End);
223   MachineBasicBlock *EHPad = TryToEHPad.lookup(Begin);
224   if (EHPad) {
225     assert(EHPadToTry.count(EHPad));
226     TryToEHPad.erase(Begin);
227     EHPadToTry.erase(EHPad);
228   }
229 }
230 
231 /// Insert a BLOCK marker for branches to MBB (if needed).
232 // TODO Consider a more generalized way of handling block (and also loop and
233 // try) signatures when we implement the multi-value proposal later.
placeBlockMarker(MachineBasicBlock & MBB)234 void WebAssemblyCFGStackify::placeBlockMarker(MachineBasicBlock &MBB) {
235   assert(!MBB.isEHPad());
236   MachineFunction &MF = *MBB.getParent();
237   auto &MDT = getAnalysis<MachineDominatorTree>();
238   const auto &TII = *MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo();
239   const auto &MFI = *MF.getInfo<WebAssemblyFunctionInfo>();
240 
241   // First compute the nearest common dominator of all forward non-fallthrough
242   // predecessors so that we minimize the time that the BLOCK is on the stack,
243   // which reduces overall stack height.
244   MachineBasicBlock *Header = nullptr;
245   bool IsBranchedTo = false;
246   bool IsBrOnExn = false;
247   MachineInstr *BrOnExn = nullptr;
248   int MBBNumber = MBB.getNumber();
249   for (MachineBasicBlock *Pred : MBB.predecessors()) {
250     if (Pred->getNumber() < MBBNumber) {
251       Header = Header ? MDT.findNearestCommonDominator(Header, Pred) : Pred;
252       if (explicitlyBranchesTo(Pred, &MBB)) {
253         IsBranchedTo = true;
254         if (Pred->getFirstTerminator()->getOpcode() == WebAssembly::BR_ON_EXN) {
255           IsBrOnExn = true;
256           assert(!BrOnExn && "There should be only one br_on_exn per block");
257           BrOnExn = &*Pred->getFirstTerminator();
258         }
259       }
260     }
261   }
262   if (!Header)
263     return;
264   if (!IsBranchedTo)
265     return;
266 
267   assert(&MBB != &MF.front() && "Header blocks shouldn't have predecessors");
268   MachineBasicBlock *LayoutPred = MBB.getPrevNode();
269 
270   // If the nearest common dominator is inside a more deeply nested context,
271   // walk out to the nearest scope which isn't more deeply nested.
272   for (MachineFunction::iterator I(LayoutPred), E(Header); I != E; --I) {
273     if (MachineBasicBlock *ScopeTop = ScopeTops[I->getNumber()]) {
274       if (ScopeTop->getNumber() > Header->getNumber()) {
275         // Skip over an intervening scope.
276         I = std::next(ScopeTop->getIterator());
277       } else {
278         // We found a scope level at an appropriate depth.
279         Header = ScopeTop;
280         break;
281       }
282     }
283   }
284 
285   // Decide where in Header to put the BLOCK.
286 
287   // Instructions that should go before the BLOCK.
288   SmallPtrSet<const MachineInstr *, 4> BeforeSet;
289   // Instructions that should go after the BLOCK.
290   SmallPtrSet<const MachineInstr *, 4> AfterSet;
291   for (const auto &MI : *Header) {
292     // If there is a previously placed LOOP marker and the bottom block of the
293     // loop is above MBB, it should be after the BLOCK, because the loop is
294     // nested in this BLOCK. Otherwise it should be before the BLOCK.
295     if (MI.getOpcode() == WebAssembly::LOOP) {
296       auto *LoopBottom = BeginToEnd[&MI]->getParent()->getPrevNode();
297       if (MBB.getNumber() > LoopBottom->getNumber())
298         AfterSet.insert(&MI);
299 #ifndef NDEBUG
300       else
301         BeforeSet.insert(&MI);
302 #endif
303     }
304 
305     // If there is a previously placed BLOCK/TRY marker and its corresponding
306     // END marker is before the current BLOCK's END marker, that should be
307     // placed after this BLOCK. Otherwise it should be placed before this BLOCK
308     // marker.
309     if (MI.getOpcode() == WebAssembly::BLOCK ||
310         MI.getOpcode() == WebAssembly::TRY) {
311       if (BeginToEnd[&MI]->getParent()->getNumber() <= MBB.getNumber())
312         AfterSet.insert(&MI);
313 #ifndef NDEBUG
314       else
315         BeforeSet.insert(&MI);
316 #endif
317     }
318 
319 #ifndef NDEBUG
320     // All END_(BLOCK|LOOP|TRY) markers should be before the BLOCK.
321     if (MI.getOpcode() == WebAssembly::END_BLOCK ||
322         MI.getOpcode() == WebAssembly::END_LOOP ||
323         MI.getOpcode() == WebAssembly::END_TRY)
324       BeforeSet.insert(&MI);
325 #endif
326 
327     // Terminators should go after the BLOCK.
328     if (MI.isTerminator())
329       AfterSet.insert(&MI);
330   }
331 
332   // Local expression tree should go after the BLOCK.
333   for (auto I = Header->getFirstTerminator(), E = Header->begin(); I != E;
334        --I) {
335     if (std::prev(I)->isDebugInstr() || std::prev(I)->isPosition())
336       continue;
337     if (WebAssembly::isChild(*std::prev(I), MFI))
338       AfterSet.insert(&*std::prev(I));
339     else
340       break;
341   }
342 
343   // Add the BLOCK.
344 
345   // 'br_on_exn' extracts exnref object and pushes variable number of values
346   // depending on its tag. For C++ exception, its a single i32 value, and the
347   // generated code will be in the form of:
348   // block i32
349   //   br_on_exn 0, $__cpp_exception
350   //   rethrow
351   // end_block
352   WebAssembly::BlockType ReturnType = WebAssembly::BlockType::Void;
353   if (IsBrOnExn) {
354     const char *TagName = BrOnExn->getOperand(1).getSymbolName();
355     if (std::strcmp(TagName, "__cpp_exception") != 0)
356       llvm_unreachable("Only C++ exception is supported");
357     ReturnType = WebAssembly::BlockType::I32;
358   }
359 
360   auto InsertPos = getLatestInsertPos(Header, BeforeSet, AfterSet);
361   MachineInstr *Begin =
362       BuildMI(*Header, InsertPos, Header->findDebugLoc(InsertPos),
363               TII.get(WebAssembly::BLOCK))
364           .addImm(int64_t(ReturnType));
365 
366   // Decide where in Header to put the END_BLOCK.
367   BeforeSet.clear();
368   AfterSet.clear();
369   for (auto &MI : MBB) {
370 #ifndef NDEBUG
371     // END_BLOCK should precede existing LOOP and TRY markers.
372     if (MI.getOpcode() == WebAssembly::LOOP ||
373         MI.getOpcode() == WebAssembly::TRY)
374       AfterSet.insert(&MI);
375 #endif
376 
377     // If there is a previously placed END_LOOP marker and the header of the
378     // loop is above this block's header, the END_LOOP should be placed after
379     // the BLOCK, because the loop contains this block. Otherwise the END_LOOP
380     // should be placed before the BLOCK. The same for END_TRY.
381     if (MI.getOpcode() == WebAssembly::END_LOOP ||
382         MI.getOpcode() == WebAssembly::END_TRY) {
383       if (EndToBegin[&MI]->getParent()->getNumber() >= Header->getNumber())
384         BeforeSet.insert(&MI);
385 #ifndef NDEBUG
386       else
387         AfterSet.insert(&MI);
388 #endif
389     }
390   }
391 
392   // Mark the end of the block.
393   InsertPos = getEarliestInsertPos(&MBB, BeforeSet, AfterSet);
394   MachineInstr *End = BuildMI(MBB, InsertPos, MBB.findPrevDebugLoc(InsertPos),
395                               TII.get(WebAssembly::END_BLOCK));
396   registerScope(Begin, End);
397 
398   // Track the farthest-spanning scope that ends at this point.
399   int Number = MBB.getNumber();
400   if (!ScopeTops[Number] ||
401       ScopeTops[Number]->getNumber() > Header->getNumber())
402     ScopeTops[Number] = Header;
403 }
404 
405 /// Insert a LOOP marker for a loop starting at MBB (if it's a loop header).
placeLoopMarker(MachineBasicBlock & MBB)406 void WebAssemblyCFGStackify::placeLoopMarker(MachineBasicBlock &MBB) {
407   MachineFunction &MF = *MBB.getParent();
408   const auto &MLI = getAnalysis<MachineLoopInfo>();
409   const auto &WEI = getAnalysis<WebAssemblyExceptionInfo>();
410   SortRegionInfo SRI(MLI, WEI);
411   const auto &TII = *MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo();
412 
413   MachineLoop *Loop = MLI.getLoopFor(&MBB);
414   if (!Loop || Loop->getHeader() != &MBB)
415     return;
416 
417   // The operand of a LOOP is the first block after the loop. If the loop is the
418   // bottom of the function, insert a dummy block at the end.
419   MachineBasicBlock *Bottom = SRI.getBottom(Loop);
420   auto Iter = std::next(Bottom->getIterator());
421   if (Iter == MF.end()) {
422     getAppendixBlock(MF);
423     Iter = std::next(Bottom->getIterator());
424   }
425   MachineBasicBlock *AfterLoop = &*Iter;
426 
427   // Decide where in Header to put the LOOP.
428   SmallPtrSet<const MachineInstr *, 4> BeforeSet;
429   SmallPtrSet<const MachineInstr *, 4> AfterSet;
430   for (const auto &MI : MBB) {
431     // LOOP marker should be after any existing loop that ends here. Otherwise
432     // we assume the instruction belongs to the loop.
433     if (MI.getOpcode() == WebAssembly::END_LOOP)
434       BeforeSet.insert(&MI);
435 #ifndef NDEBUG
436     else
437       AfterSet.insert(&MI);
438 #endif
439   }
440 
441   // Mark the beginning of the loop.
442   auto InsertPos = getEarliestInsertPos(&MBB, BeforeSet, AfterSet);
443   MachineInstr *Begin = BuildMI(MBB, InsertPos, MBB.findDebugLoc(InsertPos),
444                                 TII.get(WebAssembly::LOOP))
445                             .addImm(int64_t(WebAssembly::BlockType::Void));
446 
447   // Decide where in Header to put the END_LOOP.
448   BeforeSet.clear();
449   AfterSet.clear();
450 #ifndef NDEBUG
451   for (const auto &MI : MBB)
452     // Existing END_LOOP markers belong to parent loops of this loop
453     if (MI.getOpcode() == WebAssembly::END_LOOP)
454       AfterSet.insert(&MI);
455 #endif
456 
457   // Mark the end of the loop (using arbitrary debug location that branched to
458   // the loop end as its location).
459   InsertPos = getEarliestInsertPos(AfterLoop, BeforeSet, AfterSet);
460   DebugLoc EndDL = AfterLoop->pred_empty()
461                        ? DebugLoc()
462                        : (*AfterLoop->pred_rbegin())->findBranchDebugLoc();
463   MachineInstr *End =
464       BuildMI(*AfterLoop, InsertPos, EndDL, TII.get(WebAssembly::END_LOOP));
465   registerScope(Begin, End);
466 
467   assert((!ScopeTops[AfterLoop->getNumber()] ||
468           ScopeTops[AfterLoop->getNumber()]->getNumber() < MBB.getNumber()) &&
469          "With block sorting the outermost loop for a block should be first.");
470   if (!ScopeTops[AfterLoop->getNumber()])
471     ScopeTops[AfterLoop->getNumber()] = &MBB;
472 }
473 
placeTryMarker(MachineBasicBlock & MBB)474 void WebAssemblyCFGStackify::placeTryMarker(MachineBasicBlock &MBB) {
475   assert(MBB.isEHPad());
476   MachineFunction &MF = *MBB.getParent();
477   auto &MDT = getAnalysis<MachineDominatorTree>();
478   const auto &TII = *MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo();
479   const auto &MLI = getAnalysis<MachineLoopInfo>();
480   const auto &WEI = getAnalysis<WebAssemblyExceptionInfo>();
481   SortRegionInfo SRI(MLI, WEI);
482   const auto &MFI = *MF.getInfo<WebAssemblyFunctionInfo>();
483 
484   // Compute the nearest common dominator of all unwind predecessors
485   MachineBasicBlock *Header = nullptr;
486   int MBBNumber = MBB.getNumber();
487   for (auto *Pred : MBB.predecessors()) {
488     if (Pred->getNumber() < MBBNumber) {
489       Header = Header ? MDT.findNearestCommonDominator(Header, Pred) : Pred;
490       assert(!explicitlyBranchesTo(Pred, &MBB) &&
491              "Explicit branch to an EH pad!");
492     }
493   }
494   if (!Header)
495     return;
496 
497   // If this try is at the bottom of the function, insert a dummy block at the
498   // end.
499   WebAssemblyException *WE = WEI.getExceptionFor(&MBB);
500   assert(WE);
501   MachineBasicBlock *Bottom = SRI.getBottom(WE);
502 
503   auto Iter = std::next(Bottom->getIterator());
504   if (Iter == MF.end()) {
505     getAppendixBlock(MF);
506     Iter = std::next(Bottom->getIterator());
507   }
508   MachineBasicBlock *Cont = &*Iter;
509 
510   assert(Cont != &MF.front());
511   MachineBasicBlock *LayoutPred = Cont->getPrevNode();
512 
513   // If the nearest common dominator is inside a more deeply nested context,
514   // walk out to the nearest scope which isn't more deeply nested.
515   for (MachineFunction::iterator I(LayoutPred), E(Header); I != E; --I) {
516     if (MachineBasicBlock *ScopeTop = ScopeTops[I->getNumber()]) {
517       if (ScopeTop->getNumber() > Header->getNumber()) {
518         // Skip over an intervening scope.
519         I = std::next(ScopeTop->getIterator());
520       } else {
521         // We found a scope level at an appropriate depth.
522         Header = ScopeTop;
523         break;
524       }
525     }
526   }
527 
528   // Decide where in Header to put the TRY.
529 
530   // Instructions that should go before the TRY.
531   SmallPtrSet<const MachineInstr *, 4> BeforeSet;
532   // Instructions that should go after the TRY.
533   SmallPtrSet<const MachineInstr *, 4> AfterSet;
534   for (const auto &MI : *Header) {
535     // If there is a previously placed LOOP marker and the bottom block of the
536     // loop is above MBB, it should be after the TRY, because the loop is nested
537     // in this TRY. Otherwise it should be before the TRY.
538     if (MI.getOpcode() == WebAssembly::LOOP) {
539       auto *LoopBottom = BeginToEnd[&MI]->getParent()->getPrevNode();
540       if (MBB.getNumber() > LoopBottom->getNumber())
541         AfterSet.insert(&MI);
542 #ifndef NDEBUG
543       else
544         BeforeSet.insert(&MI);
545 #endif
546     }
547 
548     // All previously inserted BLOCK/TRY markers should be after the TRY because
549     // they are all nested trys.
550     if (MI.getOpcode() == WebAssembly::BLOCK ||
551         MI.getOpcode() == WebAssembly::TRY)
552       AfterSet.insert(&MI);
553 
554 #ifndef NDEBUG
555     // All END_(BLOCK/LOOP/TRY) markers should be before the TRY.
556     if (MI.getOpcode() == WebAssembly::END_BLOCK ||
557         MI.getOpcode() == WebAssembly::END_LOOP ||
558         MI.getOpcode() == WebAssembly::END_TRY)
559       BeforeSet.insert(&MI);
560 #endif
561 
562     // Terminators should go after the TRY.
563     if (MI.isTerminator())
564       AfterSet.insert(&MI);
565   }
566 
567   // If Header unwinds to MBB (= Header contains 'invoke'), the try block should
568   // contain the call within it. So the call should go after the TRY. The
569   // exception is when the header's terminator is a rethrow instruction, in
570   // which case that instruction, not a call instruction before it, is gonna
571   // throw.
572   MachineInstr *ThrowingCall = nullptr;
573   if (MBB.isPredecessor(Header)) {
574     auto TermPos = Header->getFirstTerminator();
575     if (TermPos == Header->end() ||
576         TermPos->getOpcode() != WebAssembly::RETHROW) {
577       for (auto &MI : reverse(*Header)) {
578         if (MI.isCall()) {
579           AfterSet.insert(&MI);
580           ThrowingCall = &MI;
581           // Possibly throwing calls are usually wrapped by EH_LABEL
582           // instructions. We don't want to split them and the call.
583           if (MI.getIterator() != Header->begin() &&
584               std::prev(MI.getIterator())->isEHLabel()) {
585             AfterSet.insert(&*std::prev(MI.getIterator()));
586             ThrowingCall = &*std::prev(MI.getIterator());
587           }
588           break;
589         }
590       }
591     }
592   }
593 
594   // Local expression tree should go after the TRY.
595   // For BLOCK placement, we start the search from the previous instruction of a
596   // BB's terminator, but in TRY's case, we should start from the previous
597   // instruction of a call that can throw, or a EH_LABEL that precedes the call,
598   // because the return values of the call's previous instructions can be
599   // stackified and consumed by the throwing call.
600   auto SearchStartPt = ThrowingCall ? MachineBasicBlock::iterator(ThrowingCall)
601                                     : Header->getFirstTerminator();
602   for (auto I = SearchStartPt, E = Header->begin(); I != E; --I) {
603     if (std::prev(I)->isDebugInstr() || std::prev(I)->isPosition())
604       continue;
605     if (WebAssembly::isChild(*std::prev(I), MFI))
606       AfterSet.insert(&*std::prev(I));
607     else
608       break;
609   }
610 
611   // Add the TRY.
612   auto InsertPos = getLatestInsertPos(Header, BeforeSet, AfterSet);
613   MachineInstr *Begin =
614       BuildMI(*Header, InsertPos, Header->findDebugLoc(InsertPos),
615               TII.get(WebAssembly::TRY))
616           .addImm(int64_t(WebAssembly::BlockType::Void));
617 
618   // Decide where in Header to put the END_TRY.
619   BeforeSet.clear();
620   AfterSet.clear();
621   for (const auto &MI : *Cont) {
622 #ifndef NDEBUG
623     // END_TRY should precede existing LOOP and BLOCK markers.
624     if (MI.getOpcode() == WebAssembly::LOOP ||
625         MI.getOpcode() == WebAssembly::BLOCK)
626       AfterSet.insert(&MI);
627 
628     // All END_TRY markers placed earlier belong to exceptions that contains
629     // this one.
630     if (MI.getOpcode() == WebAssembly::END_TRY)
631       AfterSet.insert(&MI);
632 #endif
633 
634     // If there is a previously placed END_LOOP marker and its header is after
635     // where TRY marker is, this loop is contained within the 'catch' part, so
636     // the END_TRY marker should go after that. Otherwise, the whole try-catch
637     // is contained within this loop, so the END_TRY should go before that.
638     if (MI.getOpcode() == WebAssembly::END_LOOP) {
639       // For a LOOP to be after TRY, LOOP's BB should be after TRY's BB; if they
640       // are in the same BB, LOOP is always before TRY.
641       if (EndToBegin[&MI]->getParent()->getNumber() > Header->getNumber())
642         BeforeSet.insert(&MI);
643 #ifndef NDEBUG
644       else
645         AfterSet.insert(&MI);
646 #endif
647     }
648 
649     // It is not possible for an END_BLOCK to be already in this block.
650   }
651 
652   // Mark the end of the TRY.
653   InsertPos = getEarliestInsertPos(Cont, BeforeSet, AfterSet);
654   MachineInstr *End =
655       BuildMI(*Cont, InsertPos, Bottom->findBranchDebugLoc(),
656               TII.get(WebAssembly::END_TRY));
657   registerTryScope(Begin, End, &MBB);
658 
659   // Track the farthest-spanning scope that ends at this point. We create two
660   // mappings: (BB with 'end_try' -> BB with 'try') and (BB with 'catch' -> BB
661   // with 'try'). We need to create 'catch' -> 'try' mapping here too because
662   // markers should not span across 'catch'. For example, this should not
663   // happen:
664   //
665   // try
666   //   block     --|  (X)
667   // catch         |
668   //   end_block --|
669   // end_try
670   for (int Number : {Cont->getNumber(), MBB.getNumber()}) {
671     if (!ScopeTops[Number] ||
672         ScopeTops[Number]->getNumber() > Header->getNumber())
673       ScopeTops[Number] = Header;
674   }
675 }
676 
removeUnnecessaryInstrs(MachineFunction & MF)677 void WebAssemblyCFGStackify::removeUnnecessaryInstrs(MachineFunction &MF) {
678   const auto &TII = *MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo();
679 
680   // When there is an unconditional branch right before a catch instruction and
681   // it branches to the end of end_try marker, we don't need the branch, because
682   // it there is no exception, the control flow transfers to that point anyway.
683   // bb0:
684   //   try
685   //     ...
686   //     br bb2      <- Not necessary
687   // bb1:
688   //   catch
689   //     ...
690   // bb2:
691   //   end
692   for (auto &MBB : MF) {
693     if (!MBB.isEHPad())
694       continue;
695 
696     MachineBasicBlock *TBB = nullptr, *FBB = nullptr;
697     SmallVector<MachineOperand, 4> Cond;
698     MachineBasicBlock *EHPadLayoutPred = MBB.getPrevNode();
699     MachineBasicBlock *Cont = BeginToEnd[EHPadToTry[&MBB]]->getParent();
700     bool Analyzable = !TII.analyzeBranch(*EHPadLayoutPred, TBB, FBB, Cond);
701     // This condition means either
702     // 1. This BB ends with a single unconditional branch whose destinaion is
703     //    Cont.
704     // 2. This BB ends with a conditional branch followed by an unconditional
705     //    branch, and the unconditional branch's destination is Cont.
706     // In both cases, we want to remove the last (= unconditional) branch.
707     if (Analyzable && ((Cond.empty() && TBB && TBB == Cont) ||
708                        (!Cond.empty() && FBB && FBB == Cont))) {
709       bool ErasedUncondBr = false;
710       (void)ErasedUncondBr;
711       for (auto I = EHPadLayoutPred->end(), E = EHPadLayoutPred->begin();
712            I != E; --I) {
713         auto PrevI = std::prev(I);
714         if (PrevI->isTerminator()) {
715           assert(PrevI->getOpcode() == WebAssembly::BR);
716           PrevI->eraseFromParent();
717           ErasedUncondBr = true;
718           break;
719         }
720       }
721       assert(ErasedUncondBr && "Unconditional branch not erased!");
722     }
723   }
724 
725   // When there are block / end_block markers that overlap with try / end_try
726   // markers, and the block and try markers' return types are the same, the
727   // block /end_block markers are not necessary, because try / end_try markers
728   // also can serve as boundaries for branches.
729   // block         <- Not necessary
730   //   try
731   //     ...
732   //   catch
733   //     ...
734   //   end
735   // end           <- Not necessary
736   SmallVector<MachineInstr *, 32> ToDelete;
737   for (auto &MBB : MF) {
738     for (auto &MI : MBB) {
739       if (MI.getOpcode() != WebAssembly::TRY)
740         continue;
741 
742       MachineInstr *Try = &MI, *EndTry = BeginToEnd[Try];
743       MachineBasicBlock *TryBB = Try->getParent();
744       MachineBasicBlock *Cont = EndTry->getParent();
745       int64_t RetType = Try->getOperand(0).getImm();
746       for (auto B = Try->getIterator(), E = std::next(EndTry->getIterator());
747            B != TryBB->begin() && E != Cont->end() &&
748            std::prev(B)->getOpcode() == WebAssembly::BLOCK &&
749            E->getOpcode() == WebAssembly::END_BLOCK &&
750            std::prev(B)->getOperand(0).getImm() == RetType;
751            --B, ++E) {
752         ToDelete.push_back(&*std::prev(B));
753         ToDelete.push_back(&*E);
754       }
755     }
756   }
757   for (auto *MI : ToDelete) {
758     if (MI->getOpcode() == WebAssembly::BLOCK)
759       unregisterScope(MI);
760     MI->eraseFromParent();
761   }
762 }
763 
764 // Get the appropriate copy opcode for the given register class.
getCopyOpcode(const TargetRegisterClass * RC)765 static unsigned getCopyOpcode(const TargetRegisterClass *RC) {
766   if (RC == &WebAssembly::I32RegClass)
767     return WebAssembly::COPY_I32;
768   if (RC == &WebAssembly::I64RegClass)
769     return WebAssembly::COPY_I64;
770   if (RC == &WebAssembly::F32RegClass)
771     return WebAssembly::COPY_F32;
772   if (RC == &WebAssembly::F64RegClass)
773     return WebAssembly::COPY_F64;
774   if (RC == &WebAssembly::V128RegClass)
775     return WebAssembly::COPY_V128;
776   if (RC == &WebAssembly::EXNREFRegClass)
777     return WebAssembly::COPY_EXNREF;
778   llvm_unreachable("Unexpected register class");
779 }
780 
781 // When MBB is split into MBB and Split, we should unstackify defs in MBB that
782 // have their uses in Split.
unstackifyVRegsUsedInSplitBB(MachineBasicBlock & MBB,MachineBasicBlock & Split,WebAssemblyFunctionInfo & MFI,MachineRegisterInfo & MRI,const WebAssemblyInstrInfo & TII)783 static void unstackifyVRegsUsedInSplitBB(MachineBasicBlock &MBB,
784                                          MachineBasicBlock &Split,
785                                          WebAssemblyFunctionInfo &MFI,
786                                          MachineRegisterInfo &MRI,
787                                          const WebAssemblyInstrInfo &TII) {
788   for (auto &MI : Split) {
789     for (auto &MO : MI.explicit_uses()) {
790       if (!MO.isReg() || Register::isPhysicalRegister(MO.getReg()))
791         continue;
792       if (MachineInstr *Def = MRI.getUniqueVRegDef(MO.getReg()))
793         if (Def->getParent() == &MBB)
794           MFI.unstackifyVReg(MO.getReg());
795     }
796   }
797 
798   // In RegStackify, when a register definition is used multiple times,
799   //    Reg = INST ...
800   //    INST ..., Reg, ...
801   //    INST ..., Reg, ...
802   //    INST ..., Reg, ...
803   //
804   // we introduce a TEE, which has the following form:
805   //    DefReg = INST ...
806   //    TeeReg, Reg = TEE_... DefReg
807   //    INST ..., TeeReg, ...
808   //    INST ..., Reg, ...
809   //    INST ..., Reg, ...
810   // with DefReg and TeeReg stackified but Reg not stackified.
811   //
812   // But the invariant that TeeReg should be stackified can be violated while we
813   // unstackify registers in the split BB above. In this case, we convert TEEs
814   // into two COPYs. This COPY will be eventually eliminated in ExplicitLocals.
815   //    DefReg = INST ...
816   //    TeeReg = COPY DefReg
817   //    Reg = COPY DefReg
818   //    INST ..., TeeReg, ...
819   //    INST ..., Reg, ...
820   //    INST ..., Reg, ...
821   for (auto I = MBB.begin(), E = MBB.end(); I != E;) {
822     MachineInstr &MI = *I++;
823     if (!WebAssembly::isTee(MI.getOpcode()))
824       continue;
825     Register TeeReg = MI.getOperand(0).getReg();
826     Register Reg = MI.getOperand(1).getReg();
827     Register DefReg = MI.getOperand(2).getReg();
828     if (!MFI.isVRegStackified(TeeReg)) {
829       // Now we are not using TEE anymore, so unstackify DefReg too
830       MFI.unstackifyVReg(DefReg);
831       unsigned CopyOpc = getCopyOpcode(MRI.getRegClass(DefReg));
832       BuildMI(MBB, &MI, MI.getDebugLoc(), TII.get(CopyOpc), TeeReg)
833           .addReg(DefReg);
834       BuildMI(MBB, &MI, MI.getDebugLoc(), TII.get(CopyOpc), Reg).addReg(DefReg);
835       MI.eraseFromParent();
836     }
837   }
838 }
839 
fixUnwindMismatches(MachineFunction & MF)840 bool WebAssemblyCFGStackify::fixUnwindMismatches(MachineFunction &MF) {
841   const auto &TII = *MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo();
842   auto &MFI = *MF.getInfo<WebAssemblyFunctionInfo>();
843   MachineRegisterInfo &MRI = MF.getRegInfo();
844 
845   // Linearizing the control flow by placing TRY / END_TRY markers can create
846   // mismatches in unwind destinations. There are two kinds of mismatches we
847   // try to solve here.
848 
849   // 1. When an instruction may throw, but the EH pad it will unwind to can be
850   //    different from the original CFG.
851   //
852   // Example: we have the following CFG:
853   // bb0:
854   //   call @foo (if it throws, unwind to bb2)
855   // bb1:
856   //   call @bar (if it throws, unwind to bb3)
857   // bb2 (ehpad):
858   //   catch
859   //   ...
860   // bb3 (ehpad)
861   //   catch
862   //   handler body
863   //
864   // And the CFG is sorted in this order. Then after placing TRY markers, it
865   // will look like: (BB markers are omitted)
866   // try $label1
867   //   try
868   //     call @foo
869   //     call @bar   (if it throws, unwind to bb3)
870   //   catch         <- ehpad (bb2)
871   //     ...
872   //   end_try
873   // catch           <- ehpad (bb3)
874   //   handler body
875   // end_try
876   //
877   // Now if bar() throws, it is going to end up ip in bb2, not bb3, where it
878   // is supposed to end up. We solve this problem by
879   // a. Split the target unwind EH pad (here bb3) so that the handler body is
880   //    right after 'end_try', which means we extract the handler body out of
881   //    the catch block. We do this because this handler body should be
882   //    somewhere branch-eable from the inner scope.
883   // b. Wrap the call that has an incorrect unwind destination ('call @bar'
884   //    here) with a nested try/catch/end_try scope, and within the new catch
885   //    block, branches to the handler body.
886   // c. Place a branch after the newly inserted nested end_try so it can bypass
887   //    the handler body, which is now outside of a catch block.
888   //
889   // The result will like as follows. (new: a) means this instruction is newly
890   // created in the process of doing 'a' above.
891   //
892   // block $label0                 (new: placeBlockMarker)
893   //   try $label1
894   //     try
895   //       call @foo
896   //       try                     (new: b)
897   //         call @bar
898   //       catch                   (new: b)
899   //         local.set n / drop    (new: b)
900   //         br $label1            (new: b)
901   //       end_try                 (new: b)
902   //     catch                     <- ehpad (bb2)
903   //     end_try
904   //     br $label0                (new: c)
905   //   catch                       <- ehpad (bb3)
906   //   end_try                     (hoisted: a)
907   //   handler body
908   // end_block                     (new: placeBlockMarker)
909   //
910   // Note that the new wrapping block/end_block will be generated later in
911   // placeBlockMarker.
912   //
913   // TODO Currently local.set and local.gets are generated to move exnref value
914   // created by catches. That's because we don't support yielding values from a
915   // block in LLVM machine IR yet, even though it is supported by wasm. Delete
916   // unnecessary local.get/local.sets once yielding values from a block is
917   // supported. The full EH spec requires multi-value support to do this, but
918   // for C++ we don't yet need it because we only throw a single i32.
919   //
920   // ---
921   // 2. The same as 1, but in this case an instruction unwinds to a caller
922   //    function and not another EH pad.
923   //
924   // Example: we have the following CFG:
925   // bb0:
926   //   call @foo (if it throws, unwind to bb2)
927   // bb1:
928   //   call @bar (if it throws, unwind to caller)
929   // bb2 (ehpad):
930   //   catch
931   //   ...
932   //
933   // And the CFG is sorted in this order. Then after placing TRY markers, it
934   // will look like:
935   // try
936   //   call @foo
937   //   call @bar   (if it throws, unwind to caller)
938   // catch         <- ehpad (bb2)
939   //   ...
940   // end_try
941   //
942   // Now if bar() throws, it is going to end up ip in bb2, when it is supposed
943   // throw up to the caller.
944   // We solve this problem by
945   // a. Create a new 'appendix' BB at the end of the function and put a single
946   //    'rethrow' instruction (+ local.get) in there.
947   // b. Wrap the call that has an incorrect unwind destination ('call @bar'
948   //    here) with a nested try/catch/end_try scope, and within the new catch
949   //    block, branches to the new appendix block.
950   //
951   // block $label0          (new: placeBlockMarker)
952   //   try
953   //     call @foo
954   //     try                (new: b)
955   //       call @bar
956   //     catch              (new: b)
957   //       local.set n      (new: b)
958   //       br $label0       (new: b)
959   //     end_try            (new: b)
960   //   catch                <- ehpad (bb2)
961   //     ...
962   //   end_try
963   // ...
964   // end_block              (new: placeBlockMarker)
965   // local.get n            (new: a)  <- appendix block
966   // rethrow                (new: a)
967   //
968   // In case there are multiple calls in a BB that may throw to the caller, they
969   // can be wrapped together in one nested try scope. (In 1, this couldn't
970   // happen, because may-throwing instruction there had an unwind destination,
971   // i.e., it was an invoke before, and there could be only one invoke within a
972   // BB.)
973 
974   SmallVector<const MachineBasicBlock *, 8> EHPadStack;
975   // Range of intructions to be wrapped in a new nested try/catch
976   using TryRange = std::pair<MachineInstr *, MachineInstr *>;
977   // In original CFG, <unwind destination BB, a vector of try ranges>
978   DenseMap<MachineBasicBlock *, SmallVector<TryRange, 4>> UnwindDestToTryRanges;
979   // In new CFG, <destination to branch to, a vector of try ranges>
980   DenseMap<MachineBasicBlock *, SmallVector<TryRange, 4>> BrDestToTryRanges;
981   // In new CFG, <destination to branch to, register containing exnref>
982   DenseMap<MachineBasicBlock *, unsigned> BrDestToExnReg;
983 
984   // Destinations for branches that will be newly added, for which a new
985   // BLOCK/END_BLOCK markers are necessary.
986   SmallVector<MachineBasicBlock *, 8> BrDests;
987 
988   // Gather possibly throwing calls (i.e., previously invokes) whose current
989   // unwind destination is not the same as the original CFG.
990   for (auto &MBB : reverse(MF)) {
991     bool SeenThrowableInstInBB = false;
992     for (auto &MI : reverse(MBB)) {
993       if (MI.getOpcode() == WebAssembly::TRY)
994         EHPadStack.pop_back();
995       else if (MI.getOpcode() == WebAssembly::CATCH)
996         EHPadStack.push_back(MI.getParent());
997 
998       // In this loop we only gather calls that have an EH pad to unwind. So
999       // there will be at most 1 such call (= invoke) in a BB, so after we've
1000       // seen one, we can skip the rest of BB. Also if MBB has no EH pad
1001       // successor or MI does not throw, this is not an invoke.
1002       if (SeenThrowableInstInBB || !MBB.hasEHPadSuccessor() ||
1003           !WebAssembly::mayThrow(MI))
1004         continue;
1005       SeenThrowableInstInBB = true;
1006 
1007       // If the EH pad on the stack top is where this instruction should unwind
1008       // next, we're good.
1009       MachineBasicBlock *UnwindDest = nullptr;
1010       for (auto *Succ : MBB.successors()) {
1011         if (Succ->isEHPad()) {
1012           UnwindDest = Succ;
1013           break;
1014         }
1015       }
1016       if (EHPadStack.back() == UnwindDest)
1017         continue;
1018 
1019       // If not, record the range.
1020       UnwindDestToTryRanges[UnwindDest].push_back(TryRange(&MI, &MI));
1021     }
1022   }
1023 
1024   assert(EHPadStack.empty());
1025 
1026   // Gather possibly throwing calls that are supposed to unwind up to the caller
1027   // if they throw, but currently unwind to an incorrect destination. Unlike the
1028   // loop above, there can be multiple calls within a BB that unwind to the
1029   // caller, which we should group together in a range.
1030   bool NeedAppendixBlock = false;
1031   for (auto &MBB : reverse(MF)) {
1032     MachineInstr *RangeBegin = nullptr, *RangeEnd = nullptr; // inclusive
1033     for (auto &MI : reverse(MBB)) {
1034       if (MI.getOpcode() == WebAssembly::TRY)
1035         EHPadStack.pop_back();
1036       else if (MI.getOpcode() == WebAssembly::CATCH)
1037         EHPadStack.push_back(MI.getParent());
1038 
1039       // If MBB has an EH pad successor, this inst does not unwind to caller.
1040       if (MBB.hasEHPadSuccessor())
1041         continue;
1042 
1043       // We wrap up the current range when we see a marker even if we haven't
1044       // finished a BB.
1045       if (RangeEnd && WebAssembly::isMarker(MI.getOpcode())) {
1046         NeedAppendixBlock = true;
1047         // Record the range. nullptr here means the unwind destination is the
1048         // caller.
1049         UnwindDestToTryRanges[nullptr].push_back(
1050             TryRange(RangeBegin, RangeEnd));
1051         RangeBegin = RangeEnd = nullptr; // Reset range pointers
1052       }
1053 
1054       // If EHPadStack is empty, that means it is correctly unwind to caller if
1055       // it throws, so we're good. If MI does not throw, we're good too.
1056       if (EHPadStack.empty() || !WebAssembly::mayThrow(MI))
1057         continue;
1058 
1059       // We found an instruction that unwinds to the caller but currently has an
1060       // incorrect unwind destination. Create a new range or increment the
1061       // currently existing range.
1062       if (!RangeEnd)
1063         RangeBegin = RangeEnd = &MI;
1064       else
1065         RangeBegin = &MI;
1066     }
1067 
1068     if (RangeEnd) {
1069       NeedAppendixBlock = true;
1070       // Record the range. nullptr here means the unwind destination is the
1071       // caller.
1072       UnwindDestToTryRanges[nullptr].push_back(TryRange(RangeBegin, RangeEnd));
1073       RangeBegin = RangeEnd = nullptr; // Reset range pointers
1074     }
1075   }
1076 
1077   assert(EHPadStack.empty());
1078   // We don't have any unwind destination mismatches to resolve.
1079   if (UnwindDestToTryRanges.empty())
1080     return false;
1081 
1082   // If we found instructions that should unwind to the caller but currently
1083   // have incorrect unwind destination, we create an appendix block at the end
1084   // of the function with a local.get and a rethrow instruction.
1085   if (NeedAppendixBlock) {
1086     auto *AppendixBB = getAppendixBlock(MF);
1087     Register ExnReg = MRI.createVirtualRegister(&WebAssembly::EXNREFRegClass);
1088     BuildMI(AppendixBB, DebugLoc(), TII.get(WebAssembly::RETHROW))
1089         .addReg(ExnReg);
1090     // These instruction ranges should branch to this appendix BB.
1091     for (auto Range : UnwindDestToTryRanges[nullptr])
1092       BrDestToTryRanges[AppendixBB].push_back(Range);
1093     BrDestToExnReg[AppendixBB] = ExnReg;
1094   }
1095 
1096   // We loop through unwind destination EH pads that are targeted from some
1097   // inner scopes. Because these EH pads are destination of more than one scope
1098   // now, we split them so that the handler body is after 'end_try'.
1099   // - Before
1100   // ehpad:
1101   //   catch
1102   //   local.set n / drop
1103   //   handler body
1104   // ...
1105   // cont:
1106   //   end_try
1107   //
1108   // - After
1109   // ehpad:
1110   //   catch
1111   //   local.set n / drop
1112   // brdest:               (new)
1113   //   end_try             (hoisted from 'cont' BB)
1114   //   handler body        (taken from 'ehpad')
1115   // ...
1116   // cont:
1117   for (auto &P : UnwindDestToTryRanges) {
1118     NumUnwindMismatches += P.second.size();
1119 
1120     // This means the destination is the appendix BB, which was separately
1121     // handled above.
1122     if (!P.first)
1123       continue;
1124 
1125     MachineBasicBlock *EHPad = P.first;
1126     Register ExnReg = 0;
1127     MachineInstr *Catch = findCatch(EHPad, ExnReg);
1128     auto SplitPos = std::next(Catch->getIterator());
1129 
1130     // Create a new BB that's gonna be the destination for branches from the
1131     // inner mismatched scope.
1132     MachineInstr *BeginTry = EHPadToTry[EHPad];
1133     MachineInstr *EndTry = BeginToEnd[BeginTry];
1134     MachineBasicBlock *Cont = EndTry->getParent();
1135     auto *BrDest = MF.CreateMachineBasicBlock();
1136     MF.insert(std::next(EHPad->getIterator()), BrDest);
1137     // Hoist up the existing 'end_try'.
1138     BrDest->insert(BrDest->end(), EndTry->removeFromParent());
1139     // Take out the handler body from EH pad to the new branch destination BB.
1140     BrDest->splice(BrDest->end(), EHPad, SplitPos, EHPad->end());
1141     unstackifyVRegsUsedInSplitBB(*EHPad, *BrDest, MFI, MRI, TII);
1142     // Fix predecessor-successor relationship.
1143     BrDest->transferSuccessors(EHPad);
1144     EHPad->addSuccessor(BrDest);
1145 
1146     // All try ranges that were supposed to unwind to this EH pad now have to
1147     // branch to this new branch dest BB.
1148     for (auto Range : UnwindDestToTryRanges[EHPad])
1149       BrDestToTryRanges[BrDest].push_back(Range);
1150     BrDestToExnReg[BrDest] = ExnReg;
1151 
1152     // In case we fall through to the continuation BB after the catch block, we
1153     // now have to add a branch to it.
1154     // - Before
1155     // try
1156     //   ...
1157     //   (falls through to 'cont')
1158     // catch
1159     //   handler body
1160     // end
1161     //               <-- cont
1162     //
1163     // - After
1164     // try
1165     //   ...
1166     //   br %cont    (new)
1167     // catch
1168     // end
1169     // handler body
1170     //               <-- cont
1171     MachineBasicBlock *EHPadLayoutPred = &*std::prev(EHPad->getIterator());
1172     MachineBasicBlock *TBB = nullptr, *FBB = nullptr;
1173     SmallVector<MachineOperand, 4> Cond;
1174     bool Analyzable = !TII.analyzeBranch(*EHPadLayoutPred, TBB, FBB, Cond);
1175     if (Analyzable && !TBB && !FBB) {
1176       DebugLoc DL = EHPadLayoutPred->empty()
1177                         ? DebugLoc()
1178                         : EHPadLayoutPred->rbegin()->getDebugLoc();
1179       BuildMI(EHPadLayoutPred, DL, TII.get(WebAssembly::BR)).addMBB(Cont);
1180       BrDests.push_back(Cont);
1181     }
1182   }
1183 
1184   // For possibly throwing calls whose unwind destinations are currently
1185   // incorrect because of CFG linearization, we wrap them with a nested
1186   // try/catch/end_try, and within the new catch block, we branch to the correct
1187   // handler.
1188   // - Before
1189   // mbb:
1190   //   call @foo       <- Unwind destination mismatch!
1191   // ehpad:
1192   //   ...
1193   //
1194   // - After
1195   // mbb:
1196   //   try                (new)
1197   //   call @foo
1198   // nested-ehpad:        (new)
1199   //   catch              (new)
1200   //   local.set n / drop (new)
1201   //   br %brdest         (new)
1202   // nested-end:          (new)
1203   //   end_try            (new)
1204   // ehpad:
1205   //   ...
1206   for (auto &P : BrDestToTryRanges) {
1207     MachineBasicBlock *BrDest = P.first;
1208     auto &TryRanges = P.second;
1209     unsigned ExnReg = BrDestToExnReg[BrDest];
1210 
1211     for (auto Range : TryRanges) {
1212       MachineInstr *RangeBegin = nullptr, *RangeEnd = nullptr;
1213       std::tie(RangeBegin, RangeEnd) = Range;
1214       auto *MBB = RangeBegin->getParent();
1215       // Store the first function call from this range, because RangeBegin can
1216       // be moved to point EH_LABEL before the call
1217       MachineInstr *RangeBeginCall = RangeBegin;
1218 
1219       // Include possible EH_LABELs in the range
1220       if (RangeBegin->getIterator() != MBB->begin() &&
1221           std::prev(RangeBegin->getIterator())->isEHLabel())
1222         RangeBegin = &*std::prev(RangeBegin->getIterator());
1223       if (std::next(RangeEnd->getIterator()) != MBB->end() &&
1224           std::next(RangeEnd->getIterator())->isEHLabel())
1225         RangeEnd = &*std::next(RangeEnd->getIterator());
1226 
1227       MachineBasicBlock *EHPad = nullptr;
1228       for (auto *Succ : MBB->successors()) {
1229         if (Succ->isEHPad()) {
1230           EHPad = Succ;
1231           break;
1232         }
1233       }
1234 
1235       // Local expression tree before the first call of this range should go
1236       // after the nested TRY.
1237       SmallPtrSet<const MachineInstr *, 4> AfterSet;
1238       AfterSet.insert(RangeBegin);
1239       AfterSet.insert(RangeBeginCall);
1240       for (auto I = MachineBasicBlock::iterator(RangeBeginCall),
1241                 E = MBB->begin();
1242            I != E; --I) {
1243         if (std::prev(I)->isDebugInstr() || std::prev(I)->isPosition())
1244           continue;
1245         if (WebAssembly::isChild(*std::prev(I), MFI))
1246           AfterSet.insert(&*std::prev(I));
1247         else
1248           break;
1249       }
1250 
1251       // Create the nested try instruction.
1252       auto InsertPos = getLatestInsertPos(
1253           MBB, SmallPtrSet<const MachineInstr *, 4>(), AfterSet);
1254       MachineInstr *NestedTry =
1255           BuildMI(*MBB, InsertPos, RangeBegin->getDebugLoc(),
1256                   TII.get(WebAssembly::TRY))
1257               .addImm(int64_t(WebAssembly::BlockType::Void));
1258 
1259       // Create the nested EH pad and fill instructions in.
1260       MachineBasicBlock *NestedEHPad = MF.CreateMachineBasicBlock();
1261       MF.insert(std::next(MBB->getIterator()), NestedEHPad);
1262       NestedEHPad->setIsEHPad();
1263       NestedEHPad->setIsEHScopeEntry();
1264       BuildMI(NestedEHPad, RangeEnd->getDebugLoc(), TII.get(WebAssembly::CATCH),
1265               ExnReg);
1266       BuildMI(NestedEHPad, RangeEnd->getDebugLoc(), TII.get(WebAssembly::BR))
1267           .addMBB(BrDest);
1268 
1269       // Create the nested continuation BB and end_try instruction.
1270       MachineBasicBlock *NestedCont = MF.CreateMachineBasicBlock();
1271       MF.insert(std::next(NestedEHPad->getIterator()), NestedCont);
1272       MachineInstr *NestedEndTry =
1273           BuildMI(*NestedCont, NestedCont->begin(), RangeEnd->getDebugLoc(),
1274                   TII.get(WebAssembly::END_TRY));
1275       // In case MBB has more instructions after the try range, move them to the
1276       // new nested continuation BB.
1277       NestedCont->splice(NestedCont->end(), MBB,
1278                          std::next(RangeEnd->getIterator()), MBB->end());
1279       unstackifyVRegsUsedInSplitBB(*MBB, *NestedCont, MFI, MRI, TII);
1280       registerTryScope(NestedTry, NestedEndTry, NestedEHPad);
1281 
1282       // Fix predecessor-successor relationship.
1283       NestedCont->transferSuccessors(MBB);
1284       if (EHPad) {
1285         NestedCont->removeSuccessor(EHPad);
1286         // If EHPad does not have any predecessors left after removing
1287         // NextedCont predecessor, remove its successor too, because this EHPad
1288         // is not reachable from the entry BB anyway. We can't remove EHPad BB
1289         // itself because it can contain 'catch' or 'end', which are necessary
1290         // for keeping try-catch-end structure.
1291         if (EHPad->pred_empty())
1292           EHPad->removeSuccessor(BrDest);
1293       }
1294       MBB->addSuccessor(NestedEHPad);
1295       MBB->addSuccessor(NestedCont);
1296       NestedEHPad->addSuccessor(BrDest);
1297     }
1298   }
1299 
1300   // Renumber BBs and recalculate ScopeTop info because new BBs might have been
1301   // created and inserted above.
1302   MF.RenumberBlocks();
1303   ScopeTops.clear();
1304   ScopeTops.resize(MF.getNumBlockIDs());
1305   for (auto &MBB : reverse(MF)) {
1306     for (auto &MI : reverse(MBB)) {
1307       if (ScopeTops[MBB.getNumber()])
1308         break;
1309       switch (MI.getOpcode()) {
1310       case WebAssembly::END_BLOCK:
1311       case WebAssembly::END_LOOP:
1312       case WebAssembly::END_TRY:
1313         ScopeTops[MBB.getNumber()] = EndToBegin[&MI]->getParent();
1314         break;
1315       case WebAssembly::CATCH:
1316         ScopeTops[MBB.getNumber()] = EHPadToTry[&MBB]->getParent();
1317         break;
1318       }
1319     }
1320   }
1321 
1322   // Recompute the dominator tree.
1323   getAnalysis<MachineDominatorTree>().runOnMachineFunction(MF);
1324 
1325   // Place block markers for newly added branches, if necessary.
1326 
1327   // If we've created an appendix BB and a branch to it, place a block/end_block
1328   // marker for that. For some new branches, those branch destination BBs start
1329   // with a hoisted end_try marker, so we don't need a new marker there.
1330   if (AppendixBB)
1331     BrDests.push_back(AppendixBB);
1332 
1333   llvm::sort(BrDests,
1334              [&](const MachineBasicBlock *A, const MachineBasicBlock *B) {
1335                auto ANum = A->getNumber();
1336                auto BNum = B->getNumber();
1337                return ANum < BNum;
1338              });
1339   for (auto *Dest : BrDests)
1340     placeBlockMarker(*Dest);
1341 
1342   return true;
1343 }
1344 
1345 static unsigned
getDepth(const SmallVectorImpl<const MachineBasicBlock * > & Stack,const MachineBasicBlock * MBB)1346 getDepth(const SmallVectorImpl<const MachineBasicBlock *> &Stack,
1347          const MachineBasicBlock *MBB) {
1348   unsigned Depth = 0;
1349   for (auto X : reverse(Stack)) {
1350     if (X == MBB)
1351       break;
1352     ++Depth;
1353   }
1354   assert(Depth < Stack.size() && "Branch destination should be in scope");
1355   return Depth;
1356 }
1357 
1358 /// In normal assembly languages, when the end of a function is unreachable,
1359 /// because the function ends in an infinite loop or a noreturn call or similar,
1360 /// it isn't necessary to worry about the function return type at the end of
1361 /// the function, because it's never reached. However, in WebAssembly, blocks
1362 /// that end at the function end need to have a return type signature that
1363 /// matches the function signature, even though it's unreachable. This function
1364 /// checks for such cases and fixes up the signatures.
fixEndsAtEndOfFunction(MachineFunction & MF)1365 void WebAssemblyCFGStackify::fixEndsAtEndOfFunction(MachineFunction &MF) {
1366   const auto &MFI = *MF.getInfo<WebAssemblyFunctionInfo>();
1367 
1368   if (MFI.getResults().empty())
1369     return;
1370 
1371   // MCInstLower will add the proper types to multivalue signatures based on the
1372   // function return type
1373   WebAssembly::BlockType RetType =
1374       MFI.getResults().size() > 1
1375           ? WebAssembly::BlockType::Multivalue
1376           : WebAssembly::BlockType(
1377                 WebAssembly::toValType(MFI.getResults().front()));
1378 
1379   SmallVector<MachineBasicBlock::reverse_iterator, 4> Worklist;
1380   Worklist.push_back(MF.rbegin()->rbegin());
1381 
1382   auto Process = [&](MachineBasicBlock::reverse_iterator It) {
1383     auto *MBB = It->getParent();
1384     while (It != MBB->rend()) {
1385       MachineInstr &MI = *It++;
1386       if (MI.isPosition() || MI.isDebugInstr())
1387         continue;
1388       switch (MI.getOpcode()) {
1389       case WebAssembly::END_TRY: {
1390         // If a 'try''s return type is fixed, both its try body and catch body
1391         // should satisfy the return type, so we need to search 'end'
1392         // instructions before its corresponding 'catch' too.
1393         auto *EHPad = TryToEHPad.lookup(EndToBegin[&MI]);
1394         assert(EHPad);
1395         Worklist.push_back(std::next(findCatch(EHPad)->getReverseIterator()));
1396         LLVM_FALLTHROUGH;
1397       }
1398       case WebAssembly::END_BLOCK:
1399       case WebAssembly::END_LOOP:
1400         EndToBegin[&MI]->getOperand(0).setImm(int32_t(RetType));
1401         continue;
1402       default:
1403         // Something other than an `end`. We're done for this BB.
1404         return;
1405       }
1406     }
1407     // We've reached the beginning of a BB. Continue the search in the previous
1408     // BB.
1409     Worklist.push_back(MBB->getPrevNode()->rbegin());
1410   };
1411 
1412   while (!Worklist.empty())
1413     Process(Worklist.pop_back_val());
1414 }
1415 
1416 // WebAssembly functions end with an end instruction, as if the function body
1417 // were a block.
appendEndToFunction(MachineFunction & MF,const WebAssemblyInstrInfo & TII)1418 static void appendEndToFunction(MachineFunction &MF,
1419                                 const WebAssemblyInstrInfo &TII) {
1420   BuildMI(MF.back(), MF.back().end(),
1421           MF.back().findPrevDebugLoc(MF.back().end()),
1422           TII.get(WebAssembly::END_FUNCTION));
1423 }
1424 
1425 /// Insert LOOP/TRY/BLOCK markers at appropriate places.
placeMarkers(MachineFunction & MF)1426 void WebAssemblyCFGStackify::placeMarkers(MachineFunction &MF) {
1427   // We allocate one more than the number of blocks in the function to
1428   // accommodate for the possible fake block we may insert at the end.
1429   ScopeTops.resize(MF.getNumBlockIDs() + 1);
1430   // Place the LOOP for MBB if MBB is the header of a loop.
1431   for (auto &MBB : MF)
1432     placeLoopMarker(MBB);
1433 
1434   const MCAsmInfo *MCAI = MF.getTarget().getMCAsmInfo();
1435   for (auto &MBB : MF) {
1436     if (MBB.isEHPad()) {
1437       // Place the TRY for MBB if MBB is the EH pad of an exception.
1438       if (MCAI->getExceptionHandlingType() == ExceptionHandling::Wasm &&
1439           MF.getFunction().hasPersonalityFn())
1440         placeTryMarker(MBB);
1441     } else {
1442       // Place the BLOCK for MBB if MBB is branched to from above.
1443       placeBlockMarker(MBB);
1444     }
1445   }
1446   // Fix mismatches in unwind destinations induced by linearizing the code.
1447   if (MCAI->getExceptionHandlingType() == ExceptionHandling::Wasm &&
1448       MF.getFunction().hasPersonalityFn())
1449     fixUnwindMismatches(MF);
1450 }
1451 
rewriteDepthImmediates(MachineFunction & MF)1452 void WebAssemblyCFGStackify::rewriteDepthImmediates(MachineFunction &MF) {
1453   // Now rewrite references to basic blocks to be depth immediates.
1454   SmallVector<const MachineBasicBlock *, 8> Stack;
1455   for (auto &MBB : reverse(MF)) {
1456     for (auto I = MBB.rbegin(), E = MBB.rend(); I != E; ++I) {
1457       MachineInstr &MI = *I;
1458       switch (MI.getOpcode()) {
1459       case WebAssembly::BLOCK:
1460       case WebAssembly::TRY:
1461         assert(ScopeTops[Stack.back()->getNumber()]->getNumber() <=
1462                    MBB.getNumber() &&
1463                "Block/try marker should be balanced");
1464         Stack.pop_back();
1465         break;
1466 
1467       case WebAssembly::LOOP:
1468         assert(Stack.back() == &MBB && "Loop top should be balanced");
1469         Stack.pop_back();
1470         break;
1471 
1472       case WebAssembly::END_BLOCK:
1473       case WebAssembly::END_TRY:
1474         Stack.push_back(&MBB);
1475         break;
1476 
1477       case WebAssembly::END_LOOP:
1478         Stack.push_back(EndToBegin[&MI]->getParent());
1479         break;
1480 
1481       default:
1482         if (MI.isTerminator()) {
1483           // Rewrite MBB operands to be depth immediates.
1484           SmallVector<MachineOperand, 4> Ops(MI.operands());
1485           while (MI.getNumOperands() > 0)
1486             MI.RemoveOperand(MI.getNumOperands() - 1);
1487           for (auto MO : Ops) {
1488             if (MO.isMBB())
1489               MO = MachineOperand::CreateImm(getDepth(Stack, MO.getMBB()));
1490             MI.addOperand(MF, MO);
1491           }
1492         }
1493         break;
1494       }
1495     }
1496   }
1497   assert(Stack.empty() && "Control flow should be balanced");
1498 }
1499 
releaseMemory()1500 void WebAssemblyCFGStackify::releaseMemory() {
1501   ScopeTops.clear();
1502   BeginToEnd.clear();
1503   EndToBegin.clear();
1504   TryToEHPad.clear();
1505   EHPadToTry.clear();
1506   AppendixBB = nullptr;
1507 }
1508 
runOnMachineFunction(MachineFunction & MF)1509 bool WebAssemblyCFGStackify::runOnMachineFunction(MachineFunction &MF) {
1510   LLVM_DEBUG(dbgs() << "********** CFG Stackifying **********\n"
1511                        "********** Function: "
1512                     << MF.getName() << '\n');
1513   const MCAsmInfo *MCAI = MF.getTarget().getMCAsmInfo();
1514 
1515   releaseMemory();
1516 
1517   // Liveness is not tracked for VALUE_STACK physreg.
1518   MF.getRegInfo().invalidateLiveness();
1519 
1520   // Place the BLOCK/LOOP/TRY markers to indicate the beginnings of scopes.
1521   placeMarkers(MF);
1522 
1523   // Remove unnecessary instructions possibly introduced by try/end_trys.
1524   if (MCAI->getExceptionHandlingType() == ExceptionHandling::Wasm &&
1525       MF.getFunction().hasPersonalityFn())
1526     removeUnnecessaryInstrs(MF);
1527 
1528   // Convert MBB operands in terminators to relative depth immediates.
1529   rewriteDepthImmediates(MF);
1530 
1531   // Fix up block/loop/try signatures at the end of the function to conform to
1532   // WebAssembly's rules.
1533   fixEndsAtEndOfFunction(MF);
1534 
1535   // Add an end instruction at the end of the function body.
1536   const auto &TII = *MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo();
1537   if (!MF.getSubtarget<WebAssemblySubtarget>()
1538            .getTargetTriple()
1539            .isOSBinFormatELF())
1540     appendEndToFunction(MF, TII);
1541 
1542   MF.getInfo<WebAssemblyFunctionInfo>()->setCFGStackified();
1543   return true;
1544 }
1545