summaryrefslogtreecommitdiffstats
path: root/llvm/lib/CodeGen
diff options
context:
space:
mode:
authorGreg Clayton <gclayton@apple.com>2016-12-08 01:03:48 +0000
committerGreg Clayton <gclayton@apple.com>2016-12-08 01:03:48 +0000
commit3462a420d1e6c9d28f920c0aadef280a076f5747 (patch)
tree3dcef20d4facfaab07fb63bb7c145bb116d882b0 /llvm/lib/CodeGen
parent7fb5e3434b157a159b15d642a677f8531c91c98d (diff)
downloadbcm5719-llvm-3462a420d1e6c9d28f920c0aadef280a076f5747.tar.gz
bcm5719-llvm-3462a420d1e6c9d28f920c0aadef280a076f5747.zip
Make a DWARF generator so we can unit test DWARF APIs with gtest.
The only tests we have for the DWARF parser are the tests that use llvm-dwarfdump and expect output from textual dumps. More DWARF parser modification are coming in the next few weeks and I wanted to add tests that can verify that we can encode and decode all form types, as well as test some other basic DWARF APIs where we ask DIE objects for their children and siblings. DwarfGenerator.cpp was added in the lib/CodeGen directory. This file contains the code necessary to easily create DWARF for tests: dwarfgen::Generator DG; Triple Triple("x86_64--"); bool success = DG.init(Triple, Version); if (!success) return; dwarfgen::CompileUnit &CU = DG.addCompileUnit(); dwarfgen::DIE CUDie = CU.getUnitDIE(); CUDie.addAttribute(DW_AT_name, DW_FORM_strp, "/tmp/main.c"); CUDie.addAttribute(DW_AT_language, DW_FORM_data2, DW_LANG_C); dwarfgen::DIE SubprogramDie = CUDie.addChild(DW_TAG_subprogram); SubprogramDie.addAttribute(DW_AT_name, DW_FORM_strp, "main"); SubprogramDie.addAttribute(DW_AT_low_pc, DW_FORM_addr, 0x1000U); SubprogramDie.addAttribute(DW_AT_high_pc, DW_FORM_addr, 0x2000U); dwarfgen::DIE IntDie = CUDie.addChild(DW_TAG_base_type); IntDie.addAttribute(DW_AT_name, DW_FORM_strp, "int"); IntDie.addAttribute(DW_AT_encoding, DW_FORM_data1, DW_ATE_signed); IntDie.addAttribute(DW_AT_byte_size, DW_FORM_data1, 4); dwarfgen::DIE ArgcDie = SubprogramDie.addChild(DW_TAG_formal_parameter); ArgcDie.addAttribute(DW_AT_name, DW_FORM_strp, "argc"); // ArgcDie.addAttribute(DW_AT_type, DW_FORM_ref4, IntDie); ArgcDie.addAttribute(DW_AT_type, DW_FORM_ref_addr, IntDie); StringRef FileBytes = DG.generate(); MemoryBufferRef FileBuffer(FileBytes, "dwarf"); auto Obj = object::ObjectFile::createObjectFile(FileBuffer); EXPECT_TRUE((bool)Obj); DWARFContextInMemory DwarfContext(*Obj.get()); This code is backed by the AsmPrinter code that emits DWARF for the actual compiler. While adding unit tests it was discovered that DIEValue that used DIEEntry as their values had bugs where DW_FORM_ref1, DW_FORM_ref2, DW_FORM_ref8, and DW_FORM_ref_udata forms were not supported. These are all now supported. Added support for DW_FORM_string so we can emit inlined C strings. Centralized the code to unique abbreviations into a new DIEAbbrevSet class and made both the dwarfgen::Generator and the llvm::DwarfFile classes use the new class. Fixed comments in the llvm::DIE class so that the Offset is known to be the compile/type unit offset. DIEInteger now supports more DW_FORM values. There are also unit tests that cover: Encoding and decoding all form types and values Encoding and decoding all reference types (DW_FORM_ref1, DW_FORM_ref2, DW_FORM_ref4, DW_FORM_ref8, DW_FORM_ref_udata, DW_FORM_ref_addr) including cross compile unit references with that go forward one compile unit and backward on compile unit. Differential Revision: https://reviews.llvm.org/D27326 llvm-svn: 289010
Diffstat (limited to 'llvm/lib/CodeGen')
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/DIE.cpp294
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/DIEHash.cpp6
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/DwarfFile.cpp70
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/DwarfFile.h15
-rw-r--r--llvm/lib/CodeGen/CMakeLists.txt1
-rw-r--r--llvm/lib/CodeGen/DwarfGenerator.cpp262
-rw-r--r--llvm/lib/CodeGen/DwarfGenerator.h231
7 files changed, 749 insertions, 130 deletions
diff --git a/llvm/lib/CodeGen/AsmPrinter/DIE.cpp b/llvm/lib/CodeGen/AsmPrinter/DIE.cpp
index 06023fcc51b..3fbb52f1380 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DIE.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DIE.cpp
@@ -108,6 +108,51 @@ void DIEAbbrev::print(raw_ostream &O) {
LLVM_DUMP_METHOD
void DIEAbbrev::dump() { print(dbgs()); }
+//===----------------------------------------------------------------------===//
+// DIEAbbrevSet Implementation
+//===----------------------------------------------------------------------===//
+
+DIEAbbrevSet::~DIEAbbrevSet() {
+ for (DIEAbbrev *Abbrev : Abbreviations)
+ Abbrev->~DIEAbbrev();
+}
+
+DIEAbbrev &DIEAbbrevSet::uniqueAbbreviation(DIE &Die) {
+
+ FoldingSetNodeID ID;
+ DIEAbbrev Abbrev = Die.generateAbbrev();
+ Abbrev.Profile(ID);
+
+ void *InsertPos;
+ if (DIEAbbrev *Existing =
+ AbbreviationsSet.FindNodeOrInsertPos(ID, InsertPos)) {
+ Die.setAbbrevNumber(Existing->getNumber());
+ return *Existing;
+ }
+
+ // Move the abbreviation to the heap and assign a number.
+ DIEAbbrev *New = new (Alloc) DIEAbbrev(std::move(Abbrev));
+ Abbreviations.push_back(New);
+ New->setNumber(Abbreviations.size());
+ Die.setAbbrevNumber(Abbreviations.size());
+
+ // Store it for lookup.
+ AbbreviationsSet.InsertNode(New, InsertPos);
+ return *New;
+}
+
+void DIEAbbrevSet::Emit(const AsmPrinter *AP, MCSection *Section) const {
+ if (!Abbreviations.empty()) {
+ // Start the debug abbrev section.
+ AP->OutStreamer->SwitchSection(Section);
+ AP->emitDwarfAbbrevs(Abbreviations);
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// DIE Implementation
+//===----------------------------------------------------------------------===//
+
DIE *DIE::getParent() const {
return Owner.dyn_cast<DIE*>();
}
@@ -198,6 +243,45 @@ void DIE::dump() {
print(dbgs());
}
+unsigned DIE::computeOffsetsAndAbbrevs(const AsmPrinter *AP,
+ DIEAbbrevSet &AbbrevSet,
+ unsigned CUOffset) {
+ // Unique the abbreviation and fill in the abbreviation number so this DIE
+ // can be emitted.
+ const DIEAbbrev &Abbrev = AbbrevSet.uniqueAbbreviation(*this);
+
+ // Set compile/type unit relative offset of this DIE.
+ setOffset(CUOffset);
+
+ // Add the byte size of the abbreviation code.
+ CUOffset += getULEB128Size(getAbbrevNumber());
+
+ // Add the byte size of all the DIE attribute values.
+ for (const auto &V : values())
+ CUOffset += V.SizeOf(AP);
+
+ // Let the children compute their offsets and abbreviation numbers.
+ if (hasChildren()) {
+ (void)Abbrev;
+ assert(Abbrev.hasChildren() && "Children flag not set");
+
+ for (auto &Child : children())
+ CUOffset = Child.computeOffsetsAndAbbrevs(AP, AbbrevSet, CUOffset);
+
+ // Each child chain is terminated with a zero byte, adjust the offset.
+ CUOffset += sizeof(int8_t);
+ }
+
+ // Compute the byte size of this DIE and all of its children correctly. This
+ // is needed so that top level DIE can help the compile unit set its length
+ // correctly.
+ setSize(CUOffset - getOffset());
+ return CUOffset;
+}
+
+//===----------------------------------------------------------------------===//
+// DIEUnit Implementation
+//===----------------------------------------------------------------------===//
DIEUnit::DIEUnit(uint16_t V, uint8_t A, dwarf::Tag UnitTag)
: Die(UnitTag), Section(nullptr), Offset(0), Length(0), Version(V),
AddrSize(A)
@@ -257,38 +341,65 @@ void DIEValue::dump() const {
/// EmitValue - Emit integer of appropriate size.
///
void DIEInteger::EmitValue(const AsmPrinter *Asm, dwarf::Form Form) const {
- unsigned Size = ~0U;
switch (Form) {
case dwarf::DW_FORM_flag_present:
// Emit something to keep the lines and comments in sync.
// FIXME: Is there a better way to do this?
Asm->OutStreamer->AddBlankLine();
return;
- case dwarf::DW_FORM_flag: LLVM_FALLTHROUGH;
- case dwarf::DW_FORM_ref1: LLVM_FALLTHROUGH;
- case dwarf::DW_FORM_data1: Size = 1; break;
- case dwarf::DW_FORM_ref2: LLVM_FALLTHROUGH;
- case dwarf::DW_FORM_data2: Size = 2; break;
- case dwarf::DW_FORM_sec_offset: LLVM_FALLTHROUGH;
- case dwarf::DW_FORM_strp: LLVM_FALLTHROUGH;
- case dwarf::DW_FORM_ref4: LLVM_FALLTHROUGH;
- case dwarf::DW_FORM_data4: Size = 4; break;
- case dwarf::DW_FORM_ref8: LLVM_FALLTHROUGH;
- case dwarf::DW_FORM_ref_sig8: LLVM_FALLTHROUGH;
- case dwarf::DW_FORM_data8: Size = 8; break;
- case dwarf::DW_FORM_GNU_str_index: Asm->EmitULEB128(Integer); return;
- case dwarf::DW_FORM_GNU_addr_index: Asm->EmitULEB128(Integer); return;
- case dwarf::DW_FORM_udata: Asm->EmitULEB128(Integer); return;
- case dwarf::DW_FORM_sdata: Asm->EmitSLEB128(Integer); return;
+ case dwarf::DW_FORM_flag:
+ LLVM_FALLTHROUGH;
+ case dwarf::DW_FORM_ref1:
+ LLVM_FALLTHROUGH;
+ case dwarf::DW_FORM_data1:
+ LLVM_FALLTHROUGH;
+ case dwarf::DW_FORM_ref2:
+ LLVM_FALLTHROUGH;
+ case dwarf::DW_FORM_data2:
+ LLVM_FALLTHROUGH;
+ case dwarf::DW_FORM_strp:
+ LLVM_FALLTHROUGH;
+ case dwarf::DW_FORM_ref4:
+ LLVM_FALLTHROUGH;
+ case dwarf::DW_FORM_data4:
+ LLVM_FALLTHROUGH;
+ case dwarf::DW_FORM_ref8:
+ LLVM_FALLTHROUGH;
+ case dwarf::DW_FORM_ref_sig8:
+ LLVM_FALLTHROUGH;
+ case dwarf::DW_FORM_data8:
+ LLVM_FALLTHROUGH;
+ case dwarf::DW_FORM_GNU_ref_alt:
+ LLVM_FALLTHROUGH;
+ case dwarf::DW_FORM_GNU_strp_alt:
+ LLVM_FALLTHROUGH;
+ case dwarf::DW_FORM_line_strp:
+ LLVM_FALLTHROUGH;
+ case dwarf::DW_FORM_sec_offset:
+ LLVM_FALLTHROUGH;
+ case dwarf::DW_FORM_strp_sup:
+ LLVM_FALLTHROUGH;
+ case dwarf::DW_FORM_ref_sup:
+ LLVM_FALLTHROUGH;
case dwarf::DW_FORM_addr:
- Size = Asm->getPointerSize();
- break;
+ LLVM_FALLTHROUGH;
case dwarf::DW_FORM_ref_addr:
- Size = SizeOf(Asm, dwarf::DW_FORM_ref_addr);
- break;
+ Asm->OutStreamer->EmitIntValue(Integer, SizeOf(Asm, Form));
+ return;
+ case dwarf::DW_FORM_GNU_str_index:
+ LLVM_FALLTHROUGH;
+ case dwarf::DW_FORM_GNU_addr_index:
+ LLVM_FALLTHROUGH;
+ case dwarf::DW_FORM_ref_udata:
+ LLVM_FALLTHROUGH;
+ case dwarf::DW_FORM_udata:
+ Asm->EmitULEB128(Integer);
+ return;
+ case dwarf::DW_FORM_sdata:
+ Asm->EmitSLEB128(Integer);
+ return;
default: llvm_unreachable("DIE Value form not supported yet");
}
- Asm->OutStreamer->EmitIntValue(Integer, Size);
}
/// SizeOf - Determine size of integer value in bytes.
@@ -301,23 +412,47 @@ unsigned DIEInteger::SizeOf(const AsmPrinter *AP, dwarf::Form Form) const {
case dwarf::DW_FORM_data1: return sizeof(int8_t);
case dwarf::DW_FORM_ref2: LLVM_FALLTHROUGH;
case dwarf::DW_FORM_data2: return sizeof(int16_t);
- case dwarf::DW_FORM_sec_offset: LLVM_FALLTHROUGH;
- case dwarf::DW_FORM_strp: LLVM_FALLTHROUGH;
case dwarf::DW_FORM_ref4: LLVM_FALLTHROUGH;
case dwarf::DW_FORM_data4: return sizeof(int32_t);
case dwarf::DW_FORM_ref8: LLVM_FALLTHROUGH;
case dwarf::DW_FORM_ref_sig8: LLVM_FALLTHROUGH;
case dwarf::DW_FORM_data8: return sizeof(int64_t);
- case dwarf::DW_FORM_GNU_str_index: return getULEB128Size(Integer);
- case dwarf::DW_FORM_GNU_addr_index: return getULEB128Size(Integer);
- case dwarf::DW_FORM_udata: return getULEB128Size(Integer);
- case dwarf::DW_FORM_sdata: return getSLEB128Size(Integer);
- case dwarf::DW_FORM_addr:
- return AP->getPointerSize();
case dwarf::DW_FORM_ref_addr:
if (AP->getDwarfVersion() == 2)
return AP->getPointerSize();
- return sizeof(int32_t);
+ LLVM_FALLTHROUGH;
+ case dwarf::DW_FORM_strp:
+ LLVM_FALLTHROUGH;
+ case dwarf::DW_FORM_GNU_ref_alt:
+ LLVM_FALLTHROUGH;
+ case dwarf::DW_FORM_GNU_strp_alt:
+ LLVM_FALLTHROUGH;
+ case dwarf::DW_FORM_line_strp:
+ LLVM_FALLTHROUGH;
+ case dwarf::DW_FORM_sec_offset:
+ LLVM_FALLTHROUGH;
+ case dwarf::DW_FORM_strp_sup:
+ LLVM_FALLTHROUGH;
+ case dwarf::DW_FORM_ref_sup:
+ switch (AP->OutStreamer->getContext().getDwarfFormat()) {
+ case dwarf::DWARF32:
+ return 4;
+ case dwarf::DWARF64:
+ return 8;
+ }
+ llvm_unreachable("Invalid DWARF format");
+ case dwarf::DW_FORM_GNU_str_index:
+ LLVM_FALLTHROUGH;
+ case dwarf::DW_FORM_GNU_addr_index:
+ LLVM_FALLTHROUGH;
+ case dwarf::DW_FORM_ref_udata:
+ LLVM_FALLTHROUGH;
+ case dwarf::DW_FORM_udata:
+ return getULEB128Size(Integer);
+ case dwarf::DW_FORM_sdata:
+ return getSLEB128Size(Integer);
+ case dwarf::DW_FORM_addr:
+ return AP->getPointerSize();
default: llvm_unreachable("DIE Value form not supported yet");
}
}
@@ -452,6 +587,29 @@ void DIEString::print(raw_ostream &O) const {
}
//===----------------------------------------------------------------------===//
+// DIEInlineString Implementation
+//===----------------------------------------------------------------------===//
+void DIEInlineString::EmitValue(const AsmPrinter *AP, dwarf::Form Form) const {
+ if (Form == dwarf::DW_FORM_string) {
+ for (char ch : S)
+ AP->EmitInt8(ch);
+ AP->EmitInt8(0);
+ return;
+ }
+ llvm_unreachable("Expected valid string form");
+}
+
+unsigned DIEInlineString::SizeOf(const AsmPrinter *AP, dwarf::Form Form) const {
+ // Emit string bytes + NULL byte.
+ return S.size() + 1;
+}
+
+LLVM_DUMP_METHOD
+void DIEInlineString::print(raw_ostream &O) const {
+ O << "InlineString: " << S.c_str();
+}
+
+//===----------------------------------------------------------------------===//
// DIEEntry Implementation
//===----------------------------------------------------------------------===//
@@ -459,33 +617,69 @@ void DIEString::print(raw_ostream &O) const {
///
void DIEEntry::EmitValue(const AsmPrinter *AP, dwarf::Form Form) const {
- if (Form == dwarf::DW_FORM_ref_addr) {
+ switch (Form) {
+ case dwarf::DW_FORM_ref1:
+ case dwarf::DW_FORM_ref2:
+ case dwarf::DW_FORM_ref4:
+ case dwarf::DW_FORM_ref8:
+ AP->OutStreamer->EmitIntValue(Entry->getOffset(), SizeOf(AP, Form));
+ return;
+
+ case dwarf::DW_FORM_ref_udata:
+ AP->EmitULEB128(Entry->getOffset());
+ return;
+
+ case dwarf::DW_FORM_ref_addr: {
// Get the absolute offset for this DIE within the debug info/types section.
unsigned Addr = Entry->getDebugSectionOffset();
if (AP->MAI->doesDwarfUseRelocationsAcrossSections()) {
const DwarfDebug *DD = AP->getDwarfDebug();
if (DD)
- assert(!DD->useSplitDwarf() && "TODO: dwo files can't have relocations.");
+ assert(!DD->useSplitDwarf() &&
+ "TODO: dwo files can't have relocations.");
const DIEUnit *Unit = Entry->getUnit();
assert(Unit && "CUDie should belong to a CU.");
MCSection *Section = Unit->getSection();
- assert(Section && "Must have a section if we are doing relocations");
- const MCSymbol *SectionSym = Section->getBeginSymbol();
- AP->EmitLabelPlusOffset(SectionSym, Addr, DIEEntry::getRefAddrSize(AP));
- } else
- AP->OutStreamer->EmitIntValue(Addr, DIEEntry::getRefAddrSize(AP));
- } else
- AP->EmitInt32(Entry->getOffset());
-}
-
-unsigned DIEEntry::getRefAddrSize(const AsmPrinter *AP) {
- // DWARF4: References that use the attribute form DW_FORM_ref_addr are
- // specified to be four bytes in the DWARF 32-bit format and eight bytes
- // in the DWARF 64-bit format, while DWARF Version 2 specifies that such
- // references have the same size as an address on the target system.
- if (AP->getDwarfVersion() == 2)
- return AP->getPointerSize();
- return sizeof(int32_t);
+ if (Section) {
+ const MCSymbol *SectionSym = Section->getBeginSymbol();
+ AP->EmitLabelPlusOffset(SectionSym, Addr, SizeOf(AP, Form));
+ return;
+ }
+ }
+ AP->OutStreamer->EmitIntValue(Addr, SizeOf(AP, Form));
+ return;
+ }
+ default:
+ llvm_unreachable("Improper form for DIE reference");
+ }
+}
+
+unsigned DIEEntry::SizeOf(const AsmPrinter *AP, dwarf::Form Form) const {
+ switch (Form) {
+ case dwarf::DW_FORM_ref1:
+ return 1;
+ case dwarf::DW_FORM_ref2:
+ return 2;
+ case dwarf::DW_FORM_ref4:
+ return 4;
+ case dwarf::DW_FORM_ref8:
+ return 8;
+ case dwarf::DW_FORM_ref_udata:
+ return getULEB128Size(Entry->getOffset());
+ case dwarf::DW_FORM_ref_addr:
+ if (AP->getDwarfVersion() == 2)
+ return AP->getPointerSize();
+ switch (AP->OutStreamer->getContext().getDwarfFormat()) {
+ case dwarf::DWARF32:
+ return 4;
+ case dwarf::DWARF64:
+ return 8;
+ }
+ llvm_unreachable("Invalid DWARF format");
+
+ default:
+ llvm_unreachable("Improper form for DIE reference");
+ }
}
LLVM_DUMP_METHOD
diff --git a/llvm/lib/CodeGen/AsmPrinter/DIEHash.cpp b/llvm/lib/CodeGen/AsmPrinter/DIEHash.cpp
index 74c47d151c6..d8ecc7ccfb9 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DIEHash.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DIEHash.cpp
@@ -330,6 +330,12 @@ void DIEHash::hashAttribute(const DIEValue &Value, dwarf::Tag Tag) {
addULEB128(dwarf::DW_FORM_string);
addString(Value.getDIEString().getString());
break;
+ case DIEValue::isInlineString:
+ addULEB128('A');
+ addULEB128(Attribute);
+ addULEB128(dwarf::DW_FORM_string);
+ addString(Value.getDIEInlineString().getString());
+ break;
case DIEValue::isBlock:
case DIEValue::isLoc:
case DIEValue::isLocList:
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfFile.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfFile.cpp
index 3179ab15420..595f1d91c4b 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfFile.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfFile.cpp
@@ -19,37 +19,7 @@
namespace llvm {
DwarfFile::DwarfFile(AsmPrinter *AP, StringRef Pref, BumpPtrAllocator &DA)
- : Asm(AP), StrPool(DA, *Asm, Pref) {}
-
-DwarfFile::~DwarfFile() {
- for (DIEAbbrev *Abbrev : Abbreviations)
- Abbrev->~DIEAbbrev();
-}
-
-// Define a unique number for the abbreviation.
-//
-DIEAbbrev &DwarfFile::assignAbbrevNumber(DIE &Die) {
- FoldingSetNodeID ID;
- DIEAbbrev Abbrev = Die.generateAbbrev();
- Abbrev.Profile(ID);
-
- void *InsertPos;
- if (DIEAbbrev *Existing =
- AbbreviationsSet.FindNodeOrInsertPos(ID, InsertPos)) {
- Die.setAbbrevNumber(Existing->getNumber());
- return *Existing;
- }
-
- // Move the abbreviation to the heap and assign a number.
- DIEAbbrev *New = new (AbbrevAllocator) DIEAbbrev(std::move(Abbrev));
- Abbreviations.push_back(New);
- New->setNumber(Abbreviations.size());
- Die.setAbbrevNumber(Abbreviations.size());
-
- // Store it for lookup.
- AbbreviationsSet.InsertNode(New, InsertPos);
- return *New;
-}
+ : Asm(AP), Abbrevs(AbbrevAllocator), StrPool(DA, *Asm, Pref) {}
void DwarfFile::addUnit(std::unique_ptr<DwarfCompileUnit> U) {
CUs.push_back(std::move(U));
@@ -98,44 +68,10 @@ unsigned DwarfFile::computeSizeAndOffsetsForUnit(DwarfUnit *TheU) {
// Compute the size and offset of a DIE. The offset is relative to start of the
// CU. It returns the offset after laying out the DIE.
unsigned DwarfFile::computeSizeAndOffset(DIE &Die, unsigned Offset) {
- // Record the abbreviation.
- const DIEAbbrev &Abbrev = assignAbbrevNumber(Die);
-
- // Set DIE offset
- Die.setOffset(Offset);
-
- // Start the size with the size of abbreviation code.
- Offset += getULEB128Size(Die.getAbbrevNumber());
-
- // Size the DIE attribute values.
- for (const auto &V : Die.values())
- // Size attribute value.
- Offset += V.SizeOf(Asm);
-
- // Size the DIE children if any.
- if (Die.hasChildren()) {
- (void)Abbrev;
- assert(Abbrev.hasChildren() && "Children flag not set");
-
- for (auto &Child : Die.children())
- Offset = computeSizeAndOffset(Child, Offset);
-
- // End of children marker.
- Offset += sizeof(int8_t);
- }
-
- Die.setSize(Offset - Die.getOffset());
- return Offset;
+ return Die.computeOffsetsAndAbbrevs(Asm, Abbrevs, Offset);
}
-void DwarfFile::emitAbbrevs(MCSection *Section) {
- // Check to see if it is worth the effort.
- if (!Abbreviations.empty()) {
- // Start the debug abbrev section.
- Asm->OutStreamer->SwitchSection(Section);
- Asm->emitDwarfAbbrevs(Abbreviations);
- }
-}
+void DwarfFile::emitAbbrevs(MCSection *Section) { Abbrevs.Emit(Asm, Section); }
// Emit strings into a string section.
void DwarfFile::emitStrings(MCSection *StrSection, MCSection *OffsetSection) {
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfFile.h b/llvm/lib/CodeGen/AsmPrinter/DwarfFile.h
index b73d89b0e49..d4d2ed27727 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfFile.h
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfFile.h
@@ -16,10 +16,10 @@
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
+#include "llvm/CodeGen/DIE.h"
#include "llvm/IR/Metadata.h"
#include "llvm/Support/Allocator.h"
#include <memory>
-#include <vector>
namespace llvm {
class AsmPrinter;
@@ -41,10 +41,7 @@ class DwarfFile {
BumpPtrAllocator AbbrevAllocator;
// Used to uniquely define abbreviations.
- FoldingSet<DIEAbbrev> AbbreviationsSet;
-
- // A list of all the unique abbreviations in use.
- std::vector<DIEAbbrev *> Abbreviations;
+ DIEAbbrevSet Abbrevs;
// A pointer to all units in the section.
SmallVector<std::unique_ptr<DwarfCompileUnit>, 1> CUs;
@@ -65,8 +62,6 @@ class DwarfFile {
public:
DwarfFile(AsmPrinter *AP, StringRef Pref, BumpPtrAllocator &DA);
- ~DwarfFile();
-
const SmallVectorImpl<std::unique_ptr<DwarfCompileUnit>> &getUnits() {
return CUs;
}
@@ -81,12 +76,6 @@ public:
/// \returns The size of the root DIE.
unsigned computeSizeAndOffsetsForUnit(DwarfUnit *TheU);
- /// Define a unique number for the abbreviation.
- ///
- /// Compute the abbreviation for \c Die, look up its unique number, and
- /// return a reference to it in the uniquing table.
- DIEAbbrev &assignAbbrevNumber(DIE &Die);
-
/// \brief Add a unit to the list of CUs.
void addUnit(std::unique_ptr<DwarfCompileUnit> U);
diff --git a/llvm/lib/CodeGen/CMakeLists.txt b/llvm/lib/CodeGen/CMakeLists.txt
index 398ea88363b..22ee8e9da0f 100644
--- a/llvm/lib/CodeGen/CMakeLists.txt
+++ b/llvm/lib/CodeGen/CMakeLists.txt
@@ -17,6 +17,7 @@ add_llvm_library(LLVMCodeGen
DetectDeadLanes.cpp
DFAPacketizer.cpp
DwarfEHPrepare.cpp
+ DwarfGenerator.cpp
EarlyIfConversion.cpp
EdgeBundles.cpp
ExecutionDepsFix.cpp
diff --git a/llvm/lib/CodeGen/DwarfGenerator.cpp b/llvm/lib/CodeGen/DwarfGenerator.cpp
new file mode 100644
index 00000000000..1e8e6614921
--- /dev/null
+++ b/llvm/lib/CodeGen/DwarfGenerator.cpp
@@ -0,0 +1,262 @@
+//===--- lib/CodeGen/DwarfGenerator.cpp -------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DwarfGenerator.h"
+#include "AsmPrinter/DwarfStringPool.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/CodeGen/AsmPrinter.h"
+#include "llvm/CodeGen/DIE.h"
+#include "llvm/DebugInfo/DWARF/DWARFContext.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
+#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
+#include "llvm/IR/LegacyPassManagers.h"
+#include "llvm/MC/MCAsmBackend.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCCodeEmitter.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCDwarf.h"
+#include "llvm/MC/MCInstrInfo.h"
+#include "llvm/MC/MCObjectFileInfo.h"
+#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/MC/MCStreamer.h"
+#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/MC/MCTargetOptionsCommandFlags.h"
+#include "llvm/PassAnalysisSupport.h"
+#include "llvm/Support/Dwarf.h"
+#include "llvm/Support/LEB128.h"
+#include "llvm/Support/TargetRegistry.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/Target/TargetOptions.h"
+
+using namespace llvm;
+using namespace dwarf;
+
+namespace {} // end anonymous namespace
+
+//===----------------------------------------------------------------------===//
+/// dwarfgen::DIE implementation.
+//===----------------------------------------------------------------------===//
+unsigned dwarfgen::DIE::computeSizeAndOffsets(unsigned Offset) {
+ auto &DG = CU->getGenerator();
+ return Die->computeOffsetsAndAbbrevs(DG.getAsmPrinter(), DG.getAbbrevSet(),
+ Offset);
+}
+
+void dwarfgen::DIE::addAttribute(uint16_t A, dwarf::Form Form, uint64_t U) {
+ auto &DG = CU->getGenerator();
+ Die->addValue(DG.getAllocator(), static_cast<dwarf::Attribute>(A), Form,
+ DIEInteger(U));
+}
+
+void dwarfgen::DIE::addAttribute(uint16_t A, dwarf::Form Form,
+ StringRef String) {
+ auto &DG = CU->getGenerator();
+ if (Form == DW_FORM_string) {
+ Die->addValue(DG.getAllocator(), static_cast<dwarf::Attribute>(A), Form,
+ new (DG.getAllocator()) DIEInlineString(String));
+ } else {
+ Die->addValue(
+ DG.getAllocator(), static_cast<dwarf::Attribute>(A), Form,
+ DIEString(DG.getStringPool().getEntry(*DG.getAsmPrinter(), String)));
+ }
+}
+
+void dwarfgen::DIE::addAttribute(uint16_t A, dwarf::Form Form,
+ dwarfgen::DIE &RefDie) {
+ auto &DG = CU->getGenerator();
+ Die->addValue(DG.getAllocator(), static_cast<dwarf::Attribute>(A), Form,
+ DIEEntry(*RefDie.Die));
+}
+
+void dwarfgen::DIE::addAttribute(uint16_t A, dwarf::Form Form, const void *P,
+ size_t S) {
+ auto &DG = CU->getGenerator();
+ DIEBlock *Block = new (DG.getAllocator()) DIEBlock;
+ for (size_t I = 0; I < S; ++I)
+ Block->addValue(DG.getAllocator(), (dwarf::Attribute)0,
+ dwarf::DW_FORM_data1, DIEInteger(((uint8_t *)P)[I]));
+
+ Block->ComputeSize(DG.getAsmPrinter());
+ Die->addValue(DG.getAllocator(), static_cast<dwarf::Attribute>(A), Form,
+ Block);
+}
+
+void dwarfgen::DIE::addAttribute(uint16_t A, dwarf::Form Form) {
+ auto &DG = CU->getGenerator();
+ assert(Form == DW_FORM_flag_present);
+ Die->addValue(DG.getAllocator(), static_cast<dwarf::Attribute>(A), Form,
+ DIEInteger(1));
+}
+
+dwarfgen::DIE dwarfgen::DIE::addChild(dwarf::Tag Tag) {
+ auto &DG = CU->getGenerator();
+ return dwarfgen::DIE(CU,
+ &Die->addChild(llvm::DIE::get(DG.getAllocator(), Tag)));
+}
+
+dwarfgen::DIE dwarfgen::CompileUnit::getUnitDIE() {
+ return dwarfgen::DIE(this, &DU.getUnitDie());
+}
+
+//===----------------------------------------------------------------------===//
+/// dwarfgen::Generator implementation.
+//===----------------------------------------------------------------------===//
+
+dwarfgen::Generator::Generator() : Abbreviations(Allocator) {}
+dwarfgen::Generator::~Generator() = default;
+
+llvm::Expected<std::unique_ptr<dwarfgen::Generator>>
+dwarfgen::Generator::create(Triple TheTriple, uint16_t DwarfVersion) {
+ std::unique_ptr<dwarfgen::Generator> GenUP(new dwarfgen::Generator());
+ llvm::Error error = GenUP->init(TheTriple, DwarfVersion);
+ if (error)
+ return Expected<std::unique_ptr<dwarfgen::Generator>>(std::move(error));
+ return Expected<std::unique_ptr<dwarfgen::Generator>>(std::move(GenUP));
+}
+
+llvm::Error dwarfgen::Generator::init(Triple TheTriple, uint16_t V) {
+ Version = V;
+ std::string ErrorStr;
+ std::string TripleName;
+
+ // Get the target.
+ const Target *TheTarget =
+ TargetRegistry::lookupTarget(TripleName, TheTriple, ErrorStr);
+ if (!TheTarget)
+ return make_error<StringError>(ErrorStr, inconvertibleErrorCode());
+
+ TripleName = TheTriple.getTriple();
+
+ // Create all the MC Objects.
+ MRI.reset(TheTarget->createMCRegInfo(TripleName));
+ if (!MRI)
+ return make_error<StringError>(Twine("no register info for target ") +
+ TripleName,
+ inconvertibleErrorCode());
+
+ MAI.reset(TheTarget->createMCAsmInfo(*MRI, TripleName));
+ if (!MAI)
+ return make_error<StringError>("no asm info for target " + TripleName,
+ inconvertibleErrorCode());
+
+ MOFI.reset(new MCObjectFileInfo);
+ MC.reset(new MCContext(MAI.get(), MRI.get(), MOFI.get()));
+ MOFI->InitMCObjectFileInfo(TheTriple, /*PIC*/ false, CodeModel::Default, *MC);
+
+ MCTargetOptions Options;
+ MAB = TheTarget->createMCAsmBackend(*MRI, TripleName, "", Options);
+ if (!MAB)
+ return make_error<StringError>("no asm backend for target " + TripleName,
+ inconvertibleErrorCode());
+
+ MII.reset(TheTarget->createMCInstrInfo());
+ if (!MII)
+ return make_error<StringError>("no instr info info for target " +
+ TripleName,
+ inconvertibleErrorCode());
+
+ MSTI.reset(TheTarget->createMCSubtargetInfo(TripleName, "", ""));
+ if (!MSTI)
+ return make_error<StringError>("no subtarget info for target " + TripleName,
+ inconvertibleErrorCode());
+
+ MCE = TheTarget->createMCCodeEmitter(*MII, *MRI, *MC);
+ if (!MCE)
+ return make_error<StringError>("no code emitter for target " + TripleName,
+ inconvertibleErrorCode());
+
+ Stream = make_unique<raw_svector_ostream>(FileBytes);
+
+ MCTargetOptions MCOptions = InitMCTargetOptionsFromFlags();
+ MS = TheTarget->createMCObjectStreamer(
+ TheTriple, *MC, *MAB, *Stream, MCE, *MSTI, MCOptions.MCRelaxAll,
+ MCOptions.MCIncrementalLinkerCompatible,
+ /*DWARFMustBeAtTheEnd*/ false);
+ if (!MS)
+ return make_error<StringError>("no object streamer for target " +
+ TripleName,
+ inconvertibleErrorCode());
+
+ // Finally create the AsmPrinter we'll use to emit the DIEs.
+ TM.reset(TheTarget->createTargetMachine(TripleName, "", "", TargetOptions(),
+ None));
+ if (!TM)
+ return make_error<StringError>("no target machine for target " + TripleName,
+ inconvertibleErrorCode());
+
+ Asm.reset(TheTarget->createAsmPrinter(*TM, std::unique_ptr<MCStreamer>(MS)));
+ if (!Asm)
+ return make_error<StringError>("no asm printer for target " + TripleName,
+ inconvertibleErrorCode());
+
+ // Set the DWARF version correctly on all classes that we use.
+ MC->setDwarfVersion(Version);
+ Asm->setDwarfVersion(Version);
+
+ StringPool.reset(new DwarfStringPool(Allocator, *Asm, StringRef()));
+
+ return Error::success();
+}
+
+StringRef dwarfgen::Generator::generate() {
+ // Offset from the first CU in the debug info section is 0 initially.
+ unsigned SecOffset = 0;
+
+ // Iterate over each compile unit and set the size and offsets for each
+ // DIE within each compile unit. All offsets are CU relative.
+ for (auto &CU : CompileUnits) {
+ // Set the absolute .debug_info offset for this compile unit.
+ CU->setOffset(SecOffset);
+ // The DIEs contain compile unit relative offsets.
+ unsigned CUOffset = 11;
+ CUOffset = CU->getUnitDIE().computeSizeAndOffsets(CUOffset);
+ // Update our absolute .debug_info offset.
+ SecOffset += CUOffset;
+ CU->setLength(CUOffset - 4);
+ }
+ Abbreviations.Emit(Asm.get(), MOFI->getDwarfAbbrevSection());
+ StringPool->emit(*Asm, MOFI->getDwarfStrSection());
+ MS->SwitchSection(MOFI->getDwarfInfoSection());
+ for (auto &CU : CompileUnits) {
+ uint16_t Version = CU->getVersion();
+ auto Length = CU->getLength();
+ MC->setDwarfVersion(Version);
+ assert(Length != -1U);
+ Asm->EmitInt32(Length);
+ Asm->EmitInt16(Version);
+ Asm->EmitInt32(0);
+ Asm->EmitInt8(CU->getAddressSize());
+ Asm->emitDwarfDIE(*CU->getUnitDIE().Die);
+ }
+
+ MS->Finish();
+ if (FileBytes.empty())
+ return StringRef();
+ return StringRef(FileBytes.data(), FileBytes.size());
+}
+
+bool dwarfgen::Generator::saveFile(StringRef Path) {
+ if (FileBytes.empty())
+ return false;
+ std::error_code EC;
+ raw_fd_ostream Strm(Path, EC, sys::fs::F_None);
+ if (EC)
+ return false;
+ Strm.write(FileBytes.data(), FileBytes.size());
+ Strm.close();
+ return true;
+}
+
+dwarfgen::CompileUnit &dwarfgen::Generator::addCompileUnit() {
+ CompileUnits.push_back(std::unique_ptr<CompileUnit>(
+ new CompileUnit(*this, Version, Asm->getPointerSize())));
+ return *CompileUnits.back();
+}
diff --git a/llvm/lib/CodeGen/DwarfGenerator.h b/llvm/lib/CodeGen/DwarfGenerator.h
new file mode 100644
index 00000000000..9e7bdfb6f40
--- /dev/null
+++ b/llvm/lib/CodeGen/DwarfGenerator.h
@@ -0,0 +1,231 @@
+//===--- lib/CodeGen/DwarfGenerator.h ---------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// A file that can generate DWARF debug info for unit tests.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_CODEGEN_ASMPRINTER_DWARFGENERATOR_H
+#define LLVM_LIB_CODEGEN_ASMPRINTER_DWARFGENERATOR_H
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/CodeGen/DIE.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
+#include "llvm/Support/Error.h"
+
+#include <memory>
+#include <string>
+#include <tuple>
+#include <vector>
+
+namespace llvm {
+
+class AsmPrinter;
+class DIE;
+class DIEAbbrev;
+class DwarfStringPool;
+class MCAsmBackend;
+class MCAsmInfo;
+class MCCodeEmitter;
+class MCContext;
+struct MCDwarfLineTableParams;
+class MCInstrInfo;
+class MCObjectFileInfo;
+class MCRegisterInfo;
+class MCStreamer;
+class MCSubtargetInfo;
+class raw_fd_ostream;
+class TargetMachine;
+class Triple;
+
+namespace dwarfgen {
+
+class Generator;
+class CompileUnit;
+
+/// A DWARF debug information entry class used to generate DWARF DIEs.
+///
+/// This class is used to quickly generate DWARF debug information by creating
+/// child DIEs or adding attributes to the current DIE. Instances of this class
+/// are created from the compile unit (dwarfgen::CompileUnit::getUnitDIE()) or
+/// by calling dwarfgen::DIE::addChild(...) and using the returned DIE object.
+class DIE {
+ dwarfgen::CompileUnit *CU;
+ llvm::DIE *Die;
+
+protected:
+ friend class Generator;
+ friend class CompileUnit;
+
+ DIE(CompileUnit *U = nullptr, llvm::DIE *D = nullptr) : CU(U), Die(D) {}
+
+ /// Called with a compile/type unit relative offset prior to generating the
+ /// DWARF debug info.
+ ///
+ /// \param CUOffset the compile/type unit relative offset where the
+ /// abbreviation code for this DIE will be encoded.
+ unsigned computeSizeAndOffsets(unsigned CUOffset);
+
+public:
+ /// Add an attribute value that has no value.
+ ///
+ /// \param Attr a dwarf::Attribute enumeration value or any uint16_t that
+ /// represents a user defined DWARF attribute.
+ /// \param Form the dwarf::Form to use when encoding the attribute. This is
+ /// only used with the DW_FORM_flag_present form encoding.
+ void addAttribute(uint16_t Attr, dwarf::Form Form);
+
+ /// Add an attribute value to be encoded as a DIEInteger
+ ///
+ /// \param Attr a dwarf::Attribute enumeration value or any uint16_t that
+ /// represents a user defined DWARF attribute.
+ /// \param Form the dwarf::Form to use when encoding the attribute.
+ /// \param U the unsigned integer to encode.
+ void addAttribute(uint16_t Attr, dwarf::Form Form, uint64_t U);
+
+ /// Add an attribute value to be encoded as a DIEString or DIEInlinedString.
+ ///
+ /// \param Attr a dwarf::Attribute enumeration value or any uint16_t that
+ /// represents a user defined DWARF attribute.
+ /// \param Form the dwarf::Form to use when encoding the attribute. The form
+ /// must be one of DW_FORM_strp or DW_FORM_string.
+ /// \param String the string to encode.
+ void addAttribute(uint16_t Attr, dwarf::Form Form, StringRef String);
+
+ /// Add an attribute value to be encoded as a DIEEntry.
+ ///
+ /// DIEEntry attributes refer to other llvm::DIE objects that have been
+ /// created.
+ ///
+ /// \param Attr a dwarf::Attribute enumeration value or any uint16_t that
+ /// represents a user defined DWARF attribute.
+ /// \param Form the dwarf::Form to use when encoding the attribute. The form
+ /// must be one of DW_FORM_strp or DW_FORM_string.
+ /// \param RefDie the DIE that this attriute refers to.
+ void addAttribute(uint16_t Attr, dwarf::Form Form, dwarfgen::DIE &RefDie);
+
+ /// Add an attribute value to be encoded as a DIEBlock.
+ ///
+ /// DIEBlock attributes refers to binary data that is stored as the
+ /// attribute's value.
+ ///
+ /// \param Attr a dwarf::Attribute enumeration value or any uint16_t that
+ /// represents a user defined DWARF attribute.
+ /// \param Form the dwarf::Form to use when encoding the attribute. The form
+ /// must be one of DW_FORM_strp or DW_FORM_string.
+ /// \param P a pointer to the data to store as the attribute value.
+ /// \param S the size in bytes of the data pointed to by \param P.
+ void addAttribute(uint16_t Attr, dwarf::Form Form, const void *P, size_t S);
+
+ /// Add a new child to this DIE object.
+ ///
+ /// \param Tag the dwarf::Tag to assing to the llvm::DIE object.
+ /// \returns the newly created DIE object that is now a child owned by this
+ /// object.
+ dwarfgen::DIE addChild(dwarf::Tag Tag);
+};
+
+/// A DWARF compile unit used to generate DWARF compile/type units.
+///
+/// Instances of these classes are created by instances of the Generator
+/// class. All information required to generate a DWARF compile unit is
+/// contained inside this class.
+class CompileUnit {
+ Generator &DG;
+ DIEUnit DU;
+
+public:
+ CompileUnit(Generator &D, uint16_t V, uint8_t A)
+ : DG(D), DU(V, A, dwarf::DW_TAG_compile_unit) {}
+ DIE getUnitDIE();
+ Generator &getGenerator() { return DG; }
+ uint64_t getOffset() const { return DU.getDebugSectionOffset(); }
+ uint64_t getLength() const { return DU.getLength(); }
+ uint16_t getVersion() const { return DU.getDwarfVersion(); }
+ uint16_t getAddressSize() const { return DU.getAddressSize(); }
+ void setOffset(uint64_t Offset) { DU.setDebugSectionOffset(Offset); }
+ void setLength(uint64_t Length) { DU.setLength(Length); }
+};
+
+/// A DWARF generator.
+///
+/// Generate DWARF for unit tests by creating any instance of this class and
+/// calling Generator::addCompileUnit(), and then getting the dwarfgen::DIE from
+/// the returned compile unit and adding attributes and children to each DIE.
+class Generator {
+ std::unique_ptr<MCRegisterInfo> MRI;
+ std::unique_ptr<MCAsmInfo> MAI;
+ std::unique_ptr<MCObjectFileInfo> MOFI;
+ std::unique_ptr<MCContext> MC;
+ MCAsmBackend *MAB; // Owned by MCStreamer
+ std::unique_ptr<MCInstrInfo> MII;
+ std::unique_ptr<MCSubtargetInfo> MSTI;
+ MCCodeEmitter *MCE; // Owned by MCStreamer
+ MCStreamer *MS; // Owned by AsmPrinter
+ std::unique_ptr<TargetMachine> TM;
+ std::unique_ptr<AsmPrinter> Asm;
+ std::unique_ptr<DwarfStringPool> StringPool;
+ std::vector<std::unique_ptr<CompileUnit>> CompileUnits;
+ BumpPtrAllocator Allocator;
+ DIEAbbrevSet Abbreviations;
+
+ SmallString<4096> FileBytes;
+ /// The stream we use to generate the DWARF into as an ELF file.
+ std::unique_ptr<raw_svector_ostream> Stream;
+ /// The DWARF version to generate.
+ uint16_t Version;
+
+ /// Private constructor, call Generator::Create(...) to get a DWARF generator
+ /// expected.
+ Generator();
+
+ /// Create the streamer and setup the output buffer.
+ llvm::Error init(Triple TheTriple, uint16_t DwarfVersion);
+
+public:
+ /// Create a DWARF generator or get an appropriate error.
+ ///
+ /// \param TheTriple the triple to use when creating any required support
+ /// classes needed to emit the DWARF.
+ /// \param DwarfVersion the version of DWARF to emit.
+ ///
+ /// \returns a llvm::Expected that either contains a unique_ptr to a Generator
+ /// or a llvm::Error.
+ static llvm::Expected<std::unique_ptr<Generator>>
+ create(Triple TheTriple, uint16_t DwarfVersion);
+
+ ~Generator();
+
+ /// Generate all DWARF sections and return a memory buffer that
+ /// contains an ELF file that contains the DWARF.
+ StringRef generate();
+
+ /// Add a compile unit to be generated.
+ ///
+ /// \returns a dwarfgen::CompileUnit that can be used to retrieve the compile
+ /// unit dwarfgen::DIE that can be used to add attributes and add child DIE
+ /// objedts to.
+ dwarfgen::CompileUnit &addCompileUnit();
+
+ BumpPtrAllocator &getAllocator() { return Allocator; }
+ AsmPrinter *getAsmPrinter() const { return Asm.get(); }
+ DIEAbbrevSet &getAbbrevSet() { return Abbreviations; }
+ DwarfStringPool &getStringPool() { return *StringPool; }
+
+ /// Save the generated DWARF file to disk.
+ ///
+ /// \param Path the path to save the ELF file to.
+ bool saveFile(StringRef Path);
+};
+
+} // end namespace dwarfgen
+
+} // end namespace llvm
+
+#endif // LLVM_LIB_CODEGEN_ASMPRINTER_DWARFGENERATOR_H
OpenPOWER on IntegriCloud