672 lines
22 KiB
C++
Raw Normal View History

//===---*- mode: c++; indent-tabs-mode: nil; c-basic-offset: 2 -*---------===//
//===-- CodeGen/AsmPrinter/MonoException.cpp - Dwarf Exception Impl ------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains code to emit Mono specific exception handling tables.
// It is based on code in DwarfException.cpp and MCDwarf.cpp.
//
//===----------------------------------------------------------------------===//
#include "MonoException.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Constants.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/TargetFrameLowering.h"
#include "llvm/CodeGen/TargetLoweringObjectFile.h"
#include "llvm/CodeGen/TargetRegisterInfo.h"
#include "llvm/CodeGen/TargetSubtargetInfo.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/MCSymbolELF.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/Twine.h"
using namespace llvm;
//
// The EH tables emitted by this class enable the following functionality:
// - obtaining the GNU EH information for a given method
// - obtaining the DWARF CFI unwind info for a given method
// - obtaining the address of the table itself from user
// code, ie. it is in the text segment pointed to by
// a symbol.
//
cl::opt<std::string> MonoEHFrameSymbol("mono-eh-frame-symbol", cl::NotHidden,
cl::desc("Symbol name for the mono eh frame"));
// Emit a CFI instruction in DWARF format
static void
emitCFIInstruction(MCStreamer &Streamer,
const MCCFIInstruction &Instr,
int &CFAOffset, int DataAlignmentFactor)
{
// Same as MCDwarf::EmitCFIInstruction ()
// FIXME: Unify
int dataAlignmentFactor = DataAlignmentFactor;
bool VerboseAsm = Streamer.isVerboseAsm();
switch (Instr.getOperation()) {
case MCCFIInstruction::OpWindowSave: {
Streamer.EmitIntValue(dwarf::DW_CFA_GNU_window_save, 1);
return;
}
case MCCFIInstruction::OpUndefined: {
unsigned Reg = Instr.getRegister();
if (VerboseAsm) {
Streamer.AddComment("DW_CFA_undefined");
Streamer.AddComment(Twine("Reg ") + Twine(Reg));
}
Streamer.EmitIntValue(dwarf::DW_CFA_undefined, 1);
Streamer.EmitULEB128IntValue(Reg);
return;
}
case MCCFIInstruction::OpAdjustCfaOffset:
case MCCFIInstruction::OpDefCfaOffset: {
const bool IsRelative =
Instr.getOperation() == MCCFIInstruction::OpAdjustCfaOffset;
if (VerboseAsm)
Streamer.AddComment("DW_CFA_def_cfa_offset");
Streamer.EmitIntValue(dwarf::DW_CFA_def_cfa_offset, 1);
if (IsRelative) {
CFAOffset += Instr.getOffset();
} else {
// The backends pass in a negative value,
// then createDefCfaOffset () negates it
CFAOffset = Instr.getOffset();
assert(CFAOffset >= 0);
}
if (VerboseAsm)
Streamer.AddComment(Twine("Offset " + Twine(CFAOffset)));
Streamer.EmitULEB128IntValue(CFAOffset);
return;
}
case MCCFIInstruction::OpDefCfa: {
if (VerboseAsm)
Streamer.AddComment("DW_CFA_def_cfa");
Streamer.EmitIntValue(dwarf::DW_CFA_def_cfa, 1);
if (VerboseAsm)
Streamer.AddComment(Twine("Reg ") + Twine(Instr.getRegister()));
Streamer.EmitULEB128IntValue(Instr.getRegister());
// The backends pass in a negative value,
// then createDefCfaOffset () negates it
CFAOffset = Instr.getOffset();
if (CFAOffset < 0) {
outs () << CFAOffset << "\n";
LLVM_BUILTIN_TRAP;
}
assert(CFAOffset >= 0);
if (VerboseAsm)
Streamer.AddComment(Twine("Offset " + Twine(CFAOffset)));
Streamer.EmitULEB128IntValue(CFAOffset);
return;
}
case MCCFIInstruction::OpDefCfaRegister: {
if (VerboseAsm)
Streamer.AddComment("DW_CFA_def_cfa_register");
Streamer.EmitIntValue(dwarf::DW_CFA_def_cfa_register, 1);
if (VerboseAsm)
Streamer.AddComment(Twine("Reg ") + Twine(Instr.getRegister()));
Streamer.EmitULEB128IntValue(Instr.getRegister());
return;
}
case MCCFIInstruction::OpOffset:
case MCCFIInstruction::OpRelOffset: {
const bool IsRelative =
Instr.getOperation() == MCCFIInstruction::OpRelOffset;
unsigned Reg = Instr.getRegister();
int Offset = Instr.getOffset();
if (IsRelative)
Offset -= CFAOffset;
Offset = Offset / dataAlignmentFactor;
if (Offset < 0) {
if (VerboseAsm) Streamer.AddComment("DW_CFA_offset_extended_sf");
Streamer.EmitIntValue(dwarf::DW_CFA_offset_extended_sf, 1);
if (VerboseAsm) Streamer.AddComment(Twine("Reg ") + Twine(Reg));
Streamer.EmitULEB128IntValue(Reg);
if (VerboseAsm) Streamer.AddComment(Twine("Offset ") + Twine(Offset));
Streamer.EmitSLEB128IntValue(Offset);
} else if (Reg < 64) {
if (VerboseAsm) Streamer.AddComment(Twine("DW_CFA_offset + Reg(") +
Twine(Reg) + ")");
Streamer.EmitIntValue(dwarf::DW_CFA_offset + Reg, 1);
if (VerboseAsm) Streamer.AddComment(Twine("Offset ") + Twine(Offset));
Streamer.EmitULEB128IntValue(Offset);
} else {
if (VerboseAsm) Streamer.AddComment("DW_CFA_offset_extended");
Streamer.EmitIntValue(dwarf::DW_CFA_offset_extended, 1);
if (VerboseAsm) Streamer.AddComment(Twine("Reg ") + Twine(Reg));
Streamer.EmitULEB128IntValue(Reg);
if (VerboseAsm) Streamer.AddComment(Twine("Offset ") + Twine(Offset));
Streamer.EmitULEB128IntValue(Offset);
}
return;
}
case MCCFIInstruction::OpRememberState:
if (VerboseAsm) Streamer.AddComment("DW_CFA_remember_state");
Streamer.EmitIntValue(dwarf::DW_CFA_remember_state, 1);
return;
case MCCFIInstruction::OpRestoreState:
if (VerboseAsm) Streamer.AddComment("DW_CFA_restore_state");
Streamer.EmitIntValue(dwarf::DW_CFA_restore_state, 1);
return;
case MCCFIInstruction::OpSameValue: {
unsigned Reg = Instr.getRegister();
if (VerboseAsm) Streamer.AddComment("DW_CFA_same_value");
Streamer.EmitIntValue(dwarf::DW_CFA_same_value, 1);
if (VerboseAsm) Streamer.AddComment(Twine("Reg ") + Twine(Reg));
Streamer.EmitULEB128IntValue(Reg);
return;
}
case MCCFIInstruction::OpRestore: {
unsigned Reg = Instr.getRegister();
if (VerboseAsm) {
Streamer.AddComment("DW_CFA_restore");
Streamer.AddComment(Twine("Reg ") + Twine(Reg));
}
Streamer.EmitIntValue(dwarf::DW_CFA_restore | Reg, 1);
return;
}
case MCCFIInstruction::OpEscape:
if (VerboseAsm) Streamer.AddComment("Escape bytes");
Streamer.EmitBytes(Instr.getValues());
return;
case MCCFIInstruction::OpRegister:
case MCCFIInstruction::OpGnuArgsSize:
llvm_unreachable("Unhandled case in switch");
return;
}
llvm_unreachable("Unhandled case in switch");
}
// Emit a list of CFI instructions
static void
emitCFIInstructions(MCStreamer &streamer,
const std::vector<MCCFIInstruction> &Instrs,
MCSymbol *BaseLabel,
const std::vector<MCSymbol*> *Labels,
int &CFAOffset,
int DataAlignmentFactor)
{
for (unsigned i = 0, N = Instrs.size(); i < N; ++i) {
const MCCFIInstruction &Instr = Instrs[i];
MCSymbol *Label = Labels ? ((*Labels)[i]) : NULL;
// Advance row if new location.
if (BaseLabel && Label) {
MCSymbol *ThisSym = Label;
if (ThisSym != BaseLabel) {
streamer.AddComment ("cfa_advance");
streamer.EmitDwarfAdvanceFrameAddr(BaseLabel, ThisSym);
BaseLabel = ThisSym;
}
}
emitCFIInstruction(streamer, Instr, CFAOffset, DataAlignmentFactor);
}
}
MonoException::MonoException(AsmPrinter *A, bool disableGNUEH)
: EHStreamer(A)
{
RI = nullptr;
DisableGNUEH = disableGNUEH;
}
MonoException::~MonoException()
{
}
void
MonoException::beginFunction(const MachineFunction *MF)
{
EmitFnStart();
EHLabels.clear();
}
void
MonoException::PrepareMonoLSDA(EHInfo *info)
{
const MachineFunction *MF = Asm->MF;
const std::vector<const GlobalValue *> &TypeInfos = MF->getTypeInfos();
const std::vector<LandingPadInfo> &PadInfos = MF->getLandingPads();
// Sort the landing pads in order of their type ids. This is used to fold
// duplicate actions.
SmallVector<const LandingPadInfo *, 64> LandingPads;
LandingPads.reserve(PadInfos.size());
for (unsigned i = 0, N = PadInfos.size(); i != N; ++i)
LandingPads.push_back(&PadInfos[i]);
std::sort(LandingPads.begin(), LandingPads.end(),
[](const LandingPadInfo *L,
const LandingPadInfo *R) { return L->TypeIds < R->TypeIds; });
// Invokes and nounwind calls have entries in PadMap (due to being bracketed
// by try-range labels when lowered). Ordinary calls do not, so appropriate
// try-ranges for them need be deduced when using DWARF exception handling.
RangeMapType PadMap;
for (unsigned i = 0, N = LandingPads.size(); i != N; ++i) {
const LandingPadInfo *LandingPad = LandingPads[i];
for (unsigned j = 0, E = LandingPad->BeginLabels.size(); j != E; ++j) {
MCSymbol *BeginLabel = LandingPad->BeginLabels[j];
assert(!PadMap.count(BeginLabel) && "Duplicate landing pad labels!");
PadRange P = { i, j };
PadMap[BeginLabel] = P;
}
}
// Compute the call-site table.
SmallVector<MonoCallSiteEntry, 64> CallSites;
MCSymbol *LastLabel = 0;
for (MachineFunction::const_iterator I = MF->begin(), E = MF->end();
I != E; ++I) {
for (MachineBasicBlock::const_iterator MI = I->begin(), E = I->end();
MI != E; ++MI) {
if (!MI->isLabel()) {
continue;
}
MCSymbol *BeginLabel = MI->getOperand(0).getMCSymbol();
assert(BeginLabel && "Invalid label!");
RangeMapType::iterator L = PadMap.find(BeginLabel);
if (L == PadMap.end())
continue;
PadRange P = L->second;
const LandingPadInfo *LandingPad = LandingPads[P.PadIndex];
assert(BeginLabel == LandingPad->BeginLabels[P.RangeIndex] &&
"Inconsistent landing pad map!");
// Mono emits one landing pad for each CLR exception clause,
// and the type info contains the clause index
assert (LandingPad->TypeIds.size() == 1);
assert (LandingPad->LandingPadLabel);
LastLabel = LandingPad->EndLabels[P.RangeIndex];
MonoCallSiteEntry Site = {BeginLabel, LastLabel,
LandingPad->LandingPadLabel, LandingPad->TypeIds [0]};
assert(Site.BeginLabel && Site.EndLabel && Site.PadLabel &&
"Invalid landing pad!");
// FIXME: This doesn't work because it includes ranges outside clauses
#if 0
// Try to merge with the previous call-site.
if (CallSites.size()) {
MonoCallSiteEntry &Prev = CallSites.back();
if (Site.PadLabel == Prev.PadLabel && Site.TypeID == Prev.TypeID) {
// Extend the range of the previous entry.
Prev.EndLabel = Site.EndLabel;
continue;
}
}
#endif
// Otherwise, create a new call-site.
CallSites.push_back(Site);
}
}
info->CallSites.insert(info->CallSites.begin(), CallSites.begin(), CallSites.end());
info->TypeInfos = TypeInfos;
info->PadInfos = PadInfos;
int ThisSlot = Asm->MF->getMonoThisSlot();
if (ThisSlot != -1) {
unsigned FrameReg;
info->ThisOffset = Asm->MF->getTarget ().getSubtargetImpl (Asm->MF->getFunction())->getFrameLowering ()->getFrameIndexReference (*Asm->MF, ThisSlot, FrameReg);
info->FrameReg = Asm->MF->getTarget ().getSubtargetImpl (Asm->MF->getFunction())->getRegisterInfo ()->getDwarfRegNum (FrameReg, true);
} else {
info->FrameReg = -1;
}
}
void
MonoException::EmitFnStart(void)
{
if (DisableGNUEH && Asm->MAI->getExceptionHandlingType() == ExceptionHandling::ARM)
static_cast<ARMTargetStreamer*>(Asm->OutStreamer->getTargetStreamer())->emitFnStart();
}
void
MonoException::EmitFnEnd(void)
{
if (DisableGNUEH && Asm->MAI->getExceptionHandlingType() == ExceptionHandling::ARM)
static_cast<ARMTargetStreamer*>(Asm->OutStreamer->getTargetStreamer())->emitFnEnd();
}
void
MonoException::endFunction(const MachineFunction *MF)
{
//
// Compute a mapping from method names to their AOT method index
//
if (FuncIndexes.size () == 0) {
const Module *m = MMI->getModule ();
NamedMDNode *indexes = m->getNamedMetadata ("mono.function_indexes");
if (indexes) {
for (unsigned int i = 0; i < indexes->getNumOperands (); ++i) {
MDNode *n = indexes->getOperand (i);
MDString *s = cast<MDString>(n->getOperand (0));
auto *idx = mdconst::dyn_extract<ConstantInt>(n->getOperand (1));
FuncIndexes.insert (std::make_pair(s->getString (), (int)idx->getLimitedValue () + 1));
}
}
}
// Remember the register info
RI = MF->getSubtarget().getRegisterInfo();
MachineFunction *NonConstMF = const_cast<MachineFunction*>(MF);
NonConstMF->tidyLandingPads();
int monoMethodIdx = FuncIndexes.lookup (Asm->MF->getFunction ().getName ()) - 1;
if (monoMethodIdx == -1) {
EmitFnEnd ();
return;
}
//outs () << "D: " << Asm->MF->getFunction()->getName() << " " << monoMethodIdx << "\n";
// Save information for use by endModule ()
EHInfo info;
info.FunctionNumber = Asm->getFunctionNumber();
info.BeginSym = Asm->getFunctionBegin ();
info.EndSym = Asm->getFunctionEnd ();
info.EHLabels = EHLabels;
info.MonoMethodIdx = monoMethodIdx;
info.HasLandingPads = !MF->getLandingPads().empty();
info.Instructions = MF->getFrameInstructions();
assert (info.Instructions.size () == info.EHLabels.size());
if (DisableGNUEH)
/* ARMAsmPrinter generates references to this */
Asm->OutStreamer->EmitLabel(Asm->getCurExceptionSym());
PrepareMonoLSDA(&info);
Frames.push_back(info);
EHLabels.clear();
EmitFnEnd ();
}
/// EmitMonoLSDA - Mono's version of EmitExceptionTable
///
/// The code below is a modified/simplified version of DwarfException::EmitExceptionTable()
/// We emit the information inline instead of into a separate section.
///
void
MonoException::EmitMonoLSDA(const EHInfo *info)
{
// Load saved information from EHFrameInfo
const std::vector<const GlobalValue *> &TypeInfos = info->TypeInfos;
const std::vector<LandingPadInfo> &PadInfos = info->PadInfos;
const std::vector<MonoCallSiteEntry> CallSites = info->CallSites;
int FrameReg = info->FrameReg;
int ThisOffset = info->ThisOffset;
// Sort the landing pads in order of their type ids. This is used to fold
// duplicate actions.
SmallVector<const LandingPadInfo *, 64> LandingPads;
LandingPads.reserve(PadInfos.size());
for (unsigned i = 0, N = PadInfos.size(); i != N; ++i)
LandingPads.push_back(&PadInfos[i]);
std::sort(LandingPads.begin(), LandingPads.end(),
[](const LandingPadInfo *L,
const LandingPadInfo *R) { return L->TypeIds < R->TypeIds; });
// The type_info itself is emitted
int TTypeEncoding = dwarf::DW_EH_PE_udata4;
// Emit the LSDA.
// Keep this in sync with JITDwarfEmitter::EmitExceptionTable ()
Asm->EmitULEB128(0x4d4fef4f, "MONO Magic");
Asm->EmitULEB128(1, "Version");
// Emit the LSDA header.
if (FrameReg != -1) {
Asm->EmitEncodingByte(dwarf::DW_EH_PE_udata4, "This encoding");
// Emit 'this' location
Asm->OutStreamer->AddComment("bregx");
Asm->EmitInt8((int)dwarf::DW_OP_bregx);
Asm->EmitULEB128(FrameReg, "Base reg");
Asm->EmitSLEB128(ThisOffset, "Offset");
} else {
Asm->EmitEncodingByte(dwarf::DW_EH_PE_omit, "@This encoding");
}
Asm->EmitULEB128 (CallSites.size (), "Number of call sites");
Asm->EmitAlignment(2);
for (std::vector<MonoCallSiteEntry>::const_iterator
I = CallSites.begin(), E = CallSites.end(); I != E; ++I) {
const MonoCallSiteEntry &S = *I;
MCSymbol *EHFuncBeginSym = info->BeginSym;
MCSymbol *BeginLabel = S.BeginLabel;
if (BeginLabel == 0)
BeginLabel = EHFuncBeginSym;
MCSymbol *EndLabel = S.EndLabel;
if (EndLabel == 0)
EndLabel = info->EndSym;
Asm->OutStreamer->AddComment("Region start");
Asm->EmitLabelDifference(BeginLabel, EHFuncBeginSym, 4);
Asm->OutStreamer->AddComment("Region length");
Asm->EmitLabelDifference(EndLabel, BeginLabel, 4);
Asm->OutStreamer->AddComment("Landing pad");
if (!S.PadLabel)
Asm->OutStreamer->EmitIntValue(0, 4);
else
Asm->EmitLabelDifference(S.PadLabel, EHFuncBeginSym, 4);
unsigned int TypeID = S.TypeID;
assert (TypeID > 0 && TypeID <= TypeInfos.size ());
const GlobalVariable *GV = dyn_cast<GlobalVariable>(TypeInfos[TypeID - 1]);
assert (GV);
//
// Mono typeinfos are simple constant integers. Emit the constant itself.
//
assert(GV);
const ConstantInt *ci = dyn_cast<ConstantInt>(GV->getInitializer());
Asm->OutStreamer->AddComment("TypeInfo");
Asm->OutStreamer->EmitIntValue(ci->getZExtValue(),Asm->GetSizeOfEncodedValue(TTypeEncoding));
}
}
void
MonoException::endModule()
{
const TargetLoweringObjectFile &tlof = Asm->getObjFileLowering();
auto &streamer = *Asm->OutStreamer;
// Size and sign of stack growth.
int stackGrowth = -Asm->getDataLayout().getPointerSize();
int dataAlignmentFactor = stackGrowth;
// Emit the EH table
// Can't use rodata as the symbols we reference are in the text segment
streamer.SwitchSection(tlof.getTextSection());
MCSymbol *tableSymbol =
Asm->OutContext.getOrCreateSymbol(Twine(MonoEHFrameSymbol));
MCSymbol *tableEndSym = Asm->createTempSymbol ("mono_eh_frame_end");
// Symbol
Asm->EmitAlignment(4);
streamer.EmitLabel(tableSymbol);
streamer.EmitSymbolAttribute(tableSymbol, MCSA_ELF_TypeObject);
if (Asm->MAI->hasDotTypeDotSizeDirective()) {
const MCExpr *SizeExp = MCBinaryExpr::createSub(
MCSymbolRefExpr::create(tableEndSym, Asm->OutContext),
MCSymbolRefExpr::create(tableSymbol, Asm->OutContext), Asm->OutContext);
streamer.emitELFSize(cast<MCSymbolELF>(tableSymbol), SizeExp);
}
// Header
streamer.AddComment("version");
streamer.EmitIntValue(3, 1);
streamer.AddComment ("func addr encoding");
// Unused
streamer.EmitIntValue (0, 1);
// Search table
Asm->EmitAlignment(2);
streamer.AddComment("fde_count");
streamer.EmitIntValue (Frames.size(), 4);
MCSymbol *lastBegin = nullptr;
MCSymbol *lastEnd = nullptr;
for (std::vector<EHInfo>::iterator
I = Frames.begin(), E = Frames.end(); I != E; ++I) {
EHInfo &info = *I;
info.FDESym = Asm->createTempSymbol ("mono_fde");
streamer.AddComment("mono method idx");
streamer.EmitIntValue (info.MonoMethodIdx, 4);
Asm->EmitLabelDifference(info.FDESym, tableSymbol, 4);
lastBegin = info.BeginSym;
lastEnd = info.EndSym;
}
// Emit a last entry to simplify binary searches and to enable the computation of
// the size of the last function/FDE entry
if (Frames.size() == 0) {
streamer.EmitIntValue (-1, 4);
Asm->EmitLabelDifference(tableSymbol, tableSymbol, 4);
} else {
// Emit the size of the last function, since it cannot be computed using the next table entry
Asm->EmitLabelDifference(lastEnd, lastBegin, 4);
Asm->EmitLabelDifference(tableEndSym, tableSymbol, 4);
}
// CIE
// This comes right after the search table
Asm->EmitULEB128(1, "CIE Code Alignment Factor");
Asm->EmitSLEB128(stackGrowth, "CIE Data Alignment Factor");
streamer.AddComment("CIE Return Address Column");
// RI can be null if there are no methods
if (RI)
Asm->EmitInt8(RI->getDwarfRegNum(RI->getRARegister(), true));
Asm->EmitEncodingByte(dwarf::DW_EH_PE_omit, "Personality");
int cfaOffset = 0;
// Initial CIE program
emitCFIInstructions(streamer, streamer.getContext().getAsmInfo()->getInitialFrameState(), NULL, NULL, cfaOffset, stackGrowth);
streamer.AddComment("End of CIE program");
streamer.EmitIntValue(dwarf::DW_CFA_nop, 1);
int cieCfaOffset = cfaOffset;
// FDEs
streamer.AddBlankLine();
for (std::vector<EHInfo>::iterator
I = Frames.begin(), E = Frames.end(); I != E; ++I) {
const EHInfo &info = *I;
streamer.EmitLabel(info.FDESym);
// Emit augmentation
if (info.HasLandingPads || info.FrameReg != -1) {
// Need an extra has_augmentation field as the augmentation size is always encoded
// in 4 bytes
Asm->EmitULEB128(1, "Has augmentation");
MCSymbol *fdeBeginSym = Asm->OutContext.createTempSymbol("mono_fde_aug_begin", info.FunctionNumber);
MCSymbol *fdeEndSym = Asm->OutContext.createTempSymbol("mono_fde_aug_end", info.FunctionNumber);
streamer.AddComment("Augmentation size");
Asm->EmitLabelDifference(fdeEndSym, fdeBeginSym, 4);
streamer.EmitLabel(fdeBeginSym);
EmitMonoLSDA (&info);
streamer.EmitLabel(fdeEndSym);
} else {
Asm->EmitULEB128(0, "Has augmentation");
}
// Emit unwind info
cfaOffset = cieCfaOffset;
emitCFIInstructions(streamer, info.Instructions, info.BeginSym, &info.EHLabels, cfaOffset, dataAlignmentFactor);
streamer.AddBlankLine();
}
streamer.EmitLabel(tableEndSym);
Asm->EmitAlignment(3);
}
void
MonoException::beginInstruction(const MachineInstr *MI)
{
if (MI->getOpcode() == TargetOpcode::CFI_INSTRUCTION) {
unsigned CFIIndex = MI->getOperand(0).getCFIIndex();
//outs () << "D: " << CFIIndex << " " << EHLabels.size() << "\n";
/* Emit a label and save the label-cfi index association */
if (CFIIndex != EHLabels.size())
assert (0);
MCSymbol *Label = Asm->OutContext.createTempSymbol();
Asm->OutStreamer->EmitLabel(Label);
EHLabels.push_back(Label);
}
}