| //===- llvm/unittest/DebugInfo/LogicalView/SelectElementsTest.cpp ---------===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "llvm/DebugInfo/LogicalView/Core/LVLine.h" |
| #include "llvm/DebugInfo/LogicalView/Core/LVReader.h" |
| #include "llvm/DebugInfo/LogicalView/Core/LVScope.h" |
| #include "llvm/DebugInfo/LogicalView/Core/LVSymbol.h" |
| #include "llvm/DebugInfo/LogicalView/Core/LVType.h" |
| #include "llvm/Support/ScopedPrinter.h" |
| #include "llvm/Support/ToolOutputFile.h" |
| #include "llvm/Testing/Support/Error.h" |
| |
| #include "gtest/gtest.h" |
| |
| using namespace llvm; |
| using namespace llvm::logicalview; |
| |
| namespace { |
| |
| class ReaderTestSelection : public LVReader { |
| #define CREATE(VARIABLE, CREATE_FUNCTION, SET_FUNCTION) \ |
| VARIABLE = CREATE_FUNCTION(); \ |
| EXPECT_NE(VARIABLE, nullptr); \ |
| VARIABLE->SET_FUNCTION(); |
| |
| // Types. |
| LVType *IntegerType = nullptr; |
| |
| // Scopes. |
| LVScope *NestedScope = nullptr; |
| LVScopeAggregate *Aggregate = nullptr; |
| LVScopeFunction *Function = nullptr; |
| LVScopeNamespace *Namespace = nullptr; |
| |
| // Symbols. |
| LVSymbol *ClassMember = nullptr; |
| LVSymbol *LocalVariable = nullptr; |
| LVSymbol *NestedVariable = nullptr; |
| LVSymbol *Parameter = nullptr; |
| |
| // Lines. |
| LVLine *LineOne = nullptr; |
| LVLine *LineTwo = nullptr; |
| LVLine *LineThree = nullptr; |
| LVLine *LineFour = nullptr; |
| LVLine *LineFive = nullptr; |
| |
| protected: |
| void add(LVScope *Parent, LVElement *Element); |
| void set(LVElement *Element, StringRef Name, LVOffset Offset, |
| uint32_t LineNumber = 0, LVElement *Type = nullptr); |
| |
| public: |
| ReaderTestSelection(ScopedPrinter &W) : LVReader("", "", W) { |
| setInstance(this); |
| } |
| |
| Error createScopes() { return LVReader::createScopes(); } |
| |
| void createElements(); |
| void addElements(); |
| void initElements(); |
| void resolvePatterns(LVPatterns &Patterns); |
| void checkFlexiblePatterns(); |
| void checkGenericPatterns(); |
| void checkKindPatterns(); |
| }; |
| |
| // Helper function to add a logical element to a given scope. |
| void ReaderTestSelection::add(LVScope *Parent, LVElement *Child) { |
| Parent->addElement(Child); |
| EXPECT_EQ(Child->getParent(), Parent); |
| EXPECT_EQ(Child->getLevel(), Parent->getLevel() + 1); |
| } |
| |
| // Helper function to set the initial values for a given logical element. |
| void ReaderTestSelection::set(LVElement *Element, StringRef Name, |
| LVOffset Offset, uint32_t LineNumber, |
| LVElement *Type) { |
| Element->setName(Name); |
| Element->setOffset(Offset); |
| Element->setLineNumber(LineNumber); |
| Element->setType(Type); |
| EXPECT_EQ(Element->getName(), Name); |
| EXPECT_EQ(Element->getOffset(), Offset); |
| EXPECT_EQ(Element->getLineNumber(), LineNumber); |
| EXPECT_EQ(Element->getType(), Type); |
| } |
| |
| // Create the logical elements. |
| void ReaderTestSelection::createElements() { |
| // Create scope root. |
| Error Err = createScopes(); |
| ASSERT_THAT_ERROR(std::move(Err), Succeeded()); |
| Root = getScopesRoot(); |
| EXPECT_NE(Root, nullptr); |
| |
| // Create the logical types. |
| CREATE(IntegerType, createType, setIsBase); |
| |
| // Create the logical scopes. |
| CREATE(CompileUnit, createScopeCompileUnit, setIsCompileUnit); |
| CREATE(Function, createScopeFunction, setIsFunction); |
| CREATE(NestedScope, createScope, setIsLexicalBlock); |
| CREATE(Namespace, createScopeNamespace, setIsNamespace); |
| CREATE(Aggregate, createScopeAggregate, setIsAggregate); |
| |
| // Create the logical symbols. |
| CREATE(ClassMember, createSymbol, setIsMember); |
| CREATE(LocalVariable, createSymbol, setIsVariable); |
| CREATE(NestedVariable, createSymbol, setIsVariable); |
| CREATE(Parameter, createSymbol, setIsParameter); |
| |
| // Create the logical lines. |
| CREATE(LineOne, createLine, setIsLineDebug); |
| CREATE(LineTwo, createLine, setIsBasicBlock); |
| CREATE(LineThree, createLine, setIsNewStatement); |
| CREATE(LineFour, createLine, setIsPrologueEnd); |
| CREATE(LineFive, createLine, setIsLineAssembler); |
| } |
| |
| // Create the logical view adding the created logical elements. |
| void ReaderTestSelection::addElements() { |
| setCompileUnit(CompileUnit); |
| |
| // Root |
| // CompileUnit |
| // IntegerType |
| // Namespace |
| // Aggregate |
| // ClassMember |
| // Function |
| // Parameter |
| // LocalVariable |
| // LineOne |
| // LineTwo |
| // NestedScope |
| // NestedVariable |
| // LineThree |
| // LineFour |
| // LineFive |
| |
| // Add elements to Root. |
| add(Root, CompileUnit); |
| |
| // Add elements to CompileUnit. |
| add(CompileUnit, IntegerType); |
| add(CompileUnit, Namespace); |
| add(CompileUnit, Function); |
| |
| // Add elements to Namespace. |
| add(Namespace, Aggregate); |
| |
| // Add elements to Function. |
| add(Function, Parameter); |
| add(Function, LocalVariable); |
| add(Function, LineOne); |
| add(Function, LineTwo); |
| add(Function, LineFive); |
| add(Function, NestedScope); |
| |
| // Add elements to Aggregate. |
| add(Aggregate, ClassMember); |
| |
| // Add elements to NestedScope. |
| add(NestedScope, NestedVariable); |
| add(NestedScope, LineThree); |
| add(NestedScope, LineFour); |
| } |
| |
| void ReaderTestSelection::resolvePatterns(LVPatterns &Patterns) { |
| // Traverse the given scope and its children applying the pattern match. |
| // Before applying the pattern, reset previous matched state. |
| std::function<void(LVScope * Parent)> TraverseScope = [&](LVScope *Parent) { |
| auto Traverse = [&](const auto *Set) { |
| if (Set) |
| for (const auto &Entry : *Set) { |
| Entry->resetIsMatched(); |
| Patterns.resolvePatternMatch(Entry); |
| } |
| }; |
| |
| Parent->resetIsMatched(); |
| Patterns.resolvePatternMatch(Parent); |
| |
| Traverse(Parent->getSymbols()); |
| Traverse(Parent->getTypes()); |
| Traverse(Parent->getLines()); |
| |
| if (const LVScopes *Scopes = Parent->getScopes()) |
| for (LVScope *Scope : *Scopes) { |
| Scope->resetIsMatched(); |
| Patterns.resolvePatternMatch(Scope); |
| TraverseScope(Scope); |
| } |
| }; |
| |
| // Start traversing the scopes root and apply any matching pattern. |
| TraverseScope(Root); |
| } |
| |
| // Set initial values to logical elements. |
| void ReaderTestSelection::initElements() { |
| // Types. |
| set(IntegerType, "int", 0x1000); |
| |
| // Scopes. |
| set(CompileUnit, "test.cpp", 0x2000); |
| set(Namespace, "anyNamespace", 0x3000, 300); |
| set(Aggregate, "anyClass", 0x4000, 400); |
| set(Function, "anyFunction", 0x5000, 500, IntegerType); |
| set(NestedScope, "", 0x6000, 600); |
| |
| // Symbols. |
| set(Parameter, "Param", 0x5100, 510, IntegerType); |
| set(LocalVariable, "LocalVariable", 0x5200, 520, IntegerType); |
| set(NestedVariable, "NestedVariable", 0x6200, 620, IntegerType); |
| |
| // Lines. |
| set(LineOne, "", 0x5110, 511); |
| set(LineTwo, "", 0x5210, 521); |
| set(LineThree, "", 0x6110, 611); |
| set(LineFour, "", 0x6210, 621); |
| set(LineFive, "", 0x7110, 711); |
| } |
| |
| // Check logical elements kind patterns. |
| void ReaderTestSelection::checkKindPatterns() { |
| // Add patterns. |
| LVPatterns &Patterns = patterns(); |
| Patterns.clear(); |
| |
| LVElementKindSet KindElements; // --select-elements=<Kind> |
| LVLineKindSet KindLines; // --select-lines=<Kind> |
| LVScopeKindSet KindScopes; // --select-scopes=<Kind> |
| LVSymbolKindSet KindSymbols; // --select-symbols=<Kind> |
| LVTypeKindSelection KindTypes; // --select-types=<Kind> |
| |
| KindElements.insert(LVElementKind::Global); |
| KindLines.insert(LVLineKind::IsLineDebug); |
| KindLines.insert(LVLineKind::IsNewStatement); |
| KindLines.insert(LVLineKind::IsLineAssembler); |
| KindScopes.insert(LVScopeKind::IsLexicalBlock); |
| KindSymbols.insert(LVSymbolKind::IsMember); |
| KindSymbols.insert(LVSymbolKind::IsParameter); |
| KindTypes.insert(LVTypeKind::IsBase); |
| |
| // Add requests based on the element kind. |
| Patterns.addRequest(KindElements); |
| Patterns.addRequest(KindLines); |
| Patterns.addRequest(KindScopes); |
| Patterns.addRequest(KindSymbols); |
| Patterns.addRequest(KindTypes); |
| |
| // Apply the collected patterns. |
| resolvePatterns(Patterns); |
| |
| EXPECT_FALSE(CompileUnit->getIsMatched()); |
| EXPECT_FALSE(Namespace->getIsMatched()); |
| EXPECT_FALSE(Aggregate->getIsMatched()); |
| EXPECT_FALSE(Function->getIsMatched()); |
| EXPECT_TRUE(NestedScope->getIsMatched()); |
| |
| EXPECT_TRUE(IntegerType->getIsMatched()); |
| |
| EXPECT_TRUE(ClassMember->getIsMatched()); |
| EXPECT_TRUE(Parameter->getIsMatched()); |
| EXPECT_FALSE(LocalVariable->getIsMatched()); |
| EXPECT_FALSE(NestedVariable->getIsMatched()); |
| |
| EXPECT_TRUE(LineOne->getIsMatched()); |
| EXPECT_FALSE(LineTwo->getIsMatched()); |
| EXPECT_TRUE(LineThree->getIsMatched()); |
| EXPECT_FALSE(LineFour->getIsMatched()); |
| EXPECT_TRUE(LineFive->getIsMatched()); |
| } |
| |
| // Check logical elements generic patterns (Case sensitive). |
| void ReaderTestSelection::checkGenericPatterns() { |
| // Add patterns. |
| LVPatterns &Patterns = patterns(); |
| Patterns.clear(); |
| |
| StringSet<> Generic; // --select=<Pattern> |
| Generic.insert(Function->getName()); // anyFunction |
| Generic.insert(Namespace->getName()); // anyNamespace |
| Generic.insert(LocalVariable->getName()); // LocalVariable |
| |
| LVOffsetSet Offsets; // --select-offset=<Offset> |
| Offsets.insert(IntegerType->getOffset()); |
| Offsets.insert(LineOne->getOffset()); |
| Offsets.insert(LineTwo->getOffset()); |
| |
| // Add requests based on the generic string and offset. |
| Patterns.addGenericPatterns(Generic); |
| Patterns.addOffsetPatterns(Offsets); |
| |
| // Apply the collected patterns. |
| resolvePatterns(Patterns); |
| |
| EXPECT_FALSE(CompileUnit->getIsMatched()); |
| EXPECT_TRUE(Namespace->getIsMatched()); |
| EXPECT_FALSE(Aggregate->getIsMatched()); |
| EXPECT_TRUE(Function->getIsMatched()); |
| EXPECT_FALSE(NestedScope->getIsMatched()); |
| |
| EXPECT_TRUE(IntegerType->getIsMatched()); |
| |
| EXPECT_FALSE(ClassMember->getIsMatched()); |
| EXPECT_FALSE(Parameter->getIsMatched()); |
| EXPECT_TRUE(LocalVariable->getIsMatched()); |
| EXPECT_FALSE(NestedVariable->getIsMatched()); |
| |
| EXPECT_TRUE(LineOne->getIsMatched()); |
| EXPECT_TRUE(LineTwo->getIsMatched()); |
| EXPECT_FALSE(LineThree->getIsMatched()); |
| EXPECT_FALSE(LineFour->getIsMatched()); |
| EXPECT_FALSE(LineFive->getIsMatched()); |
| } |
| |
| // Check logical elements flexible patterns (case insensitive, RegEx). |
| void ReaderTestSelection::checkFlexiblePatterns() { |
| options().setSelectIgnoreCase(); |
| options().setSelectUseRegex(); |
| |
| // Add patterns. |
| LVPatterns &Patterns = patterns(); |
| Patterns.clear(); |
| |
| StringSet<> Generic; // --select=<Pattern> |
| Generic.insert("function"); |
| Generic.insert("NaMeSpAcE"); |
| Generic.insert("[a-z]*Variable"); |
| Generic.insert("[0-9]21"); |
| |
| // Add requests based on the flexible string. |
| Patterns.addGenericPatterns(Generic); |
| |
| // Apply the collected patterns. |
| resolvePatterns(Patterns); |
| |
| EXPECT_FALSE(CompileUnit->getIsMatched()); |
| EXPECT_TRUE(Namespace->getIsMatched()); // anyNamespace |
| EXPECT_FALSE(Aggregate->getIsMatched()); |
| EXPECT_TRUE(Function->getIsMatched()); // anyFunction |
| EXPECT_FALSE(NestedScope->getIsMatched()); |
| |
| EXPECT_FALSE(IntegerType->getIsMatched()); |
| |
| EXPECT_FALSE(ClassMember->getIsMatched()); |
| EXPECT_FALSE(Parameter->getIsMatched()); |
| EXPECT_TRUE(LocalVariable->getIsMatched()); // LocalVariable |
| EXPECT_TRUE(NestedVariable->getIsMatched()); // NestedVariable |
| |
| EXPECT_FALSE(LineOne->getIsMatched()); |
| EXPECT_TRUE(LineTwo->getIsMatched()); // 521 |
| EXPECT_FALSE(LineThree->getIsMatched()); |
| EXPECT_TRUE(LineFour->getIsMatched()); // 621 |
| EXPECT_FALSE(LineFive->getIsMatched()); |
| } |
| |
| TEST(LogicalViewTest, SelectElements) { |
| ScopedPrinter W(outs()); |
| ReaderTestSelection Reader(W); |
| |
| // Reader options. |
| LVOptions ReaderOptions; |
| ReaderOptions.setAttributeOffset(); |
| ReaderOptions.setPrintAll(); |
| ReaderOptions.setReportList(); |
| ReaderOptions.setReportAnyView(); |
| |
| ReaderOptions.resolveDependencies(); |
| options().setOptions(&ReaderOptions); |
| |
| Reader.createElements(); |
| Reader.addElements(); |
| Reader.initElements(); |
| Reader.checkKindPatterns(); |
| Reader.checkGenericPatterns(); |
| Reader.checkFlexiblePatterns(); |
| } |
| |
| } // namespace |