1*0b57cec5SDimitry Andric //===-- CodeGen/AsmPrinter/DwarfException.cpp - Dwarf Exception Impl ------===// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric // 9*0b57cec5SDimitry Andric // This file contains support for writing DWARF exception info into asm files. 10*0b57cec5SDimitry Andric // 11*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 12*0b57cec5SDimitry Andric 13*0b57cec5SDimitry Andric #include "DwarfException.h" 14*0b57cec5SDimitry Andric #include "llvm/ADT/Twine.h" 15*0b57cec5SDimitry Andric #include "llvm/BinaryFormat/Dwarf.h" 16*0b57cec5SDimitry Andric #include "llvm/CodeGen/AsmPrinter.h" 17*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h" 18*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineModuleInfo.h" 19*0b57cec5SDimitry Andric #include "llvm/IR/DataLayout.h" 20*0b57cec5SDimitry Andric #include "llvm/IR/Mangler.h" 21*0b57cec5SDimitry Andric #include "llvm/IR/Module.h" 22*0b57cec5SDimitry Andric #include "llvm/MC/MCAsmInfo.h" 23*0b57cec5SDimitry Andric #include "llvm/MC/MCContext.h" 24*0b57cec5SDimitry Andric #include "llvm/MC/MCExpr.h" 25*0b57cec5SDimitry Andric #include "llvm/MC/MCSection.h" 26*0b57cec5SDimitry Andric #include "llvm/MC/MCStreamer.h" 27*0b57cec5SDimitry Andric #include "llvm/MC/MCSymbol.h" 28*0b57cec5SDimitry Andric #include "llvm/MC/MachineLocation.h" 29*0b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 30*0b57cec5SDimitry Andric #include "llvm/Support/FormattedStream.h" 31*0b57cec5SDimitry Andric #include "llvm/Target/TargetLoweringObjectFile.h" 32*0b57cec5SDimitry Andric #include "llvm/Target/TargetOptions.h" 33*0b57cec5SDimitry Andric using namespace llvm; 34*0b57cec5SDimitry Andric 35*0b57cec5SDimitry Andric DwarfCFIExceptionBase::DwarfCFIExceptionBase(AsmPrinter *A) 36*0b57cec5SDimitry Andric : EHStreamer(A), shouldEmitCFI(false), hasEmittedCFISections(false) {} 37*0b57cec5SDimitry Andric 38*0b57cec5SDimitry Andric void DwarfCFIExceptionBase::markFunctionEnd() { 39*0b57cec5SDimitry Andric endFragment(); 40*0b57cec5SDimitry Andric 41*0b57cec5SDimitry Andric // Map all labels and get rid of any dead landing pads. 42*0b57cec5SDimitry Andric if (!Asm->MF->getLandingPads().empty()) { 43*0b57cec5SDimitry Andric MachineFunction *NonConstMF = const_cast<MachineFunction*>(Asm->MF); 44*0b57cec5SDimitry Andric NonConstMF->tidyLandingPads(); 45*0b57cec5SDimitry Andric } 46*0b57cec5SDimitry Andric } 47*0b57cec5SDimitry Andric 48*0b57cec5SDimitry Andric void DwarfCFIExceptionBase::endFragment() { 49*0b57cec5SDimitry Andric if (shouldEmitCFI) 50*0b57cec5SDimitry Andric Asm->OutStreamer->EmitCFIEndProc(); 51*0b57cec5SDimitry Andric } 52*0b57cec5SDimitry Andric 53*0b57cec5SDimitry Andric DwarfCFIException::DwarfCFIException(AsmPrinter *A) 54*0b57cec5SDimitry Andric : DwarfCFIExceptionBase(A), shouldEmitPersonality(false), 55*0b57cec5SDimitry Andric forceEmitPersonality(false), shouldEmitLSDA(false), 56*0b57cec5SDimitry Andric shouldEmitMoves(false) {} 57*0b57cec5SDimitry Andric 58*0b57cec5SDimitry Andric DwarfCFIException::~DwarfCFIException() {} 59*0b57cec5SDimitry Andric 60*0b57cec5SDimitry Andric /// endModule - Emit all exception information that should come after the 61*0b57cec5SDimitry Andric /// content. 62*0b57cec5SDimitry Andric void DwarfCFIException::endModule() { 63*0b57cec5SDimitry Andric // SjLj uses this pass and it doesn't need this info. 64*0b57cec5SDimitry Andric if (!Asm->MAI->usesCFIForEH()) 65*0b57cec5SDimitry Andric return; 66*0b57cec5SDimitry Andric 67*0b57cec5SDimitry Andric const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); 68*0b57cec5SDimitry Andric 69*0b57cec5SDimitry Andric unsigned PerEncoding = TLOF.getPersonalityEncoding(); 70*0b57cec5SDimitry Andric 71*0b57cec5SDimitry Andric if ((PerEncoding & 0x80) != dwarf::DW_EH_PE_indirect) 72*0b57cec5SDimitry Andric return; 73*0b57cec5SDimitry Andric 74*0b57cec5SDimitry Andric // Emit references to all used personality functions 75*0b57cec5SDimitry Andric for (const Function *Personality : MMI->getPersonalities()) { 76*0b57cec5SDimitry Andric if (!Personality) 77*0b57cec5SDimitry Andric continue; 78*0b57cec5SDimitry Andric MCSymbol *Sym = Asm->getSymbol(Personality); 79*0b57cec5SDimitry Andric TLOF.emitPersonalityValue(*Asm->OutStreamer, Asm->getDataLayout(), Sym); 80*0b57cec5SDimitry Andric } 81*0b57cec5SDimitry Andric } 82*0b57cec5SDimitry Andric 83*0b57cec5SDimitry Andric static MCSymbol *getExceptionSym(AsmPrinter *Asm) { 84*0b57cec5SDimitry Andric return Asm->getCurExceptionSym(); 85*0b57cec5SDimitry Andric } 86*0b57cec5SDimitry Andric 87*0b57cec5SDimitry Andric void DwarfCFIException::beginFunction(const MachineFunction *MF) { 88*0b57cec5SDimitry Andric shouldEmitMoves = shouldEmitPersonality = shouldEmitLSDA = false; 89*0b57cec5SDimitry Andric const Function &F = MF->getFunction(); 90*0b57cec5SDimitry Andric 91*0b57cec5SDimitry Andric // If any landing pads survive, we need an EH table. 92*0b57cec5SDimitry Andric bool hasLandingPads = !MF->getLandingPads().empty(); 93*0b57cec5SDimitry Andric 94*0b57cec5SDimitry Andric // See if we need frame move info. 95*0b57cec5SDimitry Andric AsmPrinter::CFIMoveType MoveType = Asm->needsCFIMoves(); 96*0b57cec5SDimitry Andric 97*0b57cec5SDimitry Andric shouldEmitMoves = MoveType != AsmPrinter::CFI_M_None; 98*0b57cec5SDimitry Andric 99*0b57cec5SDimitry Andric const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); 100*0b57cec5SDimitry Andric unsigned PerEncoding = TLOF.getPersonalityEncoding(); 101*0b57cec5SDimitry Andric const Function *Per = nullptr; 102*0b57cec5SDimitry Andric if (F.hasPersonalityFn()) 103*0b57cec5SDimitry Andric Per = dyn_cast<Function>(F.getPersonalityFn()->stripPointerCasts()); 104*0b57cec5SDimitry Andric 105*0b57cec5SDimitry Andric // Emit a personality function even when there are no landing pads 106*0b57cec5SDimitry Andric forceEmitPersonality = 107*0b57cec5SDimitry Andric // ...if a personality function is explicitly specified 108*0b57cec5SDimitry Andric F.hasPersonalityFn() && 109*0b57cec5SDimitry Andric // ... and it's not known to be a noop in the absence of invokes 110*0b57cec5SDimitry Andric !isNoOpWithoutInvoke(classifyEHPersonality(Per)) && 111*0b57cec5SDimitry Andric // ... and we're not explicitly asked not to emit it 112*0b57cec5SDimitry Andric F.needsUnwindTableEntry(); 113*0b57cec5SDimitry Andric 114*0b57cec5SDimitry Andric shouldEmitPersonality = 115*0b57cec5SDimitry Andric (forceEmitPersonality || 116*0b57cec5SDimitry Andric (hasLandingPads && PerEncoding != dwarf::DW_EH_PE_omit)) && 117*0b57cec5SDimitry Andric Per; 118*0b57cec5SDimitry Andric 119*0b57cec5SDimitry Andric unsigned LSDAEncoding = TLOF.getLSDAEncoding(); 120*0b57cec5SDimitry Andric shouldEmitLSDA = shouldEmitPersonality && 121*0b57cec5SDimitry Andric LSDAEncoding != dwarf::DW_EH_PE_omit; 122*0b57cec5SDimitry Andric 123*0b57cec5SDimitry Andric shouldEmitCFI = MF->getMMI().getContext().getAsmInfo()->usesCFIForEH() && 124*0b57cec5SDimitry Andric (shouldEmitPersonality || shouldEmitMoves); 125*0b57cec5SDimitry Andric beginFragment(&*MF->begin(), getExceptionSym); 126*0b57cec5SDimitry Andric } 127*0b57cec5SDimitry Andric 128*0b57cec5SDimitry Andric void DwarfCFIException::beginFragment(const MachineBasicBlock *MBB, 129*0b57cec5SDimitry Andric ExceptionSymbolProvider ESP) { 130*0b57cec5SDimitry Andric if (!shouldEmitCFI) 131*0b57cec5SDimitry Andric return; 132*0b57cec5SDimitry Andric 133*0b57cec5SDimitry Andric if (!hasEmittedCFISections) { 134*0b57cec5SDimitry Andric if (Asm->needsOnlyDebugCFIMoves()) 135*0b57cec5SDimitry Andric Asm->OutStreamer->EmitCFISections(false, true); 136*0b57cec5SDimitry Andric hasEmittedCFISections = true; 137*0b57cec5SDimitry Andric } 138*0b57cec5SDimitry Andric 139*0b57cec5SDimitry Andric Asm->OutStreamer->EmitCFIStartProc(/*IsSimple=*/false); 140*0b57cec5SDimitry Andric 141*0b57cec5SDimitry Andric // Indicate personality routine, if any. 142*0b57cec5SDimitry Andric if (!shouldEmitPersonality) 143*0b57cec5SDimitry Andric return; 144*0b57cec5SDimitry Andric 145*0b57cec5SDimitry Andric auto &F = MBB->getParent()->getFunction(); 146*0b57cec5SDimitry Andric auto *P = dyn_cast<Function>(F.getPersonalityFn()->stripPointerCasts()); 147*0b57cec5SDimitry Andric assert(P && "Expected personality function"); 148*0b57cec5SDimitry Andric 149*0b57cec5SDimitry Andric // If we are forced to emit this personality, make sure to record 150*0b57cec5SDimitry Andric // it because it might not appear in any landingpad 151*0b57cec5SDimitry Andric if (forceEmitPersonality) 152*0b57cec5SDimitry Andric MMI->addPersonality(P); 153*0b57cec5SDimitry Andric 154*0b57cec5SDimitry Andric const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); 155*0b57cec5SDimitry Andric unsigned PerEncoding = TLOF.getPersonalityEncoding(); 156*0b57cec5SDimitry Andric const MCSymbol *Sym = TLOF.getCFIPersonalitySymbol(P, Asm->TM, MMI); 157*0b57cec5SDimitry Andric Asm->OutStreamer->EmitCFIPersonality(Sym, PerEncoding); 158*0b57cec5SDimitry Andric 159*0b57cec5SDimitry Andric // Provide LSDA information. 160*0b57cec5SDimitry Andric if (shouldEmitLSDA) 161*0b57cec5SDimitry Andric Asm->OutStreamer->EmitCFILsda(ESP(Asm), TLOF.getLSDAEncoding()); 162*0b57cec5SDimitry Andric } 163*0b57cec5SDimitry Andric 164*0b57cec5SDimitry Andric /// endFunction - Gather and emit post-function exception information. 165*0b57cec5SDimitry Andric /// 166*0b57cec5SDimitry Andric void DwarfCFIException::endFunction(const MachineFunction *MF) { 167*0b57cec5SDimitry Andric if (!shouldEmitPersonality) 168*0b57cec5SDimitry Andric return; 169*0b57cec5SDimitry Andric 170*0b57cec5SDimitry Andric emitExceptionTable(); 171*0b57cec5SDimitry Andric } 172