Skip to content

Commit c5cea09

Browse files
committed
[llvm-debuginfo-analyzer] Remove LVScope::Children container
Remove the `LVScope::Children` container and use `llvm::concat()` instead to return a view over the types, symbols, and sub-scopes contained in a given `LVScope`.
1 parent 24cad3a commit c5cea09

File tree

8 files changed

+99
-79
lines changed

8 files changed

+99
-79
lines changed

llvm/include/llvm/DebugInfo/LogicalView/Core/LVScope.h

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#ifndef LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVSCOPE_H
1515
#define LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVSCOPE_H
1616

17+
#include "llvm/ADT/STLExtras.h"
1718
#include "llvm/DebugInfo/LogicalView/Core/LVElement.h"
1819
#include "llvm/DebugInfo/LogicalView/Core/LVLocation.h"
1920
#include "llvm/DebugInfo/LogicalView/Core/LVSort.h"
@@ -94,6 +95,11 @@ class LLVM_ABI LVScope : public LVElement {
9495
LVProperties<LVScopeKind> Kinds;
9596
LVProperties<Property> Properties;
9697
static LVScopeDispatch Dispatch;
98+
// Empty containers used in `getChildren()` in case there is no Types,
99+
// Symbols, or Scopes.
100+
static const LVTypes EmptyTypes;
101+
static const LVSymbols EmptySymbols;
102+
static const LVScopes EmptyScopes;
97103

98104
// Size in bits if this scope represents also a compound type.
99105
uint32_t BitSize = 0;
@@ -128,14 +134,6 @@ class LLVM_ABI LVScope : public LVElement {
128134
std::unique_ptr<LVLines> Lines;
129135
std::unique_ptr<LVLocations> Ranges;
130136

131-
// Vector of elements (types, scopes and symbols).
132-
// It is the union of (*Types, *Symbols and *Scopes) to be used for
133-
// the following reasons:
134-
// - Preserve the order the logical elements are read in.
135-
// - To have a single container with all the logical elements, when
136-
// the traversal does not require any specific element kind.
137-
std::unique_ptr<LVElements> Children;
138-
139137
// Resolve the template parameters/arguments relationship.
140138
void resolveTemplate();
141139
void printEncodedArgs(raw_ostream &OS, bool Full) const;
@@ -213,7 +211,14 @@ class LLVM_ABI LVScope : public LVElement {
213211
const LVScopes *getScopes() const { return Scopes.get(); }
214212
const LVSymbols *getSymbols() const { return Symbols.get(); }
215213
const LVTypes *getTypes() const { return Types.get(); }
216-
const LVElements *getChildren() const { return Children.get(); }
214+
// Return view over union of child Types, Symbols, and Scopes.
215+
auto getUnsortedChildren() const {
216+
return llvm::concat<LVElement *const>(Scopes ? *Scopes : EmptyScopes,
217+
Types ? *Types : EmptyTypes,
218+
Symbols ? *Symbols : EmptySymbols);
219+
}
220+
// Return sorted children (see `LVOptions::setSortMode()`).
221+
LVElements getChildren() const;
217222

218223
void addElement(LVElement *Element);
219224
void addElement(LVLine *Line);
@@ -222,7 +227,6 @@ class LLVM_ABI LVScope : public LVElement {
222227
void addElement(LVType *Type);
223228
void addObject(LVLocation *Location);
224229
void addObject(LVAddress LowerAddress, LVAddress UpperAddress);
225-
void addToChildren(LVElement *Element);
226230

227231
// Add the missing elements from the given 'Reference', which is the
228232
// scope associated with any DW_AT_specification, DW_AT_abstract_origin.

llvm/include/llvm/DebugInfo/LogicalView/Core/LVSort.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ LLVM_ABI LVSortValue compareRange(const LVObject *LHS, const LVObject *RHS);
4646
LLVM_ABI LVSortValue sortByKind(const LVObject *LHS, const LVObject *RHS);
4747
LLVM_ABI LVSortValue sortByLine(const LVObject *LHS, const LVObject *RHS);
4848
LLVM_ABI LVSortValue sortByName(const LVObject *LHS, const LVObject *RHS);
49+
LLVM_ABI LVSortValue sortByOffset(const LVObject *LHS, const LVObject *RHS);
4950

5051
} // end namespace logicalview
5152
} // end namespace llvm

llvm/lib/DebugInfo/LogicalView/Core/LVScope.cpp

Lines changed: 42 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -107,10 +107,23 @@ LVScopeDispatch LVScope::Dispatch = {
107107
{LVScopeKind::IsTryBlock, &LVScope::getIsTryBlock},
108108
{LVScopeKind::IsUnion, &LVScope::getIsUnion}};
109109

110-
void LVScope::addToChildren(LVElement *Element) {
111-
if (!Children)
112-
Children = std::make_unique<LVElements>();
113-
Children->push_back(Element);
110+
const LVTypes LVScope::EmptyTypes{};
111+
const LVSymbols LVScope::EmptySymbols{};
112+
const LVScopes LVScope::EmptyScopes{};
113+
114+
LVElements LVScope::getChildren() const {
115+
const auto UnsortedChildren = getUnsortedChildren();
116+
LVElements Elements{UnsortedChildren.begin(), UnsortedChildren.end()};
117+
if (LVSortFunction SortFunction = getSortFunction()) {
118+
llvm::stable_sort(Elements, SortFunction);
119+
} else {
120+
// No specific sort function, sort by `LVObject::ID` which replicates the
121+
// order in which the elements were created.
122+
llvm::stable_sort(Elements, [](const LVObject *LHS, const LVObject *RHS) {
123+
return LHS->getID() < RHS->getID();
124+
});
125+
}
126+
return Elements;
114127
}
115128

116129
void LVScope::addElement(LVElement *Element) {
@@ -175,7 +188,6 @@ void LVScope::addElement(LVScope *Scope) {
175188

176189
// Add it to parent.
177190
Scopes->push_back(Scope);
178-
addToChildren(Scope);
179191
Scope->setParent(this);
180192

181193
// Notify the reader about the new element being added.
@@ -202,7 +214,6 @@ void LVScope::addElement(LVSymbol *Symbol) {
202214

203215
// Add it to parent.
204216
Symbols->push_back(Symbol);
205-
addToChildren(Symbol);
206217
Symbol->setParent(this);
207218

208219
// Notify the reader about the new element being added.
@@ -229,7 +240,6 @@ void LVScope::addElement(LVType *Type) {
229240

230241
// Add it to parent.
231242
Types->push_back(Type);
232-
addToChildren(Type);
233243
Type->setParent(this);
234244

235245
// Notify the reader about the new element being added.
@@ -277,15 +287,12 @@ bool LVScope::removeElement(LVElement *Element) {
277287
if (Element->getIsLine())
278288
return RemoveElement(Lines);
279289

280-
if (RemoveElement(Children)) {
281-
if (Element->getIsSymbol())
282-
return RemoveElement(Symbols);
283-
if (Element->getIsType())
284-
return RemoveElement(Types);
285-
if (Element->getIsScope())
286-
return RemoveElement(Scopes);
287-
llvm_unreachable("Invalid element.");
288-
}
290+
if (Element->getIsSymbol())
291+
return RemoveElement(Symbols);
292+
if (Element->getIsType())
293+
return RemoveElement(Types);
294+
if (Element->getIsScope())
295+
return RemoveElement(Scopes);
289296

290297
return false;
291298
}
@@ -356,9 +363,8 @@ void LVScope::updateLevel(LVScope *Parent, bool Moved) {
356363
setLevel(Parent->getLevel() + 1);
357364

358365
// Update the children.
359-
if (Children)
360-
for (LVElement *Element : *Children)
361-
Element->updateLevel(this, Moved);
366+
for (LVElement *Element : getUnsortedChildren())
367+
Element->updateLevel(this, Moved);
362368

363369
// Update any lines.
364370
if (Lines)
@@ -374,13 +380,12 @@ void LVScope::resolve() {
374380
LVElement::resolve();
375381

376382
// Resolve the children.
377-
if (Children)
378-
for (LVElement *Element : *Children) {
379-
if (getIsGlobalReference())
380-
// If the scope is a global reference, mark all its children as well.
381-
Element->setIsGlobalReference();
382-
Element->resolve();
383-
}
383+
for (LVElement *Element : getUnsortedChildren()) {
384+
if (getIsGlobalReference())
385+
// If the scope is a global reference, mark all its children as well.
386+
Element->setIsGlobalReference();
387+
Element->resolve();
388+
}
384389
}
385390

386391
void LVScope::resolveName() {
@@ -633,14 +638,13 @@ Error LVScope::doPrint(bool Split, bool Match, bool Print, raw_ostream &OS,
633638
options().getPrintFormatting() &&
634639
getLevel() < options().getOutputLevel()) {
635640
// Print the children.
636-
if (Children)
637-
for (const LVElement *Element : *Children) {
638-
if (Match && !Element->getHasPattern())
639-
continue;
640-
if (Error Err =
641-
Element->doPrint(Split, Match, Print, *StreamSplit, Full))
642-
return Err;
643-
}
641+
for (const LVElement *Element : getChildren()) {
642+
if (Match && !Element->getHasPattern())
643+
continue;
644+
if (Error Err =
645+
Element->doPrint(Split, Match, Print, *StreamSplit, Full))
646+
return Err;
647+
}
644648

645649
// Print the line records.
646650
if (Lines)
@@ -692,7 +696,6 @@ void LVScope::sort() {
692696
Traverse(Parent->Symbols, SortFunction);
693697
Traverse(Parent->Scopes, SortFunction);
694698
Traverse(Parent->Ranges, compareRange);
695-
Traverse(Parent->Children, SortFunction);
696699

697700
if (Parent->Scopes)
698701
for (LVScope *Scope : *Parent->Scopes)
@@ -978,9 +981,8 @@ bool LVScope::equals(const LVScopes *References, const LVScopes *Targets) {
978981
void LVScope::report(LVComparePass Pass) {
979982
getComparator().printItem(this, Pass);
980983
getComparator().push(this);
981-
if (Children)
982-
for (LVElement *Element : *Children)
983-
Element->report(Pass);
984+
for (LVElement *Element : getChildren())
985+
Element->report(Pass);
984986

985987
if (Lines)
986988
for (LVLine *Line : *Lines)
@@ -1656,9 +1658,8 @@ void LVScopeCompileUnit::printMatchedElements(raw_ostream &OS,
16561658
// Print the view for the matched scopes.
16571659
for (const LVScope *Scope : MatchedScopes) {
16581660
Scope->print(OS);
1659-
if (const LVElements *Elements = Scope->getChildren())
1660-
for (LVElement *Element : *Elements)
1661-
Element->print(OS);
1661+
for (LVElement *Element : Scope->getChildren())
1662+
Element->print(OS);
16621663
}
16631664
}
16641665

llvm/lib/DebugInfo/LogicalView/Core/LVSort.cpp

Lines changed: 34 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -64,44 +64,60 @@ LVSortValue llvm::logicalview::compareRange(const LVObject *LHS,
6464
LVSortValue llvm::logicalview::sortByKind(const LVObject *LHS,
6565
const LVObject *RHS) {
6666
// Order in which the object attributes are used for comparison:
67-
// kind, name, line number, offset.
68-
std::tuple<std::string, StringRef, uint32_t, LVOffset> Left(
69-
LHS->kind(), LHS->getName(), LHS->getLineNumber(), LHS->getOffset());
70-
std::tuple<std::string, StringRef, uint32_t, LVOffset> Right(
71-
RHS->kind(), RHS->getName(), RHS->getLineNumber(), RHS->getOffset());
67+
// kind, name, line number, offset, ID.
68+
std::tuple<std::string, StringRef, uint32_t, LVOffset, uint32_t> Left(
69+
LHS->kind(), LHS->getName(), LHS->getLineNumber(), LHS->getOffset(),
70+
LHS->getID());
71+
std::tuple<std::string, StringRef, uint32_t, LVOffset, uint32_t> Right(
72+
RHS->kind(), RHS->getName(), RHS->getLineNumber(), RHS->getOffset(),
73+
RHS->getID());
7274
return Left < Right;
7375
}
7476

7577
// Callback comparator based on multiple keys (First: Line).
7678
LVSortValue llvm::logicalview::sortByLine(const LVObject *LHS,
7779
const LVObject *RHS) {
7880
// Order in which the object attributes are used for comparison:
79-
// line number, name, kind, offset.
80-
std::tuple<uint32_t, StringRef, std::string, LVOffset> Left(
81-
LHS->getLineNumber(), LHS->getName(), LHS->kind(), LHS->getOffset());
82-
std::tuple<uint32_t, StringRef, std::string, LVOffset> Right(
83-
RHS->getLineNumber(), RHS->getName(), RHS->kind(), RHS->getOffset());
81+
// line number, name, kind, offset, ID.
82+
std::tuple<uint32_t, StringRef, std::string, LVOffset, uint32_t> Left(
83+
LHS->getLineNumber(), LHS->getName(), LHS->kind(), LHS->getOffset(),
84+
LHS->getID());
85+
std::tuple<uint32_t, StringRef, std::string, LVOffset, uint32_t> Right(
86+
RHS->getLineNumber(), RHS->getName(), RHS->kind(), RHS->getOffset(),
87+
RHS->getID());
8488
return Left < Right;
8589
}
8690

8791
// Callback comparator based on multiple keys (First: Name).
8892
LVSortValue llvm::logicalview::sortByName(const LVObject *LHS,
8993
const LVObject *RHS) {
9094
// Order in which the object attributes are used for comparison:
91-
// name, line number, kind, offset.
92-
std::tuple<StringRef, uint32_t, std::string, LVOffset> Left(
93-
LHS->getName(), LHS->getLineNumber(), LHS->kind(), LHS->getOffset());
94-
std::tuple<StringRef, uint32_t, std::string, LVOffset> Right(
95-
RHS->getName(), RHS->getLineNumber(), RHS->kind(), RHS->getOffset());
95+
// name, line number, kind, offset, ID.
96+
std::tuple<StringRef, uint32_t, std::string, LVOffset, uint32_t> Left(
97+
LHS->getName(), LHS->getLineNumber(), LHS->kind(), LHS->getOffset(),
98+
LHS->getID());
99+
std::tuple<StringRef, uint32_t, std::string, LVOffset, uint32_t> Right(
100+
RHS->getName(), RHS->getLineNumber(), RHS->kind(), RHS->getOffset(),
101+
RHS->getID());
102+
return Left < Right;
103+
}
104+
105+
// Callback comparator based on multiple keys (First: Offset).
106+
LVSortValue llvm::logicalview::sortByOffset(const LVObject *LHS,
107+
const LVObject *RHS) {
108+
// Order in which the object attributes are used for comparison:
109+
// offset, ID.
110+
std::tuple<LVOffset, uint32_t> Left(LHS->getOffset(), LHS->getID());
111+
std::tuple<LVOffset, uint32_t> Right(RHS->getOffset(), RHS->getID());
96112
return Left < Right;
97113
}
98114

99115
LVSortFunction llvm::logicalview::getSortFunction() {
100116
using LVSortInfo = std::map<LVSortMode, LVSortFunction>;
101117
static LVSortInfo SortInfo = {
102-
{LVSortMode::None, nullptr}, {LVSortMode::Kind, sortByKind},
103-
{LVSortMode::Line, sortByLine}, {LVSortMode::Name, sortByName},
104-
{LVSortMode::Offset, compareOffset},
118+
{LVSortMode::None, nullptr}, {LVSortMode::Kind, sortByKind},
119+
{LVSortMode::Line, sortByLine}, {LVSortMode::Name, sortByName},
120+
{LVSortMode::Offset, sortByOffset},
105121
};
106122

107123
LVSortFunction SortFunction = nullptr;

llvm/test/tools/llvm-debuginfo-analyzer/DWARF/01-dwarf-compare-logical-elements.test

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@
3535
; ONE-NEXT: [002] 1 {TypeAlias} 'INTPTR' -> '* const int'
3636
; ONE-NEXT: [002] 2 {Function} extern not_inlined 'foo' -> 'int'
3737
; ONE-NEXT: [003] {Block}
38-
; ONE-NEXT: [004] 5 {Variable} 'CONSTANT' -> 'const INTEGER'
3938
; ONE-NEXT: +[004] 4 {TypeAlias} 'INTEGER' -> 'int'
39+
; ONE-NEXT: [004] 5 {Variable} 'CONSTANT' -> 'const INTEGER'
4040
; ONE-NEXT: [003] 2 {Parameter} 'ParamBool' -> 'bool'
4141
; ONE-NEXT: [003] 2 {Parameter} 'ParamPtr' -> 'INTPTR'
4242
; ONE-NEXT: [003] 2 {Parameter} 'ParamUnsigned' -> 'unsigned int'

llvm/test/tools/llvm-debuginfo-analyzer/DWARF/pr-57040-incorrect-function-compare.test

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,8 @@
5555
; ONE-NEXT: [002] 1 {TypeAlias} 'INTPTR' -> '* const int'
5656
; ONE-NEXT: [002] 2 {Function} extern not_inlined 'foo' -> 'int'
5757
; ONE-NEXT: [003] {Block}
58-
; ONE-NEXT: [004] 5 {Variable} 'CONSTANT' -> 'const INTEGER'
5958
; ONE-NEXT: +[004] 4 {TypeAlias} 'INTEGER' -> 'int'
59+
; ONE-NEXT: [004] 5 {Variable} 'CONSTANT' -> 'const INTEGER'
6060
; ONE-NEXT: [003] 2 {Parameter} 'ParamBool' -> 'bool'
6161
; ONE-NEXT: [003] 2 {Parameter} 'ParamPtr' -> 'INTPTR'
6262
; ONE-NEXT: [003] 2 {Parameter} 'ParamUnsigned' -> 'unsigned int'

llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/01-wasm-compare-logical-elements.test

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@
3838
; ONE-NEXT: [002] 1 {TypeAlias} 'INTPTR' -> '* const int'
3939
; ONE-NEXT: [002] 2 {Function} extern not_inlined 'foo' -> 'int'
4040
; ONE-NEXT: [003] {Block}
41-
; ONE-NEXT: [004] 5 {Variable} 'CONSTANT' -> 'const INTEGER'
4241
; ONE-NEXT: +[004] 4 {TypeAlias} 'INTEGER' -> 'int'
42+
; ONE-NEXT: [004] 5 {Variable} 'CONSTANT' -> 'const INTEGER'
4343
; ONE-NEXT: [003] 2 {Parameter} 'ParamBool' -> 'bool'
4444
; ONE-NEXT: [003] 2 {Parameter} 'ParamPtr' -> 'INTPTR'
4545
; ONE-NEXT: [003] 2 {Parameter} 'ParamUnsigned' -> 'unsigned int'

llvm/unittests/DebugInfo/LogicalView/DWARFReaderTest.cpp

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -163,13 +163,12 @@ void checkUnspecifiedParameters(LVReader *Reader) {
163163
LVPublicNames::const_iterator IterNames = PublicNames.cbegin();
164164
LVScope *Function = (*IterNames).first;
165165
EXPECT_EQ(Function->getName(), "foo_printf");
166-
const LVElements *Elements = Function->getChildren();
167-
ASSERT_NE(Elements, nullptr);
166+
const auto Elements = Function->getChildren();
168167
// foo_printf is a variadic function whose prototype is
169168
// `int foo_printf(const char *, ...)`, where the '...' is represented by a
170169
// DW_TAG_unspecified_parameters, i.e. we expect to find at least one child
171170
// for which getIsUnspecified() returns true.
172-
EXPECT_TRUE(llvm::any_of(*Elements, [](const LVElement *elt) {
171+
EXPECT_TRUE(llvm::any_of(Elements, [](const LVElement *elt) {
173172
return elt->getIsSymbol() &&
174173
static_cast<const LVSymbol *>(elt)->getIsUnspecified();
175174
}));
@@ -183,10 +182,9 @@ void checkScopeModule(LVReader *Reader) {
183182
EXPECT_EQ(Root->getFileFormatName(), "Mach-O 64-bit x86-64");
184183
EXPECT_EQ(Root->getName(), DwarfClangModule);
185184

186-
ASSERT_NE(CompileUnit->getChildren(), nullptr);
187-
LVElement *FirstChild = *(CompileUnit->getChildren()->begin());
188-
EXPECT_EQ(FirstChild->getIsScope(), 1);
189-
LVScopeModule *Module = static_cast<LVScopeModule *>(FirstChild);
185+
ASSERT_NE(CompileUnit->getScopes(), nullptr);
186+
LVElement *FirstScope = *(CompileUnit->getScopes()->begin());
187+
LVScopeModule *Module = static_cast<LVScopeModule *>(FirstScope);
190188
EXPECT_EQ(Module->getIsModule(), 1);
191189
EXPECT_EQ(Module->getName(), "DebugModule");
192190
}

0 commit comments

Comments
 (0)