2011-01-14 21:57:53 +00:00
|
|
|
//===-- CodeGen/AsmPrinter/DwarfException.cpp - Dwarf Exception Impl ------===//
|
|
|
|
//
|
2019-01-19 08:50:56 +00:00
|
|
|
// 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
|
2011-01-14 21:57:53 +00:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This file contains support for writing DWARF exception info into asm files.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "DwarfException.h"
|
2012-12-03 16:50:05 +00:00
|
|
|
#include "llvm/ADT/Twine.h"
|
2017-06-07 03:48:56 +00:00
|
|
|
#include "llvm/BinaryFormat/Dwarf.h"
|
2011-01-14 21:57:53 +00:00
|
|
|
#include "llvm/CodeGen/AsmPrinter.h"
|
|
|
|
#include "llvm/CodeGen/MachineFunction.h"
|
2012-12-03 16:50:05 +00:00
|
|
|
#include "llvm/CodeGen/MachineModuleInfo.h"
|
2013-01-02 11:36:10 +00:00
|
|
|
#include "llvm/IR/DataLayout.h"
|
2014-01-07 21:19:40 +00:00
|
|
|
#include "llvm/IR/Mangler.h"
|
2013-01-02 11:36:10 +00:00
|
|
|
#include "llvm/IR/Module.h"
|
2011-01-14 21:57:53 +00:00
|
|
|
#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"
|
2012-12-03 16:50:05 +00:00
|
|
|
#include "llvm/MC/MachineLocation.h"
|
|
|
|
#include "llvm/Support/ErrorHandling.h"
|
|
|
|
#include "llvm/Support/FormattedStream.h"
|
2018-03-23 23:58:19 +00:00
|
|
|
#include "llvm/Target/TargetLoweringObjectFile.h"
|
2019-10-31 08:55:57 +00:00
|
|
|
#include "llvm/Target/TargetMachine.h"
|
2011-01-14 21:57:53 +00:00
|
|
|
#include "llvm/Target/TargetOptions.h"
|
|
|
|
using namespace llvm;
|
|
|
|
|
2015-03-09 18:29:12 +00:00
|
|
|
DwarfCFIExceptionBase::DwarfCFIExceptionBase(AsmPrinter *A)
|
2017-01-02 18:05:27 +00:00
|
|
|
: EHStreamer(A), shouldEmitCFI(false), hasEmittedCFISections(false) {}
|
2015-03-09 18:29:12 +00:00
|
|
|
|
|
|
|
void DwarfCFIExceptionBase::markFunctionEnd() {
|
2016-02-26 20:30:37 +00:00
|
|
|
endFragment();
|
2015-03-09 18:29:12 +00:00
|
|
|
|
|
|
|
// Map all labels and get rid of any dead landing pads.
|
2016-12-01 19:32:15 +00:00
|
|
|
if (!Asm->MF->getLandingPads().empty()) {
|
|
|
|
MachineFunction *NonConstMF = const_cast<MachineFunction*>(Asm->MF);
|
|
|
|
NonConstMF->tidyLandingPads();
|
|
|
|
}
|
2015-03-09 18:29:12 +00:00
|
|
|
}
|
|
|
|
|
2016-02-26 20:30:37 +00:00
|
|
|
void DwarfCFIExceptionBase::endFragment() {
|
Call Frame Information (CFI) Handling for Basic Block Sections
This patch handles CFI with basic block sections, which unlike DebugInfo does
not support ranges. The DWARF standard explicitly requires emitting separate
CFI Frame Descriptor Entries for each contiguous fragment of a function. Thus,
the CFI information for all callee-saved registers (possibly including the
frame pointer, if necessary) have to be emitted along with redefining the
Call Frame Address (CFA), viz. where the current frame starts.
CFI directives are emitted in FDE’s in the object file with a low_pc, high_pc
specification. So, a single FDE must point to a contiguous code region unlike
debug info which has the support for ranges. This is what complicates CFI for
basic block sections.
Now, what happens when we start placing individual basic blocks in unique
sections:
* Basic block sections allow the linker to randomly reorder basic blocks in the
address space such that a given basic block can become non-contiguous with the
original function.
* The different basic block sections can no longer share the cfi_startproc and
cfi_endproc directives. So, each basic block section should emit this
independently.
* Each (cfi_startproc, cfi_endproc) directive will result in a new FDE that
caters to that basic block section.
* Now, this basic block section needs to duplicate the information from the
entry block to compute the CFA as it is an independent entity. It cannot refer
to the FDE of the original function and hence must duplicate all the stuff that
is needed to compute the CFA on its own.
* We are working on a de-duplication patch that can share common information in
FDEs in a CIE (Common Information Entry) and we will present this as a follow up
patch. This can significantly reduce the duplication overhead and is
particularly useful when several basic block sections are created.
* The CFI directives are emitted similarly for registers that are pushed onto
the stack, like callee saved registers in the prologue. There are cfi
directives that emit how to retrieve the value of the register at that point
when the push happened. This has to be duplicated too in a basic block that is
floated as a separate section.
Differential Revision: https://reviews.llvm.org/D79978
2020-07-14 11:55:41 -07:00
|
|
|
if (shouldEmitCFI && !Asm->MF->hasBBSections())
|
2020-02-13 21:58:16 -08:00
|
|
|
Asm->OutStreamer->emitCFIEndProc();
|
2016-02-26 20:30:37 +00:00
|
|
|
}
|
|
|
|
|
2011-01-14 21:57:53 +00:00
|
|
|
DwarfCFIException::DwarfCFIException(AsmPrinter *A)
|
2015-03-09 18:29:12 +00:00
|
|
|
: DwarfCFIExceptionBase(A), shouldEmitPersonality(false),
|
2016-02-26 20:49:07 +00:00
|
|
|
forceEmitPersonality(false), shouldEmitLSDA(false),
|
2017-01-02 18:05:27 +00:00
|
|
|
shouldEmitMoves(false) {}
|
2011-01-14 21:57:53 +00:00
|
|
|
|
|
|
|
DwarfCFIException::~DwarfCFIException() {}
|
|
|
|
|
2013-11-26 13:34:55 +00:00
|
|
|
/// endModule - Emit all exception information that should come after the
|
2011-01-14 21:57:53 +00:00
|
|
|
/// content.
|
2013-11-26 13:34:55 +00:00
|
|
|
void DwarfCFIException::endModule() {
|
2015-01-23 18:49:01 +00:00
|
|
|
// SjLj uses this pass and it doesn't need this info.
|
|
|
|
if (!Asm->MAI->usesCFIForEH())
|
2011-01-14 21:57:53 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering();
|
2011-04-29 15:09:53 +00:00
|
|
|
|
2011-01-14 21:57:53 +00:00
|
|
|
unsigned PerEncoding = TLOF.getPersonalityEncoding();
|
|
|
|
|
2014-05-30 16:48:56 +00:00
|
|
|
if ((PerEncoding & 0x80) != dwarf::DW_EH_PE_indirect)
|
2011-04-15 15:11:06 +00:00
|
|
|
return;
|
|
|
|
|
2011-01-14 21:57:53 +00:00
|
|
|
// Emit references to all used personality functions
|
2015-08-31 20:02:16 +00:00
|
|
|
for (const Function *Personality : MMI->getPersonalities()) {
|
|
|
|
if (!Personality)
|
2011-04-29 14:48:51 +00:00
|
|
|
continue;
|
2015-08-31 20:02:16 +00:00
|
|
|
MCSymbol *Sym = Asm->getSymbol(Personality);
|
2015-07-16 06:04:17 +00:00
|
|
|
TLOF.emitPersonalityValue(*Asm->OutStreamer, Asm->getDataLayout(), Sym);
|
2011-01-14 21:57:53 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-26 20:30:37 +00:00
|
|
|
static MCSymbol *getExceptionSym(AsmPrinter *Asm) {
|
|
|
|
return Asm->getCurExceptionSym();
|
|
|
|
}
|
|
|
|
|
2013-11-26 13:34:55 +00:00
|
|
|
void DwarfCFIException::beginFunction(const MachineFunction *MF) {
|
2011-04-29 14:48:51 +00:00
|
|
|
shouldEmitMoves = shouldEmitPersonality = shouldEmitLSDA = false;
|
2017-12-15 22:22:58 +00:00
|
|
|
const Function &F = MF->getFunction();
|
2011-01-14 21:57:53 +00:00
|
|
|
|
|
|
|
// If any landing pads survive, we need an EH table.
|
2016-12-01 19:32:15 +00:00
|
|
|
bool hasLandingPads = !MF->getLandingPads().empty();
|
2011-01-14 21:57:53 +00:00
|
|
|
|
|
|
|
// See if we need frame move info.
|
2011-05-10 18:39:09 +00:00
|
|
|
AsmPrinter::CFIMoveType MoveType = Asm->needsCFIMoves();
|
|
|
|
|
|
|
|
shouldEmitMoves = MoveType != AsmPrinter::CFI_M_None;
|
2011-01-14 21:57:53 +00:00
|
|
|
|
2011-04-29 14:48:51 +00:00
|
|
|
const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering();
|
|
|
|
unsigned PerEncoding = TLOF.getPersonalityEncoding();
|
2015-07-14 19:22:51 +00:00
|
|
|
const Function *Per = nullptr;
|
2017-12-15 22:22:58 +00:00
|
|
|
if (F.hasPersonalityFn())
|
|
|
|
Per = dyn_cast<Function>(F.getPersonalityFn()->stripPointerCasts());
|
2015-07-14 19:22:51 +00:00
|
|
|
|
|
|
|
// Emit a personality function even when there are no landing pads
|
2016-02-26 20:30:37 +00:00
|
|
|
forceEmitPersonality =
|
2015-07-14 19:22:51 +00:00
|
|
|
// ...if a personality function is explicitly specified
|
2017-12-15 22:22:58 +00:00
|
|
|
F.hasPersonalityFn() &&
|
2015-07-14 19:22:51 +00:00
|
|
|
// ... 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
|
2017-12-15 22:22:58 +00:00
|
|
|
F.needsUnwindTableEntry();
|
2015-07-14 19:22:51 +00:00
|
|
|
|
|
|
|
shouldEmitPersonality =
|
|
|
|
(forceEmitPersonality ||
|
|
|
|
(hasLandingPads && PerEncoding != dwarf::DW_EH_PE_omit)) &&
|
|
|
|
Per;
|
2011-01-14 21:57:53 +00:00
|
|
|
|
2011-04-29 14:48:51 +00:00
|
|
|
unsigned LSDAEncoding = TLOF.getLSDAEncoding();
|
|
|
|
shouldEmitLSDA = shouldEmitPersonality &&
|
|
|
|
LSDAEncoding != dwarf::DW_EH_PE_omit;
|
2011-01-14 21:57:53 +00:00
|
|
|
|
2016-07-15 21:10:29 +00:00
|
|
|
shouldEmitCFI = MF->getMMI().getContext().getAsmInfo()->usesCFIForEH() &&
|
|
|
|
(shouldEmitPersonality || shouldEmitMoves);
|
2016-02-26 20:30:37 +00:00
|
|
|
beginFragment(&*MF->begin(), getExceptionSym);
|
|
|
|
}
|
|
|
|
|
|
|
|
void DwarfCFIException::beginFragment(const MachineBasicBlock *MBB,
|
|
|
|
ExceptionSymbolProvider ESP) {
|
2015-03-09 18:29:12 +00:00
|
|
|
if (!shouldEmitCFI)
|
2011-01-14 21:57:53 +00:00
|
|
|
return;
|
|
|
|
|
2017-01-02 18:05:27 +00:00
|
|
|
if (!hasEmittedCFISections) {
|
2017-01-05 20:55:28 +00:00
|
|
|
if (Asm->needsOnlyDebugCFIMoves())
|
2020-02-13 21:58:16 -08:00
|
|
|
Asm->OutStreamer->emitCFISections(false, true);
|
2019-10-31 08:55:57 +00:00
|
|
|
else if (Asm->TM.Options.ForceDwarfFrameSection)
|
2020-02-13 21:58:16 -08:00
|
|
|
Asm->OutStreamer->emitCFISections(true, true);
|
2017-01-02 18:05:27 +00:00
|
|
|
hasEmittedCFISections = true;
|
|
|
|
}
|
|
|
|
|
2020-02-13 21:58:16 -08:00
|
|
|
Asm->OutStreamer->emitCFIStartProc(/*IsSimple=*/false);
|
2011-01-14 21:57:53 +00:00
|
|
|
|
|
|
|
// Indicate personality routine, if any.
|
2011-04-29 14:48:51 +00:00
|
|
|
if (!shouldEmitPersonality)
|
2011-04-15 15:11:06 +00:00
|
|
|
return;
|
|
|
|
|
2017-12-15 22:22:58 +00:00
|
|
|
auto &F = MBB->getParent()->getFunction();
|
|
|
|
auto *P = dyn_cast<Function>(F.getPersonalityFn()->stripPointerCasts());
|
2016-02-26 20:30:37 +00:00
|
|
|
assert(P && "Expected personality function");
|
|
|
|
|
2015-07-14 19:22:51 +00:00
|
|
|
// If we are forced to emit this personality, make sure to record
|
|
|
|
// it because it might not appear in any landingpad
|
|
|
|
if (forceEmitPersonality)
|
2016-02-26 20:30:37 +00:00
|
|
|
MMI->addPersonality(P);
|
2015-07-14 19:22:51 +00:00
|
|
|
|
2016-02-26 20:30:37 +00:00
|
|
|
const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering();
|
|
|
|
unsigned PerEncoding = TLOF.getPersonalityEncoding();
|
2016-09-16 07:33:15 +00:00
|
|
|
const MCSymbol *Sym = TLOF.getCFIPersonalitySymbol(P, Asm->TM, MMI);
|
2020-02-13 21:58:16 -08:00
|
|
|
Asm->OutStreamer->emitCFIPersonality(Sym, PerEncoding);
|
2011-04-29 14:48:51 +00:00
|
|
|
|
|
|
|
// Provide LSDA information.
|
2016-02-26 20:30:37 +00:00
|
|
|
if (shouldEmitLSDA)
|
2020-02-13 21:58:16 -08:00
|
|
|
Asm->OutStreamer->emitCFILsda(ESP(Asm), TLOF.getLSDAEncoding());
|
2011-01-14 21:57:53 +00:00
|
|
|
}
|
|
|
|
|
2013-11-26 13:34:55 +00:00
|
|
|
/// endFunction - Gather and emit post-function exception information.
|
2011-01-14 21:57:53 +00:00
|
|
|
///
|
2016-12-01 19:32:15 +00:00
|
|
|
void DwarfCFIException::endFunction(const MachineFunction *MF) {
|
2012-01-17 04:19:20 +00:00
|
|
|
if (!shouldEmitPersonality)
|
|
|
|
return;
|
|
|
|
|
2014-06-11 01:19:03 +00:00
|
|
|
emitExceptionTable();
|
2011-01-14 21:57:53 +00:00
|
|
|
}
|
Call Frame Information (CFI) Handling for Basic Block Sections
This patch handles CFI with basic block sections, which unlike DebugInfo does
not support ranges. The DWARF standard explicitly requires emitting separate
CFI Frame Descriptor Entries for each contiguous fragment of a function. Thus,
the CFI information for all callee-saved registers (possibly including the
frame pointer, if necessary) have to be emitted along with redefining the
Call Frame Address (CFA), viz. where the current frame starts.
CFI directives are emitted in FDE’s in the object file with a low_pc, high_pc
specification. So, a single FDE must point to a contiguous code region unlike
debug info which has the support for ranges. This is what complicates CFI for
basic block sections.
Now, what happens when we start placing individual basic blocks in unique
sections:
* Basic block sections allow the linker to randomly reorder basic blocks in the
address space such that a given basic block can become non-contiguous with the
original function.
* The different basic block sections can no longer share the cfi_startproc and
cfi_endproc directives. So, each basic block section should emit this
independently.
* Each (cfi_startproc, cfi_endproc) directive will result in a new FDE that
caters to that basic block section.
* Now, this basic block section needs to duplicate the information from the
entry block to compute the CFA as it is an independent entity. It cannot refer
to the FDE of the original function and hence must duplicate all the stuff that
is needed to compute the CFA on its own.
* We are working on a de-duplication patch that can share common information in
FDEs in a CIE (Common Information Entry) and we will present this as a follow up
patch. This can significantly reduce the duplication overhead and is
particularly useful when several basic block sections are created.
* The CFI directives are emitted similarly for registers that are pushed onto
the stack, like callee saved registers in the prologue. There are cfi
directives that emit how to retrieve the value of the register at that point
when the push happened. This has to be duplicated too in a basic block that is
floated as a separate section.
Differential Revision: https://reviews.llvm.org/D79978
2020-07-14 11:55:41 -07:00
|
|
|
|
|
|
|
void DwarfCFIException::beginBasicBlock(const MachineBasicBlock &MBB) {
|
|
|
|
beginFragment(&MBB, getExceptionSym);
|
|
|
|
}
|
|
|
|
|
|
|
|
void DwarfCFIException::endBasicBlock(const MachineBasicBlock &MBB) {
|
|
|
|
if (shouldEmitCFI)
|
|
|
|
Asm->OutStreamer->emitCFIEndProc();
|
|
|
|
}
|