10b57cec5SDimitry Andric //===-- CodeGen/AsmPrinter/DwarfException.cpp - Dwarf Exception Impl ------===// 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 // This file contains support for writing DWARF exception info into asm files. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #include "DwarfException.h" 140b57cec5SDimitry Andric #include "llvm/BinaryFormat/Dwarf.h" 150b57cec5SDimitry Andric #include "llvm/CodeGen/AsmPrinter.h" 160b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h" 170b57cec5SDimitry Andric #include "llvm/CodeGen/MachineModuleInfo.h" 180b57cec5SDimitry Andric #include "llvm/MC/MCAsmInfo.h" 190b57cec5SDimitry Andric #include "llvm/MC/MCContext.h" 200b57cec5SDimitry Andric #include "llvm/MC/MCStreamer.h" 210b57cec5SDimitry Andric #include "llvm/Target/TargetLoweringObjectFile.h" 22480093f4SDimitry Andric #include "llvm/Target/TargetMachine.h" 230b57cec5SDimitry Andric #include "llvm/Target/TargetOptions.h" 240b57cec5SDimitry Andric using namespace llvm; 250b57cec5SDimitry Andric 261fd87a68SDimitry Andric DwarfCFIExceptionBase::DwarfCFIExceptionBase(AsmPrinter *A) : EHStreamer(A) {} 270b57cec5SDimitry Andric 280b57cec5SDimitry Andric void DwarfCFIExceptionBase::markFunctionEnd() { 290b57cec5SDimitry Andric endFragment(); 300b57cec5SDimitry Andric 310b57cec5SDimitry Andric // Map all labels and get rid of any dead landing pads. 320b57cec5SDimitry Andric if (!Asm->MF->getLandingPads().empty()) { 330b57cec5SDimitry Andric MachineFunction *NonConstMF = const_cast<MachineFunction*>(Asm->MF); 340b57cec5SDimitry Andric NonConstMF->tidyLandingPads(); 350b57cec5SDimitry Andric } 360b57cec5SDimitry Andric } 370b57cec5SDimitry Andric 380b57cec5SDimitry Andric void DwarfCFIExceptionBase::endFragment() { 395ffd83dbSDimitry Andric if (shouldEmitCFI && !Asm->MF->hasBBSections()) 405ffd83dbSDimitry Andric Asm->OutStreamer->emitCFIEndProc(); 410b57cec5SDimitry Andric } 420b57cec5SDimitry Andric 430b57cec5SDimitry Andric DwarfCFIException::DwarfCFIException(AsmPrinter *A) 441fd87a68SDimitry Andric : DwarfCFIExceptionBase(A) {} 450b57cec5SDimitry Andric 46*81ad6265SDimitry Andric DwarfCFIException::~DwarfCFIException() = default; 470b57cec5SDimitry Andric 480b57cec5SDimitry Andric /// endModule - Emit all exception information that should come after the 490b57cec5SDimitry Andric /// content. 500b57cec5SDimitry Andric void DwarfCFIException::endModule() { 510b57cec5SDimitry Andric // SjLj uses this pass and it doesn't need this info. 520b57cec5SDimitry Andric if (!Asm->MAI->usesCFIForEH()) 530b57cec5SDimitry Andric return; 540b57cec5SDimitry Andric 550b57cec5SDimitry Andric const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); 560b57cec5SDimitry Andric 570b57cec5SDimitry Andric unsigned PerEncoding = TLOF.getPersonalityEncoding(); 580b57cec5SDimitry Andric 590b57cec5SDimitry Andric if ((PerEncoding & 0x80) != dwarf::DW_EH_PE_indirect) 600b57cec5SDimitry Andric return; 610b57cec5SDimitry Andric 620b57cec5SDimitry Andric // Emit references to all used personality functions 630b57cec5SDimitry Andric for (const Function *Personality : MMI->getPersonalities()) { 640b57cec5SDimitry Andric if (!Personality) 650b57cec5SDimitry Andric continue; 660b57cec5SDimitry Andric MCSymbol *Sym = Asm->getSymbol(Personality); 670b57cec5SDimitry Andric TLOF.emitPersonalityValue(*Asm->OutStreamer, Asm->getDataLayout(), Sym); 680b57cec5SDimitry Andric } 690b57cec5SDimitry Andric } 700b57cec5SDimitry Andric 71e8d8bef9SDimitry Andric static MCSymbol *getExceptionSym(AsmPrinter *Asm, 72e8d8bef9SDimitry Andric const MachineBasicBlock *MBB) { 73e8d8bef9SDimitry Andric return Asm->getMBBExceptionSym(*MBB); 740b57cec5SDimitry Andric } 750b57cec5SDimitry Andric 760b57cec5SDimitry Andric void DwarfCFIException::beginFunction(const MachineFunction *MF) { 77fe6060f1SDimitry Andric shouldEmitPersonality = shouldEmitLSDA = false; 780b57cec5SDimitry Andric const Function &F = MF->getFunction(); 790b57cec5SDimitry Andric 800b57cec5SDimitry Andric // If any landing pads survive, we need an EH table. 810b57cec5SDimitry Andric bool hasLandingPads = !MF->getLandingPads().empty(); 820b57cec5SDimitry Andric 830b57cec5SDimitry Andric // See if we need frame move info. 84fe6060f1SDimitry Andric bool shouldEmitMoves = 85fe6060f1SDimitry Andric Asm->getFunctionCFISectionType(*MF) != AsmPrinter::CFISection::None; 860b57cec5SDimitry Andric 870b57cec5SDimitry Andric const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); 880b57cec5SDimitry Andric unsigned PerEncoding = TLOF.getPersonalityEncoding(); 890b57cec5SDimitry Andric const Function *Per = nullptr; 900b57cec5SDimitry Andric if (F.hasPersonalityFn()) 910b57cec5SDimitry Andric Per = dyn_cast<Function>(F.getPersonalityFn()->stripPointerCasts()); 920b57cec5SDimitry Andric 930b57cec5SDimitry Andric // Emit a personality function even when there are no landing pads 940b57cec5SDimitry Andric forceEmitPersonality = 950b57cec5SDimitry Andric // ...if a personality function is explicitly specified 960b57cec5SDimitry Andric F.hasPersonalityFn() && 970b57cec5SDimitry Andric // ... and it's not known to be a noop in the absence of invokes 980b57cec5SDimitry Andric !isNoOpWithoutInvoke(classifyEHPersonality(Per)) && 990b57cec5SDimitry Andric // ... and we're not explicitly asked not to emit it 1000b57cec5SDimitry Andric F.needsUnwindTableEntry(); 1010b57cec5SDimitry Andric 1020b57cec5SDimitry Andric shouldEmitPersonality = 1030b57cec5SDimitry Andric (forceEmitPersonality || 1040b57cec5SDimitry Andric (hasLandingPads && PerEncoding != dwarf::DW_EH_PE_omit)) && 1050b57cec5SDimitry Andric Per; 1060b57cec5SDimitry Andric 1070b57cec5SDimitry Andric unsigned LSDAEncoding = TLOF.getLSDAEncoding(); 1080b57cec5SDimitry Andric shouldEmitLSDA = shouldEmitPersonality && 1090b57cec5SDimitry Andric LSDAEncoding != dwarf::DW_EH_PE_omit; 1100b57cec5SDimitry Andric 111fe6060f1SDimitry Andric const MCAsmInfo &MAI = *MF->getMMI().getContext().getAsmInfo(); 112fe6060f1SDimitry Andric if (MAI.getExceptionHandlingType() != ExceptionHandling::None) 113fe6060f1SDimitry Andric shouldEmitCFI = 114fe6060f1SDimitry Andric MAI.usesCFIForEH() && (shouldEmitPersonality || shouldEmitMoves); 115fe6060f1SDimitry Andric else 116fe6060f1SDimitry Andric shouldEmitCFI = Asm->needsCFIForDebug() && shouldEmitMoves; 117fe6060f1SDimitry Andric 1180b57cec5SDimitry Andric beginFragment(&*MF->begin(), getExceptionSym); 1190b57cec5SDimitry Andric } 1200b57cec5SDimitry Andric 1210b57cec5SDimitry Andric void DwarfCFIException::beginFragment(const MachineBasicBlock *MBB, 1220b57cec5SDimitry Andric ExceptionSymbolProvider ESP) { 1230b57cec5SDimitry Andric if (!shouldEmitCFI) 1240b57cec5SDimitry Andric return; 1250b57cec5SDimitry Andric 1260b57cec5SDimitry Andric if (!hasEmittedCFISections) { 127fe6060f1SDimitry Andric AsmPrinter::CFISection CFISecType = Asm->getModuleCFISectionType(); 128fe6060f1SDimitry Andric // If we don't say anything it implies `.cfi_sections .eh_frame`, so we 129fe6060f1SDimitry Andric // chose not to be verbose in that case. And with `ForceDwarfFrameSection`, 130fe6060f1SDimitry Andric // we should always emit .debug_frame. 131fe6060f1SDimitry Andric if (CFISecType == AsmPrinter::CFISection::Debug || 132fe6060f1SDimitry Andric Asm->TM.Options.ForceDwarfFrameSection) 133fe6060f1SDimitry Andric Asm->OutStreamer->emitCFISections( 134fe6060f1SDimitry Andric CFISecType == AsmPrinter::CFISection::EH, true); 1350b57cec5SDimitry Andric hasEmittedCFISections = true; 1360b57cec5SDimitry Andric } 1370b57cec5SDimitry Andric 1385ffd83dbSDimitry Andric Asm->OutStreamer->emitCFIStartProc(/*IsSimple=*/false); 1390b57cec5SDimitry Andric 1400b57cec5SDimitry Andric // Indicate personality routine, if any. 1410b57cec5SDimitry Andric if (!shouldEmitPersonality) 1420b57cec5SDimitry Andric return; 1430b57cec5SDimitry Andric 1440b57cec5SDimitry Andric auto &F = MBB->getParent()->getFunction(); 1450b57cec5SDimitry Andric auto *P = dyn_cast<Function>(F.getPersonalityFn()->stripPointerCasts()); 1460b57cec5SDimitry Andric assert(P && "Expected personality function"); 1470b57cec5SDimitry Andric 1480b57cec5SDimitry Andric // If we are forced to emit this personality, make sure to record 1490b57cec5SDimitry Andric // it because it might not appear in any landingpad 1500b57cec5SDimitry Andric if (forceEmitPersonality) 1510b57cec5SDimitry Andric MMI->addPersonality(P); 1520b57cec5SDimitry Andric 1530b57cec5SDimitry Andric const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); 1540b57cec5SDimitry Andric unsigned PerEncoding = TLOF.getPersonalityEncoding(); 1550b57cec5SDimitry Andric const MCSymbol *Sym = TLOF.getCFIPersonalitySymbol(P, Asm->TM, MMI); 1565ffd83dbSDimitry Andric Asm->OutStreamer->emitCFIPersonality(Sym, PerEncoding); 1570b57cec5SDimitry Andric 1580b57cec5SDimitry Andric // Provide LSDA information. 1590b57cec5SDimitry Andric if (shouldEmitLSDA) 160e8d8bef9SDimitry Andric Asm->OutStreamer->emitCFILsda(ESP(Asm, MBB), TLOF.getLSDAEncoding()); 1610b57cec5SDimitry Andric } 1620b57cec5SDimitry Andric 1630b57cec5SDimitry Andric /// endFunction - Gather and emit post-function exception information. 1640b57cec5SDimitry Andric /// 1650b57cec5SDimitry Andric void DwarfCFIException::endFunction(const MachineFunction *MF) { 1660b57cec5SDimitry Andric if (!shouldEmitPersonality) 1670b57cec5SDimitry Andric return; 1680b57cec5SDimitry Andric 1690b57cec5SDimitry Andric emitExceptionTable(); 1700b57cec5SDimitry Andric } 1715ffd83dbSDimitry Andric 1725ffd83dbSDimitry Andric void DwarfCFIException::beginBasicBlock(const MachineBasicBlock &MBB) { 1735ffd83dbSDimitry Andric beginFragment(&MBB, getExceptionSym); 1745ffd83dbSDimitry Andric } 1755ffd83dbSDimitry Andric 1765ffd83dbSDimitry Andric void DwarfCFIException::endBasicBlock(const MachineBasicBlock &MBB) { 1775ffd83dbSDimitry Andric if (shouldEmitCFI) 1785ffd83dbSDimitry Andric Asm->OutStreamer->emitCFIEndProc(); 1795ffd83dbSDimitry Andric } 180