From: Jonas Devlieghere Date: Wed, 11 Jul 2018 17:11:11 +0000 (+0000) Subject: [DebugInfo] Make children iterator bidirectional X-Git-Tag: android-x86-8.1-r1~972 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=f8497881d6aa3d753c18d65381d372c80e727c18;p=android-x86%2Fexternal-llvm.git [DebugInfo] Make children iterator bidirectional Make the DIE iterator bidirectional so we can move to the previous sibling of a DIE. Differential revision: https://reviews.llvm.org/D49173 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@336823 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/DebugInfo/DWARF/DWARFDie.h b/include/llvm/DebugInfo/DWARF/DWARFDie.h index 3bc13c07f6d..6e6b57cbcbd 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFDie.h +++ b/include/llvm/DebugInfo/DWARF/DWARFDie.h @@ -104,12 +104,24 @@ public: /// invalid DWARFDie instance if it doesn't. DWARFDie getSibling() const; + /// Get the previous sibling of this DIE object. + /// + /// \returns a valid DWARFDie instance if this object has a sibling or an + /// invalid DWARFDie instance if it doesn't. + DWARFDie getPreviousSibling() const; + /// Get the first child of this DIE object. /// /// \returns a valid DWARFDie instance if this object has children or an /// invalid DWARFDie instance if it doesn't. DWARFDie getFirstChild() const; + /// Get the last child of this DIE object. + /// + /// \returns a valid null DWARFDie instance if this object has children or an + /// invalid DWARFDie instance if it doesn't. + DWARFDie getLastChild() const; + /// Dump the DIE and all of its attributes to the supplied stream. /// /// \param OS the stream to use for output. @@ -288,6 +300,7 @@ public: explicit attribute_iterator(DWARFDie D, bool End); attribute_iterator &operator++(); + attribute_iterator &operator--(); explicit operator bool() const { return AttrValue.isValid(); } const DWARFAttribute &operator*() const { return AttrValue; } bool operator==(const attribute_iterator &X) const { return Index == X.Index; } @@ -306,26 +319,23 @@ inline bool operator<(const DWARFDie &LHS, const DWARFDie &RHS) { return LHS.getOffset() < RHS.getOffset(); } -class DWARFDie::iterator : public iterator_facade_base { +class DWARFDie::iterator + : public iterator_facade_base { DWARFDie Die; - void skipNull() { - if (Die && Die.isNULL()) - Die = DWARFDie(); - } public: iterator() = default; explicit iterator(DWARFDie D) : Die(D) { - // If we start out with only a Null DIE then invalidate. - skipNull(); } iterator &operator++() { Die = Die.getSibling(); - // Don't include the NULL die when iterating. - skipNull(); + return *this; + } + + iterator &operator--() { + Die = Die.getPreviousSibling(); return *this; } @@ -341,7 +351,7 @@ inline DWARFDie::iterator DWARFDie::begin() const { } inline DWARFDie::iterator DWARFDie::end() const { - return iterator(); + return iterator(getLastChild()); } inline iterator_range DWARFDie::children() const { diff --git a/include/llvm/DebugInfo/DWARF/DWARFUnit.h b/include/llvm/DebugInfo/DWARF/DWARFUnit.h index 7c1a0d8c636..988a7958184 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFUnit.h +++ b/include/llvm/DebugInfo/DWARF/DWARFUnit.h @@ -508,7 +508,9 @@ public: DWARFDie getParent(const DWARFDebugInfoEntry *Die); DWARFDie getSibling(const DWARFDebugInfoEntry *Die); + DWARFDie getPreviousSibling(const DWARFDebugInfoEntry *Die); DWARFDie getFirstChild(const DWARFDebugInfoEntry *Die); + DWARFDie getLastChild(const DWARFDebugInfoEntry *Die); /// Return the DIE object for a given offset inside the /// unit's DIE vector. diff --git a/lib/DebugInfo/DWARF/DWARFDie.cpp b/lib/DebugInfo/DWARF/DWARFDie.cpp index 0ef65c2b0b6..904ceab7b28 100644 --- a/lib/DebugInfo/DWARF/DWARFDie.cpp +++ b/lib/DebugInfo/DWARF/DWARFDie.cpp @@ -555,12 +555,24 @@ DWARFDie DWARFDie::getSibling() const { return DWARFDie(); } +DWARFDie DWARFDie::getPreviousSibling() const { + if (isValid()) + return U->getPreviousSibling(Die); + return DWARFDie(); +} + DWARFDie DWARFDie::getFirstChild() const { if (isValid()) return U->getFirstChild(Die); return DWARFDie(); } +DWARFDie DWARFDie::getLastChild() const { + if (isValid()) + return U->getLastChild(Die); + return DWARFDie(); +} + iterator_range DWARFDie::attributes() const { return make_range(attribute_iterator(*this, false), attribute_iterator(*this, true)); diff --git a/lib/DebugInfo/DWARF/DWARFUnit.cpp b/lib/DebugInfo/DWARF/DWARFUnit.cpp index 6b7970d426b..7581575e2a4 100644 --- a/lib/DebugInfo/DWARF/DWARFUnit.cpp +++ b/lib/DebugInfo/DWARF/DWARFUnit.cpp @@ -584,6 +584,24 @@ DWARFDie DWARFUnit::getSibling(const DWARFDebugInfoEntry *Die) { return DWARFDie(); } +DWARFDie DWARFUnit::getPreviousSibling(const DWARFDebugInfoEntry *Die) { + if (!Die) + return DWARFDie(); + uint32_t Depth = Die->getDepth(); + // Unit DIEs always have a depth of zero and never have siblings. + if (Depth == 0) + return DWARFDie(); + + // Find the previous DIE whose depth is the same as the Die's depth. + for (size_t I = getDIEIndex(Die) - 1; I >= 0; --I) { + if (DieArray[I].getDepth() == Depth - 1) + return DWARFDie(); + if (DieArray[I].getDepth() == Depth) + return DWARFDie(this, &DieArray[I]); + } + return DWARFDie(); +} + DWARFDie DWARFUnit::getFirstChild(const DWARFDebugInfoEntry *Die) { if (!Die->hasChildren()) return DWARFDie(); @@ -595,6 +613,21 @@ DWARFDie DWARFUnit::getFirstChild(const DWARFDebugInfoEntry *Die) { return DWARFDie(this, &DieArray[I]); } +DWARFDie DWARFUnit::getLastChild(const DWARFDebugInfoEntry *Die) { + if (!Die->hasChildren()) + return DWARFDie(); + + uint32_t Depth = Die->getDepth(); + for (size_t I = getDIEIndex(Die) + 1, EndIdx = DieArray.size(); I < EndIdx; + ++I) { + if (DieArray[I].getDepth() == Depth + 1 && + DieArray[I].getTag() == dwarf::DW_TAG_null) + return DWARFDie(this, &DieArray[I]); + assert(DieArray[I].getDepth() > Depth && "Not processing children?"); + } + return DWARFDie(); +} + const DWARFAbbreviationDeclarationSet *DWARFUnit::getAbbreviations() const { if (!Abbrevs) Abbrevs = Abbrev->getAbbreviationDeclarationSet(Header.getAbbrOffset()); diff --git a/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp b/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp index 02af290a123..6b26318802a 100644 --- a/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp +++ b/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp @@ -490,6 +490,11 @@ template void TestChildren() { EXPECT_TRUE(!NullDieDG.getSibling().isValid()); EXPECT_TRUE(!NullDieDG.getFirstChild().isValid()); } + + // Verify the previous sibling of our subprogram is our integer base type. + IntDieDG = NullDieDG.getPreviousSibling(); + EXPECT_TRUE(IntDieDG.isValid()); + EXPECT_EQ(IntDieDG.getTag(), DW_TAG_base_type); } TEST(DWARFDebugInfo, TestDWARF32Version2Addr4Children) { @@ -1072,6 +1077,27 @@ TEST(DWARFDebugInfo, TestRelations) { // Make sure the parent of all the children of the B are the B. EXPECT_EQ(C1.getParent(), C); EXPECT_EQ(C2.getParent(), C); + + // Make sure bidirectional iterator works as expected. + auto Begin = A.begin(); + auto End = A.end(); + auto It = A.begin(); + + EXPECT_EQ(It, Begin); + EXPECT_EQ(*It, B); + ++It; + EXPECT_EQ(*It, C); + ++It; + EXPECT_EQ(*It, D); + ++It; + EXPECT_EQ(It, End); + --It; + EXPECT_EQ(*It, D); + --It; + EXPECT_EQ(*It, C); + --It; + EXPECT_EQ(*It, B); + EXPECT_EQ(It, Begin); } TEST(DWARFDebugInfo, TestDWARFDie) {