390 lines · cpp
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-exception6//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 20using namespace llvm;21using namespace llvm::logicalview;22 23namespace {24 25class 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 53protected: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 58public:59 ReaderTestSelection(ScopedPrinter &W) : LVReader("", "", W) {60 setInstance(this);61 }62 63 Error createScopes() override { 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.75void 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.82void 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.96void 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.128void ReaderTestSelection::addElements() {129 setCompileUnit(CompileUnit);130 131 // Root132 // CompileUnit133 // IntegerType134 // Namespace135 // Aggregate136 // ClassMember137 // Function138 // Parameter139 // LocalVariable140 // LineOne141 // LineTwo142 // NestedScope143 // NestedVariable144 // LineThree145 // LineFour146 // LineFive147 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 176void 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.208void 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.233void 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).284void ReaderTestSelection::checkGenericPatterns() {285 // Add patterns.286 LVPatterns &Patterns = patterns();287 Patterns.clear();288 289 StringSet<> Generic; // --select=<Pattern>290 Generic.insert(Function->getName()); // anyFunction291 Generic.insert(Namespace->getName()); // anyNamespace292 Generic.insert(LocalVariable->getName()); // LocalVariable293 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).327void 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()); // anyNamespace349 EXPECT_FALSE(Aggregate->getIsMatched());350 EXPECT_TRUE(Function->getIsMatched()); // anyFunction351 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()); // LocalVariable358 EXPECT_TRUE(NestedVariable->getIsMatched()); // NestedVariable359 360 EXPECT_FALSE(LineOne->getIsMatched());361 EXPECT_TRUE(LineTwo->getIsMatched()); // 521362 EXPECT_FALSE(LineThree->getIsMatched());363 EXPECT_TRUE(LineFour->getIsMatched()); // 621364 EXPECT_FALSE(LineFive->getIsMatched());365}366 367TEST(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} // namespace390