Skip to content

Commit

Permalink
This change removes the dependency on DwarfDebug that was used for DW…
Browse files Browse the repository at this point in the history
…_FORM_ref_addr by making a new DIEUnit class in DIE.cpp.

The DIEUnit class represents a compile or type unit and it owns the unit DIE as an instance variable. This allows anyone with a DIE, to get the unit DIE, and then get back to its DIEUnit without adding any new ivars to the DIE class. Why was this needed? The DIE class has an Offset that is always the CU relative DIE offset, not the "offset in debug info section" as was commented in the header file (the comment has been corrected). This is great for performance because most DIE references are compile unit relative and this means most code that accessed the DIE's offset didn't need to make it into a compile unit relative offset because it already was. When we needed to emit a DW_FORM_ref_addr though, we needed to find the absolute offset of the DIE by finding the DIE's compile/type unit. This class did have the absolute debug info/type offset and could be added to the CU relative offset to compute the absolute offset. With this change we can easily get back to a DIE's DIEUnit which will have this needed offset. Prior to this is required having a DwarfDebug and required calling:

DwarfCompileUnit *DwarfDebug::lookupUnit(const DIE *CU) const;
Now we can use the DIEUnit class to do so without needing DwarfDebug. All clients now use DIEUnit objects (the DwarfDebug stack and the DwarfLinker). A follow on patch for the DWARF generator will also take advantage of this.

