Index: llvm/trunk/include/llvm/CodeGen/DIE.h =================================================================== --- llvm/trunk/include/llvm/CodeGen/DIE.h +++ llvm/trunk/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 @@ }; //===--------------------------------------------------------------------===// -/// 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 @@ /// 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 @@ 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 @@ /// 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 @@ }; //===--------------------------------------------------------------------===// +/// 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 { Index: llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h =================================================================== --- llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h +++ llvm/trunk/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 @@ 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). Index: llvm/trunk/lib/CodeGen/AsmPrinter/DIE.cpp =================================================================== --- llvm/trunk/lib/CodeGen/AsmPrinter/DIE.cpp +++ llvm/trunk/lib/CodeGen/AsmPrinter/DIE.cpp @@ -108,6 +108,10 @@ 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 @@ 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 @@ 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 @@ 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 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()); Index: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfAccelTable.cpp =================================================================== --- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfAccelTable.cpp +++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfAccelTable.cpp @@ -221,9 +221,7 @@ 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) { Index: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h =================================================================== --- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h +++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h @@ -32,9 +32,6 @@ /// 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 @@ 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 @@ /// 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; Index: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp =================================================================== --- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp +++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp @@ -242,7 +242,7 @@ // 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()); } Index: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.h =================================================================== --- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.h +++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.h @@ -533,11 +533,6 @@ 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; } Index: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp =================================================================== --- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -437,9 +437,9 @@ } 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 @@ // 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 @@ 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 @@ 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)); Index: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfFile.cpp =================================================================== --- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfFile.cpp +++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfFile.cpp @@ -80,7 +80,7 @@ // 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()); } } Index: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.h =================================================================== --- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.h +++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.h @@ -65,7 +65,7 @@ //===----------------------------------------------------------------------===// /// 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 @@ // 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 @@ 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 @@ /// 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 @@ 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. /// Index: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.cpp =================================================================== --- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.cpp +++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.cpp @@ -73,10 +73,8 @@ 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 @@ : 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::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 @@ 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 @@ 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 @@ 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"); Index: llvm/trunk/tools/dsymutil/DwarfLinker.cpp =================================================================== --- llvm/trunk/tools/dsymutil/DwarfLinker.cpp +++ llvm/trunk/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 @@ 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 @@ 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 @@ 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 @@ // 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 @@ 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 @@ /// 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 @@ 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 @@ /// 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 @@ /// 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 @@ } 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 @@ case dwarf::DW_TAG_imported_unit: // We always want to keep these. return Flags | TF_Keep; + default: + break; } return Flags; @@ -2233,8 +2232,7 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ // 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 @@ } 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 @@ // 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 @@ .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();