From 35630c3357bbdea65d4eb631274c338682343f62 Mon Sep 17 00:00:00 2001 From: Greg Clayton Date: Thu, 1 Dec 2016 18:56:29 +0000 Subject: [PATCH] This change removes the dependency on DwarfDebug that was used for DW_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 llvm-svn: 288399 --- llvm/include/llvm/CodeGen/DIE.h | 98 ++++++++++++++-- .../llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h | 6 +- llvm/lib/CodeGen/AsmPrinter/DIE.cpp | 61 ++++++---- llvm/lib/CodeGen/AsmPrinter/DwarfAccelTable.cpp | 4 +- llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp | 2 +- llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h | 12 +- llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp | 13 +-- llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h | 5 - llvm/lib/CodeGen/AsmPrinter/DwarfFile.cpp | 2 +- llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp | 29 ++--- llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h | 20 +--- llvm/tools/dsymutil/DwarfLinker.cpp | 126 +++++++++++---------- 12 files changed, 221 insertions(+), 157 deletions(-) diff --git a/llvm/include/llvm/CodeGen/DIE.h b/llvm/include/llvm/CodeGen/DIE.h index 0436fbf..341c07f 100644 --- a/llvm/include/llvm/CodeGen/DIE.h +++ b/llvm/include/llvm/CodeGen/DIE.h @@ -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" @@ -34,7 +35,10 @@ namespace llvm { class AsmPrinter; +class DIE; +class DIEUnit; class MCExpr; +class MCSection; class MCSymbol; class raw_ostream; @@ -585,12 +589,13 @@ public: }; //===--------------------------------------------------------------------===// -/// 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; + friend class DIEUnit; - /// Offset - Offset in debug info section. + /// Offset - Dwarf unit relative offset. /// unsigned Offset; @@ -607,19 +612,31 @@ class DIE : IntrusiveBackListNode, public DIEValueList { /// Children DIEs. IntrusiveBackList 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 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(); } @@ -636,7 +653,7 @@ public: return make_range(Children.begin(), Children.end()); } - DIE *getParent() const { return Parent; } + DIE *getParent() const; /// Generate the abbreviation for this DIE. /// @@ -647,19 +664,31 @@ public: /// 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(); } @@ -675,6 +704,53 @@ public: }; //===--------------------------------------------------------------------===// +/// 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. // class DIELoc : public DIEValueList { diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h index 4ec67a4..5e3a079 100644 --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h +++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h @@ -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 { @@ -52,7 +53,10 @@ public: 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). diff --git a/llvm/lib/CodeGen/AsmPrinter/DIE.cpp b/llvm/lib/CodeGen/AsmPrinter/DIE.cpp index afb7e87..6e9834a 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DIE.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DIE.cpp @@ -108,6 +108,10 @@ void DIEAbbrev::print(raw_ostream &O) { LLVM_DUMP_METHOD void DIEAbbrev::dump() { print(dbgs()); } +DIE *DIE::getParent() const { + return Owner.dyn_cast(); +} + DIEAbbrev DIE::generateAbbrev() const { DIEAbbrev Abbrev(Tag, hasChildren()); for (const DIEValue &V : values()) @@ -115,17 +119,13 @@ DIEAbbrev DIE::generateAbbrev() const { 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 || @@ -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(); + 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. @@ -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: @@ -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()); diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfAccelTable.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfAccelTable.cpp index 4ad3e18..9c324ea 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfAccelTable.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfAccelTable.cpp @@ -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) { diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp index 1aabf69..84981ac 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp @@ -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()); } diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h index 766da4a..b1f818b 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h @@ -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; @@ -84,8 +81,6 @@ public: 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; @@ -191,14 +186,9 @@ public: /// 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; diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index 1f662e5..acb8ce0 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -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. @@ -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())); @@ -1821,7 +1821,7 @@ DwarfCompileUnit &DwarfDebug::constructSkeletonCU(const DwarfCompileUnit &CU) { auto OwnedUnit = make_unique( CU.getUniqueID(), CU.getCUNode(), Asm, this, &SkeletonHolder); DwarfCompileUnit &NewCU = *OwnedUnit; - NewCU.initSection(Asm->getObjFileLowering().getDwarfInfoSection()); + NewCU.setSection(Asm->getObjFileLowering().getDwarfInfoSection()); NewCU.initStmtList(); @@ -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)); diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h index b2d912b..3a9fa8b 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h @@ -533,11 +533,6 @@ public: 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; } diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfFile.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfFile.cpp index e9fe98a..3179ab1 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfFile.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfFile.cpp @@ -80,7 +80,7 @@ void DwarfFile::computeSizeAndOffsets() { // Iterate over each compile unit and set the size and offsets for each // DIE within each compile unit. All offsets are CU relative. for (const auto &TheU : CUs) { - TheU->setDebugInfoOffset(SecOffset); + TheU->setDebugSectionOffset(SecOffset); SecOffset += computeSizeAndOffsetsForUnit(TheU.get()); } } diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp index ab4a7a3..1923d03 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp @@ -73,10 +73,8 @@ bool DIEDwarfExpression::isFrameRegister(const TargetRegisterInfo &TRI, DwarfUnit::DwarfUnit(dwarf::Tag UnitTag, const DICompileUnit *Node, AsmPrinter *A, DwarfDebug *DW, DwarfFile *DWU) - : CUNode(Node), UnitDie(*DIE::get(DIEValueAllocator, UnitTag)), Asm(A), - DD(DW), DU(DWU), IndexTyDie(nullptr), Section(nullptr) { - assert(UnitTag == dwarf::DW_TAG_compile_unit || - UnitTag == dwarf::DW_TAG_type_unit); + : DIEUnit(A->getDwarfVersion(), A->getPointerSize(), UnitTag), CUNode(Node), + Asm(A), DD(DW), DU(DWU), IndexTyDie(nullptr) { } DwarfTypeUnit::DwarfTypeUnit(DwarfCompileUnit &CU, AsmPrinter *A, @@ -85,7 +83,7 @@ DwarfTypeUnit::DwarfTypeUnit(DwarfCompileUnit &CU, AsmPrinter *A, : DwarfUnit(dwarf::DW_TAG_type_unit, CU.getCUNode(), A, DW, DWU), CU(CU), SplitLineTable(SplitLineTable) { if (SplitLineTable) - addSectionOffset(UnitDie, dwarf::DW_AT_stmt_list, 0); + addSectionOffset(getUnitDie(), dwarf::DW_AT_stmt_list, 0); } DwarfUnit::~DwarfUnit() { @@ -294,15 +292,15 @@ void DwarfUnit::addDIETypeSignature(DIE &Die, dwarf::Attribute Attribute, void DwarfUnit::addDIEEntry(DIE &Die, dwarf::Attribute Attribute, DIEEntry Entry) { - const DIE *DieCU = Die.getUnitOrNull(); - const DIE *EntryCU = Entry.getEntry().getUnitOrNull(); - if (!DieCU) + const DIEUnit *CU = Die.getUnit(); + const DIEUnit *EntryCU = Entry.getEntry().getUnit(); + if (!CU) // We assume that Die belongs to this CU, if it is not linked to any CU yet. - DieCU = &getUnitDie(); + CU = getUnitDie().getUnit(); if (!EntryCU) - EntryCU = &getUnitDie(); + EntryCU = getUnitDie().getUnit(); Die.addValue(DIEValueAllocator, Attribute, - EntryCU == DieCU ? dwarf::DW_FORM_ref4 : dwarf::DW_FORM_ref_addr, + EntryCU == CU ? dwarf::DW_FORM_ref4 : dwarf::DW_FORM_ref_addr, Entry); } @@ -1313,7 +1311,7 @@ DIE *DwarfUnit::getIndexTyDie() { if (IndexTyDie) return IndexTyDie; // Construct an integer type to use for indexes. - IndexTyDie = &createAndAddDIE(dwarf::DW_TAG_base_type, UnitDie); + IndexTyDie = &createAndAddDIE(dwarf::DW_TAG_base_type, getUnitDie()); addString(*IndexTyDie, dwarf::DW_AT_name, "sizetype"); addUInt(*IndexTyDie, dwarf::DW_AT_byte_size, None, sizeof(int64_t)); addUInt(*IndexTyDie, dwarf::DW_AT_encoding, dwarf::DW_FORM_data1, @@ -1535,7 +1533,7 @@ DIE *DwarfUnit::getOrCreateStaticMemberDIE(const DIDerivedType *DT) { void DwarfUnit::emitHeader(bool UseOffsets) { // Emit size of content not including length itself Asm->OutStreamer->AddComment("Length of Unit"); - Asm->EmitInt32(getHeaderSize() + UnitDie.getSize()); + Asm->EmitInt32(getHeaderSize() + getUnitDie().getSize()); Asm->OutStreamer->AddComment("DWARF version number"); Asm->EmitInt16(DD->getDwarfVersion()); @@ -1555,11 +1553,6 @@ void DwarfUnit::emitHeader(bool UseOffsets) { Asm->EmitInt8(Asm->getDataLayout().getPointerSize()); } -void DwarfUnit::initSection(MCSection *Section) { - assert(!this->Section); - this->Section = Section; -} - void DwarfTypeUnit::emitHeader(bool UseOffsets) { DwarfUnit::emitHeader(UseOffsets); Asm->OutStreamer->AddComment("Type Signature"); diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h index e225f92..6d045ea 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h @@ -65,7 +65,7 @@ public: //===----------------------------------------------------------------------===// /// This dwarf writer support class manages information associated with a /// source file. -class DwarfUnit { + class DwarfUnit : public DIEUnit { protected: /// MDNode for the compile unit. const DICompileUnit *CUNode; @@ -73,9 +73,6 @@ protected: // All DIEValues are allocated through this allocator. BumpPtrAllocator DIEValueAllocator; - /// Unit debug information entry. - DIE &UnitDie; - /// Target of Dwarf emission. AsmPrinter *Asm; @@ -83,7 +80,7 @@ protected: DwarfDebug *DD; DwarfFile *DU; - /// An anonymous type for index type. Owned by UnitDie. + /// An anonymous type for index type. Owned by DIEUnit. DIE *IndexTyDie; /// Tracks the mapping of unit level debug information variables to debug @@ -101,9 +98,6 @@ protected: /// corresponds to the MDNode mapped with the subprogram DIE. DenseMap ContainingTypeMap; - /// The section this unit will be emitted in. - MCSection *Section; - DwarfUnit(dwarf::Tag, const DICompileUnit *CU, AsmPrinter *A, DwarfDebug *DW, DwarfFile *DWU); @@ -112,21 +106,13 @@ protected: public: virtual ~DwarfUnit(); - void initSection(MCSection *Section); - - MCSection *getSection() const { - assert(Section); - return Section; - } - // Accessors. AsmPrinter* getAsmPrinter() const { return Asm; } uint16_t getLanguage() const { return CUNode->getSourceLanguage(); } const DICompileUnit *getCUNode() const { return CUNode; } - DIE &getUnitDie() { return UnitDie; } /// Return true if this compile unit has something to write out. - bool hasContent() const { return UnitDie.hasChildren(); } + bool hasContent() const { return Die.hasChildren(); } /// Get string containing language specific context for a global name. /// diff --git a/llvm/tools/dsymutil/DwarfLinker.cpp b/llvm/tools/dsymutil/DwarfLinker.cpp index ef4f8a9..d692d49 100644 --- a/llvm/tools/dsymutil/DwarfLinker.cpp +++ b/llvm/tools/dsymutil/DwarfLinker.cpp @@ -38,6 +38,7 @@ #include "llvm/Support/TargetRegistry.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetOptions.h" +#include #include #include @@ -197,8 +198,11 @@ public: CompileUnit(DWARFUnit &OrigUnit, unsigned ID, bool CanUseODR, StringRef ClangModuleName) - : OrigUnit(OrigUnit), ID(ID), LowPc(UINT64_MAX), HighPc(0), RangeAlloc(), - Ranges(RangeAlloc), ClangModuleName(ClangModuleName) { + : OrigUnit(OrigUnit), ID(ID), NewUnit(OrigUnit.getVersion(), + OrigUnit.getAddressByteSize(), + OrigUnit.getUnitDIE()->getTag()), + LowPc(UINT64_MAX), HighPc(0), RangeAlloc(), Ranges(RangeAlloc), + ClangModuleName(ClangModuleName) { Info.resize(OrigUnit.getNumDIEs()); const auto *CUDie = OrigUnit.getUnitDIE(false); @@ -211,21 +215,13 @@ public: Lang == dwarf::DW_LANG_ObjC_plus_plus); } - CompileUnit(CompileUnit &&RHS) - : OrigUnit(RHS.OrigUnit), Info(std::move(RHS.Info)), - CUDie(std::move(RHS.CUDie)), StartOffset(RHS.StartOffset), - NextUnitOffset(RHS.NextUnitOffset), RangeAlloc(), Ranges(RangeAlloc) { - // The CompileUnit container has been 'reserve()'d with the right - // size. We cannot move the IntervalMap anyway. - llvm_unreachable("CompileUnits should not be moved."); - } - DWARFUnit &getOrigUnit() const { return OrigUnit; } unsigned getUniqueID() const { return ID; } - DIE *getOutputUnitDIE() const { return CUDie; } - void setOutputUnitDIE(DIE *Die) { CUDie = Die; } + DIE *getOutputUnitDIE() const { + return &const_cast(NewUnit).getUnitDie(); + } bool hasODR() const { return HasODR; } bool isClangModule() const { return !ClangModuleName.empty(); } @@ -333,7 +329,7 @@ private: DWARFUnit &OrigUnit; unsigned ID; std::vector Info; ///< DIE info indexed by DIE index. - DIE *CUDie; ///< Root of the linked DIE tree. + DIEUnit NewUnit; uint64_t StartOffset; uint64_t NextUnitOffset; @@ -401,8 +397,7 @@ uint64_t CompileUnit::computeNextUnitOffset() { // The root DIE might be null, meaning that the Unit had nothing to // contribute to the linked output. In that case, we will emit the // unit header without any actual DIE. - if (CUDie) - NextUnitOffset += CUDie->getSize(); + NextUnitOffset += NewUnit.getUnitDie().getSize(); return NextUnitOffset; } @@ -1266,13 +1261,14 @@ private: RelocationManager &RelocMgr; /// Allocator used for all the DIEValue objects. BumpPtrAllocator &DIEAlloc; - MutableArrayRef CompileUnits; + std::vector> &CompileUnits; LinkOptions Options; public: DIECloner(DwarfLinker &Linker, RelocationManager &RelocMgr, BumpPtrAllocator &DIEAlloc, - MutableArrayRef CompileUnits, LinkOptions &Options) + std::vector> &CompileUnits, + LinkOptions &Options) : Linker(Linker), RelocMgr(RelocMgr), DIEAlloc(DIEAlloc), CompileUnits(CompileUnits), Options(Options) {} @@ -1285,10 +1281,11 @@ private: /// compile unit. /// \param PCOffset (while cloning a function scope) is the offset /// applied to the entry point of the function to get the linked address. - /// + /// \param Die the output DIE to use, pass NULL to create one. /// \returns the root of the cloned tree or null if nothing was selected. DIE *cloneDIE(const DWARFDebugInfoEntryMinimal &InputDIE, CompileUnit &U, - int64_t PCOffset, uint32_t OutOffset, unsigned Flags); + int64_t PCOffset, uint32_t OutOffset, unsigned Flags, + DIE *Die = nullptr); /// Construct the output DIE tree by cloning the DIEs we /// chose to keep above. If there are no valid relocs, then there's @@ -1433,7 +1430,8 @@ private: unsigned UnitID; ///< A unique ID that identifies each compile unit. /// The units of the current debug map object. - std::vector Units; + std::vector> Units; + /// The debug map object currently under consideration. DebugMapObject *CurrentDebugObject; @@ -1468,14 +1466,14 @@ private: /// Similar to DWARFUnitSection::getUnitForOffset(), but returning our /// CompileUnit object instead. -static CompileUnit *getUnitForOffset(MutableArrayRef Units, - unsigned Offset) { +static CompileUnit *getUnitForOffset( + std::vector> &Units, unsigned Offset) { auto CU = std::upper_bound(Units.begin(), Units.end(), Offset, - [](uint32_t LHS, const CompileUnit &RHS) { - return LHS < RHS.getOrigUnit().getNextUnitOffset(); + [](uint32_t LHS, const std::unique_ptr &RHS) { + return LHS < RHS->getOrigUnit().getNextUnitOffset(); }); - return CU != Units.end() ? &*CU : nullptr; + return CU != Units.end() ? CU->get() : nullptr; } /// Resolve the DIE attribute reference that has been @@ -1483,7 +1481,7 @@ static CompileUnit *getUnitForOffset(MutableArrayRef Units, /// CompileUnit which is stored into \p ReferencedCU. /// \returns null if resolving fails for any reason. static const DWARFDebugInfoEntryMinimal *resolveDIEReference( - const DwarfLinker &Linker, MutableArrayRef Units, + const DwarfLinker &Linker, std::vector> &Units, const DWARFFormValue &RefValue, const DWARFUnit &Unit, const DWARFDebugInfoEntryMinimal &DIE, CompileUnit *&RefCU) { assert(RefValue.isFormClass(DWARFFormValue::FC_Reference)); @@ -1839,7 +1837,6 @@ static bool dieNeedsChildrenToBeMeaningful(uint32_t Tag) { } void DwarfLinker::startDebugObject(DWARFContext &Dwarf, DebugMapObject &Obj) { - Units.reserve(Dwarf.getNumCompileUnits()); // Iterate over the debug map entries and put all the ones that are // functions (because they have a size) into the Ranges map. This // map is very similar to the FunctionRanges that are stored in each @@ -2185,6 +2182,8 @@ unsigned DwarfLinker::shouldKeepDIE(RelocationManager &RelocMgr, case dwarf::DW_TAG_imported_unit: // We always want to keep these. return Flags | TF_Keep; + default: + break; } return Flags; @@ -2233,8 +2232,7 @@ void DwarfLinker::keepDIEAndDependencies(RelocationManager &RelocMgr, Val.extractValue(Data, &Offset, &Unit); CompileUnit *ReferencedCU; if (const auto *RefDIE = - resolveDIEReference(*this, MutableArrayRef(Units), Val, - Unit, Die, ReferencedCU)) { + resolveDIEReference(*this, Units, Val, Unit, Die, ReferencedCU)) { uint32_t RefIdx = ReferencedCU->getOrigUnit().getDIEIndex(RefDIE); CompileUnit::DIEInfo &Info = ReferencedCU->getInfo(RefIdx); // If the referenced DIE has a DeclContext that has already been @@ -2704,7 +2702,7 @@ shouldSkipAttribute(DWARFAbbreviationDeclaration::AttributeSpec AttrSpec, DIE *DwarfLinker::DIECloner::cloneDIE( const DWARFDebugInfoEntryMinimal &InputDIE, CompileUnit &Unit, - int64_t PCOffset, uint32_t OutOffset, unsigned Flags) { + int64_t PCOffset, uint32_t OutOffset, unsigned Flags, DIE *Die) { DWARFUnit &U = Unit.getOrigUnit(); unsigned Idx = U.getDIEIndex(&InputDIE); CompileUnit::DIEInfo &Info = Unit.getInfo(Idx); @@ -2714,11 +2712,16 @@ DIE *DwarfLinker::DIECloner::cloneDIE( return nullptr; uint32_t Offset = InputDIE.getOffset(); - // The DIE might have been already created by a forward reference - // (see cloneDieReferenceAttribute()). - DIE *Die = Info.Clone; - if (!Die) - Die = Info.Clone = DIE::get(DIEAlloc, dwarf::Tag(InputDIE.getTag())); + assert(!(Die && Info.Clone) && "Can't supply a DIE and a cloned DIE"); + if (!Die) { + // The DIE might have been already created by a forward reference + // (see cloneDieReferenceAttribute()). + if (Info.Clone) + Die = Info.Clone; + else + Die = Info.Clone = DIE::get(DIEAlloc, dwarf::Tag(InputDIE.getTag())); + } + assert(Die->getTag() == InputDIE.getTag()); Die->setOffset(OutOffset); if ((Unit.hasODR() || Unit.isClangModule()) && @@ -3374,8 +3377,9 @@ void DwarfLinker::loadClangModule(StringRef Filename, StringRef ModulePath, outs() << "cloning .debug_info from " << Filename << "\n"; } - DIECloner(*this, RelocMgr, DIEAlloc, MutableArrayRef(*Unit), - Options) + std::vector> CompileUnits; + CompileUnits.push_back(std::move(Unit)); + DIECloner(*this, RelocMgr, DIEAlloc, CompileUnits, Options) .cloneAllCompileUnits(DwarfContext); } @@ -3385,23 +3389,24 @@ void DwarfLinker::DIECloner::cloneAllCompileUnits( return; for (auto &CurrentUnit : CompileUnits) { - const auto *InputDIE = CurrentUnit.getOrigUnit().getUnitDIE(); - CurrentUnit.setStartOffset(Linker.OutputDebugInfoSize); - DIE *OutputDIE = cloneDIE(*InputDIE, CurrentUnit, 0 /* PC offset */, - 11 /* Unit Header size */, 0); - CurrentUnit.setOutputUnitDIE(OutputDIE); - Linker.OutputDebugInfoSize = CurrentUnit.computeNextUnitOffset(); + const auto *InputDIE = CurrentUnit->getOrigUnit().getUnitDIE(); + CurrentUnit->setStartOffset(Linker.OutputDebugInfoSize); + // Clonse the InputDIE into your Unit DIE in our compile unit since it + // already has a DIE inside of it. + if (!cloneDIE(*InputDIE, *CurrentUnit, 0 /* PC offset */, + 11 /* Unit Header size */, 0, + CurrentUnit->getOutputUnitDIE())) + continue; + Linker.OutputDebugInfoSize = CurrentUnit->computeNextUnitOffset(); if (Linker.Options.NoOutput) continue; // FIXME: for compatibility with the classic dsymutil, we emit // an empty line table for the unit, even if the unit doesn't // actually exist in the DIE tree. - Linker.patchLineTableForUnit(CurrentUnit, DwarfContext); - if (!OutputDIE) - continue; - Linker.patchRangesForUnit(CurrentUnit, DwarfContext); - Linker.Streamer->emitLocationsForUnit(CurrentUnit, DwarfContext); - Linker.emitAcceleratorEntriesForUnit(CurrentUnit); + Linker.patchLineTableForUnit(*CurrentUnit, DwarfContext); + Linker.patchRangesForUnit(*CurrentUnit, DwarfContext); + Linker.Streamer->emitLocationsForUnit(*CurrentUnit, DwarfContext); + Linker.emitAcceleratorEntriesForUnit(*CurrentUnit); } if (Linker.Options.NoOutput) @@ -3409,12 +3414,12 @@ void DwarfLinker::DIECloner::cloneAllCompileUnits( // Emit all the compile unit's debug information. for (auto &CurrentUnit : CompileUnits) { - Linker.generateUnitRanges(CurrentUnit); - CurrentUnit.fixupForwardReferences(); - Linker.Streamer->emitCompileUnitHeader(CurrentUnit); - if (!CurrentUnit.getOutputUnitDIE()) + Linker.generateUnitRanges(*CurrentUnit); + CurrentUnit->fixupForwardReferences(); + Linker.Streamer->emitCompileUnitHeader(*CurrentUnit); + if (!CurrentUnit->getOutputUnitDIE()) continue; - Linker.Streamer->emitDIE(*CurrentUnit.getOutputUnitDIE()); + Linker.Streamer->emitDIE(*CurrentUnit->getOutputUnitDIE()); } } @@ -3459,12 +3464,13 @@ bool DwarfLinker::link(const DebugMap &Map) { } if (!registerModuleReference(*CUDie, *CU, ModuleMap)) - Units.emplace_back(*CU, UnitID++, !Options.NoODR, ""); + Units.push_back(llvm::make_unique(*CU, UnitID++, + !Options.NoODR, "")); } // Now build the DIE parent links that we will use during the next phase. for (auto &CurrentUnit : Units) - analyzeContextInfo(CurrentUnit.getOrigUnit().getUnitDIE(), 0, CurrentUnit, + analyzeContextInfo(CurrentUnit->getOrigUnit().getUnitDIE(), 0, *CurrentUnit, &ODRContexts.getRoot(), StringPool, ODRContexts); // Then mark all the DIEs that need to be present in the linked @@ -3473,8 +3479,8 @@ bool DwarfLinker::link(const DebugMap &Map) { // references require the ParentIdx to be setup for every CU in // the object file before calling this. for (auto &CurrentUnit : Units) - lookForDIEsToKeep(RelocMgr, *CurrentUnit.getOrigUnit().getUnitDIE(), *Obj, - CurrentUnit, 0); + lookForDIEsToKeep(RelocMgr, *CurrentUnit->getOrigUnit().getUnitDIE(), *Obj, + *CurrentUnit, 0); // The calls to applyValidRelocs inside cloneDIE will walk the // reloc array again (in the same way findValidRelocsInDebugInfo() @@ -3485,7 +3491,7 @@ bool DwarfLinker::link(const DebugMap &Map) { .cloneAllCompileUnits(DwarfContext); if (!Options.NoOutput && !Units.empty()) patchFrameInfoForObject(*Obj, DwarfContext, - Units[0].getOrigUnit().getAddressByteSize()); + Units[0]->getOrigUnit().getAddressByteSize()); // Clean-up before starting working on the next object. endDebugObject(); -- 2.7.4