WebAssemblyExceptionInfo.cpp 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. //===--- WebAssemblyExceptionInfo.cpp - Exception Infomation --------------===//
  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. /// \brief This file implements WebAssemblyException information analysis.
  12. ///
  13. //===----------------------------------------------------------------------===//
  14. #include "WebAssemblyExceptionInfo.h"
  15. #include "WebAssemblyUtilities.h"
  16. #include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
  17. #include "llvm/ADT/PostOrderIterator.h"
  18. #include "llvm/CodeGen/MachineDominanceFrontier.h"
  19. #include "llvm/CodeGen/MachineDominators.h"
  20. using namespace llvm;
  21. #define DEBUG_TYPE "wasm-exception-info"
  22. char WebAssemblyExceptionInfo::ID = 0;
  23. INITIALIZE_PASS_BEGIN(WebAssemblyExceptionInfo, DEBUG_TYPE,
  24. "WebAssembly Exception Information", true, true)
  25. INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree)
  26. INITIALIZE_PASS_DEPENDENCY(MachineDominanceFrontier)
  27. INITIALIZE_PASS_END(WebAssemblyExceptionInfo, DEBUG_TYPE,
  28. "WebAssembly Exception Information", true, true)
  29. bool WebAssemblyExceptionInfo::runOnMachineFunction(MachineFunction &F) {
  30. releaseMemory();
  31. auto &MDT = getAnalysis<MachineDominatorTree>();
  32. auto &MDF = getAnalysis<MachineDominanceFrontier>();
  33. recalculate(MDT, MDF);
  34. return false;
  35. }
  36. void WebAssemblyExceptionInfo::recalculate(
  37. MachineDominatorTree &MDT, const MachineDominanceFrontier &MDF) {
  38. // Postorder traversal of the dominator tree.
  39. SmallVector<WebAssemblyException *, 8> Exceptions;
  40. for (auto DomNode : post_order(&MDT)) {
  41. MachineBasicBlock *EHPad = DomNode->getBlock();
  42. if (!EHPad->isEHPad())
  43. continue;
  44. // We group catch & catch-all terminate pads together, so skip the second
  45. // one
  46. if (WebAssembly::isCatchAllTerminatePad(*EHPad))
  47. continue;
  48. auto *WE = new WebAssemblyException(EHPad);
  49. discoverAndMapException(WE, MDT, MDF);
  50. Exceptions.push_back(WE);
  51. }
  52. // Add BBs to exceptions
  53. for (auto DomNode : post_order(&MDT)) {
  54. MachineBasicBlock *MBB = DomNode->getBlock();
  55. WebAssemblyException *WE = getExceptionFor(MBB);
  56. for (; WE; WE = WE->getParentException())
  57. WE->addBlock(MBB);
  58. }
  59. // Add subexceptions to exceptions
  60. for (auto *WE : Exceptions) {
  61. if (WE->getParentException())
  62. WE->getParentException()->getSubExceptions().push_back(WE);
  63. else
  64. addTopLevelException(WE);
  65. }
  66. // For convenience, Blocks and SubExceptions are inserted in postorder.
  67. // Reverse the lists.
  68. for (auto *WE : Exceptions) {
  69. WE->reverseBlock();
  70. std::reverse(WE->getSubExceptions().begin(), WE->getSubExceptions().end());
  71. }
  72. }
  73. void WebAssemblyExceptionInfo::releaseMemory() {
  74. BBMap.clear();
  75. DeleteContainerPointers(TopLevelExceptions);
  76. TopLevelExceptions.clear();
  77. }
  78. void WebAssemblyExceptionInfo::getAnalysisUsage(AnalysisUsage &AU) const {
  79. AU.setPreservesAll();
  80. AU.addRequired<MachineDominatorTree>();
  81. AU.addRequired<MachineDominanceFrontier>();
  82. MachineFunctionPass::getAnalysisUsage(AU);
  83. }
  84. void WebAssemblyExceptionInfo::discoverAndMapException(
  85. WebAssemblyException *WE, const MachineDominatorTree &MDT,
  86. const MachineDominanceFrontier &MDF) {
  87. unsigned NumBlocks = 0;
  88. unsigned NumSubExceptions = 0;
  89. // Map blocks that belong to a catchpad / cleanuppad
  90. MachineBasicBlock *EHPad = WE->getEHPad();
  91. // We group catch & catch-all terminate pads together within an exception
  92. if (WebAssembly::isCatchTerminatePad(*EHPad)) {
  93. assert(EHPad->succ_size() == 1 &&
  94. "Catch terminate pad has more than one successors");
  95. changeExceptionFor(EHPad, WE);
  96. changeExceptionFor(*(EHPad->succ_begin()), WE);
  97. return;
  98. }
  99. SmallVector<MachineBasicBlock *, 8> WL;
  100. WL.push_back(EHPad);
  101. while (!WL.empty()) {
  102. MachineBasicBlock *MBB = WL.pop_back_val();
  103. // Find its outermost discovered exception. If this is a discovered block,
  104. // check if it is already discovered to be a subexception of this exception.
  105. WebAssemblyException *SubE = getOutermostException(MBB);
  106. if (SubE) {
  107. if (SubE != WE) {
  108. // Discover a subexception of this exception.
  109. SubE->setParentException(WE);
  110. ++NumSubExceptions;
  111. NumBlocks += SubE->getBlocksVector().capacity();
  112. // All blocks that belong to this subexception have been already
  113. // discovered. Skip all of them. Add the subexception's landing pad's
  114. // dominance frontier to the worklist.
  115. for (auto &Frontier : MDF.find(SubE->getEHPad())->second)
  116. if (MDT.dominates(EHPad, Frontier))
  117. WL.push_back(Frontier);
  118. }
  119. continue;
  120. }
  121. // This is an undiscovered block. Map it to the current exception.
  122. changeExceptionFor(MBB, WE);
  123. ++NumBlocks;
  124. // Add successors dominated by the current BB to the worklist.
  125. for (auto *Succ : MBB->successors())
  126. if (MDT.dominates(EHPad, Succ))
  127. WL.push_back(Succ);
  128. }
  129. WE->getSubExceptions().reserve(NumSubExceptions);
  130. WE->reserveBlocks(NumBlocks);
  131. }
  132. WebAssemblyException *
  133. WebAssemblyExceptionInfo::getOutermostException(MachineBasicBlock *MBB) const {
  134. WebAssemblyException *WE = getExceptionFor(MBB);
  135. if (WE) {
  136. while (WebAssemblyException *Parent = WE->getParentException())
  137. WE = Parent;
  138. }
  139. return WE;
  140. }
  141. void WebAssemblyException::print(raw_ostream &OS, unsigned Depth) const {
  142. OS.indent(Depth * 2) << "Exception at depth " << getExceptionDepth()
  143. << " containing: ";
  144. for (unsigned I = 0; I < getBlocks().size(); ++I) {
  145. MachineBasicBlock *MBB = getBlocks()[I];
  146. if (I)
  147. OS << ", ";
  148. OS << "%bb." << MBB->getNumber();
  149. if (const auto *BB = MBB->getBasicBlock())
  150. if (BB->hasName())
  151. OS << "." << BB->getName();
  152. if (getEHPad() == MBB)
  153. OS << " (landing-pad)";
  154. }
  155. OS << "\n";
  156. for (auto &SubE : SubExceptions)
  157. SubE->print(OS, Depth + 2);
  158. }
  159. #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
  160. LLVM_DUMP_METHOD void WebAssemblyException::dump() const { print(dbgs()); }
  161. #endif
  162. raw_ostream &operator<<(raw_ostream &OS, const WebAssemblyException &WE) {
  163. WE.print(OS);
  164. return OS;
  165. }
  166. void WebAssemblyExceptionInfo::print(raw_ostream &OS, const Module *) const {
  167. for (auto *WE : TopLevelExceptions)
  168. WE->print(OS);
  169. }