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