156 lines · cpp
1//===-- CodeGen/AsmPrinter/DwarfException.cpp - Dwarf Exception Impl ------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file contains support for writing DWARF exception info into asm files.10//11//===----------------------------------------------------------------------===//12 13#include "DwarfException.h"14#include "llvm/BinaryFormat/Dwarf.h"15#include "llvm/CodeGen/AsmPrinter.h"16#include "llvm/CodeGen/MachineFunction.h"17#include "llvm/CodeGen/MachineModuleInfo.h"18#include "llvm/IR/Function.h"19#include "llvm/MC/MCAsmInfo.h"20#include "llvm/MC/MCContext.h"21#include "llvm/MC/MCStreamer.h"22#include "llvm/Target/TargetLoweringObjectFile.h"23#include "llvm/Target/TargetMachine.h"24#include "llvm/Target/TargetOptions.h"25using namespace llvm;26 27DwarfCFIException::DwarfCFIException(AsmPrinter *A) : EHStreamer(A) {}28 29DwarfCFIException::~DwarfCFIException() = default;30 31void DwarfCFIException::addPersonality(const GlobalValue *Personality) {32 if (!llvm::is_contained(Personalities, Personality))33 Personalities.push_back(Personality);34}35 36/// endModule - Emit all exception information that should come after the37/// content.38void DwarfCFIException::endModule() {39 // SjLj uses this pass and it doesn't need this info.40 if (!Asm->MAI->usesCFIForEH())41 return;42 43 const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering();44 45 unsigned PerEncoding = TLOF.getPersonalityEncoding();46 47 if ((PerEncoding & 0x80) != dwarf::DW_EH_PE_indirect)48 return;49 50 // Emit indirect reference table for all used personality functions51 for (const GlobalValue *Personality : Personalities) {52 MCSymbol *Sym = Asm->getSymbol(Personality);53 TLOF.emitPersonalityValue(*Asm->OutStreamer, Asm->getDataLayout(), Sym,54 Asm->MMI);55 }56 Personalities.clear();57}58 59void DwarfCFIException::beginFunction(const MachineFunction *MF) {60 shouldEmitPersonality = shouldEmitLSDA = false;61 const Function &F = MF->getFunction();62 63 // If any landing pads survive, we need an EH table.64 bool hasLandingPads = !MF->getLandingPads().empty();65 66 // See if we need frame move info.67 bool shouldEmitMoves =68 Asm->getFunctionCFISectionType(*MF) != AsmPrinter::CFISection::None;69 70 const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering();71 unsigned PerEncoding = TLOF.getPersonalityEncoding();72 const GlobalValue *Per = nullptr;73 if (F.hasPersonalityFn())74 Per = dyn_cast<GlobalValue>(F.getPersonalityFn()->stripPointerCasts());75 76 // Emit a personality function even when there are no landing pads77 forceEmitPersonality =78 // ...if a personality function is explicitly specified79 F.hasPersonalityFn() &&80 // ... and it's not known to be a noop in the absence of invokes81 !isNoOpWithoutInvoke(classifyEHPersonality(Per)) &&82 // ... and we're not explicitly asked not to emit it83 F.needsUnwindTableEntry();84 85 shouldEmitPersonality =86 (forceEmitPersonality ||87 (hasLandingPads && PerEncoding != dwarf::DW_EH_PE_omit)) &&88 Per;89 90 unsigned LSDAEncoding = TLOF.getLSDAEncoding();91 shouldEmitLSDA = shouldEmitPersonality &&92 LSDAEncoding != dwarf::DW_EH_PE_omit;93 94 const MCAsmInfo &MAI = *MF->getContext().getAsmInfo();95 if (MAI.getExceptionHandlingType() != ExceptionHandling::None)96 shouldEmitCFI =97 MAI.usesCFIForEH() && (shouldEmitPersonality || shouldEmitMoves);98 else99 shouldEmitCFI = Asm->usesCFIWithoutEH() && shouldEmitMoves;100}101 102void DwarfCFIException::beginBasicBlockSection(const MachineBasicBlock &MBB) {103 if (!shouldEmitCFI)104 return;105 106 if (!hasEmittedCFISections) {107 AsmPrinter::CFISection CFISecType = Asm->getModuleCFISectionType();108 // If we don't say anything it implies `.cfi_sections .eh_frame`, so we109 // chose not to be verbose in that case. And with `ForceDwarfFrameSection`,110 // we should always emit .debug_frame.111 if (CFISecType == AsmPrinter::CFISection::Debug ||112 Asm->TM.Options.ForceDwarfFrameSection ||113 Asm->TM.Options.MCOptions.EmitSFrameUnwind)114 Asm->OutStreamer->emitCFISections(115 CFISecType == AsmPrinter::CFISection::EH, true,116 Asm->TM.Options.MCOptions.EmitSFrameUnwind);117 hasEmittedCFISections = true;118 }119 120 Asm->OutStreamer->emitCFIStartProc(/*IsSimple=*/false);121 122 // Indicate personality routine, if any.123 if (!shouldEmitPersonality)124 return;125 126 auto &F = MBB.getParent()->getFunction();127 auto *P = dyn_cast<GlobalValue>(F.getPersonalityFn()->stripPointerCasts());128 assert(P && "Expected personality function");129 // Record the personality function.130 addPersonality(P);131 132 const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering();133 unsigned PerEncoding = TLOF.getPersonalityEncoding();134 const MCSymbol *Sym = TLOF.getCFIPersonalitySymbol(P, Asm->TM, MMI);135 Asm->OutStreamer->emitCFIPersonality(Sym, PerEncoding);136 137 // Provide LSDA information.138 if (shouldEmitLSDA)139 Asm->OutStreamer->emitCFILsda(Asm->getMBBExceptionSym(MBB),140 TLOF.getLSDAEncoding());141}142 143void DwarfCFIException::endBasicBlockSection(const MachineBasicBlock &MBB) {144 if (shouldEmitCFI)145 Asm->OutStreamer->emitCFIEndProc();146}147 148/// endFunction - Gather and emit post-function exception information.149///150void DwarfCFIException::endFunction(const MachineFunction *MF) {151 if (!shouldEmitPersonality)152 return;153 154 emitExceptionTable();155}156