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" 20480093f4SDimitry 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. 49*5ffd83dbSDimitry Andric SmallVector<std::unique_ptr<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; 54*5ffd83dbSDimitry Andric auto WE = std::make_unique<WebAssemblyException>(EHPad); 55*5ffd83dbSDimitry Andric discoverAndMapException(WE.get(), MDT, MDF); 56*5ffd83dbSDimitry Andric Exceptions.push_back(std::move(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 67*5ffd83dbSDimitry Andric SmallVector<WebAssemblyException*, 8> ExceptionPointers; 68*5ffd83dbSDimitry Andric ExceptionPointers.reserve(Exceptions.size()); 69*5ffd83dbSDimitry Andric 700b57cec5SDimitry Andric // Add subexceptions to exceptions 71*5ffd83dbSDimitry Andric for (auto &WE : Exceptions) { 72*5ffd83dbSDimitry Andric ExceptionPointers.push_back(WE.get()); 730b57cec5SDimitry Andric if (WE->getParentException()) 74*5ffd83dbSDimitry Andric WE->getParentException()->getSubExceptions().push_back(std::move(WE)); 750b57cec5SDimitry Andric else 76*5ffd83dbSDimitry Andric addTopLevelException(std::move(WE)); 770b57cec5SDimitry Andric } 780b57cec5SDimitry Andric 790b57cec5SDimitry Andric // For convenience, Blocks and SubExceptions are inserted in postorder. 800b57cec5SDimitry Andric // Reverse the lists. 81*5ffd83dbSDimitry Andric for (auto *WE : ExceptionPointers) { 820b57cec5SDimitry Andric WE->reverseBlock(); 830b57cec5SDimitry Andric std::reverse(WE->getSubExceptions().begin(), WE->getSubExceptions().end()); 840b57cec5SDimitry Andric } 850b57cec5SDimitry Andric } 860b57cec5SDimitry Andric 870b57cec5SDimitry Andric void WebAssemblyExceptionInfo::releaseMemory() { 880b57cec5SDimitry Andric BBMap.clear(); 890b57cec5SDimitry Andric TopLevelExceptions.clear(); 900b57cec5SDimitry Andric } 910b57cec5SDimitry Andric 920b57cec5SDimitry Andric void WebAssemblyExceptionInfo::getAnalysisUsage(AnalysisUsage &AU) const { 930b57cec5SDimitry Andric AU.setPreservesAll(); 940b57cec5SDimitry Andric AU.addRequired<MachineDominatorTree>(); 950b57cec5SDimitry Andric AU.addRequired<MachineDominanceFrontier>(); 960b57cec5SDimitry Andric MachineFunctionPass::getAnalysisUsage(AU); 970b57cec5SDimitry Andric } 980b57cec5SDimitry Andric 990b57cec5SDimitry Andric void WebAssemblyExceptionInfo::discoverAndMapException( 1000b57cec5SDimitry Andric WebAssemblyException *WE, const MachineDominatorTree &MDT, 1010b57cec5SDimitry Andric const MachineDominanceFrontier &MDF) { 1020b57cec5SDimitry Andric unsigned NumBlocks = 0; 1030b57cec5SDimitry Andric unsigned NumSubExceptions = 0; 1040b57cec5SDimitry Andric 1050b57cec5SDimitry Andric // Map blocks that belong to a catchpad / cleanuppad 1060b57cec5SDimitry Andric MachineBasicBlock *EHPad = WE->getEHPad(); 1070b57cec5SDimitry Andric SmallVector<MachineBasicBlock *, 8> WL; 1080b57cec5SDimitry Andric WL.push_back(EHPad); 1090b57cec5SDimitry Andric while (!WL.empty()) { 1100b57cec5SDimitry Andric MachineBasicBlock *MBB = WL.pop_back_val(); 1110b57cec5SDimitry Andric 1120b57cec5SDimitry Andric // Find its outermost discovered exception. If this is a discovered block, 1130b57cec5SDimitry Andric // check if it is already discovered to be a subexception of this exception. 1140b57cec5SDimitry Andric WebAssemblyException *SubE = getOutermostException(MBB); 1150b57cec5SDimitry Andric if (SubE) { 1160b57cec5SDimitry Andric if (SubE != WE) { 1170b57cec5SDimitry Andric // Discover a subexception of this exception. 1180b57cec5SDimitry Andric SubE->setParentException(WE); 1190b57cec5SDimitry Andric ++NumSubExceptions; 1200b57cec5SDimitry Andric NumBlocks += SubE->getBlocksVector().capacity(); 1210b57cec5SDimitry Andric // All blocks that belong to this subexception have been already 1220b57cec5SDimitry Andric // discovered. Skip all of them. Add the subexception's landing pad's 1230b57cec5SDimitry Andric // dominance frontier to the worklist. 1240b57cec5SDimitry Andric for (auto &Frontier : MDF.find(SubE->getEHPad())->second) 1250b57cec5SDimitry Andric if (MDT.dominates(EHPad, Frontier)) 1260b57cec5SDimitry Andric WL.push_back(Frontier); 1270b57cec5SDimitry Andric } 1280b57cec5SDimitry Andric continue; 1290b57cec5SDimitry Andric } 1300b57cec5SDimitry Andric 1310b57cec5SDimitry Andric // This is an undiscovered block. Map it to the current exception. 1320b57cec5SDimitry Andric changeExceptionFor(MBB, WE); 1330b57cec5SDimitry Andric ++NumBlocks; 1340b57cec5SDimitry Andric 1350b57cec5SDimitry Andric // Add successors dominated by the current BB to the worklist. 1360b57cec5SDimitry Andric for (auto *Succ : MBB->successors()) 1370b57cec5SDimitry Andric if (MDT.dominates(EHPad, Succ)) 1380b57cec5SDimitry Andric WL.push_back(Succ); 1390b57cec5SDimitry Andric } 1400b57cec5SDimitry Andric 1410b57cec5SDimitry Andric WE->getSubExceptions().reserve(NumSubExceptions); 1420b57cec5SDimitry Andric WE->reserveBlocks(NumBlocks); 1430b57cec5SDimitry Andric } 1440b57cec5SDimitry Andric 1450b57cec5SDimitry Andric WebAssemblyException * 1460b57cec5SDimitry Andric WebAssemblyExceptionInfo::getOutermostException(MachineBasicBlock *MBB) const { 1470b57cec5SDimitry Andric WebAssemblyException *WE = getExceptionFor(MBB); 1480b57cec5SDimitry Andric if (WE) { 1490b57cec5SDimitry Andric while (WebAssemblyException *Parent = WE->getParentException()) 1500b57cec5SDimitry Andric WE = Parent; 1510b57cec5SDimitry Andric } 1520b57cec5SDimitry Andric return WE; 1530b57cec5SDimitry Andric } 1540b57cec5SDimitry Andric 1550b57cec5SDimitry Andric void WebAssemblyException::print(raw_ostream &OS, unsigned Depth) const { 1560b57cec5SDimitry Andric OS.indent(Depth * 2) << "Exception at depth " << getExceptionDepth() 1570b57cec5SDimitry Andric << " containing: "; 1580b57cec5SDimitry Andric 1590b57cec5SDimitry Andric for (unsigned I = 0; I < getBlocks().size(); ++I) { 1600b57cec5SDimitry Andric MachineBasicBlock *MBB = getBlocks()[I]; 1610b57cec5SDimitry Andric if (I) 1620b57cec5SDimitry Andric OS << ", "; 1630b57cec5SDimitry Andric OS << "%bb." << MBB->getNumber(); 1640b57cec5SDimitry Andric if (const auto *BB = MBB->getBasicBlock()) 1650b57cec5SDimitry Andric if (BB->hasName()) 1660b57cec5SDimitry Andric OS << "." << BB->getName(); 1670b57cec5SDimitry Andric 1680b57cec5SDimitry Andric if (getEHPad() == MBB) 1690b57cec5SDimitry Andric OS << " (landing-pad)"; 1700b57cec5SDimitry Andric } 1710b57cec5SDimitry Andric OS << "\n"; 1720b57cec5SDimitry Andric 1730b57cec5SDimitry Andric for (auto &SubE : SubExceptions) 1740b57cec5SDimitry Andric SubE->print(OS, Depth + 2); 1750b57cec5SDimitry Andric } 1760b57cec5SDimitry Andric 1770b57cec5SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 1780b57cec5SDimitry Andric LLVM_DUMP_METHOD void WebAssemblyException::dump() const { print(dbgs()); } 1790b57cec5SDimitry Andric #endif 1800b57cec5SDimitry Andric 1810b57cec5SDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const WebAssemblyException &WE) { 1820b57cec5SDimitry Andric WE.print(OS); 1830b57cec5SDimitry Andric return OS; 1840b57cec5SDimitry Andric } 1850b57cec5SDimitry Andric 1860b57cec5SDimitry Andric void WebAssemblyExceptionInfo::print(raw_ostream &OS, const Module *) const { 187*5ffd83dbSDimitry Andric for (auto &WE : TopLevelExceptions) 1880b57cec5SDimitry Andric WE->print(OS); 1890b57cec5SDimitry Andric } 190