10b57cec5SDimitry Andric //===--- WebAssemblyExceptionInfo.cpp - Exception Infomation --------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric /// 90b57cec5SDimitry Andric /// \file 100b57cec5SDimitry Andric /// \brief This file implements WebAssemblyException information analysis. 110b57cec5SDimitry Andric /// 120b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 130b57cec5SDimitry Andric 140b57cec5SDimitry Andric #include "WebAssemblyExceptionInfo.h" 150b57cec5SDimitry Andric #include "MCTargetDesc/WebAssemblyMCTargetDesc.h" 160b57cec5SDimitry Andric #include "WebAssemblyUtilities.h" 170b57cec5SDimitry Andric #include "llvm/ADT/PostOrderIterator.h" 180b57cec5SDimitry Andric #include "llvm/CodeGen/MachineDominanceFrontier.h" 190b57cec5SDimitry Andric #include "llvm/CodeGen/MachineDominators.h" 20*480093f4SDimitry Andric #include "llvm/InitializePasses.h" 210b57cec5SDimitry Andric 220b57cec5SDimitry Andric using namespace llvm; 230b57cec5SDimitry Andric 240b57cec5SDimitry Andric #define DEBUG_TYPE "wasm-exception-info" 250b57cec5SDimitry Andric 260b57cec5SDimitry Andric char WebAssemblyExceptionInfo::ID = 0; 270b57cec5SDimitry Andric 280b57cec5SDimitry Andric INITIALIZE_PASS_BEGIN(WebAssemblyExceptionInfo, DEBUG_TYPE, 290b57cec5SDimitry Andric "WebAssembly Exception Information", true, true) 300b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree) 310b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(MachineDominanceFrontier) 320b57cec5SDimitry Andric INITIALIZE_PASS_END(WebAssemblyExceptionInfo, DEBUG_TYPE, 330b57cec5SDimitry Andric "WebAssembly Exception Information", true, true) 340b57cec5SDimitry Andric 350b57cec5SDimitry Andric bool WebAssemblyExceptionInfo::runOnMachineFunction(MachineFunction &MF) { 360b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "********** Exception Info Calculation **********\n" 370b57cec5SDimitry Andric "********** Function: " 380b57cec5SDimitry Andric << MF.getName() << '\n'); 390b57cec5SDimitry Andric releaseMemory(); 400b57cec5SDimitry Andric auto &MDT = getAnalysis<MachineDominatorTree>(); 410b57cec5SDimitry Andric auto &MDF = getAnalysis<MachineDominanceFrontier>(); 420b57cec5SDimitry Andric recalculate(MDT, MDF); 430b57cec5SDimitry Andric return false; 440b57cec5SDimitry Andric } 450b57cec5SDimitry Andric 460b57cec5SDimitry Andric void WebAssemblyExceptionInfo::recalculate( 470b57cec5SDimitry Andric MachineDominatorTree &MDT, const MachineDominanceFrontier &MDF) { 480b57cec5SDimitry Andric // Postorder traversal of the dominator tree. 490b57cec5SDimitry Andric SmallVector<WebAssemblyException *, 8> Exceptions; 500b57cec5SDimitry Andric for (auto DomNode : post_order(&MDT)) { 510b57cec5SDimitry Andric MachineBasicBlock *EHPad = DomNode->getBlock(); 520b57cec5SDimitry Andric if (!EHPad->isEHPad()) 530b57cec5SDimitry Andric continue; 540b57cec5SDimitry Andric auto *WE = new WebAssemblyException(EHPad); 550b57cec5SDimitry Andric discoverAndMapException(WE, MDT, MDF); 560b57cec5SDimitry Andric Exceptions.push_back(WE); 570b57cec5SDimitry Andric } 580b57cec5SDimitry Andric 590b57cec5SDimitry Andric // Add BBs to exceptions 600b57cec5SDimitry Andric for (auto DomNode : post_order(&MDT)) { 610b57cec5SDimitry Andric MachineBasicBlock *MBB = DomNode->getBlock(); 620b57cec5SDimitry Andric WebAssemblyException *WE = getExceptionFor(MBB); 630b57cec5SDimitry Andric for (; WE; WE = WE->getParentException()) 640b57cec5SDimitry Andric WE->addBlock(MBB); 650b57cec5SDimitry Andric } 660b57cec5SDimitry Andric 670b57cec5SDimitry Andric // Add subexceptions to exceptions 680b57cec5SDimitry Andric for (auto *WE : Exceptions) { 690b57cec5SDimitry Andric if (WE->getParentException()) 700b57cec5SDimitry Andric WE->getParentException()->getSubExceptions().push_back(WE); 710b57cec5SDimitry Andric else 720b57cec5SDimitry Andric addTopLevelException(WE); 730b57cec5SDimitry Andric } 740b57cec5SDimitry Andric 750b57cec5SDimitry Andric // For convenience, Blocks and SubExceptions are inserted in postorder. 760b57cec5SDimitry Andric // Reverse the lists. 770b57cec5SDimitry Andric for (auto *WE : Exceptions) { 780b57cec5SDimitry Andric WE->reverseBlock(); 790b57cec5SDimitry Andric std::reverse(WE->getSubExceptions().begin(), WE->getSubExceptions().end()); 800b57cec5SDimitry Andric } 810b57cec5SDimitry Andric } 820b57cec5SDimitry Andric 830b57cec5SDimitry Andric void WebAssemblyExceptionInfo::releaseMemory() { 840b57cec5SDimitry Andric BBMap.clear(); 850b57cec5SDimitry Andric DeleteContainerPointers(TopLevelExceptions); 860b57cec5SDimitry Andric TopLevelExceptions.clear(); 870b57cec5SDimitry Andric } 880b57cec5SDimitry Andric 890b57cec5SDimitry Andric void WebAssemblyExceptionInfo::getAnalysisUsage(AnalysisUsage &AU) const { 900b57cec5SDimitry Andric AU.setPreservesAll(); 910b57cec5SDimitry Andric AU.addRequired<MachineDominatorTree>(); 920b57cec5SDimitry Andric AU.addRequired<MachineDominanceFrontier>(); 930b57cec5SDimitry Andric MachineFunctionPass::getAnalysisUsage(AU); 940b57cec5SDimitry Andric } 950b57cec5SDimitry Andric 960b57cec5SDimitry Andric void WebAssemblyExceptionInfo::discoverAndMapException( 970b57cec5SDimitry Andric WebAssemblyException *WE, const MachineDominatorTree &MDT, 980b57cec5SDimitry Andric const MachineDominanceFrontier &MDF) { 990b57cec5SDimitry Andric unsigned NumBlocks = 0; 1000b57cec5SDimitry Andric unsigned NumSubExceptions = 0; 1010b57cec5SDimitry Andric 1020b57cec5SDimitry Andric // Map blocks that belong to a catchpad / cleanuppad 1030b57cec5SDimitry Andric MachineBasicBlock *EHPad = WE->getEHPad(); 1040b57cec5SDimitry Andric SmallVector<MachineBasicBlock *, 8> WL; 1050b57cec5SDimitry Andric WL.push_back(EHPad); 1060b57cec5SDimitry Andric while (!WL.empty()) { 1070b57cec5SDimitry Andric MachineBasicBlock *MBB = WL.pop_back_val(); 1080b57cec5SDimitry Andric 1090b57cec5SDimitry Andric // Find its outermost discovered exception. If this is a discovered block, 1100b57cec5SDimitry Andric // check if it is already discovered to be a subexception of this exception. 1110b57cec5SDimitry Andric WebAssemblyException *SubE = getOutermostException(MBB); 1120b57cec5SDimitry Andric if (SubE) { 1130b57cec5SDimitry Andric if (SubE != WE) { 1140b57cec5SDimitry Andric // Discover a subexception of this exception. 1150b57cec5SDimitry Andric SubE->setParentException(WE); 1160b57cec5SDimitry Andric ++NumSubExceptions; 1170b57cec5SDimitry Andric NumBlocks += SubE->getBlocksVector().capacity(); 1180b57cec5SDimitry Andric // All blocks that belong to this subexception have been already 1190b57cec5SDimitry Andric // discovered. Skip all of them. Add the subexception's landing pad's 1200b57cec5SDimitry Andric // dominance frontier to the worklist. 1210b57cec5SDimitry Andric for (auto &Frontier : MDF.find(SubE->getEHPad())->second) 1220b57cec5SDimitry Andric if (MDT.dominates(EHPad, Frontier)) 1230b57cec5SDimitry Andric WL.push_back(Frontier); 1240b57cec5SDimitry Andric } 1250b57cec5SDimitry Andric continue; 1260b57cec5SDimitry Andric } 1270b57cec5SDimitry Andric 1280b57cec5SDimitry Andric // This is an undiscovered block. Map it to the current exception. 1290b57cec5SDimitry Andric changeExceptionFor(MBB, WE); 1300b57cec5SDimitry Andric ++NumBlocks; 1310b57cec5SDimitry Andric 1320b57cec5SDimitry Andric // Add successors dominated by the current BB to the worklist. 1330b57cec5SDimitry Andric for (auto *Succ : MBB->successors()) 1340b57cec5SDimitry Andric if (MDT.dominates(EHPad, Succ)) 1350b57cec5SDimitry Andric WL.push_back(Succ); 1360b57cec5SDimitry Andric } 1370b57cec5SDimitry Andric 1380b57cec5SDimitry Andric WE->getSubExceptions().reserve(NumSubExceptions); 1390b57cec5SDimitry Andric WE->reserveBlocks(NumBlocks); 1400b57cec5SDimitry Andric } 1410b57cec5SDimitry Andric 1420b57cec5SDimitry Andric WebAssemblyException * 1430b57cec5SDimitry Andric WebAssemblyExceptionInfo::getOutermostException(MachineBasicBlock *MBB) const { 1440b57cec5SDimitry Andric WebAssemblyException *WE = getExceptionFor(MBB); 1450b57cec5SDimitry Andric if (WE) { 1460b57cec5SDimitry Andric while (WebAssemblyException *Parent = WE->getParentException()) 1470b57cec5SDimitry Andric WE = Parent; 1480b57cec5SDimitry Andric } 1490b57cec5SDimitry Andric return WE; 1500b57cec5SDimitry Andric } 1510b57cec5SDimitry Andric 1520b57cec5SDimitry Andric void WebAssemblyException::print(raw_ostream &OS, unsigned Depth) const { 1530b57cec5SDimitry Andric OS.indent(Depth * 2) << "Exception at depth " << getExceptionDepth() 1540b57cec5SDimitry Andric << " containing: "; 1550b57cec5SDimitry Andric 1560b57cec5SDimitry Andric for (unsigned I = 0; I < getBlocks().size(); ++I) { 1570b57cec5SDimitry Andric MachineBasicBlock *MBB = getBlocks()[I]; 1580b57cec5SDimitry Andric if (I) 1590b57cec5SDimitry Andric OS << ", "; 1600b57cec5SDimitry Andric OS << "%bb." << MBB->getNumber(); 1610b57cec5SDimitry Andric if (const auto *BB = MBB->getBasicBlock()) 1620b57cec5SDimitry Andric if (BB->hasName()) 1630b57cec5SDimitry Andric OS << "." << BB->getName(); 1640b57cec5SDimitry Andric 1650b57cec5SDimitry Andric if (getEHPad() == MBB) 1660b57cec5SDimitry Andric OS << " (landing-pad)"; 1670b57cec5SDimitry Andric } 1680b57cec5SDimitry Andric OS << "\n"; 1690b57cec5SDimitry Andric 1700b57cec5SDimitry Andric for (auto &SubE : SubExceptions) 1710b57cec5SDimitry Andric SubE->print(OS, Depth + 2); 1720b57cec5SDimitry Andric } 1730b57cec5SDimitry Andric 1740b57cec5SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 1750b57cec5SDimitry Andric LLVM_DUMP_METHOD void WebAssemblyException::dump() const { print(dbgs()); } 1760b57cec5SDimitry Andric #endif 1770b57cec5SDimitry Andric 1780b57cec5SDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const WebAssemblyException &WE) { 1790b57cec5SDimitry Andric WE.print(OS); 1800b57cec5SDimitry Andric return OS; 1810b57cec5SDimitry Andric } 1820b57cec5SDimitry Andric 1830b57cec5SDimitry Andric void WebAssemblyExceptionInfo::print(raw_ostream &OS, const Module *) const { 1840b57cec5SDimitry Andric for (auto *WE : TopLevelExceptions) 1850b57cec5SDimitry Andric WE->print(OS); 1860b57cec5SDimitry Andric } 187