43#define DEBUG_TYPE "wasm-cfg-stackify" 
   45STATISTIC(NumCallUnwindMismatches, 
"Number of call unwind mismatches found");
 
   46STATISTIC(NumCatchUnwindMismatches, 
"Number of catch unwind mismatches found");
 
   52  StringRef getPassName()
 const override { 
return "WebAssembly CFG Stackify"; }
 
   54  void getAnalysisUsage(AnalysisUsage &AU)
 const override {
 
   61  bool runOnMachineFunction(MachineFunction &MF) 
override;
 
   66  SmallVector<MachineBasicBlock *, 8> ScopeTops;
 
   67  void updateScopeTops(MachineBasicBlock *Begin, MachineBasicBlock *End) {
 
   70    if (!ScopeTops[EndNo] || ScopeTops[EndNo]->getNumber() > BeginNo)
 
   71      ScopeTops[EndNo] = Begin;
 
   75  void placeMarkers(MachineFunction &MF);
 
   76  void placeBlockMarker(MachineBasicBlock &
MBB);
 
   77  void placeLoopMarker(MachineBasicBlock &
MBB);
 
   78  void placeTryMarker(MachineBasicBlock &
MBB);
 
   79  void placeTryTableMarker(MachineBasicBlock &
MBB);
 
   83  bool fixCallUnwindMismatches(MachineFunction &MF);
 
   84  bool fixCatchUnwindMismatches(MachineFunction &MF);
 
   85  void recalculateScopeTops(MachineFunction &MF);
 
   87  void addNestedTryDelegate(MachineInstr *RangeBegin, MachineInstr *RangeEnd,
 
   88                            MachineBasicBlock *UnwindDest);
 
   89  void removeUnnecessaryInstrs(MachineFunction &MF);
 
   91  void addNestedTryTable(MachineInstr *RangeBegin, MachineInstr *RangeEnd,
 
   92                         MachineBasicBlock *UnwindDest);
 
   93  MachineBasicBlock *getTrampolineBlock(MachineBasicBlock *UnwindDest);
 
   97      std::pair<const MachineBasicBlock *, const MachineInstr *>;
 
   98  unsigned getBranchDepth(
const SmallVectorImpl<EndMarkerInfo> &Stack,
 
   99                          const MachineBasicBlock *
MBB);
 
  100  unsigned getDelegateDepth(
const SmallVectorImpl<EndMarkerInfo> &Stack,
 
  101                            const MachineBasicBlock *
MBB);
 
  102  unsigned getRethrowDepth(
const SmallVectorImpl<EndMarkerInfo> &Stack,
 
  103                           const MachineBasicBlock *EHPadToRethrow);
 
  104  void rewriteDepthImmediates(MachineFunction &MF);
 
  105  void fixEndsAtEndOfFunction(MachineFunction &MF);
 
  106  void cleanupFunctionData(MachineFunction &MF);
 
  110  DenseMap<const MachineInstr *, MachineInstr *> BeginToEnd;
 
  113  DenseMap<const MachineInstr *, MachineInstr *> EndToBegin;
 
  115  DenseMap<const MachineInstr *, MachineBasicBlock *> TryToEHPad;
 
  117  DenseMap<const MachineBasicBlock *, MachineInstr *> EHPadToTry;
 
  119  DenseMap<const MachineBasicBlock *, MachineBasicBlock *>
 
  120      UnwindDestToTrampoline;
 
  124  MachineBasicBlock *AppendixBB = 
nullptr;
 
  125  MachineBasicBlock *getAppendixBlock(MachineFunction &MF) {
 
  132      if (CallerTrampolineBB)
 
  133        MF.
insert(CallerTrampolineBB->getIterator(), AppendixBB);
 
  142  MachineBasicBlock *CallerTrampolineBB = 
nullptr;
 
  143  MachineBasicBlock *getCallerTrampolineBlock(MachineFunction &MF) {
 
  144    if (!CallerTrampolineBB) {
 
  148    return CallerTrampolineBB;
 
  157  MachineBasicBlock *FakeCallerBB = 
nullptr;
 
  158  MachineBasicBlock *getFakeCallerBlock(MachineFunction &MF) {
 
  166  void registerScope(MachineInstr *Begin, MachineInstr *End);
 
  167  void registerTryScope(MachineInstr *Begin, MachineInstr *End,
 
  168                        MachineBasicBlock *EHPad);
 
  169  void unregisterScope(MachineInstr *Begin);
 
  173  WebAssemblyCFGStackify() : MachineFunctionPass(ID) {}
 
  174  ~WebAssemblyCFGStackify()
 override { releaseMemory(); }
 
  175  void releaseMemory() 
override;
 
  179char WebAssemblyCFGStackify::ID = 0;
 
  182    "Insert BLOCK/LOOP/TRY/TRY_TABLE markers for WebAssembly scopes", 
false,
 
  186  return new WebAssemblyCFGStackify();
 
 
  198      if (MO.isMBB() && MO.getMBB() == 
MBB)
 
 
  208template <
typename Container>
 
  211                     const Container &AfterSet) {
 
  212  auto InsertPos = 
MBB->end();
 
  213  while (InsertPos != 
MBB->begin()) {
 
  214    if (BeforeSet.count(&*std::prev(InsertPos))) {
 
  217      for (
auto Pos = InsertPos, 
E = 
MBB->begin(); Pos != 
E; --Pos)
 
  218        assert(!AfterSet.count(&*std::prev(Pos)));
 
 
  232template <
typename Container>
 
  235                   const Container &AfterSet) {
 
  236  auto InsertPos = 
MBB->begin();
 
  237  while (InsertPos != 
MBB->end()) {
 
  238    if (AfterSet.count(&*InsertPos)) {
 
  241      for (
auto Pos = InsertPos, 
E = 
MBB->end(); Pos != 
E; ++Pos)
 
  242        assert(!BeforeSet.count(&*Pos));
 
 
  251void WebAssemblyCFGStackify::registerScope(
MachineInstr *Begin,
 
  253  BeginToEnd[Begin] = End;
 
  254  EndToBegin[End] = Begin;
 
  258void WebAssemblyCFGStackify::registerTryScope(MachineInstr *Begin,
 
  260                                              MachineBasicBlock *EHPad) {
 
  261  registerScope(Begin, End);
 
  262  TryToEHPad[Begin] = EHPad;
 
  263  EHPadToTry[EHPad] = Begin;
 
  266void WebAssemblyCFGStackify::unregisterScope(MachineInstr *Begin) {
 
  268  MachineInstr *End = BeginToEnd[Begin];
 
  270  BeginToEnd.
erase(Begin);
 
  271  EndToBegin.
erase(End);
 
  272  MachineBasicBlock *EHPad = TryToEHPad.
lookup(Begin);
 
  275    TryToEHPad.
erase(Begin);
 
  276    EHPadToTry.
erase(EHPad);
 
  283void WebAssemblyCFGStackify::placeBlockMarker(MachineBasicBlock &
MBB) {
 
  286  const auto &
TII = *MF.
getSubtarget<WebAssemblySubtarget>().getInstrInfo();
 
  287  const auto &MFI = *MF.
getInfo<WebAssemblyFunctionInfo>();
 
  292  MachineBasicBlock *Header = 
nullptr;
 
  293  bool IsBranchedTo = 
false;
 
  296    if (Pred->getNumber() < MBBNumber) {
 
  297      Header = Header ? MDT->findNearestCommonDominator(Header, Pred) : Pred;
 
  307  assert(&
MBB != &MF.
front() && 
"Header blocks shouldn't have predecessors");
 
  313    if (MachineBasicBlock *ScopeTop = ScopeTops[
I->getNumber()]) {
 
  314      if (ScopeTop->getNumber() > Header->getNumber()) {
 
  316        I = std::next(ScopeTop->getIterator());
 
  328  SmallPtrSet<const MachineInstr *, 4> BeforeSet;
 
  330  SmallPtrSet<const MachineInstr *, 4> AfterSet;
 
  331  for (
const auto &
MI : *Header) {
 
  335    if (
MI.getOpcode() == WebAssembly::LOOP) {
 
  336      auto *LoopBottom = BeginToEnd[&
MI]->getParent()->getPrevNode();
 
  349    if (
MI.getOpcode() == WebAssembly::BLOCK ||
 
  350        MI.getOpcode() == WebAssembly::TRY ||
 
  351        MI.getOpcode() == WebAssembly::TRY_TABLE) {
 
  362    if (
MI.getOpcode() == WebAssembly::END_BLOCK ||
 
  363        MI.getOpcode() == WebAssembly::END_LOOP ||
 
  364        MI.getOpcode() == WebAssembly::END_TRY ||
 
  365        MI.getOpcode() == WebAssembly::END_TRY_TABLE)
 
  370    if (
MI.isTerminator())
 
  375  for (
auto I = Header->getFirstTerminator(), 
E = Header->begin(); 
I != 
E;
 
  377    if (std::prev(
I)->isDebugInstr() || std::prev(
I)->isPosition())
 
  380      AfterSet.
insert(&*std::prev(
I));
 
  388  MachineInstr *Begin =
 
  389      BuildMI(*Header, InsertPos, Header->findDebugLoc(InsertPos),
 
  390              TII.get(WebAssembly::BLOCK))
 
  391          .
addImm(int64_t(ReturnType));
 
  396  for (
auto &
MI : 
MBB) {
 
  399    if (
MI.getOpcode() == WebAssembly::LOOP)
 
  412    if (
MI.getOpcode() == WebAssembly::END_LOOP ||
 
  413        MI.getOpcode() == WebAssembly::END_TRY) {
 
  414      if (EndToBegin[&
MI]->
getParent()->getNumber() >= Header->getNumber())
 
  426                              TII.get(WebAssembly::END_BLOCK));
 
  427  registerScope(Begin, End);
 
  430  updateScopeTops(Header, &
MBB);
 
  434void WebAssemblyCFGStackify::placeLoopMarker(MachineBasicBlock &
MBB) {
 
  436  const auto &MLI = getAnalysis<MachineLoopInfoWrapperPass>().getLI();
 
  437  const auto &WEI = getAnalysis<WebAssemblyExceptionInfo>();
 
  438  SortRegionInfo SRI(MLI, WEI);
 
  439  const auto &
TII = *MF.
getSubtarget<WebAssemblySubtarget>().getInstrInfo();
 
  441  MachineLoop *Loop = MLI.getLoopFor(&
MBB);
 
  447  MachineBasicBlock *Bottom = SRI.getBottom(Loop);
 
  449  if (Iter == MF.
end()) {
 
  450    getAppendixBlock(MF);
 
  453  MachineBasicBlock *AfterLoop = &*Iter;
 
  456  SmallPtrSet<const MachineInstr *, 4> BeforeSet;
 
  457  SmallPtrSet<const MachineInstr *, 4> AfterSet;
 
  458  for (
const auto &
MI : 
MBB) {
 
  461    if (
MI.getOpcode() == WebAssembly::END_LOOP)
 
  472                                TII.get(WebAssembly::LOOP))
 
  473                            .
addImm(int64_t(WebAssembly::BlockType::Void));
 
  479  for (
const auto &
MI : 
MBB)
 
  481    if (
MI.getOpcode() == WebAssembly::END_LOOP)
 
  490                       : (*AfterLoop->pred_rbegin())->findBranchDebugLoc();
 
  492      BuildMI(*AfterLoop, InsertPos, EndDL, 
TII.get(WebAssembly::END_LOOP));
 
  493  registerScope(Begin, End);
 
  497         "With block sorting the outermost loop for a block should be first.");
 
  498  updateScopeTops(&
MBB, AfterLoop);
 
  501void WebAssemblyCFGStackify::placeTryMarker(MachineBasicBlock &
MBB) {
 
  504  auto &MDT = getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
 
  505  const auto &
TII = *MF.
getSubtarget<WebAssemblySubtarget>().getInstrInfo();
 
  506  const auto &MLI = getAnalysis<MachineLoopInfoWrapperPass>().getLI();
 
  507  const auto &WEI = getAnalysis<WebAssemblyExceptionInfo>();
 
  508  SortRegionInfo SRI(MLI, WEI);
 
  509  const auto &MFI = *MF.
getInfo<WebAssemblyFunctionInfo>();
 
  512  MachineBasicBlock *Header = 
nullptr;
 
  515    if (Pred->getNumber() < MBBNumber) {
 
  516      Header = Header ? MDT.findNearestCommonDominator(Header, Pred) : Pred;
 
  518             "Explicit branch to an EH pad!");
 
  526  WebAssemblyException *WE = WEI.getExceptionFor(&
MBB);
 
  528  MachineBasicBlock *Bottom = SRI.getBottom(WE);
 
  530  if (Iter == MF.
end()) {
 
  531    getAppendixBlock(MF);
 
  534  MachineBasicBlock *Cont = &*Iter;
 
  539    if (MachineBasicBlock *ScopeTop = ScopeTops[
I->getNumber()]) {
 
  540      if (ScopeTop->getNumber() > Header->getNumber()) {
 
  542        I = std::next(ScopeTop->getIterator());
 
  554  SmallPtrSet<const MachineInstr *, 4> BeforeSet;
 
  556  SmallPtrSet<const MachineInstr *, 4> AfterSet;
 
  557  for (
const auto &
MI : *Header) {
 
  561    if (
MI.getOpcode() == WebAssembly::LOOP) {
 
  562      auto *LoopBottom = BeginToEnd[&
MI]->getParent()->getPrevNode();
 
  573    if (
MI.getOpcode() == WebAssembly::BLOCK ||
 
  574        MI.getOpcode() == WebAssembly::TRY)
 
  579    if (
MI.getOpcode() == WebAssembly::END_BLOCK ||
 
  580        MI.getOpcode() == WebAssembly::END_LOOP ||
 
  581        MI.getOpcode() == WebAssembly::END_TRY)
 
  586    if (
MI.isTerminator())
 
  595  MachineInstr *ThrowingCall = 
nullptr;
 
  597    auto TermPos = Header->getFirstTerminator();
 
  598    if (TermPos == Header->end() ||
 
  599        TermPos->getOpcode() != WebAssembly::RETHROW) {
 
  606          if (
MI.getIterator() != Header->begin() &&
 
  607              std::prev(
MI.getIterator())->isEHLabel()) {
 
  608            AfterSet.
insert(&*std::prev(
MI.getIterator()));
 
  609            ThrowingCall = &*std::prev(
MI.getIterator());
 
  624                                    : Header->getFirstTerminator();
 
  625  for (
auto I = SearchStartPt, 
E = Header->begin(); 
I != 
E; --
I) {
 
  626    if (std::prev(I)->isDebugInstr() || std::prev(I)->isPosition())
 
  628    if (WebAssembly::isChild(*std::prev(I), MFI))
 
  629      AfterSet.insert(&*std::prev(I));
 
  636  MachineInstr *Begin =
 
  637      BuildMI(*Header, InsertPos, Header->findDebugLoc(InsertPos),
 
  638              TII.get(WebAssembly::TRY))
 
  639          .
addImm(int64_t(WebAssembly::BlockType::Void));
 
  644  for (
const auto &
MI : *Cont) {
 
  647    if (
MI.getOpcode() == WebAssembly::LOOP)
 
  652    if (
MI.getOpcode() == WebAssembly::END_TRY)
 
  660    if (
MI.getOpcode() == WebAssembly::END_LOOP) {
 
  663      if (EndToBegin[&
MI]->
getParent()->getNumber() > Header->getNumber())
 
  677                              TII.get(WebAssembly::END_TRY));
 
  678  registerTryScope(Begin, End, &
MBB);
 
  691  for (
auto *End : {&
MBB, Cont})
 
  692    updateScopeTops(Header, End);
 
  695void WebAssemblyCFGStackify::placeTryTableMarker(MachineBasicBlock &
MBB) {
 
  698  auto &MDT = getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
 
  699  const auto &
TII = *MF.
getSubtarget<WebAssemblySubtarget>().getInstrInfo();
 
  700  const auto &MLI = getAnalysis<MachineLoopInfoWrapperPass>().getLI();
 
  701  const auto &WEI = getAnalysis<WebAssemblyExceptionInfo>();
 
  702  SortRegionInfo SRI(MLI, WEI);
 
  703  const auto &MFI = *MF.
getInfo<WebAssemblyFunctionInfo>();
 
  706  MachineBasicBlock *Header = 
nullptr;
 
  709    if (Pred->getNumber() < MBBNumber) {
 
  710      Header = Header ? MDT.findNearestCommonDominator(Header, Pred) : Pred;
 
  712             "Explicit branch to an EH pad!");
 
  721  WebAssemblyException *WE = WEI.getExceptionFor(&
MBB);
 
  723  MachineBasicBlock *Bottom = SRI.getBottom(WE);
 
  725  if (Iter == MF.
end())
 
  727  MachineBasicBlock *Cont = &*Iter;
 
  732    if (MachineBasicBlock *ScopeTop = ScopeTops[
I->getNumber()]) {
 
  733      if (ScopeTop->getNumber() > Header->getNumber()) {
 
  735        I = std::next(ScopeTop->getIterator());
 
  747  SmallPtrSet<const MachineInstr *, 4> BeforeSet;
 
  749  SmallPtrSet<const MachineInstr *, 4> AfterSet;
 
  750  for (
const auto &
MI : *Header) {
 
  754    if (
MI.getOpcode() == WebAssembly::LOOP) {
 
  755      auto *LoopBottom = BeginToEnd[&
MI]->getParent()->getPrevNode();
 
  766    if (
MI.getOpcode() == WebAssembly::BLOCK ||
 
  767        MI.getOpcode() == WebAssembly::TRY_TABLE)
 
  772    if (
MI.getOpcode() == WebAssembly::END_BLOCK ||
 
  773        MI.getOpcode() == WebAssembly::END_LOOP ||
 
  774        MI.getOpcode() == WebAssembly::END_TRY_TABLE)
 
  779    if (
MI.isTerminator())
 
  788  MachineInstr *ThrowingCall = 
nullptr;
 
  790    auto TermPos = Header->getFirstTerminator();
 
  791    if (TermPos == Header->end() ||
 
  792        TermPos->getOpcode() != WebAssembly::RETHROW) {
 
  799          if (
MI.getIterator() != Header->begin() &&
 
  800              std::prev(
MI.getIterator())->isEHLabel()) {
 
  801            AfterSet.
insert(&*std::prev(
MI.getIterator()));
 
  802            ThrowingCall = &*std::prev(
MI.getIterator());
 
  817                                    : Header->getFirstTerminator();
 
  818  for (
auto I = SearchStartPt, 
E = Header->begin(); 
I != 
E; --
I) {
 
  819    if (std::prev(I)->isDebugInstr() || std::prev(I)->isPosition())
 
  821    if (WebAssembly::isChild(*std::prev(I), MFI))
 
  822      AfterSet.insert(&*std::prev(I));
 
  841  MachineInstrBuilder BlockMIB =
 
  842      BuildMI(*Header, InsertPos, Header->findDebugLoc(InsertPos),
 
  843              TII.get(WebAssembly::BLOCK));
 
  845  MachineInstrBuilder TryTableMIB =
 
  846      BuildMI(*Header, InsertPos, Header->findDebugLoc(InsertPos),
 
  847              TII.get(WebAssembly::TRY_TABLE))
 
  848          .
addImm(int64_t(WebAssembly::BlockType::Void))
 
  850  auto *TryTable = TryTableMIB.
getInstr();
 
  856      *MF.
getSubtarget<WebAssemblySubtarget>().getTargetLowering();
 
  859          ? WebAssembly::BlockType::I32
 
  860          : WebAssembly::BlockType::I64;
 
  862  switch (
Catch->getOpcode()) {
 
  863  case WebAssembly::CATCH:
 
  867    BlockMIB.
addImm(int64_t(PtrTy));
 
  869    for (
const auto &Use : 
Catch->uses()) {
 
  876  case WebAssembly::CATCH_REF:
 
  881    BlockMIB.
addImm(int64_t(WebAssembly::BlockType::Multivalue));
 
  884    for (
const auto &Use : 
Catch->uses()) {
 
  890  case WebAssembly::CATCH_ALL:
 
  892    BlockMIB.
addImm(int64_t(WebAssembly::BlockType::Void));
 
  896  case WebAssembly::CATCH_ALL_REF:
 
  898    BlockMIB.
addImm(int64_t(WebAssembly::BlockType::Exnref));
 
  908  for (
const auto &
MI : 
MBB) {
 
  911    if (
MI.getOpcode() == WebAssembly::LOOP)
 
  919    if (
MI.getOpcode() == WebAssembly::END_LOOP) {
 
  920      if (EndToBegin[&
MI]->
getParent()->getNumber() >= Header->getNumber())
 
  939  MachineInstr *EndTryTable =
 
  941              TII.get(WebAssembly::END_TRY_TABLE));
 
  942  registerTryScope(TryTable, EndTryTable, &
MBB);
 
  943  MachineInstr *EndBlock =
 
  945              TII.get(WebAssembly::END_BLOCK));
 
  946  registerScope(
Block, EndBlock);
 
  988  for (
auto *End : {&
MBB, Cont})
 
  989    updateScopeTops(Header, End);
 
  992void WebAssemblyCFGStackify::removeUnnecessaryInstrs(MachineFunction &MF) {
 
  993  const auto &
TII = *MF.
getSubtarget<WebAssemblySubtarget>().getInstrInfo();
 
 1028  for (
auto &
MBB : MF) {
 
 1032    MachineBasicBlock *
TBB = 
nullptr, *FBB = 
nullptr;
 
 1036    MachineBasicBlock *Cont = &
MBB;
 
 1038      MachineInstr *Try = EHPadToTry[Cont];
 
 1039      MachineInstr *EndTry = BeginToEnd[Try];
 
 1052    if (Analyzable && ((
Cond.empty() && 
TBB && 
TBB == Cont) ||
 
 1053                       (!
Cond.empty() && FBB && FBB == Cont))) {
 
 1054      bool ErasedUncondBr = 
false;
 
 1055      (void)ErasedUncondBr;
 
 1056      for (
auto I = EHPadLayoutPred->
end(), 
E = EHPadLayoutPred->
begin();
 
 1058        auto PrevI = std::prev(
I);
 
 1059        if (PrevI->isTerminator()) {
 
 1060          assert(PrevI->getOpcode() == WebAssembly::BR);
 
 1061          PrevI->eraseFromParent();
 
 1062          ErasedUncondBr = 
true;
 
 1066      assert(ErasedUncondBr && 
"Unconditional branch not erased!");
 
 1082  for (
auto &
MBB : MF) {
 
 1083    for (
auto &
MI : 
MBB) {
 
 1084      if (
MI.getOpcode() != WebAssembly::TRY)
 
 1086      MachineInstr *Try = &
MI, *EndTry = BeginToEnd[Try];
 
 1087      if (EndTry->getOpcode() == WebAssembly::DELEGATE)
 
 1090      MachineBasicBlock *TryBB = Try->
getParent();
 
 1091      MachineBasicBlock *Cont = EndTry->
getParent();
 
 1093      for (
auto B = Try->
getIterator(), 
E = std::next(EndTry->getIterator());
 
 1095           std::prev(
B)->getOpcode() == WebAssembly::BLOCK &&
 
 1096           E->getOpcode() == WebAssembly::END_BLOCK &&
 
 1097           std::prev(
B)->getOperand(0).getImm() == RetType;
 
 1104  for (
auto *
MI : ToDelete) {
 
 1105    if (
MI->getOpcode() == WebAssembly::BLOCK)
 
 1106      unregisterScope(
MI);
 
 1107    MI->eraseFromParent();
 
 1120  for (
auto &
MI : Split) {
 
 1121    for (
auto &MO : 
MI.explicit_uses()) {
 
 1122      if (!MO.isReg() || MO.getReg().isPhysical())
 
 1125        if (Def->getParent() == &
MBB)
 
 1126          MFI.unstackifyVReg(MO.getReg());
 
 1159    if (!MFI.isVRegStackified(TeeReg)) {
 
 1161      MFI.unstackifyVReg(DefReg);
 
 1167      MI.eraseFromParent();
 
 
 1174void WebAssemblyCFGStackify::addNestedTryDelegate(
 
 1175    MachineInstr *RangeBegin, MachineInstr *RangeEnd,
 
 1176    MachineBasicBlock *UnwindDest) {
 
 1177  auto *BeginBB = RangeBegin->
getParent();
 
 1179  MachineFunction &MF = *BeginBB->
getParent();
 
 1180  const auto &MFI = *MF.
getInfo<WebAssemblyFunctionInfo>();
 
 1181  const auto &
TII = *MF.
getSubtarget<WebAssemblySubtarget>().getInstrInfo();
 
 1185  SmallPtrSet<const MachineInstr *, 4> AfterSet;
 
 1186  AfterSet.
insert(RangeBegin);
 
 1189    if (std::prev(
I)->isDebugInstr() || std::prev(
I)->isPosition())
 
 1192      AfterSet.
insert(&*std::prev(
I));
 
 1199      BeginBB, SmallPtrSet<const MachineInstr *, 4>(), AfterSet);
 
 1201                              TII.get(WebAssembly::TRY))
 
 1202                          .
addImm(int64_t(WebAssembly::BlockType::Void));
 
 1208  if (UnwindDest != FakeCallerBB)
 
 1211  auto SplitPos = std::next(RangeEnd->
getIterator());
 
 1212  if (SplitPos == EndBB->end()) {
 
 1215    MF.
insert(std::next(EndBB->getIterator()), DelegateBB);
 
 1216    EndBB->addSuccessor(DelegateBB);
 
 1226    bool CatchAfterSplit = 
false;
 
 1227    if (EndBB->isEHPad()) {
 
 1231          CatchAfterSplit = 
true;
 
 1237    MachineBasicBlock *PreBB = 
nullptr, *PostBB = 
nullptr;
 
 1238    if (!CatchAfterSplit) {
 
 1257      PostBB->splice(PostBB->end(), PreBB, SplitPos, PreBB->
end());
 
 1258      PostBB->transferSuccessors(PreBB);
 
 1274      assert(EndBB->isEHPad());
 
 1277      MF.
insert(PostBB->getIterator(), PreBB);
 
 1278      MF.
insert(PostBB->getIterator(), DelegateBB);
 
 1279      PreBB->
splice(PreBB->
end(), PostBB, PostBB->begin(), SplitPos);
 
 1291                                   TII.get(WebAssembly::DELEGATE))
 
 1293  registerTryScope(Try, Delegate, 
nullptr);
 
 1312WebAssemblyCFGStackify::getTrampolineBlock(MachineBasicBlock *UnwindDest) {
 
 1316  auto It = UnwindDestToTrampoline.
find(UnwindDest);
 
 1317  if (It != UnwindDestToTrampoline.
end())
 
 1322  const auto &
TII = *MF.
getSubtarget<WebAssemblySubtarget>().getInstrInfo();
 
 1324  MachineInstr *
Block = 
nullptr;
 
 1325  MachineBasicBlock *TrampolineBB = 
nullptr;
 
 1328  if (UnwindDest == getFakeCallerBlock(MF)) {
 
 1332    auto BeginPos = MF.
begin()->begin();
 
 1336                    TII.get(WebAssembly::BLOCK))
 
 1337                .
addImm(int64_t(WebAssembly::BlockType::Exnref));
 
 1338    TrampolineBB = getCallerTrampolineBlock(MF);
 
 1339    MachineBasicBlock *PrevBB = &*std::prev(CallerTrampolineBB->
getIterator());
 
 1345    auto *TargetBeginTry = EHPadToTry[UnwindDest];
 
 1346    auto *TargetEndTry = BeginToEnd[TargetBeginTry];
 
 1347    auto *TargetBeginBB = TargetBeginTry->getParent();
 
 1348    auto *TargetEndBB = TargetEndTry->getParent();
 
 1350    Block = 
BuildMI(*TargetBeginBB, std::next(TargetBeginTry->getIterator()),
 
 1351                    TargetBeginTry->getDebugLoc(), 
TII.get(WebAssembly::BLOCK))
 
 1352                .
addImm(int64_t(WebAssembly::BlockType::Exnref));
 
 1354    EndDebugLoc = TargetEndTry->getDebugLoc();
 
 1355    MF.
insert(TargetEndBB->getIterator(), TrampolineBB);
 
 1361  MachineInstr *EndBlock =
 
 1362      BuildMI(TrampolineBB, EndDebugLoc, 
TII.get(WebAssembly::END_BLOCK));
 
 1363  auto ExnReg = 
MRI.createVirtualRegister(&WebAssembly::EXNREFRegClass);
 
 1364  BuildMI(TrampolineBB, EndDebugLoc, 
TII.get(WebAssembly::CATCH_ALL_REF))
 
 1366  BuildMI(TrampolineBB, EndDebugLoc, 
TII.get(WebAssembly::THROW_REF))
 
 1372  MachineBasicBlock *TrampolineLayoutPred = TrampolineBB->
getPrevNode();
 
 1374          TII.get(WebAssembly::UNREACHABLE));
 
 1376  registerScope(
Block, EndBlock);
 
 1377  UnwindDestToTrampoline[UnwindDest] = TrampolineBB;
 
 1378  return TrampolineBB;
 
 1383void WebAssemblyCFGStackify::addNestedTryTable(MachineInstr *RangeBegin,
 
 1384                                               MachineInstr *RangeEnd,
 
 1385                                               MachineBasicBlock *UnwindDest) {
 
 1386  auto *BeginBB = RangeBegin->
getParent();
 
 1389  MachineFunction &MF = *BeginBB->getParent();
 
 1390  const auto &MFI = *MF.
getInfo<WebAssemblyFunctionInfo>();
 
 1391  const auto &
TII = *MF.
getSubtarget<WebAssemblySubtarget>().getInstrInfo();
 
 1394  auto *TrampolineBB = getTrampolineBlock(UnwindDest);
 
 1398  SmallPtrSet<const MachineInstr *, 4> AfterSet;
 
 1399  AfterSet.
insert(RangeBegin);
 
 1402    if (std::prev(
I)->isDebugInstr() || std::prev(
I)->isPosition())
 
 1405      AfterSet.
insert(&*std::prev(
I));
 
 1412      BeginBB, SmallPtrSet<const MachineInstr *, 4>(), AfterSet);
 
 1413  MachineInstr *TryTable =
 
 1415              TII.get(WebAssembly::TRY_TABLE))
 
 1416          .
addImm(int64_t(WebAssembly::BlockType::Void))
 
 1425  auto SplitPos = std::next(RangeEnd->
getIterator());
 
 1426  if (SplitPos == EndBB->end()) {
 
 1429    MF.
insert(std::next(EndBB->getIterator()), EndTryTableBB);
 
 1430    EndBB->addSuccessor(EndTryTableBB);
 
 1440    bool CatchAfterSplit = 
false;
 
 1441    if (EndBB->isEHPad()) {
 
 1445          CatchAfterSplit = 
true;
 
 1451    MachineBasicBlock *PreBB = 
nullptr, *PostBB = 
nullptr;
 
 1452    if (!CatchAfterSplit) {
 
 1471      PostBB->splice(PostBB->end(), PreBB, SplitPos, PreBB->
end());
 
 1472      PostBB->transferSuccessors(PreBB);
 
 1488      assert(EndBB->isEHPad());
 
 1491      MF.
insert(PostBB->getIterator(), PreBB);
 
 1492      MF.
insert(PostBB->getIterator(), EndTryTableBB);
 
 1493      PreBB->
splice(PreBB->
end(), PostBB, PostBB->begin(), SplitPos);
 
 1505                                      TII.get(WebAssembly::END_TRY_TABLE));
 
 1506  registerTryScope(TryTable, EndTryTable, 
nullptr);
 
 1558  MachineInstr *EndTryTable = 
nullptr, *EndLoop = 
nullptr;
 
 1559  for (
auto &
MI : 
reverse(*EndTryTableBB)) {
 
 1560    if (
MI.getOpcode() == WebAssembly::END_TRY_TABLE) {
 
 1564    if (EndTryTable && 
MI.getOpcode() == WebAssembly::END_LOOP) {
 
 1574  auto SplitPos = std::next(EndLoop->getIterator());
 
 1575  EndLoopBB->splice(EndLoopBB->end(), EndTryTableBB, EndTryTableBB->
begin(),
 
 1577  EndLoopBB->addSuccessor(EndTryTableBB);
 
 
 1580bool WebAssemblyCFGStackify::fixCallUnwindMismatches(MachineFunction &MF) {
 
 1827  using TryRange = std::pair<MachineInstr *, MachineInstr *>;
 
 1829  DenseMap<MachineBasicBlock *, SmallVector<TryRange, 4>> UnwindDestToTryRanges;
 
 1835    bool SeenThrowableInstInBB = 
false;
 
 1849      SeenThrowableInstInBB = 
true;
 
 1853      MachineBasicBlock *UnwindDest = 
nullptr;
 
 1859        if (Succ->isEHPad()) {
 
 1864      if (EHPadStack.
back() == UnwindDest)
 
 1868      MachineInstr *RangeBegin = &
MI, *RangeEnd = &
MI;
 
 1870          std::prev(RangeBegin->
getIterator())->isEHLabel())
 
 1871        RangeBegin = &*std::prev(RangeBegin->
getIterator());
 
 1872      if (std::next(RangeEnd->getIterator()) != 
MBB.
end() &&
 
 1873          std::next(RangeEnd->getIterator())->isEHLabel())
 
 1874        RangeEnd = &*std::next(RangeEnd->getIterator());
 
 1877      UnwindDestToTryRanges[UnwindDest].push_back(
 
 1878          TryRange(RangeBegin, RangeEnd));
 
 1880                        << 
"\nCall = " << 
MI 
 1881                        << 
"\nOriginal dest = " << UnwindDest->
getName()
 
 1882                        << 
"  Current dest = " << EHPadStack.
back()->getName()
 
 1894  MachineInstr *RangeBegin = 
nullptr, *RangeEnd = 
nullptr; 
 
 1897  auto RecordCallerMismatchRange = [&](
const MachineBasicBlock *CurrentDest) {
 
 1898    UnwindDestToTryRanges[getFakeCallerBlock(MF)].push_back(
 
 1899        TryRange(RangeBegin, RangeEnd));
 
 1902                      << 
"\nRange begin = " << *RangeBegin
 
 1903                      << 
"Range end = " << *RangeEnd
 
 1904                      << 
"\nOriginal dest = caller  Current dest = " 
 1905                      << CurrentDest->getName() << 
"\n\n");
 
 1906    RangeBegin = RangeEnd = 
nullptr; 
 
 1910    bool SeenThrowableInstInBB = 
false;
 
 1918        SeenThrowableInstInBB = 
true;
 
 1923        RecordCallerMismatchRange(EHPadStack.
back());
 
 1927      else if (EHPadStack.
empty() || !MayThrow) {
 
 1935          RangeBegin = RangeEnd = &
MI;
 
 1948      RecordCallerMismatchRange(EHPadStack.
back());
 
 1954  if (UnwindDestToTryRanges.
empty())
 
 1960    for (
auto &[UnwindDest, 
_] : UnwindDestToTryRanges) {
 
 1961      auto It = EHPadToTry.
find(UnwindDest);
 
 1964      if (It != EHPadToTry.
end()) {
 
 1965        auto *TryTable = It->second;
 
 1966        auto *EndTryTable = BeginToEnd[TryTable];
 
 1972  for (
auto &
P : UnwindDestToTryRanges) {
 
 1973    NumCallUnwindMismatches += 
P.second.size();
 
 1974    MachineBasicBlock *UnwindDest = 
P.first;
 
 1975    auto &TryRanges = 
P.second;
 
 1977    for (
auto Range : TryRanges) {
 
 1978      MachineInstr *RangeBegin = 
nullptr, *RangeEnd = 
nullptr;
 
 1979      std::tie(RangeBegin, RangeEnd) = 
Range;
 
 1988      if (UnwindDest != getFakeCallerBlock(MF)) {
 
 1989        MachineBasicBlock *EHPad = 
nullptr;
 
 1991          if (Succ->isEHPad()) {
 
 2001        addNestedTryDelegate(RangeBegin, RangeEnd, UnwindDest);
 
 2003        addNestedTryTable(RangeBegin, RangeEnd, UnwindDest);
 
 2028bool WebAssemblyCFGStackify::fixCatchUnwindMismatches(MachineFunction &MF) {
 
 2134  DenseMap<MachineBasicBlock *, MachineBasicBlock *> EHPadToUnwindDest;
 
 2138      if (
MI.getOpcode() == WebAssembly::TRY)
 
 2140      else if (
MI.getOpcode() == WebAssembly::TRY_TABLE) {
 
 2146      } 
else if (
MI.getOpcode() == WebAssembly::DELEGATE)
 
 2164        else if (EHPadStack.
empty() && EHInfo->hasUnwindDest(EHPad)) {
 
 2166                            << 
"'s unwind destination does not exist anymore" 
 2172        else if (!EHPadStack.
empty() && !EHInfo->hasUnwindDest(EHPad)) {
 
 2173          EHPadToUnwindDest[EHPad] = getFakeCallerBlock(MF);
 
 2175                     << 
"- Catch unwind mismatch:\nEHPad = " << EHPad->
getName()
 
 2176                     << 
"  Original dest = caller  Current dest = " 
 2177                     << EHPadStack.
back()->getName() << 
"\n\n");
 
 2182        else if (!EHPadStack.
empty() && EHInfo->hasUnwindDest(EHPad)) {
 
 2183          auto *UnwindDest = EHInfo->getUnwindDest(EHPad);
 
 2184          if (EHPadStack.
back() != UnwindDest) {
 
 2185            EHPadToUnwindDest[EHPad] = UnwindDest;
 
 2187                              << EHPad->
getName() << 
"  Original dest = " 
 2188                              << UnwindDest->
getName() << 
"  Current dest = " 
 2189                              << EHPadStack.
back()->getName() << 
"\n\n");
 
 2199  if (EHPadToUnwindDest.
empty())
 
 2204  for (
auto &[
_, UnwindDest] : EHPadToUnwindDest) {
 
 2205    auto It = EHPadToTry.
find(UnwindDest);
 
 2207    if (It != EHPadToTry.
end()) {
 
 2208      auto *TryTable = It->second;
 
 2209      auto *EndTryTable = BeginToEnd[TryTable];
 
 2214  NumCatchUnwindMismatches += EHPadToUnwindDest.size();
 
 2215  SmallPtrSet<MachineBasicBlock *, 4> NewEndTryBBs;
 
 2217  for (
auto &[EHPad, UnwindDest] : EHPadToUnwindDest) {
 
 2218    MachineInstr *Try = EHPadToTry[EHPad];
 
 2219    MachineInstr *EndTry = BeginToEnd[Try];
 
 2221      addNestedTryDelegate(Try, EndTry, UnwindDest);
 
 2224      addNestedTryTable(Try, EndTry, UnwindDest);
 
 2275  for (
auto &
MBB : MF) {
 
 2276    for (
auto &
MI : 
MBB) {
 
 2277      if (
MI.isTerminator()) {
 
 2278        for (
auto &MO : 
MI.operands()) {
 
 2279          if (MO.isMBB() && NewEndTryBBs.
count(MO.getMBB())) {
 
 2280            auto *BrDest = MO.getMBB();
 
 2281            bool FoundEndBlock = 
false;
 
 2282            for (; std::next(BrDest->getIterator()) != MF.end();
 
 2283                 BrDest = BrDest->getNextNode()) {
 
 2284              for (
const auto &
MI : *BrDest) {
 
 2285                if (
MI.getOpcode() == WebAssembly::END_BLOCK) {
 
 2286                  FoundEndBlock = 
true;
 
 2304void WebAssemblyCFGStackify::recalculateScopeTops(MachineFunction &MF) {
 
 2308  MDT->updateBlockNumbers();
 
 2315      switch (
MI.getOpcode()) {
 
 2316      case WebAssembly::END_BLOCK:
 
 2317      case WebAssembly::END_LOOP:
 
 2318      case WebAssembly::END_TRY:
 
 2319      case WebAssembly::END_TRY_TABLE:
 
 2320      case WebAssembly::DELEGATE:
 
 2323      case WebAssembly::CATCH_LEGACY:
 
 2324      case WebAssembly::CATCH_ALL_LEGACY:
 
 2339void WebAssemblyCFGStackify::fixEndsAtEndOfFunction(MachineFunction &MF) {
 
 2340  const auto &MFI = *MF.
getInfo<WebAssemblyFunctionInfo>();
 
 2342  if (MFI.getResults().empty())
 
 2348      MFI.getResults().size() > 1
 
 2349          ? WebAssembly::BlockType::Multivalue
 
 2359      MachineInstr &
MI = *It++;
 
 2360      if (
MI.isPosition() || 
MI.isDebugInstr())
 
 2362      switch (
MI.getOpcode()) {
 
 2363      case WebAssembly::END_TRY: {
 
 2367        auto *EHPad = TryToEHPad.
lookup(EndToBegin[&
MI]);
 
 2371        if (NextIt != EHPad->
rend())
 
 2375      case WebAssembly::END_BLOCK:
 
 2376      case WebAssembly::END_LOOP:
 
 2377      case WebAssembly::END_TRY_TABLE:
 
 2378      case WebAssembly::DELEGATE:
 
 2379        EndToBegin[&
MI]->getOperand(0).setImm(int32_t(RetType));
 
 2391  while (!Worklist.
empty())
 
 2401          TII.get(WebAssembly::END_FUNCTION));
 
 
 2427  std::vector<MachineInstr *> EndTryTables;
 
 2428  for (
auto &
MBB : MF)
 
 2429    for (
auto &
MI : 
MBB)
 
 2430      if (
MI.getOpcode() == WebAssembly::END_TRY_TABLE)
 
 2431        EndTryTables.push_back(&
MI);
 
 2433  for (
auto *EndTryTable : EndTryTables) {
 
 2436    MF.
insert(
MBB->getIterator(), NewEndTryTableBB);
 
 2437    auto SplitPos = std::next(EndTryTable->
getIterator());
 
 2438    NewEndTryTableBB->splice(NewEndTryTableBB->end(), 
MBB, 
MBB->begin(),
 
 2440    NewEndTryTableBB->addSuccessor(
MBB);
 
 2442            TII.get(WebAssembly::UNREACHABLE));
 
 
 2447void WebAssemblyCFGStackify::placeMarkers(MachineFunction &MF) {
 
 2452  for (
auto &
MBB : MF)
 
 2453    placeLoopMarker(
MBB);
 
 2455  const MCAsmInfo *MCAI = MF.getTarget().getMCAsmInfo();
 
 2456  for (
auto &
MBB : MF) {
 
 2460          MF.getFunction().hasPersonalityFn()) {
 
 2462          placeTryMarker(
MBB);
 
 2464          placeTryTableMarker(
MBB);
 
 2468      placeBlockMarker(
MBB);
 
 2473      MF.getFunction().hasPersonalityFn()) {
 
 2474    const auto &
TII = *MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo();
 
 2478    fixCallUnwindMismatches(MF);
 
 2479    fixCatchUnwindMismatches(MF);
 
 2482    recalculateScopeTops(MF);
 
 2486unsigned WebAssemblyCFGStackify::getBranchDepth(
 
 2487    const SmallVectorImpl<EndMarkerInfo> &Stack, 
const MachineBasicBlock *
MBB) {
 
 2498unsigned WebAssemblyCFGStackify::getDelegateDepth(
 
 2499    const SmallVectorImpl<EndMarkerInfo> &Stack, 
const MachineBasicBlock *
MBB) {
 
 2500  if (
MBB == FakeCallerBB)
 
 2501    return Stack.size();
 
 2507    return getBranchDepth(Stack, 
MBB);
 
 2523  const MachineInstr *EndTry = BeginToEnd[EHPadToTry[
MBB]];
 
 2525    if (
X.first == EndTry->
getParent() && 
X.second == EndTry)
 
 2533unsigned WebAssemblyCFGStackify::getRethrowDepth(
 
 2534    const SmallVectorImpl<EndMarkerInfo> &Stack,
 
 2535    const MachineBasicBlock *EHPadToRethrow) {
 
 2538    const MachineInstr *End = 
X.second;
 
 2539    if (End->
getOpcode() == WebAssembly::END_TRY) {
 
 2540      auto *EHPad = TryToEHPad[EndToBegin[End]];
 
 2541      if (EHPadToRethrow == EHPad)
 
 2550void WebAssemblyCFGStackify::rewriteDepthImmediates(MachineFunction &MF) {
 
 2554  auto RewriteOperands = [&](MachineInstr &
MI) {
 
 2557    while (
MI.getNumOperands() > 0)
 
 2558      MI.removeOperand(
MI.getNumOperands() - 1);
 
 2559    for (
auto MO : 
Ops) {
 
 2561        if (
MI.getOpcode() == WebAssembly::DELEGATE)
 
 2563        else if (
MI.getOpcode() == WebAssembly::RETHROW)
 
 2568      MI.addOperand(MF, MO);
 
 2574      switch (
MI.getOpcode()) {
 
 2575      case WebAssembly::BLOCK:
 
 2576      case WebAssembly::TRY:
 
 2577        assert(ScopeTops[
Stack.back().first->getNumber()]->getNumber() <=
 
 2579               "Block/try/try_table marker should be balanced");
 
 2583      case WebAssembly::TRY_TABLE:
 
 2584        assert(ScopeTops[
Stack.back().first->getNumber()]->getNumber() <=
 
 2586               "Block/try/try_table marker should be balanced");
 
 2588        RewriteOperands(
MI);
 
 2591      case WebAssembly::LOOP:
 
 2592        assert(
Stack.back().first == &
MBB && 
"Loop top should be balanced");
 
 2596      case WebAssembly::END_BLOCK:
 
 2597      case WebAssembly::END_TRY:
 
 2598      case WebAssembly::END_TRY_TABLE:
 
 2602      case WebAssembly::END_LOOP:
 
 2606      case WebAssembly::DELEGATE:
 
 2607        RewriteOperands(
MI);
 
 2612        if (
MI.isTerminator())
 
 2613          RewriteOperands(
MI);
 
 2618  assert(
Stack.empty() && 
"Control flow should be balanced");
 
 2621void WebAssemblyCFGStackify::cleanupFunctionData(MachineFunction &MF) {
 
 2624  AppendixBB = FakeCallerBB = CallerTrampolineBB = 
nullptr;
 
 2627void WebAssemblyCFGStackify::releaseMemory() {
 
 2633  UnwindDestToTrampoline.
clear();
 
 2636bool WebAssemblyCFGStackify::runOnMachineFunction(MachineFunction &MF) {
 
 2638                       "********** Function: " 
 2641  MDT = &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
 
 2655    removeUnnecessaryInstrs(MF);
 
 2658  rewriteDepthImmediates(MF);
 
 2662  fixEndsAtEndOfFunction(MF);
 
 2665  const auto &
TII = *MF.
getSubtarget<WebAssemblySubtarget>().getInstrInfo();
 
 2668  cleanupFunctionData(MF);
 
 2670  MF.
getInfo<WebAssemblyFunctionInfo>()->setCFGStackified();
 
unsigned const MachineRegisterInfo * MRI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static const Function * getParent(const Value *V)
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
const HexagonInstrInfo * TII
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
const SmallVectorImpl< MachineOperand > MachineBasicBlock * TBB
const SmallVectorImpl< MachineOperand > & Cond
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
static TableGen::Emitter::OptClass< SkeletonEmitter > X("gen-skeleton-class", "Generate example skeleton class")
static bool explicitlyBranchesTo(MachineBasicBlock *Pred, MachineBasicBlock *MBB)
Test whether Pred has any terminators explicitly branching to MBB, as opposed to falling through.
static void addUnreachableAfterTryTables(MachineFunction &MF, const WebAssemblyInstrInfo &TII)
static MachineBasicBlock::iterator getLatestInsertPos(MachineBasicBlock *MBB, const Container &BeforeSet, const Container &AfterSet)
static void splitEndLoopBB(MachineBasicBlock *EndTryTableBB)
static void appendEndToFunction(MachineFunction &MF, const WebAssemblyInstrInfo &TII)
static void unstackifyVRegsUsedInSplitBB(MachineBasicBlock &MBB, MachineBasicBlock &Split)
static MachineBasicBlock * getSingleUnwindDest(const MachineInstr *TryTable)
static MachineBasicBlock::iterator getEarliestInsertPos(MachineBasicBlock *MBB, const Container &BeforeSet, const Container &AfterSet)
This file implements WebAssemblyException information analysis.
This file declares WebAssembly-specific per-machine-function information.
This file implements regions used in CFGSort and CFGStackify.
This file declares the WebAssembly-specific subclass of TargetSubtarget.
This file declares the WebAssembly-specific subclass of TargetMachine.
This file contains the declaration of the WebAssembly-specific type parsing utility functions.
This file contains the declaration of the WebAssembly-specific utility functions.
This file contains the entry points for global functions defined in the LLVM WebAssembly back-end.
AnalysisUsage & addRequired()
ValueT lookup(const_arg_type_t< KeyT > Val) const
lookup - Return the entry for the specified key, or a default constructed value if no such entry exis...
iterator find(const_arg_type_t< KeyT > Val)
bool erase(const KeyT &Val)
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
FunctionPass class - This class is used to implement most global optimizations.
bool hasPersonalityFn() const
Check whether this function has a personality function.
bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl< MachineOperand > &Cond, bool AllowModify) const override
Analyze the branching code at the end of MBB, returning true if it cannot be understood (e....
BlockT * getHeader() const
ExceptionHandling getExceptionHandlingType() const
LLVM_ABI bool hasEHPadSuccessor() const
bool isEHPad() const
Returns true if the block is a landing pad.
int getNumber() const
MachineBasicBlocks are uniquely numbered at the function level, unless they're not in a MachineFuncti...
LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
LLVM_ABI void removeSuccessor(MachineBasicBlock *Succ, bool NormalizeSuccProbs=false)
Remove successor from the successors list of this MachineBasicBlock.
LLVM_ABI bool isPredecessor(const MachineBasicBlock *MBB) const
Return true if the specified MBB is a predecessor of this block.
LLVM_ABI DebugLoc findDebugLoc(instr_iterator MBBI)
Find the next valid DebugLoc starting at MBBI, skipping any debug instructions.
MachineInstrBundleIterator< MachineInstr, true > reverse_iterator
LLVM_ABI DebugLoc findPrevDebugLoc(instr_iterator MBBI)
Find the previous valid DebugLoc preceding MBBI, skipping any debug instructions.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
LLVM_ABI DebugLoc findBranchDebugLoc()
Find and return the merged DebugLoc of the branch instructions of the block.
iterator_range< succ_iterator > successors()
reverse_iterator rbegin()
iterator_range< pred_iterator > predecessors()
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
MachineInstrBundleIterator< MachineInstr > iterator
LLVM_ABI StringRef getName() const
Return the name of the corresponding LLVM basic block, or an empty string.
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
void push_back(MachineBasicBlock *MBB)
reverse_iterator rbegin()
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
void deleteMachineBasicBlock(MachineBasicBlock *MBB)
DeleteMachineBasicBlock - Delete the given MachineBasicBlock.
Function & getFunction()
Return the LLVM function that this machine code represents.
unsigned getNumBlockIDs() const
getNumBlockIDs - Return the number of MBB ID's allocated.
const MachineBasicBlock & back() const
BasicBlockListType::iterator iterator
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
const WasmEHFuncInfo * getWasmEHFuncInfo() const
getWasmEHFuncInfo - Return information about how the current function uses Wasm exception handling.
void RenumberBlocks(MachineBasicBlock *MBBFrom=nullptr)
RenumberBlocks - This discards all of the MachineBasicBlock numbers and recomputes them.
const MachineBasicBlock & front() const
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
void insert(iterator MBBI, MachineBasicBlock *MBB)
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
const MachineInstrBuilder & addExternalSymbol(const char *FnName, unsigned TargetFlags=0) const
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
MachineInstr * getInstr() const
If conversion operators fail, use this method to get the MachineInstr explicitly.
const MachineInstrBuilder & addDef(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register definition operand.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const MachineBasicBlock * getParent() const
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
const MachineOperand & getOperand(unsigned i) const
MachineOperand class - Representation of each machine instruction operand.
MachineBasicBlock * getMBB() const
static MachineOperand CreateImm(int64_t Val)
void setTargetFlags(unsigned F)
void invalidateLiveness()
invalidateLiveness - Indicates that register liveness is no longer being tracked accurately.
Wrapper class representing virtual and physical registers.
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
void push_back(const T &Elt)
StringRef - Represent a constant reference to a string, i.e.
const MCAsmInfo * getMCAsmInfo() const
Return target specific asm information.
This class is derived from MachineFunctionInfo and contains private WebAssembly-specific information ...
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
bool isChild(const MachineInstr &MI, const WebAssemblyFunctionInfo &MFI)
Test whether MI is a child of some other node in an expression tree.
bool isArgument(unsigned Opc)
bool isCatchAll(unsigned Opc)
bool isMarker(unsigned Opc)
unsigned getCopyOpcodeForRegClass(const TargetRegisterClass *RC)
Returns the appropriate copy opcode for the given register class.
wasm::ValType toValType(MVT Type)
cl::opt< bool > WasmUseLegacyEH
MachineInstr * findCatch(MachineBasicBlock *EHPad)
Find a catch instruction from an EH pad.
bool isCatch(unsigned Opc)
BlockType
Used as immediate MachineOperands for block signatures.
bool mayThrow(const MachineInstr &MI)
NodeAddr< UseNode * > Use
@ WASM_OPCODE_CATCH_ALL_REF
This is an optimization pass for GlobalISel generic memory operations.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
auto reverse(ContainerTy &&C)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
FunctionPass * createWebAssemblyCFGStackify()
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...