forked from OSchip/llvm-project
400 lines
12 KiB
C++
400 lines
12 KiB
C++
//===- 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 {
|
|
// 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);
|
|
template <typename T, typename F> T *create(F Function) {
|
|
// 'Function' will update a specific kind of the logical element to
|
|
// have the ability of kind selection.
|
|
T *Element = new (std::nothrow) T();
|
|
EXPECT_NE(Element, nullptr);
|
|
(Element->*Function)();
|
|
return 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.
|
|
IntegerType = create<LVType, LVTypeSetFunction>(&LVType::setIsBase);
|
|
|
|
// Create the logical scopes.
|
|
CompileUnit = create<LVScopeCompileUnit, LVScopeSetFunction>(
|
|
&LVScope::setIsCompileUnit);
|
|
Function =
|
|
create<LVScopeFunction, LVScopeSetFunction>(&LVScope::setIsFunction);
|
|
NestedScope =
|
|
create<LVScope, LVScopeSetFunction>(&LVScope::setIsLexicalBlock);
|
|
Namespace =
|
|
create<LVScopeNamespace, LVScopeSetFunction>(&LVScope::setIsNamespace);
|
|
Aggregate =
|
|
create<LVScopeAggregate, LVScopeSetFunction>(&LVScope::setIsAggregate);
|
|
|
|
// Create the logical symbols.
|
|
ClassMember = create<LVSymbol, LVSymbolSetFunction>(&LVSymbol::setIsMember);
|
|
LocalVariable =
|
|
create<LVSymbol, LVSymbolSetFunction>(&LVSymbol::setIsVariable);
|
|
NestedVariable =
|
|
create<LVSymbol, LVSymbolSetFunction>(&LVSymbol::setIsVariable);
|
|
Parameter = create<LVSymbol, LVSymbolSetFunction>(&LVSymbol::setIsParameter);
|
|
|
|
// Create the logical lines.
|
|
LineOne = create<LVLine, LVLineSetFunction>(&LVLine::setIsLineDebug);
|
|
LineTwo = create<LVLine, LVLineSetFunction>(&LVLine::setIsBasicBlock);
|
|
LineThree = create<LVLine, LVLineSetFunction>(&LVLine::setIsNewStatement);
|
|
LineFour = create<LVLine, LVLineSetFunction>(&LVLine::setIsPrologueEnd);
|
|
LineFive = create<LVLine, LVLineSetFunction>(&LVLine::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
|