diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h +++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h @@ -12,8 +12,8 @@ #include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h" #include "llvm/Support/DataExtractor.h" #include +#include #include -#include namespace llvm { @@ -21,20 +21,21 @@ class DWARFAbbreviationDeclarationSet { uint64_t Offset; + mutable uint64_t CurOffset; /// Code of the first abbreviation, if all abbreviations in the set have /// consecutive codes. UINT32_MAX otherwise. - uint32_t FirstAbbrCode; - std::vector Decls; + mutable uint32_t FirstAbbrCode; + mutable std::deque Decls; + mutable std::optional Data; - using const_iterator = - std::vector::const_iterator; + using const_iterator = decltype(Decls)::const_iterator; public: DWARFAbbreviationDeclarationSet(); uint64_t getOffset() const { return Offset; } void dump(raw_ostream &OS) const; - bool extract(DataExtractor Data, uint64_t *OffsetPtr); + bool extract(DataExtractor Data, uint64_t *OffsetPtr, bool Lazy = false); const DWARFAbbreviationDeclaration * getAbbreviationDeclaration(uint32_t AbbrCode) const; @@ -65,7 +66,7 @@ DWARFDebugAbbrev(); const DWARFAbbreviationDeclarationSet * - getAbbreviationDeclarationSet(uint64_t CUAbbrOffset) const; + getAbbreviationDeclarationSet(uint64_t CUAbbrOffset, bool Lazy = false) const; void dump(raw_ostream &OS) const; void parse() const; diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h +++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h @@ -402,7 +402,8 @@ uint64_t getAbbreviationsOffset() const { return Header.getAbbrOffset(); } - const DWARFAbbreviationDeclarationSet *getAbbreviations() const; + const DWARFAbbreviationDeclarationSet * + getAbbreviations(bool Lazy = false) const; static bool isMatchingUnitTypeAndTag(uint8_t UnitType, dwarf::Tag Tag) { switch (UnitType) { diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugAbbrev.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugAbbrev.cpp --- a/llvm/lib/DebugInfo/DWARF/DWARFDebugAbbrev.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugAbbrev.cpp @@ -22,14 +22,15 @@ void DWARFAbbreviationDeclarationSet::clear() { Offset = 0; FirstAbbrCode = 0; + Data = std::nullopt; + CurOffset = 0; Decls.clear(); } bool DWARFAbbreviationDeclarationSet::extract(DataExtractor Data, - uint64_t *OffsetPtr) { + uint64_t *OffsetPtr, bool Lazy) { clear(); - const uint64_t BeginOffset = *OffsetPtr; - Offset = BeginOffset; + Offset = *OffsetPtr; DWARFAbbreviationDeclaration AbbrDecl; uint32_t PrevAbbrCode = 0; while (AbbrDecl.extract(Data, OffsetPtr)) { @@ -43,8 +44,13 @@ } PrevAbbrCode = AbbrDecl.getCode(); Decls.push_back(std::move(AbbrDecl)); + if (Lazy) { + this->Data = Data; + CurOffset = *OffsetPtr; + return true; + } } - return BeginOffset != *OffsetPtr; + return Offset != *OffsetPtr; } void DWARFAbbreviationDeclarationSet::dump(raw_ostream &OS) const { @@ -60,11 +66,31 @@ if (Decl.getCode() == AbbrCode) return &Decl; } - return nullptr; + } else if (AbbrCode >= FirstAbbrCode && + AbbrCode < FirstAbbrCode + Decls.size()) { + return &Decls[AbbrCode - FirstAbbrCode]; } - if (AbbrCode < FirstAbbrCode || AbbrCode >= FirstAbbrCode + Decls.size()) - return nullptr; - return &Decls[AbbrCode - FirstAbbrCode]; + if (Data) { + DWARFAbbreviationDeclaration AbbrDecl; + uint32_t PrevAbbrCode = 0; + while (AbbrDecl.extract(*Data, &CurOffset)) { + if (FirstAbbrCode == 0) { + FirstAbbrCode = AbbrDecl.getCode(); + } else { + if (PrevAbbrCode + 1 != AbbrDecl.getCode()) { + // Codes are not consecutive, can't do O(1) lookups. + FirstAbbrCode = UINT32_MAX; + } + } + PrevAbbrCode = AbbrDecl.getCode(); + Decls.push_back(std::move(AbbrDecl)); + if (AbbrDecl.getCode()) + return &Decls.back(); + } + CurOffset = 0; + Data = std::nullopt; + } + return nullptr; } std::string DWARFAbbreviationDeclarationSet::getCodeRange() const { @@ -139,8 +165,9 @@ } } -const DWARFAbbreviationDeclarationSet* -DWARFDebugAbbrev::getAbbreviationDeclarationSet(uint64_t CUAbbrOffset) const { +const DWARFAbbreviationDeclarationSet * +DWARFDebugAbbrev::getAbbreviationDeclarationSet(uint64_t CUAbbrOffset, + bool Lazy) const { const auto End = AbbrDeclSets.end(); if (PrevAbbrOffsetPos != End && PrevAbbrOffsetPos->first == CUAbbrOffset) { return &(PrevAbbrOffsetPos->second); @@ -155,7 +182,7 @@ if (Data && CUAbbrOffset < Data->getData().size()) { uint64_t Offset = CUAbbrOffset; DWARFAbbreviationDeclarationSet AbbrDecls; - if (!AbbrDecls.extract(*Data, &Offset)) + if (!AbbrDecls.extract(*Data, &Offset, Lazy)) return nullptr; PrevAbbrOffsetPos = AbbrDeclSets.insert(std::make_pair(CUAbbrOffset, std::move(AbbrDecls))) diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp --- a/llvm/lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp @@ -40,7 +40,7 @@ AbbrevDecl = nullptr; return true; } - const auto *AbbrevSet = U.getAbbreviations(); + const auto *AbbrevSet = U.getAbbreviations(/*Lazy=*/true); if (!AbbrevSet) { U.getContext().getWarningHandler()( createStringError(errc::invalid_argument, diff --git a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp --- a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp @@ -1039,9 +1039,11 @@ return nullptr; } -const DWARFAbbreviationDeclarationSet *DWARFUnit::getAbbreviations() const { +const DWARFAbbreviationDeclarationSet * +DWARFUnit::getAbbreviations(bool Lazy) const { if (!Abbrevs) - Abbrevs = Abbrev->getAbbreviationDeclarationSet(getAbbreviationsOffset()); + Abbrevs = + Abbrev->getAbbreviationDeclarationSet(getAbbreviationsOffset(), Lazy); return Abbrevs; }