LLVM  8.0.1
WebAssemblyCFGStackify.cpp
Go to the documentation of this file.
1 //===-- WebAssemblyCFGStackify.cpp - CFG Stackification -------------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 ///
10 /// \file
11 /// This file implements a CFG stacking pass.
12 ///
13 /// This pass inserts BLOCK, LOOP, and TRY markers to mark the start of scopes,
14 /// since scope boundaries serve as the labels for WebAssembly's control
15 /// transfers.
16 ///
17 /// This is sufficient to convert arbitrary CFGs into a form that works on
18 /// WebAssembly, provided that all loops are single-entry.
19 ///
20 /// In case we use exceptions, this pass also fixes mismatches in unwind
21 /// destinations created during transforming CFG into wasm structured format.
22 ///
23 //===----------------------------------------------------------------------===//
24 
26 #include "WebAssembly.h"
29 #include "WebAssemblySubtarget.h"
30 #include "WebAssemblyUtilities.h"
36 #include "llvm/CodeGen/Passes.h"
38 #include "llvm/MC/MCAsmInfo.h"
39 #include "llvm/Support/Debug.h"
41 using namespace llvm;
42 
43 #define DEBUG_TYPE "wasm-cfg-stackify"
44 
45 namespace {
46 class WebAssemblyCFGStackify final : public MachineFunctionPass {
47  StringRef getPassName() const override { return "WebAssembly CFG Stackify"; }
48 
49  void getAnalysisUsage(AnalysisUsage &AU) const override {
54  }
55 
56  bool runOnMachineFunction(MachineFunction &MF) override;
57 
58  // For each block whose label represents the end of a scope, record the block
59  // which holds the beginning of the scope. This will allow us to quickly skip
60  // over scoped regions when walking blocks.
62 
63  void placeMarkers(MachineFunction &MF);
64  void placeBlockMarker(MachineBasicBlock &MBB);
65  void placeLoopMarker(MachineBasicBlock &MBB);
66  void placeTryMarker(MachineBasicBlock &MBB);
67  void rewriteDepthImmediates(MachineFunction &MF);
68  void fixEndsAtEndOfFunction(MachineFunction &MF);
69 
70  // For each BLOCK|LOOP|TRY, the corresponding END_(BLOCK|LOOP|TRY).
72  // For each END_(BLOCK|LOOP|TRY), the corresponding BLOCK|LOOP|TRY.
74  // <TRY marker, EH pad> map
76  // <EH pad, TRY marker> map
78  // <LOOP|TRY marker, Loop/exception bottom BB> map
80 
81  // Helper functions to register scope information created by marker
82  // instructions.
83  void registerScope(MachineInstr *Begin, MachineInstr *End);
84  void registerTryScope(MachineInstr *Begin, MachineInstr *End,
85  MachineBasicBlock *EHPad);
86 
88 
89 public:
90  static char ID; // Pass identification, replacement for typeid
91  WebAssemblyCFGStackify() : MachineFunctionPass(ID) {}
92  ~WebAssemblyCFGStackify() override { releaseMemory(); }
93  void releaseMemory() override;
94 };
95 } // end anonymous namespace
96 
98 INITIALIZE_PASS(WebAssemblyCFGStackify, DEBUG_TYPE,
99  "Insert BLOCK and LOOP markers for WebAssembly scopes", false,
100  false)
101 
103  return new WebAssemblyCFGStackify();
104 }
105 
106 /// Test whether Pred has any terminators explicitly branching to MBB, as
107 /// opposed to falling through. Note that it's possible (eg. in unoptimized
108 /// code) for a branch instruction to both branch to a block and fallthrough
109 /// to it, so we check the actual branch operands to see if there are any
110 /// explicit mentions.
112  MachineBasicBlock *MBB) {
113  for (MachineInstr &MI : Pred->terminators())
114  // Even if a rethrow takes a BB argument, it is not a branch
116  for (MachineOperand &MO : MI.explicit_operands())
117  if (MO.isMBB() && MO.getMBB() == MBB)
118  return true;
119  return false;
120 }
121 
122 // Returns an iterator to the earliest position possible within the MBB,
123 // satisfying the restrictions given by BeforeSet and AfterSet. BeforeSet
124 // contains instructions that should go before the marker, and AfterSet contains
125 // ones that should go after the marker. In this function, AfterSet is only
126 // used for sanity checking.
129  const SmallPtrSet<const MachineInstr *, 4> &BeforeSet,
130  const SmallPtrSet<const MachineInstr *, 4> &AfterSet) {
131  auto InsertPos = MBB->end();
132  while (InsertPos != MBB->begin()) {
133  if (BeforeSet.count(&*std::prev(InsertPos))) {
134 #ifndef NDEBUG
135  // Sanity check
136  for (auto Pos = InsertPos, E = MBB->begin(); Pos != E; --Pos)
137  assert(!AfterSet.count(&*std::prev(Pos)));
138 #endif
139  break;
140  }
141  --InsertPos;
142  }
143  return InsertPos;
144 }
145 
146 // Returns an iterator to the latest position possible within the MBB,
147 // satisfying the restrictions given by BeforeSet and AfterSet. BeforeSet
148 // contains instructions that should go before the marker, and AfterSet contains
149 // ones that should go after the marker. In this function, BeforeSet is only
150 // used for sanity checking.
153  const SmallPtrSet<const MachineInstr *, 4> &BeforeSet,
154  const SmallPtrSet<const MachineInstr *, 4> &AfterSet) {
155  auto InsertPos = MBB->begin();
156  while (InsertPos != MBB->end()) {
157  if (AfterSet.count(&*InsertPos)) {
158 #ifndef NDEBUG
159  // Sanity check
160  for (auto Pos = InsertPos, E = MBB->end(); Pos != E; ++Pos)
161  assert(!BeforeSet.count(&*Pos));
162 #endif
163  break;
164  }
165  ++InsertPos;
166  }
167  return InsertPos;
168 }
169 
170 void WebAssemblyCFGStackify::registerScope(MachineInstr *Begin,
171  MachineInstr *End) {
172  BeginToEnd[Begin] = End;
173  EndToBegin[End] = Begin;
174 }
175 
176 void WebAssemblyCFGStackify::registerTryScope(MachineInstr *Begin,
177  MachineInstr *End,
178  MachineBasicBlock *EHPad) {
179  registerScope(Begin, End);
180  TryToEHPad[Begin] = EHPad;
181  EHPadToTry[EHPad] = Begin;
182 }
183 
184 // Given a LOOP/TRY marker, returns its bottom BB. Use cached information if any
185 // to prevent recomputation.
188  const auto &MLI = getAnalysis<MachineLoopInfo>();
189  const auto &WEI = getAnalysis<WebAssemblyExceptionInfo>();
190  if (BeginToBottom.count(Begin))
191  return BeginToBottom[Begin];
192  if (Begin->getOpcode() == WebAssembly::LOOP) {
193  MachineLoop *L = MLI.getLoopFor(Begin->getParent());
194  assert(L);
195  BeginToBottom[Begin] = WebAssembly::getBottom(L);
196  } else if (Begin->getOpcode() == WebAssembly::TRY) {
197  WebAssemblyException *WE = WEI.getExceptionFor(TryToEHPad[Begin]);
198  assert(WE);
199  BeginToBottom[Begin] = WebAssembly::getBottom(WE);
200  } else
201  assert(false);
202  return BeginToBottom[Begin];
203 }
204 
205 /// Insert a BLOCK marker for branches to MBB (if needed).
206 void WebAssemblyCFGStackify::placeBlockMarker(MachineBasicBlock &MBB) {
207  // This should have been handled in placeTryMarker.
208  if (MBB.isEHPad())
209  return;
210 
211  MachineFunction &MF = *MBB.getParent();
212  auto &MDT = getAnalysis<MachineDominatorTree>();
213  const auto &TII = *MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo();
214  const auto &MFI = *MF.getInfo<WebAssemblyFunctionInfo>();
215 
216  // First compute the nearest common dominator of all forward non-fallthrough
217  // predecessors so that we minimize the time that the BLOCK is on the stack,
218  // which reduces overall stack height.
219  MachineBasicBlock *Header = nullptr;
220  bool IsBranchedTo = false;
221  int MBBNumber = MBB.getNumber();
222  for (MachineBasicBlock *Pred : MBB.predecessors()) {
223  if (Pred->getNumber() < MBBNumber) {
224  Header = Header ? MDT.findNearestCommonDominator(Header, Pred) : Pred;
225  if (ExplicitlyBranchesTo(Pred, &MBB))
226  IsBranchedTo = true;
227  }
228  }
229  if (!Header)
230  return;
231  if (!IsBranchedTo)
232  return;
233 
234  assert(&MBB != &MF.front() && "Header blocks shouldn't have predecessors");
235  MachineBasicBlock *LayoutPred = &*std::prev(MachineFunction::iterator(&MBB));
236 
237  // If the nearest common dominator is inside a more deeply nested context,
238  // walk out to the nearest scope which isn't more deeply nested.
239  for (MachineFunction::iterator I(LayoutPred), E(Header); I != E; --I) {
240  if (MachineBasicBlock *ScopeTop = ScopeTops[I->getNumber()]) {
241  if (ScopeTop->getNumber() > Header->getNumber()) {
242  // Skip over an intervening scope.
243  I = std::next(MachineFunction::iterator(ScopeTop));
244  } else {
245  // We found a scope level at an appropriate depth.
246  Header = ScopeTop;
247  break;
248  }
249  }
250  }
251 
252  // Decide where in Header to put the BLOCK.
253 
254  // Instructions that should go before the BLOCK.
256  // Instructions that should go after the BLOCK.
258  for (const auto &MI : *Header) {
259  // If there is a previously placed LOOP/TRY marker and the bottom block of
260  // the loop/exception is above MBB, it should be after the BLOCK, because
261  // the loop/exception is nested in this block. Otherwise it should be before
262  // the BLOCK.
263  if (MI.getOpcode() == WebAssembly::LOOP ||
264  MI.getOpcode() == WebAssembly::TRY) {
265  if (MBB.getNumber() > getBottom(&MI)->getNumber())
266  AfterSet.insert(&MI);
267 #ifndef NDEBUG
268  else
269  BeforeSet.insert(&MI);
270 #endif
271  }
272 
273  // All previously inserted BLOCK markers should be after the BLOCK because
274  // they are all nested blocks.
275  if (MI.getOpcode() == WebAssembly::BLOCK)
276  AfterSet.insert(&MI);
277 
278 #ifndef NDEBUG
279  // All END_(BLOCK|LOOP|TRY) markers should be before the BLOCK.
280  if (MI.getOpcode() == WebAssembly::END_BLOCK ||
281  MI.getOpcode() == WebAssembly::END_LOOP ||
282  MI.getOpcode() == WebAssembly::END_TRY)
283  BeforeSet.insert(&MI);
284 #endif
285 
286  // Terminators should go after the BLOCK.
287  if (MI.isTerminator())
288  AfterSet.insert(&MI);
289  }
290 
291  // Local expression tree should go after the BLOCK.
292  for (auto I = Header->getFirstTerminator(), E = Header->begin(); I != E;
293  --I) {
294  if (std::prev(I)->isDebugInstr() || std::prev(I)->isPosition())
295  continue;
296  if (WebAssembly::isChild(*std::prev(I), MFI))
297  AfterSet.insert(&*std::prev(I));
298  else
299  break;
300  }
301 
302  // Add the BLOCK.
303  auto InsertPos = GetLatestInsertPos(Header, BeforeSet, AfterSet);
304  MachineInstr *Begin =
305  BuildMI(*Header, InsertPos, Header->findDebugLoc(InsertPos),
306  TII.get(WebAssembly::BLOCK))
307  .addImm(int64_t(WebAssembly::ExprType::Void));
308 
309  // Decide where in Header to put the END_BLOCK.
310  BeforeSet.clear();
311  AfterSet.clear();
312  for (auto &MI : MBB) {
313 #ifndef NDEBUG
314  // END_BLOCK should precede existing LOOP and TRY markers.
315  if (MI.getOpcode() == WebAssembly::LOOP ||
316  MI.getOpcode() == WebAssembly::TRY)
317  AfterSet.insert(&MI);
318 #endif
319 
320  // If there is a previously placed END_LOOP marker and the header of the
321  // loop is above this block's header, the END_LOOP should be placed after
322  // the BLOCK, because the loop contains this block. Otherwise the END_LOOP
323  // should be placed before the BLOCK. The same for END_TRY.
324  if (MI.getOpcode() == WebAssembly::END_LOOP ||
325  MI.getOpcode() == WebAssembly::END_TRY) {
326  if (EndToBegin[&MI]->getParent()->getNumber() >= Header->getNumber())
327  BeforeSet.insert(&MI);
328 #ifndef NDEBUG
329  else
330  AfterSet.insert(&MI);
331 #endif
332  }
333  }
334 
335  // Mark the end of the block.
336  InsertPos = GetEarliestInsertPos(&MBB, BeforeSet, AfterSet);
337  MachineInstr *End = BuildMI(MBB, InsertPos, MBB.findPrevDebugLoc(InsertPos),
338  TII.get(WebAssembly::END_BLOCK));
339  registerScope(Begin, End);
340 
341  // Track the farthest-spanning scope that ends at this point.
342  int Number = MBB.getNumber();
343  if (!ScopeTops[Number] ||
344  ScopeTops[Number]->getNumber() > Header->getNumber())
345  ScopeTops[Number] = Header;
346 }
347 
348 /// Insert a LOOP marker for a loop starting at MBB (if it's a loop header).
349 void WebAssemblyCFGStackify::placeLoopMarker(MachineBasicBlock &MBB) {
350  MachineFunction &MF = *MBB.getParent();
351  const auto &MLI = getAnalysis<MachineLoopInfo>();
352  const auto &TII = *MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo();
353 
354  MachineLoop *Loop = MLI.getLoopFor(&MBB);
355  if (!Loop || Loop->getHeader() != &MBB)
356  return;
357 
358  // The operand of a LOOP is the first block after the loop. If the loop is the
359  // bottom of the function, insert a dummy block at the end.
361  auto Iter = std::next(MachineFunction::iterator(Bottom));
362  if (Iter == MF.end()) {
364  // Give it a fake predecessor so that AsmPrinter prints its label.
365  Label->addSuccessor(Label);
366  MF.push_back(Label);
367  Iter = std::next(MachineFunction::iterator(Bottom));
368  }
369  MachineBasicBlock *AfterLoop = &*Iter;
370 
371  // Decide where in Header to put the LOOP.
374  for (const auto &MI : MBB) {
375  // LOOP marker should be after any existing loop that ends here. Otherwise
376  // we assume the instruction belongs to the loop.
377  if (MI.getOpcode() == WebAssembly::END_LOOP)
378  BeforeSet.insert(&MI);
379 #ifndef NDEBUG
380  else
381  AfterSet.insert(&MI);
382 #endif
383  }
384 
385  // Mark the beginning of the loop.
386  auto InsertPos = GetEarliestInsertPos(&MBB, BeforeSet, AfterSet);
387  MachineInstr *Begin = BuildMI(MBB, InsertPos, MBB.findDebugLoc(InsertPos),
388  TII.get(WebAssembly::LOOP))
389  .addImm(int64_t(WebAssembly::ExprType::Void));
390 
391  // Decide where in Header to put the END_LOOP.
392  BeforeSet.clear();
393  AfterSet.clear();
394 #ifndef NDEBUG
395  for (const auto &MI : MBB)
396  // Existing END_LOOP markers belong to parent loops of this loop
397  if (MI.getOpcode() == WebAssembly::END_LOOP)
398  AfterSet.insert(&MI);
399 #endif
400 
401  // Mark the end of the loop (using arbitrary debug location that branched to
402  // the loop end as its location).
403  InsertPos = GetEarliestInsertPos(AfterLoop, BeforeSet, AfterSet);
404  DebugLoc EndDL = (*AfterLoop->pred_rbegin())->findBranchDebugLoc();
405  MachineInstr *End =
406  BuildMI(*AfterLoop, InsertPos, EndDL, TII.get(WebAssembly::END_LOOP));
407  registerScope(Begin, End);
408 
409  assert((!ScopeTops[AfterLoop->getNumber()] ||
410  ScopeTops[AfterLoop->getNumber()]->getNumber() < MBB.getNumber()) &&
411  "With block sorting the outermost loop for a block should be first.");
412  if (!ScopeTops[AfterLoop->getNumber()])
413  ScopeTops[AfterLoop->getNumber()] = &MBB;
414 }
415 
416 void WebAssemblyCFGStackify::placeTryMarker(MachineBasicBlock &MBB) {
417  if (!MBB.isEHPad())
418  return;
419 
420  // catch_all terminate pad is grouped together with catch terminate pad and
421  // does not need a separate TRY and END_TRY marker.
423  return;
424 
425  MachineFunction &MF = *MBB.getParent();
426  auto &MDT = getAnalysis<MachineDominatorTree>();
427  const auto &TII = *MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo();
428  const auto &WEI = getAnalysis<WebAssemblyExceptionInfo>();
429  const auto &MFI = *MF.getInfo<WebAssemblyFunctionInfo>();
430 
431  // Compute the nearest common dominator of all unwind predecessors
432  MachineBasicBlock *Header = nullptr;
433  int MBBNumber = MBB.getNumber();
434  for (auto *Pred : MBB.predecessors()) {
435  if (Pred->getNumber() < MBBNumber) {
436  Header = Header ? MDT.findNearestCommonDominator(Header, Pred) : Pred;
437  assert(!ExplicitlyBranchesTo(Pred, &MBB) &&
438  "Explicit branch to an EH pad!");
439  }
440  }
441  if (!Header)
442  return;
443 
444  // If this try is at the bottom of the function, insert a dummy block at the
445  // end.
446  WebAssemblyException *WE = WEI.getExceptionFor(&MBB);
447  assert(WE);
449 
450  auto Iter = std::next(MachineFunction::iterator(Bottom));
451  if (Iter == MF.end()) {
453  // Give it a fake predecessor so that AsmPrinter prints its label.
454  Label->addSuccessor(Label);
455  MF.push_back(Label);
456  Iter = std::next(MachineFunction::iterator(Bottom));
457  }
458  MachineBasicBlock *AfterTry = &*Iter;
459 
460  assert(AfterTry != &MF.front());
461  MachineBasicBlock *LayoutPred =
462  &*std::prev(MachineFunction::iterator(AfterTry));
463 
464  // If the nearest common dominator is inside a more deeply nested context,
465  // walk out to the nearest scope which isn't more deeply nested.
466  for (MachineFunction::iterator I(LayoutPred), E(Header); I != E; --I) {
467  if (MachineBasicBlock *ScopeTop = ScopeTops[I->getNumber()]) {
468  if (ScopeTop->getNumber() > Header->getNumber()) {
469  // Skip over an intervening scope.
470  I = std::next(MachineFunction::iterator(ScopeTop));
471  } else {
472  // We found a scope level at an appropriate depth.
473  Header = ScopeTop;
474  break;
475  }
476  }
477  }
478 
479  // Decide where in Header to put the TRY.
480 
481  // Instructions that should go before the BLOCK.
483  // Instructions that should go after the BLOCK.
485  for (const auto &MI : *Header) {
486  // If there is a previously placed LOOP marker and the bottom block of
487  // the loop is above MBB, the LOOP should be after the TRY, because the
488  // loop is nested in this try. Otherwise it should be before the TRY.
489  if (MI.getOpcode() == WebAssembly::LOOP) {
490  if (MBB.getNumber() > Bottom->getNumber())
491  AfterSet.insert(&MI);
492 #ifndef NDEBUG
493  else
494  BeforeSet.insert(&MI);
495 #endif
496  }
497 
498  // All previously inserted TRY markers should be after the TRY because they
499  // are all nested trys.
500  if (MI.getOpcode() == WebAssembly::TRY)
501  AfterSet.insert(&MI);
502 
503 #ifndef NDEBUG
504  // All END_(LOOP/TRY) markers should be before the TRY.
505  if (MI.getOpcode() == WebAssembly::END_LOOP ||
506  MI.getOpcode() == WebAssembly::END_TRY)
507  BeforeSet.insert(&MI);
508 #endif
509 
510  // Terminators should go after the TRY.
511  if (MI.isTerminator())
512  AfterSet.insert(&MI);
513  }
514 
515  // Local expression tree should go after the TRY.
516  for (auto I = Header->getFirstTerminator(), E = Header->begin(); I != E;
517  --I) {
518  if (std::prev(I)->isDebugInstr() || std::prev(I)->isPosition())
519  continue;
520  if (WebAssembly::isChild(*std::prev(I), MFI))
521  AfterSet.insert(&*std::prev(I));
522  else
523  break;
524  }
525 
526  // If Header unwinds to MBB (= Header contains 'invoke'), the try block should
527  // contain the call within it. So the call should go after the TRY. The
528  // exception is when the header's terminator is a rethrow instruction, in
529  // which case that instruction, not a call instruction before it, is gonna
530  // throw.
531  if (MBB.isPredecessor(Header)) {
532  auto TermPos = Header->getFirstTerminator();
533  if (TermPos == Header->end() || !WebAssembly::isRethrow(*TermPos)) {
534  for (const auto &MI : reverse(*Header)) {
535  if (MI.isCall()) {
536  AfterSet.insert(&MI);
537  break;
538  }
539  }
540  }
541  }
542 
543  // Add the TRY.
544  auto InsertPos = GetLatestInsertPos(Header, BeforeSet, AfterSet);
545  MachineInstr *Begin =
546  BuildMI(*Header, InsertPos, Header->findDebugLoc(InsertPos),
547  TII.get(WebAssembly::TRY))
548  .addImm(int64_t(WebAssembly::ExprType::Void));
549 
550  // Decide where in Header to put the END_TRY.
551  BeforeSet.clear();
552  AfterSet.clear();
553  for (const auto &MI : *AfterTry) {
554 #ifndef NDEBUG
555  // END_TRY should precede existing LOOP markers.
556  if (MI.getOpcode() == WebAssembly::LOOP)
557  AfterSet.insert(&MI);
558 
559  // All END_TRY markers placed earlier belong to exceptions that contains
560  // this one.
561  if (MI.getOpcode() == WebAssembly::END_TRY)
562  AfterSet.insert(&MI);
563 #endif
564 
565  // If there is a previously placed END_LOOP marker and its header is after
566  // where TRY marker is, this loop is contained within the 'catch' part, so
567  // the END_TRY marker should go after that. Otherwise, the whole try-catch
568  // is contained within this loop, so the END_TRY should go before that.
569  if (MI.getOpcode() == WebAssembly::END_LOOP) {
570  if (EndToBegin[&MI]->getParent()->getNumber() >= Header->getNumber())
571  BeforeSet.insert(&MI);
572 #ifndef NDEBUG
573  else
574  AfterSet.insert(&MI);
575 #endif
576  }
577  }
578 
579  // Mark the end of the TRY.
580  InsertPos = GetEarliestInsertPos(AfterTry, BeforeSet, AfterSet);
581  MachineInstr *End =
582  BuildMI(*AfterTry, InsertPos, Bottom->findBranchDebugLoc(),
583  TII.get(WebAssembly::END_TRY));
584  registerTryScope(Begin, End, &MBB);
585 
586  // Track the farthest-spanning scope that ends at this point.
587  int Number = AfterTry->getNumber();
588  if (!ScopeTops[Number] ||
589  ScopeTops[Number]->getNumber() > Header->getNumber())
590  ScopeTops[Number] = Header;
591 }
592 
593 static unsigned
595  const MachineBasicBlock *MBB) {
596  unsigned Depth = 0;
597  for (auto X : reverse(Stack)) {
598  if (X == MBB)
599  break;
600  ++Depth;
601  }
602  assert(Depth < Stack.size() && "Branch destination should be in scope");
603  return Depth;
604 }
605 
606 /// In normal assembly languages, when the end of a function is unreachable,
607 /// because the function ends in an infinite loop or a noreturn call or similar,
608 /// it isn't necessary to worry about the function return type at the end of
609 /// the function, because it's never reached. However, in WebAssembly, blocks
610 /// that end at the function end need to have a return type signature that
611 /// matches the function signature, even though it's unreachable. This function
612 /// checks for such cases and fixes up the signatures.
613 void WebAssemblyCFGStackify::fixEndsAtEndOfFunction(MachineFunction &MF) {
614  const auto &MFI = *MF.getInfo<WebAssemblyFunctionInfo>();
615  assert(MFI.getResults().size() <= 1);
616 
617  if (MFI.getResults().empty())
618  return;
619 
620  WebAssembly::ExprType retType;
621  switch (MFI.getResults().front().SimpleTy) {
622  case MVT::i32:
623  retType = WebAssembly::ExprType::I32;
624  break;
625  case MVT::i64:
626  retType = WebAssembly::ExprType::I64;
627  break;
628  case MVT::f32:
629  retType = WebAssembly::ExprType::F32;
630  break;
631  case MVT::f64:
632  retType = WebAssembly::ExprType::F64;
633  break;
634  case MVT::v16i8:
635  case MVT::v8i16:
636  case MVT::v4i32:
637  case MVT::v2i64:
638  case MVT::v4f32:
639  case MVT::v2f64:
640  retType = WebAssembly::ExprType::V128;
641  break;
642  case MVT::ExceptRef:
644  break;
645  default:
646  llvm_unreachable("unexpected return type");
647  }
648 
649  for (MachineBasicBlock &MBB : reverse(MF)) {
650  for (MachineInstr &MI : reverse(MBB)) {
651  if (MI.isPosition() || MI.isDebugInstr())
652  continue;
653  if (MI.getOpcode() == WebAssembly::END_BLOCK) {
654  EndToBegin[&MI]->getOperand(0).setImm(int32_t(retType));
655  continue;
656  }
657  if (MI.getOpcode() == WebAssembly::END_LOOP) {
658  EndToBegin[&MI]->getOperand(0).setImm(int32_t(retType));
659  continue;
660  }
661  // Something other than an `end`. We're done.
662  return;
663  }
664  }
665 }
666 
667 // WebAssembly functions end with an end instruction, as if the function body
668 // were a block.
670  const WebAssemblyInstrInfo &TII) {
671  BuildMI(MF.back(), MF.back().end(),
672  MF.back().findPrevDebugLoc(MF.back().end()),
673  TII.get(WebAssembly::END_FUNCTION));
674 }
675 
676 /// Insert LOOP/TRY/BLOCK markers at appropriate places.
677 void WebAssemblyCFGStackify::placeMarkers(MachineFunction &MF) {
678  const MCAsmInfo *MCAI = MF.getTarget().getMCAsmInfo();
679  // We allocate one more than the number of blocks in the function to
680  // accommodate for the possible fake block we may insert at the end.
681  ScopeTops.resize(MF.getNumBlockIDs() + 1);
682  // Place the LOOP for MBB if MBB is the header of a loop.
683  for (auto &MBB : MF)
684  placeLoopMarker(MBB);
685  // Place the TRY for MBB if MBB is the EH pad of an exception.
687  MF.getFunction().hasPersonalityFn())
688  for (auto &MBB : MF)
689  placeTryMarker(MBB);
690  // Place the BLOCK for MBB if MBB is branched to from above.
691  for (auto &MBB : MF)
692  placeBlockMarker(MBB);
693 }
694 
695 void WebAssemblyCFGStackify::rewriteDepthImmediates(MachineFunction &MF) {
696  const auto &TII = *MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo();
697  // Now rewrite references to basic blocks to be depth immediates.
698  // We need two stacks: one for normal scopes and the other for EH pad scopes.
699  // EH pad stack is used to rewrite depths in rethrow instructions.
702  for (auto &MBB : reverse(MF)) {
703  for (auto I = MBB.rbegin(), E = MBB.rend(); I != E; ++I) {
704  MachineInstr &MI = *I;
705  switch (MI.getOpcode()) {
706  case WebAssembly::BLOCK:
707  assert(ScopeTops[Stack.back()->getNumber()]->getNumber() <=
708  MBB.getNumber() &&
709  "Block/try should be balanced");
710  Stack.pop_back();
711  break;
712 
713  case WebAssembly::TRY:
714  assert(ScopeTops[Stack.back()->getNumber()]->getNumber() <=
715  MBB.getNumber() &&
716  "Block/try marker should be balanced");
717  Stack.pop_back();
718  EHPadStack.pop_back();
719  break;
720 
721  case WebAssembly::CATCH_I32:
722  case WebAssembly::CATCH_I64:
723  case WebAssembly::CATCH_ALL:
724  // Currently the only case there are more than one catch for a try is
725  // for catch terminate pad, in the form of
726  // try
727  // catch
728  // call @__clang_call_terminate
729  // unreachable
730  // catch_all
731  // call @std::terminate
732  // unreachable
733  // end
734  // So we shouldn't push the current BB for the second catch_all block
735  // here.
737  EHPadStack.push_back(&MBB);
738  break;
739 
740  case WebAssembly::LOOP:
741  assert(Stack.back() == &MBB && "Loop top should be balanced");
742  Stack.pop_back();
743  break;
744 
746  case WebAssembly::END_TRY:
747  Stack.push_back(&MBB);
748  break;
749 
750  case WebAssembly::END_LOOP:
751  Stack.push_back(EndToBegin[&MI]->getParent());
752  break;
753 
754  case WebAssembly::RETHROW: {
755  // Rewrite MBB operands to be depth immediates.
756  unsigned EHPadDepth = GetDepth(EHPadStack, MI.getOperand(0).getMBB());
757  MI.RemoveOperand(0);
758  MI.addOperand(MF, MachineOperand::CreateImm(EHPadDepth));
759  break;
760  }
761 
762  case WebAssembly::RETHROW_TO_CALLER: {
763  MachineInstr *Rethrow =
764  BuildMI(MBB, MI, MI.getDebugLoc(), TII.get(WebAssembly::RETHROW))
765  .addImm(EHPadStack.size());
766  MI.eraseFromParent();
768  break;
769  }
770 
771  default:
772  if (MI.isTerminator()) {
773  // Rewrite MBB operands to be depth immediates.
775  while (MI.getNumOperands() > 0)
776  MI.RemoveOperand(MI.getNumOperands() - 1);
777  for (auto MO : Ops) {
778  if (MO.isMBB())
779  MO = MachineOperand::CreateImm(GetDepth(Stack, MO.getMBB()));
780  MI.addOperand(MF, MO);
781  }
782  }
783  break;
784  }
785  }
786  }
787  assert(Stack.empty() && "Control flow should be balanced");
788 }
789 
790 void WebAssemblyCFGStackify::releaseMemory() {
791  ScopeTops.clear();
792  BeginToEnd.clear();
793  EndToBegin.clear();
794  TryToEHPad.clear();
795  EHPadToTry.clear();
796  BeginToBottom.clear();
797 }
798 
799 bool WebAssemblyCFGStackify::runOnMachineFunction(MachineFunction &MF) {
800  LLVM_DEBUG(dbgs() << "********** CFG Stackifying **********\n"
801  "********** Function: "
802  << MF.getName() << '\n');
803 
804  releaseMemory();
805 
806  // Liveness is not tracked for VALUE_STACK physreg.
808 
809  // Place the BLOCK/LOOP/TRY markers to indicate the beginnings of scopes.
810  placeMarkers(MF);
811 
812  // Convert MBB operands in terminators to relative depth immediates.
813  rewriteDepthImmediates(MF);
814 
815  // Fix up block/loop/try signatures at the end of the function to conform to
816  // WebAssembly's rules.
817  fixEndsAtEndOfFunction(MF);
818 
819  // Add an end instruction at the end of the function body.
820  const auto &TII = *MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo();
822  .getTargetTriple()
823  .isOSBinFormatELF())
825 
826  return true;
827 }
pred_reverse_iterator pred_rbegin()
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
DILocation * get() const
Get the underlying DILocation.
Definition: DebugLoc.cpp:22
MachineBasicBlock * getMBB() const
This class represents lattice values for constants.
Definition: AllocatorList.h:24
bool isOSBinFormatELF() const
Tests whether the OS uses the ELF binary format.
Definition: Triple.h:604
unsigned getNumBlockIDs() const
getNumBlockIDs - Return the number of MBB ID&#39;s allocated.
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
Definition: MachineInstr.h:383
A debug info location.
Definition: DebugLoc.h:34
iterator_range< mop_iterator > operands()
Definition: MachineInstr.h:459
This file contains the entry points for global functions defined in the LLVM WebAssembly back-end...
static bool ExplicitlyBranchesTo(MachineBasicBlock *Pred, MachineBasicBlock *MBB)
Test whether Pred has any terminators explicitly branching to MBB, as opposed to falling through...
AnalysisUsage & addRequired()
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
const HexagonInstrInfo * TII
unsigned getNumOperands() const
Retuns the total number of operands.
Definition: MachineInstr.h:412
INITIALIZE_PASS(WebAssemblyCFGStackify, DEBUG_TYPE, "Insert BLOCK and LOOP markers for WebAssembly scopes", false, false) FunctionPass *llvm
static unsigned GetDepth(const SmallVectorImpl< const MachineBasicBlock *> &Stack, const MachineBasicBlock *MBB)
MachineBasicBlock iterator that automatically skips over MIs that are inside bundles (i...
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: APFloat.h:42
void eraseFromParent()
Unlink &#39;this&#39; from the containing basic block and delete it.
bool isTerminator(QueryType Type=AnyInBundle) const
Returns true if this instruction part of the terminator for a basic block.
Definition: MachineInstr.h:649
iterator_range< iterator > terminators()
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:409
BlockT * getHeader() const
Definition: LoopInfo.h:100
#define DEBUG_TYPE
auto reverse(ContainerTy &&C, typename std::enable_if< has_rbegin< ContainerTy >::value >::type *=nullptr) -> decltype(make_range(C.rbegin(), C.rend()))
Definition: STLExtras.h:267
DebugLoc findPrevDebugLoc(instr_iterator MBBI)
Find the previous valid DebugLoc preceding MBBI, skipping and DBG_VALUE instructions.
MachineInstrBundleIterator< MachineInstr, true > reverse_iterator
int getNumber() const
MachineBasicBlocks are uniquely numbered at the function level, unless they&#39;re not in a MachineFuncti...
This file implements WebAssemblyException information analysis.
reverse_iterator rend()
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *bb=nullptr)
CreateMachineBasicBlock - Allocate a new MachineBasicBlock.
reverse_iterator rbegin()
static void AppendEndToFunction(MachineFunction &MF, const WebAssemblyInstrInfo &TII)
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
Windows Exception Handling.
This class is intended to be used as a base class for asm properties and features specific to the tar...
Definition: MCAsmInfo.h:56
This file contains the declaration of the WebAssembly-specific utility functions. ...
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
const Triple & getTargetTriple() const
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
const MCAsmInfo * getMCAsmInfo() const
Return target specific asm information.
This file provides WebAssembly-specific target descriptions.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
Definition: SmallPtrSet.h:371
bool isPredecessor(const MachineBasicBlock *MBB) const
Return true if the specified MBB is a predecessor of this block.
Represent the analysis usage information of a pass.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:285
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
Definition: SmallPtrSet.h:382
bool isRethrow(const MachineInstr &MI)
iterator_range< pred_iterator > predecessors()
const MachineBasicBlock & front() const
size_t size() const
Definition: SmallVector.h:53
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
This file declares the WebAssembly-specific subclass of TargetSubtarget.
Iterator for intrusive lists based on ilist_node.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements...
Definition: SmallPtrSet.h:418
void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
void addOperand(MachineFunction &MF, const MachineOperand &Op)
Add the specified operand to the instruction.
MachineOperand class - Representation of each machine instruction operand.
This is a &#39;vector&#39; (really, a variable-sized array), optimized for the case when the array is small...
Definition: SmallVector.h:847
ExprType
This is used to indicate block signatures.
void invalidateLiveness()
invalidateLiveness - Indicates that register liveness is no longer being tracked accurately.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:133
DebugLoc findBranchDebugLoc()
Find and return the merged DebugLoc of the branch instructions of the block.
const MachineBasicBlock * getParent() const
Definition: MachineInstr.h:254
Representation of each machine instruction.
Definition: MachineInstr.h:64
This class is derived from MachineFunctionInfo and contains private WebAssembly-specific information ...
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
bool isEHPad() const
Returns true if the block is a landing pad.
LLVM_NODISCARD bool empty() const
Definition: SmallVector.h:56
Represents a single loop in the control flow graph.
Definition: LoopInfo.h:465
static MachineOperand CreateImm(int64_t Val)
#define I(x, y, z)
Definition: MD5.cpp:58
This file declares WebAssembly-specific per-machine-function information.
const MachineBasicBlock & back() const
const LLVMTargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
FunctionPass * createWebAssemblyCFGStackify()
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
MachineBasicBlock * getBottom(const T *Unit)
Return the "bottom" block of an entity, which can be either a MachineLoop or WebAssemblyException.
void push_back(MachineBasicBlock *MBB)
static const Function * getParent(const Value *V)
ExceptionHandling getExceptionHandlingType() const
Definition: MCAsmInfo.h:570
IRTranslator LLVM IR MI
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:49
void RemoveOperand(unsigned OpNo)
Erase an operand from an instruction, leaving it with one fewer operand than it started with...
static MachineBasicBlock::iterator GetEarliestInsertPos(MachineBasicBlock *MBB, const SmallPtrSet< const MachineInstr *, 4 > &BeforeSet, const SmallPtrSet< const MachineInstr *, 4 > &AfterSet)
#define LLVM_DEBUG(X)
Definition: Debug.h:123
bool isChild(const MachineInstr &MI, const WebAssemblyFunctionInfo &MFI)
Test whether MI is a child of some other node in an expression tree.
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:414
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...
static MachineBasicBlock::iterator GetLatestInsertPos(MachineBasicBlock *MBB, const SmallPtrSet< const MachineInstr *, 4 > &BeforeSet, const SmallPtrSet< const MachineInstr *, 4 > &AfterSet)
bool isCatchAllTerminatePad(const MachineBasicBlock &MBB)
Returns if the given BB is a single BB terminate pad which starts with a &#39;catch_all&#39; insrtruction...