xref: /llvm-project/llvm/unittests/DebugInfo/LogicalView/SelectElementsTest.cpp (revision 0332a8e7d6da29be945d16cc8c392ed7902397f5)
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   // Types.
27   LVType *IntegerType = nullptr;
28 
29   // Scopes.
30   LVScope *NestedScope = nullptr;
31   LVScopeAggregate *Aggregate = nullptr;
32   LVScopeFunction *Function = nullptr;
33   LVScopeNamespace *Namespace = nullptr;
34 
35   // Symbols.
36   LVSymbol *ClassMember = nullptr;
37   LVSymbol *LocalVariable = nullptr;
38   LVSymbol *NestedVariable = nullptr;
39   LVSymbol *Parameter = nullptr;
40 
41   // Lines.
42   LVLine *LineOne = nullptr;
43   LVLine *LineTwo = nullptr;
44   LVLine *LineThree = nullptr;
45   LVLine *LineFour = nullptr;
46   LVLine *LineFive = nullptr;
47 
48 protected:
49   void add(LVScope *Parent, LVElement *Element);
50   template <typename T, typename F> T *create(F Function) {
51     // 'Function' will update a specific kind of the logical element to
52     // have the ability of kind selection.
53     T *Element = new (std::nothrow) T();
54     EXPECT_NE(Element, nullptr);
55     (Element->*Function)();
56     return Element;
57   }
58   void set(LVElement *Element, StringRef Name, LVOffset Offset,
59            uint32_t LineNumber = 0, LVElement *Type = nullptr);
60 
61 public:
62   ReaderTestSelection(ScopedPrinter &W) : LVReader("", "", W) {
63     setInstance(this);
64   }
65 
66   Error createScopes() { return LVReader::createScopes(); }
67 
68   void createElements();
69   void addElements();
70   void initElements();
71   void resolvePatterns(LVPatterns &Patterns);
72   void checkFlexiblePatterns();
73   void checkGenericPatterns();
74   void checkKindPatterns();
75 };
76 
77 // Helper function to add a logical element to a given scope.
78 void ReaderTestSelection::add(LVScope *Parent, LVElement *Child) {
79   Parent->addElement(Child);
80   EXPECT_EQ(Child->getParent(), Parent);
81   EXPECT_EQ(Child->getLevel(), Parent->getLevel() + 1);
82 }
83 
84 // Helper function to set the initial values for a given logical element.
85 void ReaderTestSelection::set(LVElement *Element, StringRef Name,
86                               LVOffset Offset, uint32_t LineNumber,
87                               LVElement *Type) {
88   Element->setName(Name);
89   Element->setOffset(Offset);
90   Element->setLineNumber(LineNumber);
91   Element->setType(Type);
92   EXPECT_EQ(Element->getName(), Name);
93   EXPECT_EQ(Element->getOffset(), Offset);
94   EXPECT_EQ(Element->getLineNumber(), LineNumber);
95   EXPECT_EQ(Element->getType(), Type);
96 }
97 
98 // Create the logical elements.
99 void ReaderTestSelection::createElements() {
100   // Create scope root.
101   Error Err = createScopes();
102   ASSERT_THAT_ERROR(std::move(Err), Succeeded());
103   Root = getScopesRoot();
104   EXPECT_NE(Root, nullptr);
105 
106   // Create the logical types.
107   IntegerType = create<LVType, LVTypeSetFunction>(&LVType::setIsBase);
108 
109   // Create the logical scopes.
110   CompileUnit = create<LVScopeCompileUnit, LVScopeSetFunction>(
111       &LVScope::setIsCompileUnit);
112   Function =
113       create<LVScopeFunction, LVScopeSetFunction>(&LVScope::setIsFunction);
114   NestedScope =
115       create<LVScope, LVScopeSetFunction>(&LVScope::setIsLexicalBlock);
116   Namespace =
117       create<LVScopeNamespace, LVScopeSetFunction>(&LVScope::setIsNamespace);
118   Aggregate =
119       create<LVScopeAggregate, LVScopeSetFunction>(&LVScope::setIsAggregate);
120 
121   // Create the logical symbols.
122   ClassMember = create<LVSymbol, LVSymbolSetFunction>(&LVSymbol::setIsMember);
123   LocalVariable =
124       create<LVSymbol, LVSymbolSetFunction>(&LVSymbol::setIsVariable);
125   NestedVariable =
126       create<LVSymbol, LVSymbolSetFunction>(&LVSymbol::setIsVariable);
127   Parameter = create<LVSymbol, LVSymbolSetFunction>(&LVSymbol::setIsParameter);
128 
129   // Create the logical lines.
130   LineOne = create<LVLine, LVLineSetFunction>(&LVLine::setIsLineDebug);
131   LineTwo = create<LVLine, LVLineSetFunction>(&LVLine::setIsBasicBlock);
132   LineThree = create<LVLine, LVLineSetFunction>(&LVLine::setIsNewStatement);
133   LineFour = create<LVLine, LVLineSetFunction>(&LVLine::setIsPrologueEnd);
134   LineFive = create<LVLine, LVLineSetFunction>(&LVLine::setIsLineAssembler);
135 }
136 
137 // Create the logical view adding the created logical elements.
138 void ReaderTestSelection::addElements() {
139   setCompileUnit(CompileUnit);
140 
141   // Root
142   //   CompileUnit
143   //     IntegerType
144   //     Namespace
145   //       Aggregate
146   //         ClassMember
147   //     Function
148   //       Parameter
149   //       LocalVariable
150   //       LineOne
151   //       LineTwo
152   //       NestedScope
153   //         NestedVariable
154   //         LineThree
155   //         LineFour
156   //       LineFive
157 
158   // Add elements to Root.
159   add(Root, CompileUnit);
160 
161   // Add elements to CompileUnit.
162   add(CompileUnit, IntegerType);
163   add(CompileUnit, Namespace);
164   add(CompileUnit, Function);
165 
166   // Add elements to Namespace.
167   add(Namespace, Aggregate);
168 
169   // Add elements to Function.
170   add(Function, Parameter);
171   add(Function, LocalVariable);
172   add(Function, LineOne);
173   add(Function, LineTwo);
174   add(Function, LineFive);
175   add(Function, NestedScope);
176 
177   // Add elements to Aggregate.
178   add(Aggregate, ClassMember);
179 
180   // Add elements to NestedScope.
181   add(NestedScope, NestedVariable);
182   add(NestedScope, LineThree);
183   add(NestedScope, LineFour);
184 }
185 
186 void ReaderTestSelection::resolvePatterns(LVPatterns &Patterns) {
187   // Traverse the given scope and its children applying the pattern match.
188   // Before applying the pattern, reset previous matched state.
189   std::function<void(LVScope * Parent)> TraverseScope = [&](LVScope *Parent) {
190     auto Traverse = [&](const auto *Set) {
191       if (Set)
192         for (const auto &Entry : *Set) {
193           Entry->resetIsMatched();
194           Patterns.resolvePatternMatch(Entry);
195         }
196     };
197 
198     Parent->resetIsMatched();
199     Patterns.resolvePatternMatch(Parent);
200 
201     Traverse(Parent->getSymbols());
202     Traverse(Parent->getTypes());
203     Traverse(Parent->getLines());
204 
205     if (const LVScopes *Scopes = Parent->getScopes())
206       for (LVScope *Scope : *Scopes) {
207         Scope->resetIsMatched();
208         Patterns.resolvePatternMatch(Scope);
209         TraverseScope(Scope);
210       }
211   };
212 
213   // Start traversing the scopes root and apply any matching pattern.
214   TraverseScope(Root);
215 }
216 
217 // Set initial values to logical elements.
218 void ReaderTestSelection::initElements() {
219   // Types.
220   set(IntegerType, "int", 0x1000);
221 
222   // Scopes.
223   set(CompileUnit, "test.cpp", 0x2000);
224   set(Namespace, "anyNamespace", 0x3000, 300);
225   set(Aggregate, "anyClass", 0x4000, 400);
226   set(Function, "anyFunction", 0x5000, 500, IntegerType);
227   set(NestedScope, "", 0x6000, 600);
228 
229   // Symbols.
230   set(Parameter, "Param", 0x5100, 510, IntegerType);
231   set(LocalVariable, "LocalVariable", 0x5200, 520, IntegerType);
232   set(NestedVariable, "NestedVariable", 0x6200, 620, IntegerType);
233 
234   // Lines.
235   set(LineOne, "", 0x5110, 511);
236   set(LineTwo, "", 0x5210, 521);
237   set(LineThree, "", 0x6110, 611);
238   set(LineFour, "", 0x6210, 621);
239   set(LineFive, "", 0x7110, 711);
240 }
241 
242 // Check logical elements kind patterns.
243 void ReaderTestSelection::checkKindPatterns() {
244   // Add patterns.
245   LVPatterns &Patterns = patterns();
246   Patterns.clear();
247 
248   LVElementKindSet KindElements; // --select-elements=<Kind>
249   LVLineKindSet KindLines;       // --select-lines=<Kind>
250   LVScopeKindSet KindScopes;     // --select-scopes=<Kind>
251   LVSymbolKindSet KindSymbols;   // --select-symbols=<Kind>
252   LVTypeKindSelection KindTypes; // --select-types=<Kind>
253 
254   KindElements.insert(LVElementKind::Global);
255   KindLines.insert(LVLineKind::IsLineDebug);
256   KindLines.insert(LVLineKind::IsNewStatement);
257   KindLines.insert(LVLineKind::IsLineAssembler);
258   KindScopes.insert(LVScopeKind::IsLexicalBlock);
259   KindSymbols.insert(LVSymbolKind::IsMember);
260   KindSymbols.insert(LVSymbolKind::IsParameter);
261   KindTypes.insert(LVTypeKind::IsBase);
262 
263   // Add requests based on the element kind.
264   Patterns.addRequest(KindElements);
265   Patterns.addRequest(KindLines);
266   Patterns.addRequest(KindScopes);
267   Patterns.addRequest(KindSymbols);
268   Patterns.addRequest(KindTypes);
269 
270   // Apply the collected patterns.
271   resolvePatterns(Patterns);
272 
273   EXPECT_FALSE(CompileUnit->getIsMatched());
274   EXPECT_FALSE(Namespace->getIsMatched());
275   EXPECT_FALSE(Aggregate->getIsMatched());
276   EXPECT_FALSE(Function->getIsMatched());
277   EXPECT_TRUE(NestedScope->getIsMatched());
278 
279   EXPECT_TRUE(IntegerType->getIsMatched());
280 
281   EXPECT_TRUE(ClassMember->getIsMatched());
282   EXPECT_TRUE(Parameter->getIsMatched());
283   EXPECT_FALSE(LocalVariable->getIsMatched());
284   EXPECT_FALSE(NestedVariable->getIsMatched());
285 
286   EXPECT_TRUE(LineOne->getIsMatched());
287   EXPECT_FALSE(LineTwo->getIsMatched());
288   EXPECT_TRUE(LineThree->getIsMatched());
289   EXPECT_FALSE(LineFour->getIsMatched());
290   EXPECT_TRUE(LineFive->getIsMatched());
291 }
292 
293 // Check logical elements generic patterns (Case sensitive).
294 void ReaderTestSelection::checkGenericPatterns() {
295   // Add patterns.
296   LVPatterns &Patterns = patterns();
297   Patterns.clear();
298 
299   StringSet<> Generic;                      // --select=<Pattern>
300   Generic.insert(Function->getName());      // anyFunction
301   Generic.insert(Namespace->getName());     // anyNamespace
302   Generic.insert(LocalVariable->getName()); // LocalVariable
303 
304   LVOffsetSet Offsets; // --select-offset=<Offset>
305   Offsets.insert(IntegerType->getOffset());
306   Offsets.insert(LineOne->getOffset());
307   Offsets.insert(LineTwo->getOffset());
308 
309   // Add requests based on the generic string and offset.
310   Patterns.addGenericPatterns(Generic);
311   Patterns.addOffsetPatterns(Offsets);
312 
313   // Apply the collected patterns.
314   resolvePatterns(Patterns);
315 
316   EXPECT_FALSE(CompileUnit->getIsMatched());
317   EXPECT_TRUE(Namespace->getIsMatched());
318   EXPECT_FALSE(Aggregate->getIsMatched());
319   EXPECT_TRUE(Function->getIsMatched());
320   EXPECT_FALSE(NestedScope->getIsMatched());
321 
322   EXPECT_TRUE(IntegerType->getIsMatched());
323 
324   EXPECT_FALSE(ClassMember->getIsMatched());
325   EXPECT_FALSE(Parameter->getIsMatched());
326   EXPECT_TRUE(LocalVariable->getIsMatched());
327   EXPECT_FALSE(NestedVariable->getIsMatched());
328 
329   EXPECT_TRUE(LineOne->getIsMatched());
330   EXPECT_TRUE(LineTwo->getIsMatched());
331   EXPECT_FALSE(LineThree->getIsMatched());
332   EXPECT_FALSE(LineFour->getIsMatched());
333   EXPECT_FALSE(LineFive->getIsMatched());
334 }
335 
336 // Check logical elements flexible patterns (case insensitive, RegEx).
337 void ReaderTestSelection::checkFlexiblePatterns() {
338   options().setSelectIgnoreCase();
339   options().setSelectUseRegex();
340 
341   // Add patterns.
342   LVPatterns &Patterns = patterns();
343   Patterns.clear();
344 
345   StringSet<> Generic; // --select=<Pattern>
346   Generic.insert("function");
347   Generic.insert("NaMeSpAcE");
348   Generic.insert("[a-z]*Variable");
349   Generic.insert("[0-9]21");
350 
351   // Add requests based on the flexible string.
352   Patterns.addGenericPatterns(Generic);
353 
354   // Apply the collected patterns.
355   resolvePatterns(Patterns);
356 
357   EXPECT_FALSE(CompileUnit->getIsMatched());
358   EXPECT_TRUE(Namespace->getIsMatched()); // anyNamespace
359   EXPECT_FALSE(Aggregate->getIsMatched());
360   EXPECT_TRUE(Function->getIsMatched()); // anyFunction
361   EXPECT_FALSE(NestedScope->getIsMatched());
362 
363   EXPECT_FALSE(IntegerType->getIsMatched());
364 
365   EXPECT_FALSE(ClassMember->getIsMatched());
366   EXPECT_FALSE(Parameter->getIsMatched());
367   EXPECT_TRUE(LocalVariable->getIsMatched());  // LocalVariable
368   EXPECT_TRUE(NestedVariable->getIsMatched()); // NestedVariable
369 
370   EXPECT_FALSE(LineOne->getIsMatched());
371   EXPECT_TRUE(LineTwo->getIsMatched()); // 521
372   EXPECT_FALSE(LineThree->getIsMatched());
373   EXPECT_TRUE(LineFour->getIsMatched()); // 621
374   EXPECT_FALSE(LineFive->getIsMatched());
375 }
376 
377 TEST(LogicalViewTest, SelectElements) {
378   ScopedPrinter W(outs());
379   ReaderTestSelection Reader(W);
380 
381   // Reader options.
382   LVOptions ReaderOptions;
383   ReaderOptions.setAttributeOffset();
384   ReaderOptions.setPrintAll();
385   ReaderOptions.setReportList();
386   ReaderOptions.setReportAnyView();
387 
388   ReaderOptions.resolveDependencies();
389   options().setOptions(&ReaderOptions);
390 
391   Reader.createElements();
392   Reader.addElements();
393   Reader.initElements();
394   Reader.checkKindPatterns();
395   Reader.checkGenericPatterns();
396   Reader.checkFlexiblePatterns();
397 }
398 
399 } // namespace
400