1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-25 04:02:41 +01:00
llvm-mirror/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp
RamNalamothu e6c5012dd8 [MCAsmInfo] Support UsesCFIForDebug for targets with no exception handling
This change enables emitting CFI unwind information for debugging purpose
for targets with MCAsmInfo::ExceptionsType == ExceptionHandling::None.

Currently generating CFI unwind information is entangled with supporting
the exceptions, even when AsmPrinter explicitly recognizes that the unwind
tables are being generated as debug information.

In fact, the unwind information is not generated even if we specify
--force-dwarf-frame-section, unless exceptions are enabled. The LIT test
llvm/test/CodeGen/AMDGPU/debug_frame.ll demonstrates this behavior.

Enable this option for AMDGPU to prepare for future patches which add
complete CFI support.

Reviewed By: dblaikie, MaskRay

Differential Revision: https://reviews.llvm.org/D78778
2021-05-06 04:53:45 +05:30

192 lines
6.5 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/ADT/Twine.h"
#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Mangler.h"
#include "llvm/IR/Module.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCSection.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/MC/MachineLocation.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FormattedStream.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), shouldEmitCFI(false), hasEmittedCFISections(false) {}
void DwarfCFIExceptionBase::markFunctionEnd() {
endFragment();
// 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();
}
}
void DwarfCFIExceptionBase::endFragment() {
if (shouldEmitCFI && !Asm->MF->hasBBSections())
Asm->OutStreamer->emitCFIEndProc();
}
DwarfCFIException::DwarfCFIException(AsmPrinter *A)
: DwarfCFIExceptionBase(A), shouldEmitPersonality(false),
forceEmitPersonality(false), shouldEmitLSDA(false) {}
DwarfCFIException::~DwarfCFIException() {}
/// 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);
}
}
static MCSymbol *getExceptionSym(AsmPrinter *Asm,
const MachineBasicBlock *MBB) {
return Asm->getMBBExceptionSym(*MBB);
}
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;
beginFragment(&*MF->begin(), getExceptionSym);
}
void DwarfCFIException::beginFragment(const MachineBasicBlock *MBB,
ExceptionSymbolProvider ESP) {
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(ESP(Asm, MBB), TLOF.getLSDAEncoding());
}
/// endFunction - Gather and emit post-function exception information.
///
void DwarfCFIException::endFunction(const MachineFunction *MF) {
if (!shouldEmitPersonality)
return;
emitExceptionTable();
}
void DwarfCFIException::beginBasicBlock(const MachineBasicBlock &MBB) {
beginFragment(&MBB, getExceptionSym);
}
void DwarfCFIException::endBasicBlock(const MachineBasicBlock &MBB) {
if (shouldEmitCFI)
Asm->OutStreamer->emitCFIEndProc();
}