blob: 70835ce05507c25fca89c085855a26733457ddc9 [file] [log] [blame]
//===- 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