xref: /llvm-project/llvm/unittests/DebugInfo/LogicalView/SelectElementsTest.cpp (revision 7fbcc24409efdb37cec79ad461ef383f6ffc5ef2)
1 //===- llvm/unittest/DebugInfo/LogicalView/SelectElementsTest.cpp ---------===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
8 
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"
17 
18 #include "gtest/gtest.h"
19 
20 using namespace llvm;
21 using namespace llvm::logicalview;
22 
23 namespace {
24 
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();
30 
31   // Types.
32   LVType *IntegerType = nullptr;
33 
34   // Scopes.
35   LVScope *NestedScope = nullptr;
36   LVScopeAggregate *Aggregate = nullptr;
37   LVScopeFunction *Function = nullptr;
38   LVScopeNamespace *Namespace = nullptr;
39 
40   // Symbols.
41   LVSymbol *ClassMember = nullptr;
42   LVSymbol *LocalVariable = nullptr;
43   LVSymbol *NestedVariable = nullptr;
44   LVSymbol *Parameter = nullptr;
45 
46   // Lines.
47   LVLine *LineOne = nullptr;
48   LVLine *LineTwo = nullptr;
49   LVLine *LineThree = nullptr;
50   LVLine *LineFour = nullptr;
51   LVLine *LineFive = nullptr;
52 
53 protected:
54   void add(LVScope *Parent, LVElement *Element);
55   void set(LVElement *Element, StringRef Name, LVOffset Offset,
56            uint32_t LineNumber = 0, LVElement *Type = nullptr);
57 
58 public:
ReaderTestSelection(ScopedPrinter & W)59   ReaderTestSelection(ScopedPrinter &W) : LVReader("", "", W) {
60     setInstance(this);
61   }
62 
createScopes()63   Error createScopes() { return LVReader::createScopes(); }
64 
65   void createElements();
66   void addElements();
67   void initElements();
68   void resolvePatterns(LVPatterns &Patterns);
69   void checkFlexiblePatterns();
70   void checkGenericPatterns();
71   void checkKindPatterns();
72 };
73 
74 // Helper function to add a logical element to a given scope.
add(LVScope * Parent,LVElement * Child)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);
79 }
80 
81 // Helper function to set the initial values for a given logical element.
set(LVElement * Element,StringRef Name,LVOffset Offset,uint32_t LineNumber,LVElement * Type)82 void ReaderTestSelection::set(LVElement *Element, StringRef Name,
83                               LVOffset Offset, uint32_t LineNumber,
84                               LVElement *Type) {
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);
93 }
94 
95 // Create the logical elements.
createElements()96 void ReaderTestSelection::createElements() {
97   // Create scope root.
98   Error Err = createScopes();
99   ASSERT_THAT_ERROR(std::move(Err), Succeeded());
100   Root = getScopesRoot();
101   EXPECT_NE(Root, nullptr);
102 
103   // Create the logical types.
104   CREATE(IntegerType, createType, setIsBase);
105 
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);
112 
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);
118 
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);
125 }
126 
127 // Create the logical view adding the created logical elements.
addElements()128 void ReaderTestSelection::addElements() {
129   setCompileUnit(CompileUnit);
130 
131   // Root
132   //   CompileUnit
133   //     IntegerType
134   //     Namespace
135   //       Aggregate
136   //         ClassMember
137   //     Function
138   //       Parameter
139   //       LocalVariable
140   //       LineOne
141   //       LineTwo
142   //       NestedScope
143   //         NestedVariable
144   //         LineThree
145   //         LineFour
146   //       LineFive
147 
148   // Add elements to Root.
149   add(Root, CompileUnit);
150 
151   // Add elements to CompileUnit.
152   add(CompileUnit, IntegerType);
153   add(CompileUnit, Namespace);
154   add(CompileUnit, Function);
155 
156   // Add elements to Namespace.
157   add(Namespace, Aggregate);
158 
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);
166 
167   // Add elements to Aggregate.
168   add(Aggregate, ClassMember);
169 
170   // Add elements to NestedScope.
171   add(NestedScope, NestedVariable);
172   add(NestedScope, LineThree);
173   add(NestedScope, LineFour);
174 }
175 
resolvePatterns(LVPatterns & Patterns)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) {
181       if (Set)
182         for (const auto &Entry : *Set) {
183           Entry->resetIsMatched();
184           Patterns.resolvePatternMatch(Entry);
185         }
186     };
187 
188     Parent->resetIsMatched();
189     Patterns.resolvePatternMatch(Parent);
190 
191     Traverse(Parent->getSymbols());
192     Traverse(Parent->getTypes());
193     Traverse(Parent->getLines());
194 
195     if (const LVScopes *Scopes = Parent->getScopes())
196       for (LVScope *Scope : *Scopes) {
197         Scope->resetIsMatched();
198         Patterns.resolvePatternMatch(Scope);
199         TraverseScope(Scope);
200       }
201   };
202 
203   // Start traversing the scopes root and apply any matching pattern.
204   TraverseScope(Root);
205 }
206 
207 // Set initial values to logical elements.
initElements()208 void ReaderTestSelection::initElements() {
209   // Types.
210   set(IntegerType, "int", 0x1000);
211 
212   // Scopes.
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);
218 
219   // Symbols.
220   set(Parameter, "Param", 0x5100, 510, IntegerType);
221   set(LocalVariable, "LocalVariable", 0x5200, 520, IntegerType);
222   set(NestedVariable, "NestedVariable", 0x6200, 620, IntegerType);
223 
224   // Lines.
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);
230 }
231 
232 // Check logical elements kind patterns.
checkKindPatterns()233 void ReaderTestSelection::checkKindPatterns() {
234   // Add patterns.
235   LVPatterns &Patterns = patterns();
236   Patterns.clear();
237 
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>
243 
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);
252 
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);
259 
260   // Apply the collected patterns.
261   resolvePatterns(Patterns);
262 
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());
268 
269   EXPECT_TRUE(IntegerType->getIsMatched());
270 
271   EXPECT_TRUE(ClassMember->getIsMatched());
272   EXPECT_TRUE(Parameter->getIsMatched());
273   EXPECT_FALSE(LocalVariable->getIsMatched());
274   EXPECT_FALSE(NestedVariable->getIsMatched());
275 
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());
281 }
282 
283 // Check logical elements generic patterns (Case sensitive).
checkGenericPatterns()284 void ReaderTestSelection::checkGenericPatterns() {
285   // Add patterns.
286   LVPatterns &Patterns = patterns();
287   Patterns.clear();
288 
289   StringSet<> Generic;                      // --select=<Pattern>
290   Generic.insert(Function->getName());      // anyFunction
291   Generic.insert(Namespace->getName());     // anyNamespace
292   Generic.insert(LocalVariable->getName()); // LocalVariable
293 
294   LVOffsetSet Offsets; // --select-offset=<Offset>
295   Offsets.insert(IntegerType->getOffset());
296   Offsets.insert(LineOne->getOffset());
297   Offsets.insert(LineTwo->getOffset());
298 
299   // Add requests based on the generic string and offset.
300   Patterns.addGenericPatterns(Generic);
301   Patterns.addOffsetPatterns(Offsets);
302 
303   // Apply the collected patterns.
304   resolvePatterns(Patterns);
305 
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());
311 
312   EXPECT_TRUE(IntegerType->getIsMatched());
313 
314   EXPECT_FALSE(ClassMember->getIsMatched());
315   EXPECT_FALSE(Parameter->getIsMatched());
316   EXPECT_TRUE(LocalVariable->getIsMatched());
317   EXPECT_FALSE(NestedVariable->getIsMatched());
318 
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());
324 }
325 
326 // Check logical elements flexible patterns (case insensitive, RegEx).
checkFlexiblePatterns()327 void ReaderTestSelection::checkFlexiblePatterns() {
328   options().setSelectIgnoreCase();
329   options().setSelectUseRegex();
330 
331   // Add patterns.
332   LVPatterns &Patterns = patterns();
333   Patterns.clear();
334 
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");
340 
341   // Add requests based on the flexible string.
342   Patterns.addGenericPatterns(Generic);
343 
344   // Apply the collected patterns.
345   resolvePatterns(Patterns);
346 
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());
352 
353   EXPECT_FALSE(IntegerType->getIsMatched());
354 
355   EXPECT_FALSE(ClassMember->getIsMatched());
356   EXPECT_FALSE(Parameter->getIsMatched());
357   EXPECT_TRUE(LocalVariable->getIsMatched());  // LocalVariable
358   EXPECT_TRUE(NestedVariable->getIsMatched()); // NestedVariable
359 
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());
365 }
366 
TEST(LogicalViewTest,SelectElements)367 TEST(LogicalViewTest, SelectElements) {
368   ScopedPrinter W(outs());
369   ReaderTestSelection Reader(W);
370 
371   // Reader options.
372   LVOptions ReaderOptions;
373   ReaderOptions.setAttributeOffset();
374   ReaderOptions.setPrintAll();
375   ReaderOptions.setReportList();
376   ReaderOptions.setReportAnyView();
377 
378   ReaderOptions.resolveDependencies();
379   options().setOptions(&ReaderOptions);
380 
381   Reader.createElements();
382   Reader.addElements();
383   Reader.initElements();
384   Reader.checkKindPatterns();
385   Reader.checkGenericPatterns();
386   Reader.checkFlexiblePatterns();
387 }
388 
389 } // namespace
390