mirror of
https://github.com/llvm/llvm-project.git
synced 2025-05-02 13:56:07 +00:00

The existing behaviors and callbacks were overlapping and had very confusing semantics: beginBasicBlock/endBasicBlock were not always called, beginFragment/endFragment seemed like they were meant to mean the same thing, but were slightly different, etc. This resulted in confusing semantics, virtual method overloads, and control flow. Remove the above, and replace with new beginBasicBlockSection and endBasicBlockSection callbacks. And document them. These are always called before the first and after the last blocks in a function, even when basic-block-sections are disabled.
162 lines
5.6 KiB
C++
162 lines
5.6 KiB
C++
//===-- 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;
|
|
|
|
DwarfCFIExceptionBase::DwarfCFIExceptionBase(AsmPrinter *A) : EHStreamer(A) {}
|
|
|
|
void DwarfCFIExceptionBase::markFunctionEnd() {
|
|
// Map all labels and get rid of any dead landing pads.
|
|
if (!Asm->MF->getLandingPads().empty()) {
|
|
MachineFunction *NonConstMF = const_cast<MachineFunction*>(Asm->MF);
|
|
NonConstMF->tidyLandingPads();
|
|
}
|
|
}
|
|
|
|
DwarfCFIException::DwarfCFIException(AsmPrinter *A)
|
|
: DwarfCFIExceptionBase(A) {}
|
|
|
|
DwarfCFIException::~DwarfCFIException() = default;
|
|
|
|
/// 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 references to all used personality functions
|
|
for (const Function *Personality : MMI->getPersonalities()) {
|
|
if (!Personality)
|
|
continue;
|
|
MCSymbol *Sym = Asm->getSymbol(Personality);
|
|
TLOF.emitPersonalityValue(*Asm->OutStreamer, Asm->getDataLayout(), Sym);
|
|
}
|
|
}
|
|
|
|
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 Function *Per = nullptr;
|
|
if (F.hasPersonalityFn())
|
|
Per = dyn_cast<Function>(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->needsCFIForDebug() && 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<Function>(F.getPersonalityFn()->stripPointerCasts());
|
|
assert(P && "Expected personality function");
|
|
|
|
// If we are forced to emit this personality, make sure to record
|
|
// it because it might not appear in any landingpad
|
|
if (forceEmitPersonality)
|
|
MMI->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();
|
|
}
|