diff options
Diffstat (limited to 'contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp')
| -rw-r--r-- | contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp | 151 |
1 files changed, 151 insertions, 0 deletions
diff --git a/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp b/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp new file mode 100644 index 000000000000..10c844ddb14a --- /dev/null +++ b/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp @@ -0,0 +1,151 @@ +//===-- CodeGen/AsmPrinter/DwarfException.cpp - Dwarf Exception Impl ------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file contains support for writing DWARF exception info into asm files. +// +//===----------------------------------------------------------------------===// + +#include "DwarfException.h" +#include "llvm/BinaryFormat/Dwarf.h" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/Target/TargetLoweringObjectFile.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetOptions.h" +using namespace llvm; + +DwarfCFIException::DwarfCFIException(AsmPrinter *A) : EHStreamer(A) {} + +DwarfCFIException::~DwarfCFIException() = default; + +void DwarfCFIException::addPersonality(const GlobalValue *Personality) { + if (!llvm::is_contained(Personalities, Personality)) + Personalities.push_back(Personality); +} + +/// endModule - Emit all exception information that should come after the +/// content. +void DwarfCFIException::endModule() { + // SjLj uses this pass and it doesn't need this info. + if (!Asm->MAI->usesCFIForEH()) + return; + + const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); + + unsigned PerEncoding = TLOF.getPersonalityEncoding(); + + if ((PerEncoding & 0x80) != dwarf::DW_EH_PE_indirect) + return; + + // Emit indirect reference table for all used personality functions + for (const GlobalValue *Personality : Personalities) { + MCSymbol *Sym = Asm->getSymbol(Personality); + TLOF.emitPersonalityValue(*Asm->OutStreamer, Asm->getDataLayout(), Sym); + } + Personalities.clear(); +} + +void DwarfCFIException::beginFunction(const MachineFunction *MF) { + shouldEmitPersonality = shouldEmitLSDA = false; + const Function &F = MF->getFunction(); + + // If any landing pads survive, we need an EH table. + bool hasLandingPads = !MF->getLandingPads().empty(); + + // See if we need frame move info. + bool shouldEmitMoves = + Asm->getFunctionCFISectionType(*MF) != AsmPrinter::CFISection::None; + + const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); + unsigned PerEncoding = TLOF.getPersonalityEncoding(); + const GlobalValue *Per = nullptr; + if (F.hasPersonalityFn()) + Per = dyn_cast<GlobalValue>(F.getPersonalityFn()->stripPointerCasts()); + + // Emit a personality function even when there are no landing pads + forceEmitPersonality = + // ...if a personality function is explicitly specified + F.hasPersonalityFn() && + // ... and it's not known to be a noop in the absence of invokes + !isNoOpWithoutInvoke(classifyEHPersonality(Per)) && + // ... and we're not explicitly asked not to emit it + F.needsUnwindTableEntry(); + + shouldEmitPersonality = + (forceEmitPersonality || + (hasLandingPads && PerEncoding != dwarf::DW_EH_PE_omit)) && + Per; + + unsigned LSDAEncoding = TLOF.getLSDAEncoding(); + shouldEmitLSDA = shouldEmitPersonality && + LSDAEncoding != dwarf::DW_EH_PE_omit; + + const MCAsmInfo &MAI = *MF->getMMI().getContext().getAsmInfo(); + if (MAI.getExceptionHandlingType() != ExceptionHandling::None) + shouldEmitCFI = + MAI.usesCFIForEH() && (shouldEmitPersonality || shouldEmitMoves); + else + shouldEmitCFI = Asm->usesCFIWithoutEH() && shouldEmitMoves; +} + +void DwarfCFIException::beginBasicBlockSection(const MachineBasicBlock &MBB) { + if (!shouldEmitCFI) + return; + + if (!hasEmittedCFISections) { + AsmPrinter::CFISection CFISecType = Asm->getModuleCFISectionType(); + // If we don't say anything it implies `.cfi_sections .eh_frame`, so we + // chose not to be verbose in that case. And with `ForceDwarfFrameSection`, + // we should always emit .debug_frame. + if (CFISecType == AsmPrinter::CFISection::Debug || + Asm->TM.Options.ForceDwarfFrameSection) + Asm->OutStreamer->emitCFISections( + CFISecType == AsmPrinter::CFISection::EH, true); + hasEmittedCFISections = true; + } + + Asm->OutStreamer->emitCFIStartProc(/*IsSimple=*/false); + + // Indicate personality routine, if any. + if (!shouldEmitPersonality) + return; + + auto &F = MBB.getParent()->getFunction(); + auto *P = dyn_cast<GlobalValue>(F.getPersonalityFn()->stripPointerCasts()); + assert(P && "Expected personality function"); + // Record the personality function. + addPersonality(P); + + const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); + unsigned PerEncoding = TLOF.getPersonalityEncoding(); + const MCSymbol *Sym = TLOF.getCFIPersonalitySymbol(P, Asm->TM, MMI); + Asm->OutStreamer->emitCFIPersonality(Sym, PerEncoding); + + // Provide LSDA information. + if (shouldEmitLSDA) + Asm->OutStreamer->emitCFILsda(Asm->getMBBExceptionSym(MBB), + TLOF.getLSDAEncoding()); +} + +void DwarfCFIException::endBasicBlockSection(const MachineBasicBlock &MBB) { + if (shouldEmitCFI) + Asm->OutStreamer->emitCFIEndProc(); +} + +/// endFunction - Gather and emit post-function exception information. +/// +void DwarfCFIException::endFunction(const MachineFunction *MF) { + if (!shouldEmitPersonality) + return; + + emitExceptionTable(); +} |
