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 26bdd1243dSDimitry Andric DwarfCFIException::DwarfCFIException(AsmPrinter *A) : EHStreamer(A) {} 270b57cec5SDimitry Andric 2881ad6265SDimitry Andric DwarfCFIException::~DwarfCFIException() = default; 290b57cec5SDimitry Andric 30bdd1243dSDimitry Andric void DwarfCFIException::addPersonality(const GlobalValue *Personality) { 31bdd1243dSDimitry Andric if (!llvm::is_contained(Personalities, Personality)) 32bdd1243dSDimitry Andric Personalities.push_back(Personality); 33bdd1243dSDimitry Andric } 34bdd1243dSDimitry Andric 350b57cec5SDimitry Andric /// endModule - Emit all exception information that should come after the 360b57cec5SDimitry Andric /// content. 370b57cec5SDimitry Andric void DwarfCFIException::endModule() { 380b57cec5SDimitry Andric // SjLj uses this pass and it doesn't need this info. 390b57cec5SDimitry Andric if (!Asm->MAI->usesCFIForEH()) 400b57cec5SDimitry Andric return; 410b57cec5SDimitry Andric 420b57cec5SDimitry Andric const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); 430b57cec5SDimitry Andric 440b57cec5SDimitry Andric unsigned PerEncoding = TLOF.getPersonalityEncoding(); 450b57cec5SDimitry Andric 460b57cec5SDimitry Andric if ((PerEncoding & 0x80) != dwarf::DW_EH_PE_indirect) 470b57cec5SDimitry Andric return; 480b57cec5SDimitry Andric 49bdd1243dSDimitry Andric // Emit indirect reference table for all used personality functions 50bdd1243dSDimitry Andric for (const GlobalValue *Personality : Personalities) { 510b57cec5SDimitry Andric MCSymbol *Sym = Asm->getSymbol(Personality); 520b57cec5SDimitry Andric TLOF.emitPersonalityValue(*Asm->OutStreamer, Asm->getDataLayout(), Sym); 530b57cec5SDimitry Andric } 54bdd1243dSDimitry Andric Personalities.clear(); 550b57cec5SDimitry Andric } 560b57cec5SDimitry Andric 570b57cec5SDimitry Andric void DwarfCFIException::beginFunction(const MachineFunction *MF) { 58fe6060f1SDimitry Andric shouldEmitPersonality = shouldEmitLSDA = false; 590b57cec5SDimitry Andric const Function &F = MF->getFunction(); 600b57cec5SDimitry Andric 610b57cec5SDimitry Andric // If any landing pads survive, we need an EH table. 620b57cec5SDimitry Andric bool hasLandingPads = !MF->getLandingPads().empty(); 630b57cec5SDimitry Andric 640b57cec5SDimitry Andric // See if we need frame move info. 65fe6060f1SDimitry Andric bool shouldEmitMoves = 66fe6060f1SDimitry Andric Asm->getFunctionCFISectionType(*MF) != AsmPrinter::CFISection::None; 670b57cec5SDimitry Andric 680b57cec5SDimitry Andric const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); 690b57cec5SDimitry Andric unsigned PerEncoding = TLOF.getPersonalityEncoding(); 70bdd1243dSDimitry Andric const GlobalValue *Per = nullptr; 710b57cec5SDimitry Andric if (F.hasPersonalityFn()) 72bdd1243dSDimitry Andric Per = dyn_cast<GlobalValue>(F.getPersonalityFn()->stripPointerCasts()); 730b57cec5SDimitry Andric 740b57cec5SDimitry Andric // Emit a personality function even when there are no landing pads 750b57cec5SDimitry Andric forceEmitPersonality = 760b57cec5SDimitry Andric // ...if a personality function is explicitly specified 770b57cec5SDimitry Andric F.hasPersonalityFn() && 780b57cec5SDimitry Andric // ... and it's not known to be a noop in the absence of invokes 790b57cec5SDimitry Andric !isNoOpWithoutInvoke(classifyEHPersonality(Per)) && 800b57cec5SDimitry Andric // ... and we're not explicitly asked not to emit it 810b57cec5SDimitry Andric F.needsUnwindTableEntry(); 820b57cec5SDimitry Andric 830b57cec5SDimitry Andric shouldEmitPersonality = 840b57cec5SDimitry Andric (forceEmitPersonality || 850b57cec5SDimitry Andric (hasLandingPads && PerEncoding != dwarf::DW_EH_PE_omit)) && 860b57cec5SDimitry Andric Per; 870b57cec5SDimitry Andric 880b57cec5SDimitry Andric unsigned LSDAEncoding = TLOF.getLSDAEncoding(); 890b57cec5SDimitry Andric shouldEmitLSDA = shouldEmitPersonality && 900b57cec5SDimitry Andric LSDAEncoding != dwarf::DW_EH_PE_omit; 910b57cec5SDimitry Andric 92fe6060f1SDimitry Andric const MCAsmInfo &MAI = *MF->getMMI().getContext().getAsmInfo(); 93fe6060f1SDimitry Andric if (MAI.getExceptionHandlingType() != ExceptionHandling::None) 94fe6060f1SDimitry Andric shouldEmitCFI = 95fe6060f1SDimitry Andric MAI.usesCFIForEH() && (shouldEmitPersonality || shouldEmitMoves); 96fe6060f1SDimitry Andric else 97*06c3fb27SDimitry Andric shouldEmitCFI = Asm->usesCFIWithoutEH() && shouldEmitMoves; 980b57cec5SDimitry Andric } 990b57cec5SDimitry Andric 100bdd1243dSDimitry Andric void DwarfCFIException::beginBasicBlockSection(const MachineBasicBlock &MBB) { 1010b57cec5SDimitry Andric if (!shouldEmitCFI) 1020b57cec5SDimitry Andric return; 1030b57cec5SDimitry Andric 1040b57cec5SDimitry Andric if (!hasEmittedCFISections) { 105fe6060f1SDimitry Andric AsmPrinter::CFISection CFISecType = Asm->getModuleCFISectionType(); 106fe6060f1SDimitry Andric // If we don't say anything it implies `.cfi_sections .eh_frame`, so we 107fe6060f1SDimitry Andric // chose not to be verbose in that case. And with `ForceDwarfFrameSection`, 108fe6060f1SDimitry Andric // we should always emit .debug_frame. 109fe6060f1SDimitry Andric if (CFISecType == AsmPrinter::CFISection::Debug || 110fe6060f1SDimitry Andric Asm->TM.Options.ForceDwarfFrameSection) 111fe6060f1SDimitry Andric Asm->OutStreamer->emitCFISections( 112fe6060f1SDimitry Andric CFISecType == AsmPrinter::CFISection::EH, true); 1130b57cec5SDimitry Andric hasEmittedCFISections = true; 1140b57cec5SDimitry Andric } 1150b57cec5SDimitry Andric 1165ffd83dbSDimitry Andric Asm->OutStreamer->emitCFIStartProc(/*IsSimple=*/false); 1170b57cec5SDimitry Andric 1180b57cec5SDimitry Andric // Indicate personality routine, if any. 1190b57cec5SDimitry Andric if (!shouldEmitPersonality) 1200b57cec5SDimitry Andric return; 1210b57cec5SDimitry Andric 122bdd1243dSDimitry Andric auto &F = MBB.getParent()->getFunction(); 123bdd1243dSDimitry Andric auto *P = dyn_cast<GlobalValue>(F.getPersonalityFn()->stripPointerCasts()); 1240b57cec5SDimitry Andric assert(P && "Expected personality function"); 125bdd1243dSDimitry Andric // Record the personality function. 126bdd1243dSDimitry Andric addPersonality(P); 1270b57cec5SDimitry Andric 1280b57cec5SDimitry Andric const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); 1290b57cec5SDimitry Andric unsigned PerEncoding = TLOF.getPersonalityEncoding(); 1300b57cec5SDimitry Andric const MCSymbol *Sym = TLOF.getCFIPersonalitySymbol(P, Asm->TM, MMI); 1315ffd83dbSDimitry Andric Asm->OutStreamer->emitCFIPersonality(Sym, PerEncoding); 1320b57cec5SDimitry Andric 1330b57cec5SDimitry Andric // Provide LSDA information. 1340b57cec5SDimitry Andric if (shouldEmitLSDA) 135bdd1243dSDimitry Andric Asm->OutStreamer->emitCFILsda(Asm->getMBBExceptionSym(MBB), 136bdd1243dSDimitry Andric TLOF.getLSDAEncoding()); 137bdd1243dSDimitry Andric } 138bdd1243dSDimitry Andric 139bdd1243dSDimitry Andric void DwarfCFIException::endBasicBlockSection(const MachineBasicBlock &MBB) { 140bdd1243dSDimitry Andric if (shouldEmitCFI) 141bdd1243dSDimitry Andric Asm->OutStreamer->emitCFIEndProc(); 1420b57cec5SDimitry Andric } 1430b57cec5SDimitry Andric 1440b57cec5SDimitry Andric /// endFunction - Gather and emit post-function exception information. 1450b57cec5SDimitry Andric /// 1460b57cec5SDimitry Andric void DwarfCFIException::endFunction(const MachineFunction *MF) { 1470b57cec5SDimitry Andric if (!shouldEmitPersonality) 1480b57cec5SDimitry Andric return; 1490b57cec5SDimitry Andric 1500b57cec5SDimitry Andric emitExceptionTable(); 1510b57cec5SDimitry Andric } 152