2010-04-05 03:09:29 +08:00
|
|
|
//===-- AsmPrinterDwarf.cpp - AsmPrinter Dwarf Support --------------------===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This file implements the Dwarf emissions parts of AsmPrinter.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2014-03-08 06:40:37 +08:00
|
|
|
#include "ByteStreamer.h"
|
2015-03-03 06:02:33 +08:00
|
|
|
#include "DwarfDebug.h"
|
2015-01-13 06:19:22 +08:00
|
|
|
#include "DwarfExpression.h"
|
2012-12-04 00:50:05 +08:00
|
|
|
#include "llvm/ADT/Twine.h"
|
2015-01-14 19:23:27 +08:00
|
|
|
#include "llvm/CodeGen/AsmPrinter.h"
|
2015-03-04 10:30:17 +08:00
|
|
|
#include "llvm/CodeGen/DIE.h"
|
2015-03-03 06:02:36 +08:00
|
|
|
#include "llvm/CodeGen/MachineFunction.h"
|
2015-02-20 07:29:42 +08:00
|
|
|
#include "llvm/CodeGen/MachineModuleInfo.h"
|
2013-01-02 19:36:10 +08:00
|
|
|
#include "llvm/IR/DataLayout.h"
|
2010-04-05 03:09:29 +08:00
|
|
|
#include "llvm/MC/MCAsmInfo.h"
|
2015-02-20 07:29:42 +08:00
|
|
|
#include "llvm/MC/MCRegisterInfo.h"
|
2010-04-05 07:25:33 +08:00
|
|
|
#include "llvm/MC/MCSection.h"
|
2010-04-05 03:09:29 +08:00
|
|
|
#include "llvm/MC/MCStreamer.h"
|
2010-04-05 07:25:33 +08:00
|
|
|
#include "llvm/MC/MCSymbol.h"
|
2012-12-04 00:50:05 +08:00
|
|
|
#include "llvm/MC/MachineLocation.h"
|
|
|
|
#include "llvm/Support/Dwarf.h"
|
|
|
|
#include "llvm/Support/ErrorHandling.h"
|
2010-04-05 04:20:50 +08:00
|
|
|
#include "llvm/Target/TargetLoweringObjectFile.h"
|
|
|
|
#include "llvm/Target/TargetMachine.h"
|
2015-03-03 06:02:33 +08:00
|
|
|
#include "llvm/Target/TargetSubtargetInfo.h"
|
2010-04-05 03:09:29 +08:00
|
|
|
using namespace llvm;
|
|
|
|
|
2014-04-22 10:02:50 +08:00
|
|
|
#define DEBUG_TYPE "asm-printer"
|
|
|
|
|
2010-04-05 07:41:46 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Dwarf Emission Helper Routines
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2010-04-05 03:09:29 +08:00
|
|
|
/// EmitSLEB128 - emit the specified signed leb128 value.
|
2013-06-24 02:31:11 +08:00
|
|
|
void AsmPrinter::EmitSLEB128(int64_t Value, const char *Desc) const {
|
2010-04-05 03:09:29 +08:00
|
|
|
if (isVerbose() && Desc)
|
2015-04-25 03:11:51 +08:00
|
|
|
OutStreamer->AddComment(Desc);
|
2010-04-05 03:09:29 +08:00
|
|
|
|
2015-04-25 03:11:51 +08:00
|
|
|
OutStreamer->EmitSLEB128IntValue(Value);
|
2010-04-05 03:09:29 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// EmitULEB128 - emit the specified signed leb128 value.
|
2013-06-24 02:31:11 +08:00
|
|
|
void AsmPrinter::EmitULEB128(uint64_t Value, const char *Desc,
|
2010-04-05 03:09:29 +08:00
|
|
|
unsigned PadTo) const {
|
|
|
|
if (isVerbose() && Desc)
|
2015-04-25 03:11:51 +08:00
|
|
|
OutStreamer->AddComment(Desc);
|
2010-11-05 02:17:08 +08:00
|
|
|
|
2015-04-25 03:11:51 +08:00
|
|
|
OutStreamer->EmitULEB128IntValue(Value, PadTo);
|
2010-04-05 03:09:29 +08:00
|
|
|
}
|
|
|
|
|
2010-04-05 04:01:25 +08:00
|
|
|
/// EmitCFAByte - Emit a .byte 42 directive for a DW_CFA_xxx value.
|
|
|
|
void AsmPrinter::EmitCFAByte(unsigned Val) const {
|
|
|
|
if (isVerbose()) {
|
2013-12-05 06:26:43 +08:00
|
|
|
if (Val >= dwarf::DW_CFA_offset && Val < dwarf::DW_CFA_offset + 64)
|
2015-04-25 03:11:51 +08:00
|
|
|
OutStreamer->AddComment("DW_CFA_offset + Reg (" +
|
|
|
|
Twine(Val - dwarf::DW_CFA_offset) + ")");
|
2010-04-05 04:01:25 +08:00
|
|
|
else
|
2015-04-25 03:11:51 +08:00
|
|
|
OutStreamer->AddComment(dwarf::CallFrameString(Val));
|
2010-04-05 04:01:25 +08:00
|
|
|
}
|
2015-04-25 03:11:51 +08:00
|
|
|
OutStreamer->EmitIntValue(Val, 1);
|
2010-04-05 04:01:25 +08:00
|
|
|
}
|
|
|
|
|
2010-04-05 04:04:21 +08:00
|
|
|
static const char *DecodeDWARFEncoding(unsigned Encoding) {
|
|
|
|
switch (Encoding) {
|
2013-12-05 06:26:43 +08:00
|
|
|
case dwarf::DW_EH_PE_absptr:
|
|
|
|
return "absptr";
|
|
|
|
case dwarf::DW_EH_PE_omit:
|
|
|
|
return "omit";
|
|
|
|
case dwarf::DW_EH_PE_pcrel:
|
|
|
|
return "pcrel";
|
|
|
|
case dwarf::DW_EH_PE_udata4:
|
|
|
|
return "udata4";
|
|
|
|
case dwarf::DW_EH_PE_udata8:
|
|
|
|
return "udata8";
|
|
|
|
case dwarf::DW_EH_PE_sdata4:
|
|
|
|
return "sdata4";
|
|
|
|
case dwarf::DW_EH_PE_sdata8:
|
|
|
|
return "sdata8";
|
|
|
|
case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata4:
|
|
|
|
return "pcrel udata4";
|
|
|
|
case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4:
|
|
|
|
return "pcrel sdata4";
|
|
|
|
case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata8:
|
|
|
|
return "pcrel udata8";
|
|
|
|
case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata8:
|
|
|
|
return "pcrel sdata8";
|
|
|
|
case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata4
|
|
|
|
:
|
2010-04-05 04:04:21 +08:00
|
|
|
return "indirect pcrel udata4";
|
2013-12-05 06:26:43 +08:00
|
|
|
case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4
|
|
|
|
:
|
2010-04-05 04:04:21 +08:00
|
|
|
return "indirect pcrel sdata4";
|
2013-12-05 06:26:43 +08:00
|
|
|
case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata8
|
|
|
|
:
|
2010-04-05 04:04:21 +08:00
|
|
|
return "indirect pcrel udata8";
|
2013-12-05 06:26:43 +08:00
|
|
|
case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata8
|
|
|
|
:
|
2010-04-05 04:04:21 +08:00
|
|
|
return "indirect pcrel sdata8";
|
|
|
|
}
|
2012-11-21 04:34:47 +08:00
|
|
|
|
2010-04-05 04:04:21 +08:00
|
|
|
return "<unknown encoding>";
|
|
|
|
}
|
|
|
|
|
|
|
|
/// EmitEncodingByte - Emit a .byte 42 directive that corresponds to an
|
|
|
|
/// encoding. If verbose assembly output is enabled, we output comments
|
|
|
|
/// describing the encoding. Desc is an optional string saying what the
|
|
|
|
/// encoding is specifying (e.g. "LSDA").
|
2010-04-05 07:41:46 +08:00
|
|
|
void AsmPrinter::EmitEncodingByte(unsigned Val, const char *Desc) const {
|
2010-04-05 04:04:21 +08:00
|
|
|
if (isVerbose()) {
|
2013-12-05 06:29:02 +08:00
|
|
|
if (Desc)
|
2015-04-25 03:11:51 +08:00
|
|
|
OutStreamer->AddComment(Twine(Desc) + " Encoding = " +
|
|
|
|
Twine(DecodeDWARFEncoding(Val)));
|
2010-04-05 04:04:21 +08:00
|
|
|
else
|
2015-04-25 03:11:51 +08:00
|
|
|
OutStreamer->AddComment(Twine("Encoding = ") + DecodeDWARFEncoding(Val));
|
2010-04-05 04:04:21 +08:00
|
|
|
}
|
2012-11-21 04:34:47 +08:00
|
|
|
|
2015-04-25 03:11:51 +08:00
|
|
|
OutStreamer->EmitIntValue(Val, 1);
|
2010-04-05 04:04:21 +08:00
|
|
|
}
|
|
|
|
|
2010-04-05 04:20:50 +08:00
|
|
|
/// GetSizeOfEncodedValue - Return the size of the encoding in bytes.
|
|
|
|
unsigned AsmPrinter::GetSizeOfEncodedValue(unsigned Encoding) const {
|
|
|
|
if (Encoding == dwarf::DW_EH_PE_omit)
|
|
|
|
return 0;
|
2012-11-21 04:34:47 +08:00
|
|
|
|
2010-04-05 04:20:50 +08:00
|
|
|
switch (Encoding & 0x07) {
|
2013-12-05 06:26:43 +08:00
|
|
|
default:
|
|
|
|
llvm_unreachable("Invalid encoded value.");
|
|
|
|
case dwarf::DW_EH_PE_absptr:
|
2015-01-27 03:03:15 +08:00
|
|
|
return TM.getDataLayout()->getPointerSize();
|
2013-12-05 06:26:43 +08:00
|
|
|
case dwarf::DW_EH_PE_udata2:
|
|
|
|
return 2;
|
|
|
|
case dwarf::DW_EH_PE_udata4:
|
|
|
|
return 4;
|
|
|
|
case dwarf::DW_EH_PE_udata8:
|
|
|
|
return 8;
|
2010-04-05 04:20:50 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-11-21 04:34:47 +08:00
|
|
|
void AsmPrinter::EmitTTypeReference(const GlobalValue *GV,
|
|
|
|
unsigned Encoding) const {
|
2012-11-20 05:17:20 +08:00
|
|
|
if (GV) {
|
|
|
|
const TargetLoweringObjectFile &TLOF = getObjFileLowering();
|
2012-11-21 04:34:47 +08:00
|
|
|
|
2012-11-20 05:17:20 +08:00
|
|
|
const MCExpr *Exp =
|
2015-04-25 03:11:51 +08:00
|
|
|
TLOF.getTTypeGlobalReference(GV, Encoding, *Mang, TM, MMI,
|
|
|
|
*OutStreamer);
|
|
|
|
OutStreamer->EmitValue(Exp, GetSizeOfEncodedValue(Encoding));
|
2012-11-20 05:17:20 +08:00
|
|
|
} else
|
2015-04-25 03:11:51 +08:00
|
|
|
OutStreamer->EmitIntValue(0, GetSizeOfEncodedValue(Encoding));
|
2010-04-05 04:20:50 +08:00
|
|
|
}
|
2010-04-05 07:25:33 +08:00
|
|
|
|
2015-06-17 07:22:02 +08:00
|
|
|
void AsmPrinter::emitDwarfSymbolReference(const MCSymbol *Label,
|
|
|
|
bool ForceOffset) const {
|
|
|
|
if (!ForceOffset) {
|
|
|
|
// On COFF targets, we have to emit the special .secrel32 directive.
|
|
|
|
if (MAI->needsDwarfSectionOffsetDirective()) {
|
|
|
|
OutStreamer->EmitCOFFSecRel32(Label);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If the format uses relocations with dwarf, refer to the symbol directly.
|
|
|
|
if (MAI->doesDwarfUseRelocationsAcrossSections()) {
|
|
|
|
OutStreamer->EmitSymbolValue(Label, 4);
|
|
|
|
return;
|
|
|
|
}
|
2011-03-12 21:07:37 +08:00
|
|
|
}
|
2012-11-21 04:34:47 +08:00
|
|
|
|
2010-04-05 07:25:33 +08:00
|
|
|
// Otherwise, emit it as a label difference from the start of the section.
|
2015-03-11 00:58:10 +08:00
|
|
|
EmitLabelDifference(Label, Label->getSection().getBeginSymbol(), 4);
|
2010-04-05 07:25:33 +08:00
|
|
|
}
|
2014-03-07 09:44:14 +08:00
|
|
|
|
2015-05-25 00:48:54 +08:00
|
|
|
void AsmPrinter::emitDwarfStringOffset(DwarfStringPoolEntryRef S) const {
|
|
|
|
if (MAI->doesDwarfUseRelocationsAcrossSections()) {
|
2015-06-17 07:22:02 +08:00
|
|
|
emitDwarfSymbolReference(S.getSymbol());
|
2015-05-25 00:48:54 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Just emit the offset directly; no need for symbol math.
|
|
|
|
EmitInt32(S.getOffset());
|
|
|
|
}
|
|
|
|
|
2014-03-07 09:44:14 +08:00
|
|
|
/// EmitDwarfRegOp - Emit dwarf register operation.
|
2014-03-08 06:40:37 +08:00
|
|
|
void AsmPrinter::EmitDwarfRegOp(ByteStreamer &Streamer,
|
2015-01-20 01:57:29 +08:00
|
|
|
const MachineLocation &MLoc) const {
|
2015-03-03 06:02:36 +08:00
|
|
|
DebugLocDwarfExpression Expr(*MF->getSubtarget().getRegisterInfo(),
|
2015-05-21 06:37:48 +08:00
|
|
|
getDwarfDebug()->getDwarfVersion(), Streamer);
|
2015-02-20 07:29:42 +08:00
|
|
|
const MCRegisterInfo *MRI = MMI->getContext().getRegisterInfo();
|
|
|
|
int Reg = MRI->getDwarfRegNum(MLoc.getReg(), false);
|
2014-03-07 09:44:14 +08:00
|
|
|
if (Reg < 0) {
|
|
|
|
// We assume that pointers are always in an addressable register.
|
2015-01-20 01:57:29 +08:00
|
|
|
if (MLoc.isIndirect())
|
2014-03-07 09:44:14 +08:00
|
|
|
// FIXME: We have no reasonable way of handling errors in here. The
|
|
|
|
// caller might be in the middle of a dwarf expression. We should
|
|
|
|
// probably assert that Reg >= 0 once debug info generation is more
|
|
|
|
// mature.
|
2015-01-13 07:03:23 +08:00
|
|
|
return Expr.EmitOp(dwarf::DW_OP_nop,
|
|
|
|
"nop (could not find a dwarf register number)");
|
2014-03-07 09:44:14 +08:00
|
|
|
|
|
|
|
// Attempt to find a valid super- or sub-register.
|
2015-01-14 09:01:28 +08:00
|
|
|
if (!Expr.AddMachineRegPiece(MLoc.getReg()))
|
|
|
|
Expr.EmitOp(dwarf::DW_OP_nop,
|
|
|
|
"nop (could not find a dwarf register number)");
|
|
|
|
return;
|
2014-03-07 09:44:14 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (MLoc.isIndirect())
|
2015-01-20 01:57:29 +08:00
|
|
|
Expr.AddRegIndirect(Reg, MLoc.getOffset());
|
2014-03-07 09:44:14 +08:00
|
|
|
else
|
2015-01-13 06:19:22 +08:00
|
|
|
Expr.AddReg(Reg);
|
2014-03-07 09:44:14 +08:00
|
|
|
}
|
2010-04-05 07:25:33 +08:00
|
|
|
|
2010-04-05 07:41:46 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Dwarf Lowering Routines
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2013-05-13 09:16:13 +08:00
|
|
|
void AsmPrinter::emitCFIInstruction(const MCCFIInstruction &Inst) const {
|
|
|
|
switch (Inst.getOperation()) {
|
|
|
|
default:
|
|
|
|
llvm_unreachable("Unexpected instruction");
|
|
|
|
case MCCFIInstruction::OpDefCfaOffset:
|
2015-04-25 03:11:51 +08:00
|
|
|
OutStreamer->EmitCFIDefCfaOffset(Inst.getOffset());
|
2013-05-13 09:16:13 +08:00
|
|
|
break;
|
|
|
|
case MCCFIInstruction::OpDefCfa:
|
2015-04-25 03:11:51 +08:00
|
|
|
OutStreamer->EmitCFIDefCfa(Inst.getRegister(), Inst.getOffset());
|
2013-05-13 09:16:13 +08:00
|
|
|
break;
|
|
|
|
case MCCFIInstruction::OpDefCfaRegister:
|
2015-04-25 03:11:51 +08:00
|
|
|
OutStreamer->EmitCFIDefCfaRegister(Inst.getRegister());
|
2013-05-13 09:16:13 +08:00
|
|
|
break;
|
|
|
|
case MCCFIInstruction::OpOffset:
|
2015-04-25 03:11:51 +08:00
|
|
|
OutStreamer->EmitCFIOffset(Inst.getRegister(), Inst.getOffset());
|
2013-05-13 09:16:13 +08:00
|
|
|
break;
|
2013-09-26 23:11:00 +08:00
|
|
|
case MCCFIInstruction::OpRegister:
|
2015-04-25 03:11:51 +08:00
|
|
|
OutStreamer->EmitCFIRegister(Inst.getRegister(), Inst.getRegister2());
|
2013-09-26 23:11:00 +08:00
|
|
|
break;
|
2013-09-26 22:49:40 +08:00
|
|
|
case MCCFIInstruction::OpWindowSave:
|
2015-04-25 03:11:51 +08:00
|
|
|
OutStreamer->EmitCFIWindowSave();
|
2013-09-26 22:49:40 +08:00
|
|
|
break;
|
2014-04-03 00:10:33 +08:00
|
|
|
case MCCFIInstruction::OpSameValue:
|
2015-04-25 03:11:51 +08:00
|
|
|
OutStreamer->EmitCFISameValue(Inst.getRegister());
|
2014-04-03 00:10:33 +08:00
|
|
|
break;
|
2011-04-16 04:32:03 +08:00
|
|
|
}
|
|
|
|
}
|
2015-03-04 10:30:17 +08:00
|
|
|
|
|
|
|
void AsmPrinter::emitDwarfDIE(const DIE &Die) const {
|
|
|
|
// Emit the code (index) for the abbreviation.
|
|
|
|
if (isVerbose())
|
2015-05-28 06:31:41 +08:00
|
|
|
OutStreamer->AddComment("Abbrev [" + Twine(Die.getAbbrevNumber()) + "] 0x" +
|
|
|
|
Twine::utohexstr(Die.getOffset()) + ":0x" +
|
|
|
|
Twine::utohexstr(Die.getSize()) + " " +
|
|
|
|
dwarf::TagString(Die.getTag()));
|
|
|
|
EmitULEB128(Die.getAbbrevNumber());
|
2015-03-04 10:30:17 +08:00
|
|
|
|
|
|
|
// Emit the DIE attribute values.
|
2015-05-28 06:44:06 +08:00
|
|
|
for (const auto &V : Die.values()) {
|
|
|
|
dwarf::Attribute Attr = V.getAttribute();
|
|
|
|
dwarf::Form Form = V.getForm();
|
2015-03-04 10:30:17 +08:00
|
|
|
assert(Form && "Too many attributes for DIE (check abbreviation)");
|
|
|
|
|
|
|
|
if (isVerbose()) {
|
2015-04-25 03:11:51 +08:00
|
|
|
OutStreamer->AddComment(dwarf::AttributeString(Attr));
|
2015-03-04 10:30:17 +08:00
|
|
|
if (Attr == dwarf::DW_AT_accessibility)
|
Reapply "AsmPrinter: Change DIEValue to be stored by value"
This reverts commit r238350, effectively reapplying r238349 after fixing
(all?) the problems, all somehow related to how I was using
`AlignedArrayCharUnion<>` inside `DIEValue`:
- MSVC can only handle `sizeof()` on types, not values. Change the
assert.
- GCC doesn't know the `is_trivially_copyable` type trait. Instead of
asserting it, add destructors.
- Call placement new even when constructing POD (i.e., the pointers).
- Instead of copying the char buffer, copy the casted classes.
I've left in a couple of `static_assert`s that I think both MSVC and GCC
know how to handle. If the bots disagree with me, I'll remove them.
- Check that the constructed type is either standard layout or a
pointer. This protects against a programming error: we really want
the "small" `DIEValue`s to be small and simple, so don't
accidentally change them not to be.
- Similarly, check that the size of the buffer is no bigger than a
`uint64_t` or a pointer. (I thought checking against
`sizeof(uint64_t)` would be good enough, but Chandler suggested that
pointers might sometimes be bigger than that in the context of
sanitizers.)
I've also committed r238359 in the meantime, which introduces a
DIEValue.def to simplify dispatching between the various types (thanks
to a review comment by David Blaikie). Without that, this commit would
be almost unintelligible.
Here's the original commit message:
--
Change `DIEValue` to be stored/passed/etc. by value, instead of
reference. It's now a discriminated union, with a `Val` field storing
the actual type. The classes that used to inherit from `DIEValue` no
longer do. There are two categories of these:
- Small values fit in a single pointer and are stored by value.
- Large values require auxiliary storage, and are stored by reference.
The only non-mechanical change is to tools/dsymutil/DwarfLinker.cpp. It
was relying on `DIEInteger`s being passed around by reference, so I
replaced that assumption with a `PatchLocation` type that stores a safe
reference to where the `DIEInteger` lives instead.
This commit causes a temporary regression in memory usage, since I've
left merging `DIEAbbrevData` into `DIEValue` for a follow-up commit. I
measured an increase from 845 MB to 879 MB, around 3.9%. The follow-up
drops it lower than the starting point, and I've only recently brought
the memory this low anyway, so I'm committing these changes separately
to keep them incremental. (I also considered swapping the commits, but
the other one first would cause a lot more code churn.)
(I'm looking at `llc` memory usage on `verify-uselistorder.lto.opt.bc`;
see r236629 for details.)
--
llvm-svn: 238362
2015-05-28 06:14:58 +08:00
|
|
|
OutStreamer->AddComment(
|
2015-05-28 06:44:06 +08:00
|
|
|
dwarf::AccessibilityString(V.getDIEInteger().getValue()));
|
2015-03-04 10:30:17 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Emit an attribute using the defined form.
|
2015-05-28 06:44:06 +08:00
|
|
|
V.EmitValue(this, Form);
|
2015-03-04 10:30:17 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Emit the DIE children if any.
|
2015-05-28 06:31:41 +08:00
|
|
|
if (Die.hasChildren()) {
|
2015-05-29 03:56:34 +08:00
|
|
|
for (auto &Child : Die.children())
|
2015-03-04 10:30:17 +08:00
|
|
|
emitDwarfDIE(*Child);
|
|
|
|
|
2015-04-25 03:11:51 +08:00
|
|
|
OutStreamer->AddComment("End Of Children Mark");
|
2015-03-04 10:30:17 +08:00
|
|
|
EmitInt8(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
AsmPrinter::emitDwarfAbbrevs(const std::vector<DIEAbbrev *>& Abbrevs) const {
|
|
|
|
// For each abbrevation.
|
|
|
|
for (const DIEAbbrev *Abbrev : Abbrevs) {
|
|
|
|
// Emit the abbrevations code (base 1 index.)
|
|
|
|
EmitULEB128(Abbrev->getNumber(), "Abbreviation Code");
|
|
|
|
|
|
|
|
// Emit the abbreviations data.
|
|
|
|
Abbrev->Emit(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Mark end of abbreviations.
|
|
|
|
EmitULEB128(0, "EOM(3)");
|
|
|
|
}
|