Differential Revision: https://reviews.llvm.org/D27170



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@288399 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
Greg Clayton committed Dec 1, 2016
1 parent 171807f commit fc1fc8b
Show file tree
Hide file tree
Showing 12 changed files with 221 additions and 157 deletions.
98 changes: 87 additions & 11 deletions include/llvm/CodeGen/DIE.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "llvm/ADT/iterator.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/CodeGen/DwarfStringPoolEntry.h"
Expand All @@ -34,7 +35,10 @@
namespace llvm {

class AsmPrinter;
class DIE;
class DIEUnit;
class MCExpr;
class MCSection;
class MCSymbol;
class raw_ostream;

Expand Down Expand Up @@ -585,12 +589,13 @@ class DIEValueList {
};

//===--------------------------------------------------------------------===//
/// DIE - A structured debug information entry. Has an abbreviation which
/// A structured debug information entry. Has an abbreviation which
/// describes its organization.
class DIE : IntrusiveBackListNode, public DIEValueList {
friend class IntrusiveBackList<DIE>;
friend class DIEUnit;

/// Offset - Offset in debug info section.
/// Offset - Dwarf unit relative offset.
///
unsigned Offset;

Expand All @@ -607,19 +612,31 @@ class DIE : IntrusiveBackListNode, public DIEValueList {
/// Children DIEs.
IntrusiveBackList<DIE> Children;

DIE *Parent = nullptr;
/// The owner is either the parent DIE for children of other DIEs, or a
/// DIEUnit which contains this DIE as its unit DIE.
PointerUnion<DIE *, DIEUnit *> Owner;

DIE() = delete;
explicit DIE(dwarf::Tag Tag) : Offset(0), Size(0), Tag(Tag) {}

protected:
void setUnit(DIEUnit *U) {
Owner = U;
}
public:
static DIE *get(BumpPtrAllocator &Alloc, dwarf::Tag Tag) {
return new (Alloc) DIE(Tag);
}

DIE(const DIE &RHS) = delete;
DIE(DIE &&RHS) = delete;
void operator=(const DIE &RHS) = delete;
void operator=(const DIE &&RHS) = delete;

// Accessors.
unsigned getAbbrevNumber() const { return AbbrevNumber; }
dwarf::Tag getTag() const { return Tag; }
/// Get the compile/type unit relative offset of this DIE.
unsigned getOffset() const { return Offset; }
unsigned getSize() const { return Size; }
bool hasChildren() const { return !Children.empty(); }
Expand All @@ -636,7 +653,7 @@ class DIE : IntrusiveBackListNode, public DIEValueList {
return make_range(Children.begin(), Children.end());
}

DIE *getParent() const { return Parent; }
DIE *getParent() const;

/// Generate the abbreviation for this DIE.
///
Expand All @@ -647,19 +664,31 @@ class DIE : IntrusiveBackListNode, public DIEValueList {
/// Set the abbreviation number for this DIE.
void setAbbrevNumber(unsigned I) { AbbrevNumber = I; }

/// Climb up the parent chain to get the compile or type unit DIE this DIE
/// belongs to.
const DIE *getUnit() const;
/// Similar to getUnit, returns null when DIE is not added to an
/// owner yet.
const DIE *getUnitOrNull() const;
/// Get the absolute offset within the .debug_info or .debug_types section
/// for this DIE.
unsigned getDebugSectionOffset() const;

/// Climb up the parent chain to get the compile unit or type unit DIE that
/// this DIE belongs to.
///
/// \returns the compile or type unit DIE that owns this DIE, or NULL if
/// this DIE hasn't been added to a unit DIE.
const DIE *getUnitDie() const;

/// Climb up the parent chain to get the compile unit or type unit that this
/// DIE belongs to.
///
/// \returns the DIEUnit that represents the compile or type unit that owns
/// this DIE, or NULL if this DIE hasn't been added to a unit DIE.
const DIEUnit *getUnit() const;

void setOffset(unsigned O) { Offset = O; }
void setSize(unsigned S) { Size = S; }

/// Add a child to the DIE.
DIE &addChild(DIE *Child) {
assert(!Child->getParent() && "Child should be orphaned");
Child->Parent = this;
Child->Owner = this;
Children.push_back(*Child);
return Children.back();
}
Expand All @@ -674,6 +703,53 @@ class DIE : IntrusiveBackListNode, public DIEValueList {
void dump();
};

//===--------------------------------------------------------------------===//
/// Represents a compile or type unit.
class DIEUnit {
protected:
/// The compile unit or type unit DIE. This variable must be an instance of
/// DIE so that we can calculate the DIEUnit from any DIE by traversing the
/// parent backchain and getting the Unit DIE, and then casting itself to a
/// DIEUnit. This allows us to be able to find the DIEUnit for any DIE without
/// having to store a pointer to the DIEUnit in each DIE instance.
DIE Die;
/// The section this unit will be emitted in. This may or may not be set to
/// a valid section depending on the client that is emitting DWARF.
MCSection *Section;
uint64_t Offset; /// .debug_info or .debug_types absolute section offset.
uint32_t Length; /// The length in bytes of all of the DIEs in this unit.
const uint16_t Version; /// The Dwarf version number for this unit.
const uint8_t AddrSize; /// The size in bytes of an address for this unit.
public:
DIEUnit(uint16_t Version, uint8_t AddrSize, dwarf::Tag UnitTag);
DIEUnit(const DIEUnit &RHS) = delete;
DIEUnit(DIEUnit &&RHS) = delete;
void operator=(const DIEUnit &RHS) = delete;
void operator=(const DIEUnit &&RHS) = delete;
/// Set the section that this DIEUnit will be emitted into.
///
/// This function is used by some clients to set the section. Not all clients
/// that emit DWARF use this section variable.
void setSection(MCSection *Section) {
assert(!this->Section);
this->Section = Section;
}

/// Return the section that this DIEUnit will be emitted into.
///
/// \returns Section pointer which can be NULL.
MCSection *getSection() const { return Section; }
void setDebugSectionOffset(unsigned O) { Offset = O; }
unsigned getDebugSectionOffset() const { return Offset; }
void setLength(uint64_t L) { Length = L; }
uint64_t getLength() const { return Length; }
uint16_t getDwarfVersion() const { return Version; }
uint16_t getAddressSize() const { return AddrSize; }
DIE &getUnitDie() { return Die; }
const DIE &getUnitDie() const { return Die; }
};


//===--------------------------------------------------------------------===//
/// DIELoc - Represents an expression location.
//
Expand Down
6 changes: 5 additions & 1 deletion include/llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/Support/Dwarf.h"

namespace llvm {

Expand Down Expand Up @@ -52,7 +53,10 @@ class DWARFDebugInfoEntryMinimal {
bool extractFast(const DWARFUnit &U, uint32_t *OffsetPtr,
const DataExtractor &DebugInfoData, uint32_t UEndOffset);

uint32_t getTag() const { return AbbrevDecl ? AbbrevDecl->getTag() : 0; }
dwarf::Tag getTag() const {
return AbbrevDecl ? AbbrevDecl->getTag() : dwarf::DW_TAG_null;
}

bool isNULL() const { return AbbrevDecl == nullptr; }

/// Returns true if DIE represents a subprogram (not inlined).
Expand Down
61 changes: 39 additions & 22 deletions lib/CodeGen/AsmPrinter/DIE.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,24 +108,24 @@ void DIEAbbrev::print(raw_ostream &O) {
LLVM_DUMP_METHOD
void DIEAbbrev::dump() { print(dbgs()); }

DIE *DIE::getParent() const {
return Owner.dyn_cast<DIE*>();
}

DIEAbbrev DIE::generateAbbrev() const {
DIEAbbrev Abbrev(Tag, hasChildren());
for (const DIEValue &V : values())
Abbrev.AddAttribute(V.getAttribute(), V.getForm());
return Abbrev;
}

/// Climb up the parent chain to get the unit DIE to which this DIE
/// belongs.
const DIE *DIE::getUnit() const {
const DIE *Cu = getUnitOrNull();
assert(Cu && "We should not have orphaned DIEs.");
return Cu;
unsigned DIE::getDebugSectionOffset() const {
const DIEUnit *Unit = getUnit();
assert(Unit && "DIE must be owned by a DIEUnit to get its absolute offset");
return getUnit()->getDebugSectionOffset() + getOffset();
}

/// Climb up the parent chain to get the unit DIE this DIE belongs
/// to. Return NULL if DIE is not added to an owner yet.
const DIE *DIE::getUnitOrNull() const {
const DIE *DIE::getUnitDie() const {
const DIE *p = this;
while (p) {
if (p->getTag() == dwarf::DW_TAG_compile_unit ||
Expand All @@ -136,6 +136,13 @@ const DIE *DIE::getUnitOrNull() const {
return nullptr;
}

const DIEUnit *DIE::getUnit() const {
const DIE *UnitDie = getUnitDie();
if (UnitDie)
return UnitDie->Owner.dyn_cast<DIEUnit*>();
return nullptr;
}

DIEValue DIE::findAttribute(dwarf::Attribute Attribute) const {
// Iterate through all the attributes until we find the one we're
// looking for, if we can't find it return NULL.
Expand Down Expand Up @@ -191,6 +198,16 @@ void DIE::dump() {
print(dbgs());
}

DIEUnit::DIEUnit(uint16_t V, uint8_t A, dwarf::Tag UnitTag)
: Die(UnitTag), Section(nullptr), Offset(0), Length(0), Version(V),
AddrSize(A)
{
Die.setUnit(this);
assert((UnitTag == dwarf::DW_TAG_compile_unit ||
UnitTag == dwarf::DW_TAG_type_unit ||
UnitTag == dwarf::DW_TAG_partial_unit) && "expected a unit TAG");
}

void DIEValue::EmitValue(const AsmPrinter *AP) const {
switch (Ty) {
case isNone:
Expand Down Expand Up @@ -443,19 +460,19 @@ void DIEString::print(raw_ostream &O) const {
void DIEEntry::EmitValue(const AsmPrinter *AP, dwarf::Form Form) const {

if (Form == dwarf::DW_FORM_ref_addr) {
const DwarfDebug *DD = AP->getDwarfDebug();
unsigned Addr = Entry->getOffset();
assert(!DD->useSplitDwarf() && "TODO: dwo files can't have relocations.");
// For DW_FORM_ref_addr, output the offset from beginning of debug info
// section. Entry->getOffset() returns the offset from start of the
// compile unit.
DwarfCompileUnit *CU = DD->lookupUnit(Entry->getUnit());
assert(CU && "CUDie should belong to a CU.");
Addr += CU->getDebugInfoOffset();
if (AP->MAI->doesDwarfUseRelocationsAcrossSections())
AP->EmitLabelPlusOffset(CU->getSectionSym(), Addr,
DIEEntry::getRefAddrSize(AP));
else
// 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.");
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());
Expand Down
4 changes: 1 addition & 3 deletions lib/CodeGen/AsmPrinter/DwarfAccelTable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -221,9 +221,7 @@ void DwarfAccelTable::EmitData(AsmPrinter *Asm, DwarfDebug *D) {
Asm->EmitInt32((*HI)->Data.Values.size());
for (HashDataContents *HD : (*HI)->Data.Values) {
// Emit the DIE offset
DwarfCompileUnit *CU = D->lookupUnit(HD->Die->getUnit());
assert(CU && "Accelerated DIE should belong to a CU.");
Asm->EmitInt32(HD->Die->getOffset() + CU->getDebugInfoOffset());
Asm->EmitInt32(HD->Die->getDebugSectionOffset());
// If we have multiple Atoms emit that info too.
// FIXME: A bit of a hack, we either emit only one atom or all info.
if (HeaderData.Atoms.size() > 1) {
Expand Down
2 changes: 1 addition & 1 deletion lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ void DwarfCompileUnit::initStmtList() {
// is not okay to use line_table_start here.
const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering();
StmtListValue =
addSectionLabel(UnitDie, dwarf::DW_AT_stmt_list, LineTableStartSym,
addSectionLabel(getUnitDie(), dwarf::DW_AT_stmt_list, LineTableStartSym,
TLOF.getDwarfLineSection()->getBeginSymbol());
}

Expand Down
12 changes: 1 addition & 11 deletions lib/CodeGen/AsmPrinter/DwarfCompileUnit.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,6 @@ class DwarfCompileUnit : public DwarfUnit {
/// A numeric ID unique among all CUs in the module
unsigned UniqueID;

/// Offset of the UnitDie from beginning of debug info section.
unsigned DebugInfoOffset = 0;

/// The attribute index of DW_AT_stmt_list in the compile unit DIE, avoiding
/// the need to search for it in applyStmtList.
DIE::value_iterator StmtListValue;
Expand Down Expand Up @@ -84,8 +81,6 @@ class DwarfCompileUnit : public DwarfUnit {
DwarfDebug *DW, DwarfFile *DWU);

unsigned getUniqueID() const { return UniqueID; }
unsigned getDebugInfoOffset() const { return DebugInfoOffset; }
void setDebugInfoOffset(unsigned DbgInfoOff) { DebugInfoOffset = DbgInfoOff; }

DwarfCompileUnit *getSkeleton() const {
return Skeleton;
Expand Down Expand Up @@ -191,14 +186,9 @@ class DwarfCompileUnit : public DwarfUnit {
/// Set the skeleton unit associated with this unit.
void setSkeleton(DwarfCompileUnit &Skel) { Skeleton = &Skel; }

const MCSymbol *getSectionSym() const {
assert(Section);
return Section->getBeginSymbol();
}

unsigned getLength() {
return sizeof(uint32_t) + // Length field
getHeaderSize() + UnitDie.getSize();
getHeaderSize() + getUnitDie().getSize();
}

void emitHeader(bool UseOffsets) override;
Expand Down
13 changes: 6 additions & 7 deletions lib/CodeGen/AsmPrinter/DwarfDebug.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -437,9 +437,9 @@ DwarfDebug::constructDwarfCompileUnit(const DICompileUnit *DIUnit) {
}

if (useSplitDwarf())
NewCU.initSection(Asm->getObjFileLowering().getDwarfInfoDWOSection());
NewCU.setSection(Asm->getObjFileLowering().getDwarfInfoDWOSection());
else
NewCU.initSection(Asm->getObjFileLowering().getDwarfInfoSection());
NewCU.setSection(Asm->getObjFileLowering().getDwarfInfoSection());

if (DIUnit->getDWOId()) {
// This CU is either a clang module DWO or a skeleton CU.
Expand Down Expand Up @@ -520,7 +520,7 @@ void DwarfDebug::finishVariableDefinitions() {
// FIXME: Consider the time-space tradeoff of just storing the unit pointer
// in the ConcreteVariables list, rather than looking it up again here.
// DIE::getUnit isn't simple - it walks parent pointers, etc.
DwarfCompileUnit *Unit = lookupUnit(VariableDie->getUnit());
DwarfCompileUnit *Unit = CUDieMap.lookup(VariableDie->getUnitDie());
assert(Unit);
DbgVariable *AbsVar = getExistingAbstractVariable(
InlinedVariable(Var->getVariable(), Var->getInlinedAt()));
Expand Down Expand Up @@ -1821,7 +1821,7 @@ DwarfCompileUnit &DwarfDebug::constructSkeletonCU(const DwarfCompileUnit &CU) {
auto OwnedUnit = make_unique<DwarfCompileUnit>(
CU.getUniqueID(), CU.getCUNode(), Asm, this, &SkeletonHolder);
DwarfCompileUnit &NewCU = *OwnedUnit;
NewCU.initSection(Asm->getObjFileLowering().getDwarfInfoSection());
NewCU.setSection(Asm->getObjFileLowering().getDwarfInfoSection());

NewCU.initStmtList();

Expand Down Expand Up @@ -1913,11 +1913,10 @@ void DwarfDebug::addDwarfTypeUnitType(DwarfCompileUnit &CU,
Ins.first->second = Signature;

if (useSplitDwarf())
NewTU.initSection(Asm->getObjFileLowering().getDwarfTypesDWOSection());
NewTU.setSection(Asm->getObjFileLowering().getDwarfTypesDWOSection());
else {
CU.applyStmtList(UnitDie);
NewTU.initSection(
Asm->getObjFileLowering().getDwarfTypesSection(Signature));
NewTU.setSection(Asm->getObjFileLowering().getDwarfTypesSection(Signature));
}

NewTU.setType(NewTU.createTypeDIE(CTy));
Expand Down
5 changes: 0 additions & 5 deletions lib/CodeGen/AsmPrinter/DwarfDebug.h
Original file line number Diff line number Diff line change
Expand Up @@ -533,11 +533,6 @@ class DwarfDebug : public DebugHandlerBase {
return Ref.resolve();
}

/// Find the DwarfCompileUnit for the given CU Die.
DwarfCompileUnit *lookupUnit(const DIE *CU) const {
return CUDieMap.lookup(CU);
}

void addSubprogramNames(const DISubprogram *SP, DIE &Die);

AddressPool &getAddressPool() { return AddrPool; }
Expand Down
Loading

0 comments on commit fc1fc8b

Please sign in to comment.