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/ADT/Twine.h" 150b57cec5SDimitry Andric #include "llvm/BinaryFormat/Dwarf.h" 160b57cec5SDimitry Andric #include "llvm/CodeGen/AsmPrinter.h" 170b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h" 180b57cec5SDimitry Andric #include "llvm/CodeGen/MachineModuleInfo.h" 190b57cec5SDimitry Andric #include "llvm/IR/DataLayout.h" 200b57cec5SDimitry Andric #include "llvm/IR/Mangler.h" 210b57cec5SDimitry Andric #include "llvm/IR/Module.h" 220b57cec5SDimitry Andric #include "llvm/MC/MCAsmInfo.h" 230b57cec5SDimitry Andric #include "llvm/MC/MCContext.h" 240b57cec5SDimitry Andric #include "llvm/MC/MCExpr.h" 250b57cec5SDimitry Andric #include "llvm/MC/MCSection.h" 260b57cec5SDimitry Andric #include "llvm/MC/MCStreamer.h" 270b57cec5SDimitry Andric #include "llvm/MC/MCSymbol.h" 280b57cec5SDimitry Andric #include "llvm/MC/MachineLocation.h" 290b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 300b57cec5SDimitry Andric #include "llvm/Support/FormattedStream.h" 310b57cec5SDimitry Andric #include "llvm/Target/TargetLoweringObjectFile.h" 32480093f4SDimitry Andric #include "llvm/Target/TargetMachine.h" 330b57cec5SDimitry Andric #include "llvm/Target/TargetOptions.h" 340b57cec5SDimitry Andric using namespace llvm; 350b57cec5SDimitry Andric 360b57cec5SDimitry Andric DwarfCFIExceptionBase::DwarfCFIExceptionBase(AsmPrinter *A) 370b57cec5SDimitry Andric : EHStreamer(A), shouldEmitCFI(false), hasEmittedCFISections(false) {} 380b57cec5SDimitry Andric 390b57cec5SDimitry Andric void DwarfCFIExceptionBase::markFunctionEnd() { 400b57cec5SDimitry Andric endFragment(); 410b57cec5SDimitry Andric 420b57cec5SDimitry Andric // Map all labels and get rid of any dead landing pads. 430b57cec5SDimitry Andric if (!Asm->MF->getLandingPads().empty()) { 440b57cec5SDimitry Andric MachineFunction *NonConstMF = const_cast<MachineFunction*>(Asm->MF); 450b57cec5SDimitry Andric NonConstMF->tidyLandingPads(); 460b57cec5SDimitry Andric } 470b57cec5SDimitry Andric } 480b57cec5SDimitry Andric 490b57cec5SDimitry Andric void DwarfCFIExceptionBase::endFragment() { 50*5ffd83dbSDimitry Andric if (shouldEmitCFI && !Asm->MF->hasBBSections()) 51*5ffd83dbSDimitry Andric Asm->OutStreamer->emitCFIEndProc(); 520b57cec5SDimitry Andric } 530b57cec5SDimitry Andric 540b57cec5SDimitry Andric DwarfCFIException::DwarfCFIException(AsmPrinter *A) 550b57cec5SDimitry Andric : DwarfCFIExceptionBase(A), shouldEmitPersonality(false), 560b57cec5SDimitry Andric forceEmitPersonality(false), shouldEmitLSDA(false), 570b57cec5SDimitry Andric shouldEmitMoves(false) {} 580b57cec5SDimitry Andric 590b57cec5SDimitry Andric DwarfCFIException::~DwarfCFIException() {} 600b57cec5SDimitry Andric 610b57cec5SDimitry Andric /// endModule - Emit all exception information that should come after the 620b57cec5SDimitry Andric /// content. 630b57cec5SDimitry Andric void DwarfCFIException::endModule() { 640b57cec5SDimitry Andric // SjLj uses this pass and it doesn't need this info. 650b57cec5SDimitry Andric if (!Asm->MAI->usesCFIForEH()) 660b57cec5SDimitry Andric return; 670b57cec5SDimitry Andric 680b57cec5SDimitry Andric const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); 690b57cec5SDimitry Andric 700b57cec5SDimitry Andric unsigned PerEncoding = TLOF.getPersonalityEncoding(); 710b57cec5SDimitry Andric 720b57cec5SDimitry Andric if ((PerEncoding & 0x80) != dwarf::DW_EH_PE_indirect) 730b57cec5SDimitry Andric return; 740b57cec5SDimitry Andric 750b57cec5SDimitry Andric // Emit references to all used personality functions 760b57cec5SDimitry Andric for (const Function *Personality : MMI->getPersonalities()) { 770b57cec5SDimitry Andric if (!Personality) 780b57cec5SDimitry Andric continue; 790b57cec5SDimitry Andric MCSymbol *Sym = Asm->getSymbol(Personality); 800b57cec5SDimitry Andric TLOF.emitPersonalityValue(*Asm->OutStreamer, Asm->getDataLayout(), Sym); 810b57cec5SDimitry Andric } 820b57cec5SDimitry Andric } 830b57cec5SDimitry Andric 840b57cec5SDimitry Andric static MCSymbol *getExceptionSym(AsmPrinter *Asm) { 850b57cec5SDimitry Andric return Asm->getCurExceptionSym(); 860b57cec5SDimitry Andric } 870b57cec5SDimitry Andric 880b57cec5SDimitry Andric void DwarfCFIException::beginFunction(const MachineFunction *MF) { 890b57cec5SDimitry Andric shouldEmitMoves = shouldEmitPersonality = shouldEmitLSDA = false; 900b57cec5SDimitry Andric const Function &F = MF->getFunction(); 910b57cec5SDimitry Andric 920b57cec5SDimitry Andric // If any landing pads survive, we need an EH table. 930b57cec5SDimitry Andric bool hasLandingPads = !MF->getLandingPads().empty(); 940b57cec5SDimitry Andric 950b57cec5SDimitry Andric // See if we need frame move info. 960b57cec5SDimitry Andric AsmPrinter::CFIMoveType MoveType = Asm->needsCFIMoves(); 970b57cec5SDimitry Andric 980b57cec5SDimitry Andric shouldEmitMoves = MoveType != AsmPrinter::CFI_M_None; 990b57cec5SDimitry Andric 1000b57cec5SDimitry Andric const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); 1010b57cec5SDimitry Andric unsigned PerEncoding = TLOF.getPersonalityEncoding(); 1020b57cec5SDimitry Andric const Function *Per = nullptr; 1030b57cec5SDimitry Andric if (F.hasPersonalityFn()) 1040b57cec5SDimitry Andric Per = dyn_cast<Function>(F.getPersonalityFn()->stripPointerCasts()); 1050b57cec5SDimitry Andric 1060b57cec5SDimitry Andric // Emit a personality function even when there are no landing pads 1070b57cec5SDimitry Andric forceEmitPersonality = 1080b57cec5SDimitry Andric // ...if a personality function is explicitly specified 1090b57cec5SDimitry Andric F.hasPersonalityFn() && 1100b57cec5SDimitry Andric // ... and it's not known to be a noop in the absence of invokes 1110b57cec5SDimitry Andric !isNoOpWithoutInvoke(classifyEHPersonality(Per)) && 1120b57cec5SDimitry Andric // ... and we're not explicitly asked not to emit it 1130b57cec5SDimitry Andric F.needsUnwindTableEntry(); 1140b57cec5SDimitry Andric 1150b57cec5SDimitry Andric shouldEmitPersonality = 1160b57cec5SDimitry Andric (forceEmitPersonality || 1170b57cec5SDimitry Andric (hasLandingPads && PerEncoding != dwarf::DW_EH_PE_omit)) && 1180b57cec5SDimitry Andric Per; 1190b57cec5SDimitry Andric 1200b57cec5SDimitry Andric unsigned LSDAEncoding = TLOF.getLSDAEncoding(); 1210b57cec5SDimitry Andric shouldEmitLSDA = shouldEmitPersonality && 1220b57cec5SDimitry Andric LSDAEncoding != dwarf::DW_EH_PE_omit; 1230b57cec5SDimitry Andric 1240b57cec5SDimitry Andric shouldEmitCFI = MF->getMMI().getContext().getAsmInfo()->usesCFIForEH() && 1250b57cec5SDimitry Andric (shouldEmitPersonality || shouldEmitMoves); 1260b57cec5SDimitry Andric beginFragment(&*MF->begin(), getExceptionSym); 1270b57cec5SDimitry Andric } 1280b57cec5SDimitry Andric 1290b57cec5SDimitry Andric void DwarfCFIException::beginFragment(const MachineBasicBlock *MBB, 1300b57cec5SDimitry Andric ExceptionSymbolProvider ESP) { 1310b57cec5SDimitry Andric if (!shouldEmitCFI) 1320b57cec5SDimitry Andric return; 1330b57cec5SDimitry Andric 1340b57cec5SDimitry Andric if (!hasEmittedCFISections) { 1350b57cec5SDimitry Andric if (Asm->needsOnlyDebugCFIMoves()) 136*5ffd83dbSDimitry Andric Asm->OutStreamer->emitCFISections(false, true); 137480093f4SDimitry Andric else if (Asm->TM.Options.ForceDwarfFrameSection) 138*5ffd83dbSDimitry Andric Asm->OutStreamer->emitCFISections(true, true); 1390b57cec5SDimitry Andric hasEmittedCFISections = true; 1400b57cec5SDimitry Andric } 1410b57cec5SDimitry Andric 142*5ffd83dbSDimitry Andric Asm->OutStreamer->emitCFIStartProc(/*IsSimple=*/false); 1430b57cec5SDimitry Andric 1440b57cec5SDimitry Andric // Indicate personality routine, if any. 1450b57cec5SDimitry Andric if (!shouldEmitPersonality) 1460b57cec5SDimitry Andric return; 1470b57cec5SDimitry Andric 1480b57cec5SDimitry Andric auto &F = MBB->getParent()->getFunction(); 1490b57cec5SDimitry Andric auto *P = dyn_cast<Function>(F.getPersonalityFn()->stripPointerCasts()); 1500b57cec5SDimitry Andric assert(P && "Expected personality function"); 1510b57cec5SDimitry Andric 1520b57cec5SDimitry Andric // If we are forced to emit this personality, make sure to record 1530b57cec5SDimitry Andric // it because it might not appear in any landingpad 1540b57cec5SDimitry Andric if (forceEmitPersonality) 1550b57cec5SDimitry Andric MMI->addPersonality(P); 1560b57cec5SDimitry Andric 1570b57cec5SDimitry Andric const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); 1580b57cec5SDimitry Andric unsigned PerEncoding = TLOF.getPersonalityEncoding(); 1590b57cec5SDimitry Andric const MCSymbol *Sym = TLOF.getCFIPersonalitySymbol(P, Asm->TM, MMI); 160*5ffd83dbSDimitry Andric Asm->OutStreamer->emitCFIPersonality(Sym, PerEncoding); 1610b57cec5SDimitry Andric 1620b57cec5SDimitry Andric // Provide LSDA information. 1630b57cec5SDimitry Andric if (shouldEmitLSDA) 164*5ffd83dbSDimitry Andric Asm->OutStreamer->emitCFILsda(ESP(Asm), TLOF.getLSDAEncoding()); 1650b57cec5SDimitry Andric } 1660b57cec5SDimitry Andric 1670b57cec5SDimitry Andric /// endFunction - Gather and emit post-function exception information. 1680b57cec5SDimitry Andric /// 1690b57cec5SDimitry Andric void DwarfCFIException::endFunction(const MachineFunction *MF) { 1700b57cec5SDimitry Andric if (!shouldEmitPersonality) 1710b57cec5SDimitry Andric return; 1720b57cec5SDimitry Andric 1730b57cec5SDimitry Andric emitExceptionTable(); 1740b57cec5SDimitry Andric } 175*5ffd83dbSDimitry Andric 176*5ffd83dbSDimitry Andric void DwarfCFIException::beginBasicBlock(const MachineBasicBlock &MBB) { 177*5ffd83dbSDimitry Andric beginFragment(&MBB, getExceptionSym); 178*5ffd83dbSDimitry Andric } 179*5ffd83dbSDimitry Andric 180*5ffd83dbSDimitry Andric void DwarfCFIException::endBasicBlock(const MachineBasicBlock &MBB) { 181*5ffd83dbSDimitry Andric if (shouldEmitCFI) 182*5ffd83dbSDimitry Andric Asm->OutStreamer->emitCFIEndProc(); 183*5ffd83dbSDimitry Andric } 184