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() { 505ffd83dbSDimitry Andric if (shouldEmitCFI && !Asm->MF->hasBBSections()) 515ffd83dbSDimitry Andric Asm->OutStreamer->emitCFIEndProc(); 520b57cec5SDimitry Andric } 530b57cec5SDimitry Andric 540b57cec5SDimitry Andric DwarfCFIException::DwarfCFIException(AsmPrinter *A) 550b57cec5SDimitry Andric : DwarfCFIExceptionBase(A), shouldEmitPersonality(false), 56*fe6060f1SDimitry Andric forceEmitPersonality(false), shouldEmitLSDA(false) {} 570b57cec5SDimitry Andric 580b57cec5SDimitry Andric DwarfCFIException::~DwarfCFIException() {} 590b57cec5SDimitry Andric 600b57cec5SDimitry Andric /// endModule - Emit all exception information that should come after the 610b57cec5SDimitry Andric /// content. 620b57cec5SDimitry Andric void DwarfCFIException::endModule() { 630b57cec5SDimitry Andric // SjLj uses this pass and it doesn't need this info. 640b57cec5SDimitry Andric if (!Asm->MAI->usesCFIForEH()) 650b57cec5SDimitry Andric return; 660b57cec5SDimitry Andric 670b57cec5SDimitry Andric const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); 680b57cec5SDimitry Andric 690b57cec5SDimitry Andric unsigned PerEncoding = TLOF.getPersonalityEncoding(); 700b57cec5SDimitry Andric 710b57cec5SDimitry Andric if ((PerEncoding & 0x80) != dwarf::DW_EH_PE_indirect) 720b57cec5SDimitry Andric return; 730b57cec5SDimitry Andric 740b57cec5SDimitry Andric // Emit references to all used personality functions 750b57cec5SDimitry Andric for (const Function *Personality : MMI->getPersonalities()) { 760b57cec5SDimitry Andric if (!Personality) 770b57cec5SDimitry Andric continue; 780b57cec5SDimitry Andric MCSymbol *Sym = Asm->getSymbol(Personality); 790b57cec5SDimitry Andric TLOF.emitPersonalityValue(*Asm->OutStreamer, Asm->getDataLayout(), Sym); 800b57cec5SDimitry Andric } 810b57cec5SDimitry Andric } 820b57cec5SDimitry Andric 83e8d8bef9SDimitry Andric static MCSymbol *getExceptionSym(AsmPrinter *Asm, 84e8d8bef9SDimitry Andric const MachineBasicBlock *MBB) { 85e8d8bef9SDimitry Andric return Asm->getMBBExceptionSym(*MBB); 860b57cec5SDimitry Andric } 870b57cec5SDimitry Andric 880b57cec5SDimitry Andric void DwarfCFIException::beginFunction(const MachineFunction *MF) { 89*fe6060f1SDimitry Andric 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. 96*fe6060f1SDimitry Andric bool shouldEmitMoves = 97*fe6060f1SDimitry Andric Asm->getFunctionCFISectionType(*MF) != AsmPrinter::CFISection::None; 980b57cec5SDimitry Andric 990b57cec5SDimitry Andric const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); 1000b57cec5SDimitry Andric unsigned PerEncoding = TLOF.getPersonalityEncoding(); 1010b57cec5SDimitry Andric const Function *Per = nullptr; 1020b57cec5SDimitry Andric if (F.hasPersonalityFn()) 1030b57cec5SDimitry Andric Per = dyn_cast<Function>(F.getPersonalityFn()->stripPointerCasts()); 1040b57cec5SDimitry Andric 1050b57cec5SDimitry Andric // Emit a personality function even when there are no landing pads 1060b57cec5SDimitry Andric forceEmitPersonality = 1070b57cec5SDimitry Andric // ...if a personality function is explicitly specified 1080b57cec5SDimitry Andric F.hasPersonalityFn() && 1090b57cec5SDimitry Andric // ... and it's not known to be a noop in the absence of invokes 1100b57cec5SDimitry Andric !isNoOpWithoutInvoke(classifyEHPersonality(Per)) && 1110b57cec5SDimitry Andric // ... and we're not explicitly asked not to emit it 1120b57cec5SDimitry Andric F.needsUnwindTableEntry(); 1130b57cec5SDimitry Andric 1140b57cec5SDimitry Andric shouldEmitPersonality = 1150b57cec5SDimitry Andric (forceEmitPersonality || 1160b57cec5SDimitry Andric (hasLandingPads && PerEncoding != dwarf::DW_EH_PE_omit)) && 1170b57cec5SDimitry Andric Per; 1180b57cec5SDimitry Andric 1190b57cec5SDimitry Andric unsigned LSDAEncoding = TLOF.getLSDAEncoding(); 1200b57cec5SDimitry Andric shouldEmitLSDA = shouldEmitPersonality && 1210b57cec5SDimitry Andric LSDAEncoding != dwarf::DW_EH_PE_omit; 1220b57cec5SDimitry Andric 123*fe6060f1SDimitry Andric const MCAsmInfo &MAI = *MF->getMMI().getContext().getAsmInfo(); 124*fe6060f1SDimitry Andric if (MAI.getExceptionHandlingType() != ExceptionHandling::None) 125*fe6060f1SDimitry Andric shouldEmitCFI = 126*fe6060f1SDimitry Andric MAI.usesCFIForEH() && (shouldEmitPersonality || shouldEmitMoves); 127*fe6060f1SDimitry Andric else 128*fe6060f1SDimitry Andric shouldEmitCFI = Asm->needsCFIForDebug() && shouldEmitMoves; 129*fe6060f1SDimitry Andric 1300b57cec5SDimitry Andric beginFragment(&*MF->begin(), getExceptionSym); 1310b57cec5SDimitry Andric } 1320b57cec5SDimitry Andric 1330b57cec5SDimitry Andric void DwarfCFIException::beginFragment(const MachineBasicBlock *MBB, 1340b57cec5SDimitry Andric ExceptionSymbolProvider ESP) { 1350b57cec5SDimitry Andric if (!shouldEmitCFI) 1360b57cec5SDimitry Andric return; 1370b57cec5SDimitry Andric 1380b57cec5SDimitry Andric if (!hasEmittedCFISections) { 139*fe6060f1SDimitry Andric AsmPrinter::CFISection CFISecType = Asm->getModuleCFISectionType(); 140*fe6060f1SDimitry Andric // If we don't say anything it implies `.cfi_sections .eh_frame`, so we 141*fe6060f1SDimitry Andric // chose not to be verbose in that case. And with `ForceDwarfFrameSection`, 142*fe6060f1SDimitry Andric // we should always emit .debug_frame. 143*fe6060f1SDimitry Andric if (CFISecType == AsmPrinter::CFISection::Debug || 144*fe6060f1SDimitry Andric Asm->TM.Options.ForceDwarfFrameSection) 145*fe6060f1SDimitry Andric Asm->OutStreamer->emitCFISections( 146*fe6060f1SDimitry Andric CFISecType == AsmPrinter::CFISection::EH, true); 1470b57cec5SDimitry Andric hasEmittedCFISections = true; 1480b57cec5SDimitry Andric } 1490b57cec5SDimitry Andric 1505ffd83dbSDimitry Andric Asm->OutStreamer->emitCFIStartProc(/*IsSimple=*/false); 1510b57cec5SDimitry Andric 1520b57cec5SDimitry Andric // Indicate personality routine, if any. 1530b57cec5SDimitry Andric if (!shouldEmitPersonality) 1540b57cec5SDimitry Andric return; 1550b57cec5SDimitry Andric 1560b57cec5SDimitry Andric auto &F = MBB->getParent()->getFunction(); 1570b57cec5SDimitry Andric auto *P = dyn_cast<Function>(F.getPersonalityFn()->stripPointerCasts()); 1580b57cec5SDimitry Andric assert(P && "Expected personality function"); 1590b57cec5SDimitry Andric 1600b57cec5SDimitry Andric // If we are forced to emit this personality, make sure to record 1610b57cec5SDimitry Andric // it because it might not appear in any landingpad 1620b57cec5SDimitry Andric if (forceEmitPersonality) 1630b57cec5SDimitry Andric MMI->addPersonality(P); 1640b57cec5SDimitry Andric 1650b57cec5SDimitry Andric const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); 1660b57cec5SDimitry Andric unsigned PerEncoding = TLOF.getPersonalityEncoding(); 1670b57cec5SDimitry Andric const MCSymbol *Sym = TLOF.getCFIPersonalitySymbol(P, Asm->TM, MMI); 1685ffd83dbSDimitry Andric Asm->OutStreamer->emitCFIPersonality(Sym, PerEncoding); 1690b57cec5SDimitry Andric 1700b57cec5SDimitry Andric // Provide LSDA information. 1710b57cec5SDimitry Andric if (shouldEmitLSDA) 172e8d8bef9SDimitry Andric Asm->OutStreamer->emitCFILsda(ESP(Asm, MBB), TLOF.getLSDAEncoding()); 1730b57cec5SDimitry Andric } 1740b57cec5SDimitry Andric 1750b57cec5SDimitry Andric /// endFunction - Gather and emit post-function exception information. 1760b57cec5SDimitry Andric /// 1770b57cec5SDimitry Andric void DwarfCFIException::endFunction(const MachineFunction *MF) { 1780b57cec5SDimitry Andric if (!shouldEmitPersonality) 1790b57cec5SDimitry Andric return; 1800b57cec5SDimitry Andric 1810b57cec5SDimitry Andric emitExceptionTable(); 1820b57cec5SDimitry Andric } 1835ffd83dbSDimitry Andric 1845ffd83dbSDimitry Andric void DwarfCFIException::beginBasicBlock(const MachineBasicBlock &MBB) { 1855ffd83dbSDimitry Andric beginFragment(&MBB, getExceptionSym); 1865ffd83dbSDimitry Andric } 1875ffd83dbSDimitry Andric 1885ffd83dbSDimitry Andric void DwarfCFIException::endBasicBlock(const MachineBasicBlock &MBB) { 1895ffd83dbSDimitry Andric if (shouldEmitCFI) 1905ffd83dbSDimitry Andric Asm->OutStreamer->emitCFIEndProc(); 1915ffd83dbSDimitry Andric } 192