1 //===- llvm/unittest/DebugInfo/LogicalView/SelectElementsTest.cpp ---------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "llvm/DebugInfo/LogicalView/Core/LVLine.h"
10 #include "llvm/DebugInfo/LogicalView/Core/LVReader.h"
11 #include "llvm/DebugInfo/LogicalView/Core/LVScope.h"
12 #include "llvm/DebugInfo/LogicalView/Core/LVSymbol.h"
13 #include "llvm/DebugInfo/LogicalView/Core/LVType.h"
14 #include "llvm/Support/ScopedPrinter.h"
15 #include "llvm/Support/ToolOutputFile.h"
16 #include "llvm/Testing/Support/Error.h"
18 #include "gtest/gtest.h"
21 using namespace llvm::logicalview
;
25 class ReaderTestSelection
: public LVReader
{
26 #define CREATE(VARIABLE, CREATE_FUNCTION, SET_FUNCTION) \
27 VARIABLE = CREATE_FUNCTION(); \
28 EXPECT_NE(VARIABLE, nullptr); \
29 VARIABLE->SET_FUNCTION();
32 LVType
*IntegerType
= nullptr;
35 LVScope
*NestedScope
= nullptr;
36 LVScopeAggregate
*Aggregate
= nullptr;
37 LVScopeFunction
*Function
= nullptr;
38 LVScopeNamespace
*Namespace
= nullptr;
41 LVSymbol
*ClassMember
= nullptr;
42 LVSymbol
*LocalVariable
= nullptr;
43 LVSymbol
*NestedVariable
= nullptr;
44 LVSymbol
*Parameter
= nullptr;
47 LVLine
*LineOne
= nullptr;
48 LVLine
*LineTwo
= nullptr;
49 LVLine
*LineThree
= nullptr;
50 LVLine
*LineFour
= nullptr;
51 LVLine
*LineFive
= nullptr;
54 void add(LVScope
*Parent
, LVElement
*Element
);
55 void set(LVElement
*Element
, StringRef Name
, LVOffset Offset
,
56 uint32_t LineNumber
= 0, LVElement
*Type
= nullptr);
59 ReaderTestSelection(ScopedPrinter
&W
) : LVReader("", "", W
) {
63 Error
createScopes() { return LVReader::createScopes(); }
65 void createElements();
68 void resolvePatterns(LVPatterns
&Patterns
);
69 void checkFlexiblePatterns();
70 void checkGenericPatterns();
71 void checkKindPatterns();
74 // Helper function to add a logical element to a given scope.
75 void ReaderTestSelection::add(LVScope
*Parent
, LVElement
*Child
) {
76 Parent
->addElement(Child
);
77 EXPECT_EQ(Child
->getParent(), Parent
);
78 EXPECT_EQ(Child
->getLevel(), Parent
->getLevel() + 1);
81 // Helper function to set the initial values for a given logical element.
82 void ReaderTestSelection::set(LVElement
*Element
, StringRef Name
,
83 LVOffset Offset
, uint32_t LineNumber
,
85 Element
->setName(Name
);
86 Element
->setOffset(Offset
);
87 Element
->setLineNumber(LineNumber
);
88 Element
->setType(Type
);
89 EXPECT_EQ(Element
->getName(), Name
);
90 EXPECT_EQ(Element
->getOffset(), Offset
);
91 EXPECT_EQ(Element
->getLineNumber(), LineNumber
);
92 EXPECT_EQ(Element
->getType(), Type
);
95 // Create the logical elements.
96 void ReaderTestSelection::createElements() {
98 Error Err
= createScopes();
99 ASSERT_THAT_ERROR(std::move(Err
), Succeeded());
100 Root
= getScopesRoot();
101 EXPECT_NE(Root
, nullptr);
103 // Create the logical types.
104 CREATE(IntegerType
, createType
, setIsBase
);
106 // Create the logical scopes.
107 CREATE(CompileUnit
, createScopeCompileUnit
, setIsCompileUnit
);
108 CREATE(Function
, createScopeFunction
, setIsFunction
);
109 CREATE(NestedScope
, createScope
, setIsLexicalBlock
);
110 CREATE(Namespace
, createScopeNamespace
, setIsNamespace
);
111 CREATE(Aggregate
, createScopeAggregate
, setIsAggregate
);
113 // Create the logical symbols.
114 CREATE(ClassMember
, createSymbol
, setIsMember
);
115 CREATE(LocalVariable
, createSymbol
, setIsVariable
);
116 CREATE(NestedVariable
, createSymbol
, setIsVariable
);
117 CREATE(Parameter
, createSymbol
, setIsParameter
);
119 // Create the logical lines.
120 CREATE(LineOne
, createLine
, setIsLineDebug
);
121 CREATE(LineTwo
, createLine
, setIsBasicBlock
);
122 CREATE(LineThree
, createLine
, setIsNewStatement
);
123 CREATE(LineFour
, createLine
, setIsPrologueEnd
);
124 CREATE(LineFive
, createLine
, setIsLineAssembler
);
127 // Create the logical view adding the created logical elements.
128 void ReaderTestSelection::addElements() {
129 setCompileUnit(CompileUnit
);
148 // Add elements to Root.
149 add(Root
, CompileUnit
);
151 // Add elements to CompileUnit.
152 add(CompileUnit
, IntegerType
);
153 add(CompileUnit
, Namespace
);
154 add(CompileUnit
, Function
);
156 // Add elements to Namespace.
157 add(Namespace
, Aggregate
);
159 // Add elements to Function.
160 add(Function
, Parameter
);
161 add(Function
, LocalVariable
);
162 add(Function
, LineOne
);
163 add(Function
, LineTwo
);
164 add(Function
, LineFive
);
165 add(Function
, NestedScope
);
167 // Add elements to Aggregate.
168 add(Aggregate
, ClassMember
);
170 // Add elements to NestedScope.
171 add(NestedScope
, NestedVariable
);
172 add(NestedScope
, LineThree
);
173 add(NestedScope
, LineFour
);
176 void ReaderTestSelection::resolvePatterns(LVPatterns
&Patterns
) {
177 // Traverse the given scope and its children applying the pattern match.
178 // Before applying the pattern, reset previous matched state.
179 std::function
<void(LVScope
* Parent
)> TraverseScope
= [&](LVScope
*Parent
) {
180 auto Traverse
= [&](const auto *Set
) {
182 for (const auto &Entry
: *Set
) {
183 Entry
->resetIsMatched();
184 Patterns
.resolvePatternMatch(Entry
);
188 Parent
->resetIsMatched();
189 Patterns
.resolvePatternMatch(Parent
);
191 Traverse(Parent
->getSymbols());
192 Traverse(Parent
->getTypes());
193 Traverse(Parent
->getLines());
195 if (const LVScopes
*Scopes
= Parent
->getScopes())
196 for (LVScope
*Scope
: *Scopes
) {
197 Scope
->resetIsMatched();
198 Patterns
.resolvePatternMatch(Scope
);
199 TraverseScope(Scope
);
203 // Start traversing the scopes root and apply any matching pattern.
207 // Set initial values to logical elements.
208 void ReaderTestSelection::initElements() {
210 set(IntegerType
, "int", 0x1000);
213 set(CompileUnit
, "test.cpp", 0x2000);
214 set(Namespace
, "anyNamespace", 0x3000, 300);
215 set(Aggregate
, "anyClass", 0x4000, 400);
216 set(Function
, "anyFunction", 0x5000, 500, IntegerType
);
217 set(NestedScope
, "", 0x6000, 600);
220 set(Parameter
, "Param", 0x5100, 510, IntegerType
);
221 set(LocalVariable
, "LocalVariable", 0x5200, 520, IntegerType
);
222 set(NestedVariable
, "NestedVariable", 0x6200, 620, IntegerType
);
225 set(LineOne
, "", 0x5110, 511);
226 set(LineTwo
, "", 0x5210, 521);
227 set(LineThree
, "", 0x6110, 611);
228 set(LineFour
, "", 0x6210, 621);
229 set(LineFive
, "", 0x7110, 711);
232 // Check logical elements kind patterns.
233 void ReaderTestSelection::checkKindPatterns() {
235 LVPatterns
&Patterns
= patterns();
238 LVElementKindSet KindElements
; // --select-elements=<Kind>
239 LVLineKindSet KindLines
; // --select-lines=<Kind>
240 LVScopeKindSet KindScopes
; // --select-scopes=<Kind>
241 LVSymbolKindSet KindSymbols
; // --select-symbols=<Kind>
242 LVTypeKindSelection KindTypes
; // --select-types=<Kind>
244 KindElements
.insert(LVElementKind::Global
);
245 KindLines
.insert(LVLineKind::IsLineDebug
);
246 KindLines
.insert(LVLineKind::IsNewStatement
);
247 KindLines
.insert(LVLineKind::IsLineAssembler
);
248 KindScopes
.insert(LVScopeKind::IsLexicalBlock
);
249 KindSymbols
.insert(LVSymbolKind::IsMember
);
250 KindSymbols
.insert(LVSymbolKind::IsParameter
);
251 KindTypes
.insert(LVTypeKind::IsBase
);
253 // Add requests based on the element kind.
254 Patterns
.addRequest(KindElements
);
255 Patterns
.addRequest(KindLines
);
256 Patterns
.addRequest(KindScopes
);
257 Patterns
.addRequest(KindSymbols
);
258 Patterns
.addRequest(KindTypes
);
260 // Apply the collected patterns.
261 resolvePatterns(Patterns
);
263 EXPECT_FALSE(CompileUnit
->getIsMatched());
264 EXPECT_FALSE(Namespace
->getIsMatched());
265 EXPECT_FALSE(Aggregate
->getIsMatched());
266 EXPECT_FALSE(Function
->getIsMatched());
267 EXPECT_TRUE(NestedScope
->getIsMatched());
269 EXPECT_TRUE(IntegerType
->getIsMatched());
271 EXPECT_TRUE(ClassMember
->getIsMatched());
272 EXPECT_TRUE(Parameter
->getIsMatched());
273 EXPECT_FALSE(LocalVariable
->getIsMatched());
274 EXPECT_FALSE(NestedVariable
->getIsMatched());
276 EXPECT_TRUE(LineOne
->getIsMatched());
277 EXPECT_FALSE(LineTwo
->getIsMatched());
278 EXPECT_TRUE(LineThree
->getIsMatched());
279 EXPECT_FALSE(LineFour
->getIsMatched());
280 EXPECT_TRUE(LineFive
->getIsMatched());
283 // Check logical elements generic patterns (Case sensitive).
284 void ReaderTestSelection::checkGenericPatterns() {
286 LVPatterns
&Patterns
= patterns();
289 StringSet
<> Generic
; // --select=<Pattern>
290 Generic
.insert(Function
->getName()); // anyFunction
291 Generic
.insert(Namespace
->getName()); // anyNamespace
292 Generic
.insert(LocalVariable
->getName()); // LocalVariable
294 LVOffsetSet Offsets
; // --select-offset=<Offset>
295 Offsets
.insert(IntegerType
->getOffset());
296 Offsets
.insert(LineOne
->getOffset());
297 Offsets
.insert(LineTwo
->getOffset());
299 // Add requests based on the generic string and offset.
300 Patterns
.addGenericPatterns(Generic
);
301 Patterns
.addOffsetPatterns(Offsets
);
303 // Apply the collected patterns.
304 resolvePatterns(Patterns
);
306 EXPECT_FALSE(CompileUnit
->getIsMatched());
307 EXPECT_TRUE(Namespace
->getIsMatched());
308 EXPECT_FALSE(Aggregate
->getIsMatched());
309 EXPECT_TRUE(Function
->getIsMatched());
310 EXPECT_FALSE(NestedScope
->getIsMatched());
312 EXPECT_TRUE(IntegerType
->getIsMatched());
314 EXPECT_FALSE(ClassMember
->getIsMatched());
315 EXPECT_FALSE(Parameter
->getIsMatched());
316 EXPECT_TRUE(LocalVariable
->getIsMatched());
317 EXPECT_FALSE(NestedVariable
->getIsMatched());
319 EXPECT_TRUE(LineOne
->getIsMatched());
320 EXPECT_TRUE(LineTwo
->getIsMatched());
321 EXPECT_FALSE(LineThree
->getIsMatched());
322 EXPECT_FALSE(LineFour
->getIsMatched());
323 EXPECT_FALSE(LineFive
->getIsMatched());
326 // Check logical elements flexible patterns (case insensitive, RegEx).
327 void ReaderTestSelection::checkFlexiblePatterns() {
328 options().setSelectIgnoreCase();
329 options().setSelectUseRegex();
332 LVPatterns
&Patterns
= patterns();
335 StringSet
<> Generic
; // --select=<Pattern>
336 Generic
.insert("function");
337 Generic
.insert("NaMeSpAcE");
338 Generic
.insert("[a-z]*Variable");
339 Generic
.insert("[0-9]21");
341 // Add requests based on the flexible string.
342 Patterns
.addGenericPatterns(Generic
);
344 // Apply the collected patterns.
345 resolvePatterns(Patterns
);
347 EXPECT_FALSE(CompileUnit
->getIsMatched());
348 EXPECT_TRUE(Namespace
->getIsMatched()); // anyNamespace
349 EXPECT_FALSE(Aggregate
->getIsMatched());
350 EXPECT_TRUE(Function
->getIsMatched()); // anyFunction
351 EXPECT_FALSE(NestedScope
->getIsMatched());
353 EXPECT_FALSE(IntegerType
->getIsMatched());
355 EXPECT_FALSE(ClassMember
->getIsMatched());
356 EXPECT_FALSE(Parameter
->getIsMatched());
357 EXPECT_TRUE(LocalVariable
->getIsMatched()); // LocalVariable
358 EXPECT_TRUE(NestedVariable
->getIsMatched()); // NestedVariable
360 EXPECT_FALSE(LineOne
->getIsMatched());
361 EXPECT_TRUE(LineTwo
->getIsMatched()); // 521
362 EXPECT_FALSE(LineThree
->getIsMatched());
363 EXPECT_TRUE(LineFour
->getIsMatched()); // 621
364 EXPECT_FALSE(LineFive
->getIsMatched());
367 TEST(LogicalViewTest
, SelectElements
) {
368 ScopedPrinter
W(outs());
369 ReaderTestSelection
Reader(W
);
372 LVOptions ReaderOptions
;
373 ReaderOptions
.setAttributeOffset();
374 ReaderOptions
.setPrintAll();
375 ReaderOptions
.setReportList();
376 ReaderOptions
.setReportAnyView();
378 ReaderOptions
.resolveDependencies();
379 options().setOptions(&ReaderOptions
);
381 Reader
.createElements();
382 Reader
.addElements();
383 Reader
.initElements();
384 Reader
.checkKindPatterns();
385 Reader
.checkGenericPatterns();
386 Reader
.checkFlexiblePatterns();