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