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" 18*0fca6ea1SDimitry Andric #include "llvm/IR/Function.h" 190b57cec5SDimitry Andric #include "llvm/MC/MCAsmInfo.h" 200b57cec5SDimitry Andric #include "llvm/MC/MCContext.h" 210b57cec5SDimitry Andric #include "llvm/MC/MCStreamer.h" 220b57cec5SDimitry Andric #include "llvm/Target/TargetLoweringObjectFile.h" 23480093f4SDimitry Andric #include "llvm/Target/TargetMachine.h" 240b57cec5SDimitry Andric #include "llvm/Target/TargetOptions.h" 250b57cec5SDimitry Andric using namespace llvm; 260b57cec5SDimitry Andric 27bdd1243dSDimitry Andric DwarfCFIException::DwarfCFIException(AsmPrinter *A) : EHStreamer(A) {} 280b57cec5SDimitry Andric 2981ad6265SDimitry Andric DwarfCFIException::~DwarfCFIException() = default; 300b57cec5SDimitry Andric 31bdd1243dSDimitry Andric void DwarfCFIException::addPersonality(const GlobalValue *Personality) { 32bdd1243dSDimitry Andric if (!llvm::is_contained(Personalities, Personality)) 33bdd1243dSDimitry Andric Personalities.push_back(Personality); 34bdd1243dSDimitry Andric } 35bdd1243dSDimitry Andric 360b57cec5SDimitry Andric /// endModule - Emit all exception information that should come after the 370b57cec5SDimitry Andric /// content. 380b57cec5SDimitry Andric void DwarfCFIException::endModule() { 390b57cec5SDimitry Andric // SjLj uses this pass and it doesn't need this info. 400b57cec5SDimitry Andric if (!Asm->MAI->usesCFIForEH()) 410b57cec5SDimitry Andric return; 420b57cec5SDimitry Andric 430b57cec5SDimitry Andric const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); 440b57cec5SDimitry Andric 450b57cec5SDimitry Andric unsigned PerEncoding = TLOF.getPersonalityEncoding(); 460b57cec5SDimitry Andric 470b57cec5SDimitry Andric if ((PerEncoding & 0x80) != dwarf::DW_EH_PE_indirect) 480b57cec5SDimitry Andric return; 490b57cec5SDimitry Andric 50bdd1243dSDimitry Andric // Emit indirect reference table for all used personality functions 51bdd1243dSDimitry Andric for (const GlobalValue *Personality : Personalities) { 520b57cec5SDimitry Andric MCSymbol *Sym = Asm->getSymbol(Personality); 530b57cec5SDimitry Andric TLOF.emitPersonalityValue(*Asm->OutStreamer, Asm->getDataLayout(), Sym); 540b57cec5SDimitry Andric } 55bdd1243dSDimitry Andric Personalities.clear(); 560b57cec5SDimitry Andric } 570b57cec5SDimitry Andric 580b57cec5SDimitry Andric void DwarfCFIException::beginFunction(const MachineFunction *MF) { 59fe6060f1SDimitry Andric shouldEmitPersonality = shouldEmitLSDA = false; 600b57cec5SDimitry Andric const Function &F = MF->getFunction(); 610b57cec5SDimitry Andric 620b57cec5SDimitry Andric // If any landing pads survive, we need an EH table. 630b57cec5SDimitry Andric bool hasLandingPads = !MF->getLandingPads().empty(); 640b57cec5SDimitry Andric 650b57cec5SDimitry Andric // See if we need frame move info. 66fe6060f1SDimitry Andric bool shouldEmitMoves = 67fe6060f1SDimitry Andric Asm->getFunctionCFISectionType(*MF) != AsmPrinter::CFISection::None; 680b57cec5SDimitry Andric 690b57cec5SDimitry Andric const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); 700b57cec5SDimitry Andric unsigned PerEncoding = TLOF.getPersonalityEncoding(); 71bdd1243dSDimitry Andric const GlobalValue *Per = nullptr; 720b57cec5SDimitry Andric if (F.hasPersonalityFn()) 73bdd1243dSDimitry Andric Per = dyn_cast<GlobalValue>(F.getPersonalityFn()->stripPointerCasts()); 740b57cec5SDimitry Andric 750b57cec5SDimitry Andric // Emit a personality function even when there are no landing pads 760b57cec5SDimitry Andric forceEmitPersonality = 770b57cec5SDimitry Andric // ...if a personality function is explicitly specified 780b57cec5SDimitry Andric F.hasPersonalityFn() && 790b57cec5SDimitry Andric // ... and it's not known to be a noop in the absence of invokes 800b57cec5SDimitry Andric !isNoOpWithoutInvoke(classifyEHPersonality(Per)) && 810b57cec5SDimitry Andric // ... and we're not explicitly asked not to emit it 820b57cec5SDimitry Andric F.needsUnwindTableEntry(); 830b57cec5SDimitry Andric 840b57cec5SDimitry Andric shouldEmitPersonality = 850b57cec5SDimitry Andric (forceEmitPersonality || 860b57cec5SDimitry Andric (hasLandingPads && PerEncoding != dwarf::DW_EH_PE_omit)) && 870b57cec5SDimitry Andric Per; 880b57cec5SDimitry Andric 890b57cec5SDimitry Andric unsigned LSDAEncoding = TLOF.getLSDAEncoding(); 900b57cec5SDimitry Andric shouldEmitLSDA = shouldEmitPersonality && 910b57cec5SDimitry Andric LSDAEncoding != dwarf::DW_EH_PE_omit; 920b57cec5SDimitry Andric 93*0fca6ea1SDimitry Andric const MCAsmInfo &MAI = *MF->getContext().getAsmInfo(); 94fe6060f1SDimitry Andric if (MAI.getExceptionHandlingType() != ExceptionHandling::None) 95fe6060f1SDimitry Andric shouldEmitCFI = 96fe6060f1SDimitry Andric MAI.usesCFIForEH() && (shouldEmitPersonality || shouldEmitMoves); 97fe6060f1SDimitry Andric else 9806c3fb27SDimitry Andric shouldEmitCFI = Asm->usesCFIWithoutEH() && shouldEmitMoves; 990b57cec5SDimitry Andric } 1000b57cec5SDimitry Andric 101bdd1243dSDimitry Andric void DwarfCFIException::beginBasicBlockSection(const MachineBasicBlock &MBB) { 1020b57cec5SDimitry Andric if (!shouldEmitCFI) 1030b57cec5SDimitry Andric return; 1040b57cec5SDimitry Andric 1050b57cec5SDimitry Andric if (!hasEmittedCFISections) { 106fe6060f1SDimitry Andric AsmPrinter::CFISection CFISecType = Asm->getModuleCFISectionType(); 107fe6060f1SDimitry Andric // If we don't say anything it implies `.cfi_sections .eh_frame`, so we 108fe6060f1SDimitry Andric // chose not to be verbose in that case. And with `ForceDwarfFrameSection`, 109fe6060f1SDimitry Andric // we should always emit .debug_frame. 110fe6060f1SDimitry Andric if (CFISecType == AsmPrinter::CFISection::Debug || 111fe6060f1SDimitry Andric Asm->TM.Options.ForceDwarfFrameSection) 112fe6060f1SDimitry Andric Asm->OutStreamer->emitCFISections( 113fe6060f1SDimitry Andric CFISecType == AsmPrinter::CFISection::EH, true); 1140b57cec5SDimitry Andric hasEmittedCFISections = true; 1150b57cec5SDimitry Andric } 1160b57cec5SDimitry Andric 1175ffd83dbSDimitry Andric Asm->OutStreamer->emitCFIStartProc(/*IsSimple=*/false); 1180b57cec5SDimitry Andric 1190b57cec5SDimitry Andric // Indicate personality routine, if any. 1200b57cec5SDimitry Andric if (!shouldEmitPersonality) 1210b57cec5SDimitry Andric return; 1220b57cec5SDimitry Andric 123bdd1243dSDimitry Andric auto &F = MBB.getParent()->getFunction(); 124bdd1243dSDimitry Andric auto *P = dyn_cast<GlobalValue>(F.getPersonalityFn()->stripPointerCasts()); 1250b57cec5SDimitry Andric assert(P && "Expected personality function"); 126bdd1243dSDimitry Andric // Record the personality function. 127bdd1243dSDimitry Andric addPersonality(P); 1280b57cec5SDimitry Andric 1290b57cec5SDimitry Andric const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); 1300b57cec5SDimitry Andric unsigned PerEncoding = TLOF.getPersonalityEncoding(); 1310b57cec5SDimitry Andric const MCSymbol *Sym = TLOF.getCFIPersonalitySymbol(P, Asm->TM, MMI); 1325ffd83dbSDimitry Andric Asm->OutStreamer->emitCFIPersonality(Sym, PerEncoding); 1330b57cec5SDimitry Andric 1340b57cec5SDimitry Andric // Provide LSDA information. 1350b57cec5SDimitry Andric if (shouldEmitLSDA) 136bdd1243dSDimitry Andric Asm->OutStreamer->emitCFILsda(Asm->getMBBExceptionSym(MBB), 137bdd1243dSDimitry Andric TLOF.getLSDAEncoding()); 138bdd1243dSDimitry Andric } 139bdd1243dSDimitry Andric 140bdd1243dSDimitry Andric void DwarfCFIException::endBasicBlockSection(const MachineBasicBlock &MBB) { 141bdd1243dSDimitry Andric if (shouldEmitCFI) 142bdd1243dSDimitry Andric Asm->OutStreamer->emitCFIEndProc(); 1430b57cec5SDimitry Andric } 1440b57cec5SDimitry Andric 1450b57cec5SDimitry Andric /// endFunction - Gather and emit post-function exception information. 1460b57cec5SDimitry Andric /// 1470b57cec5SDimitry Andric void DwarfCFIException::endFunction(const MachineFunction *MF) { 1480b57cec5SDimitry Andric if (!shouldEmitPersonality) 1490b57cec5SDimitry Andric return; 1500b57cec5SDimitry Andric 1510b57cec5SDimitry Andric emitExceptionTable(); 1520b57cec5SDimitry Andric } 153