|
//===-- LVOptions.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 |
|
// |
|
//===----------------------------------------------------------------------===// |
|
// |
|
// This implements the LVOptions class. |
|
// |
|
//===----------------------------------------------------------------------===// |
|
|
|
#include "llvm/DebugInfo/LogicalView/Core/LVOptions.h" |
|
#include "llvm/DebugInfo/LogicalView/Core/LVReader.h" |
|
#include "llvm/Support/Errc.h" |
|
|
|
using namespace llvm; |
|
using namespace llvm::logicalview; |
|
|
|
#define DEBUG_TYPE "Options" |
|
|
|
//===----------------------------------------------------------------------===// |
|
// Options extracted from the command line. |
|
//===----------------------------------------------------------------------===// |
|
static LVOptions Options; |
|
LVOptions *LVOptions::getOptions() { return &Options; } |
|
void LVOptions::setOptions(LVOptions *CmdOptions) { Options = *CmdOptions; } |
|
|
|
void LVOptions::resolveDependencies() { |
|
// Attributes that are classified as standard options. |
|
auto StandardAttributes = [&]() { |
|
// Set the 'standard' attribute to indicate its associated attributes. |
|
setAttributeStandard(); |
|
|
|
setAttributeBase(); |
|
setAttributeCoverage(); |
|
setAttributeDirectories(); |
|
setAttributeDiscriminator(); |
|
setAttributeFilename(); |
|
setAttributeFiles(); |
|
setAttributeFormat(); |
|
setAttributeLanguage(); |
|
setAttributeLevel(); |
|
setAttributeProducer(); |
|
setAttributePublics(); |
|
setAttributeRange(); |
|
setAttributeReference(); |
|
setAttributeZero(); |
|
}; |
|
|
|
// Attributes that are classified as extended options. |
|
auto ExtendedAttributes = [&]() { |
|
// Set the 'extended' attribute to indicate its associated attributes. |
|
setAttributeExtended(); |
|
|
|
setAttributeArgument(); |
|
setAttributeDiscarded(); |
|
setAttributeEncoded(); |
|
setAttributeGaps(); |
|
setAttributeGenerated(); |
|
setAttributeGlobal(); |
|
setAttributeInserted(); |
|
setAttributeLinkage(); |
|
setAttributeLocal(); |
|
setAttributeLocation(); |
|
setAttributeOffset(); |
|
setAttributePathname(); |
|
setAttributeQualified(); |
|
setAttributeQualifier(); |
|
setAttributeRegister(); |
|
setAttributeSize(); |
|
setAttributeSubrange(); |
|
setAttributeSystem(); |
|
setAttributeTypename(); |
|
}; |
|
|
|
// '--Attribute=standard' settings. |
|
if (getAttributeStandard()) |
|
StandardAttributes(); |
|
|
|
// '--Attribute=extended' settings. |
|
if (getAttributeExtended()) |
|
ExtendedAttributes(); |
|
|
|
// '--Attribute=all' settings. |
|
if (getAttributeAll()) { |
|
StandardAttributes(); |
|
ExtendedAttributes(); |
|
} |
|
|
|
// '--attribute=pathname' supersedes '--attribute=filename'. |
|
if (getAttributePathname()) |
|
resetAttributeFilename(); |
|
|
|
// Assume '--output=text' as default |
|
if (!getOutputText() && !getOutputJson()) |
|
setOutputText(); |
|
|
|
// '--output=all' settings. |
|
if (getOutputAll()) { |
|
setOutputJson(); |
|
setOutputSplit(); |
|
setOutputText(); |
|
} |
|
|
|
// A view split folder was specified. |
|
if (getOutputFolder().length()) |
|
setOutputSplit(); |
|
|
|
// Always use the full pathname with splitted output. |
|
if (getOutputSplit()) |
|
setAttributePathname(); |
|
|
|
// '--print=elements' settings. |
|
if (getPrintElements()) { |
|
setPrintInstructions(); |
|
setPrintLines(); |
|
setPrintScopes(); |
|
setPrintSymbols(); |
|
setPrintTypes(); |
|
} |
|
|
|
// '--print=all' settings. |
|
if (getPrintAll()) { |
|
setPrintInstructions(); |
|
setPrintLines(); |
|
setPrintScopes(); |
|
setPrintSizes(); |
|
setPrintSymbols(); |
|
setPrintSummary(); |
|
setPrintTypes(); |
|
setPrintWarnings(); |
|
} |
|
|
|
// '--warning=all' settings. |
|
if (getWarningAll()) { |
|
setWarningCoverages(); |
|
setWarningLines(); |
|
setWarningLocations(); |
|
setWarningRanges(); |
|
} |
|
|
|
// '--internal=all' settings. |
|
if (getInternalAll()) { |
|
setInternalCmdline(); |
|
setInternalID(); |
|
setInternalIntegrity(); |
|
setInternalNone(); |
|
setInternalTag(); |
|
} |
|
|
|
// '--compare=all' settings. |
|
if (getCompareAll()) { |
|
setCompareLines(); |
|
setCompareScopes(); |
|
setCompareSymbols(); |
|
setCompareTypes(); |
|
} |
|
|
|
// Compare the scopes if a request for compare symbols, types, lines. |
|
if (getCompareLines() || getCompareSymbols() || getCompareTypes()) |
|
setCompareScopes(); |
|
|
|
// Generic request for comparison. |
|
if (getCompareScopes()) |
|
setCompareExecute(); |
|
|
|
// Print any logical line (debug or instruction). |
|
if (getPrintInstructions() || getPrintLines()) |
|
setPrintAnyLine(); |
|
|
|
// Print any logical element (line, scope, symbol or type). |
|
if (getPrintAnyLine() || getPrintScopes() || getPrintSymbols() || |
|
getPrintTypes()) |
|
setPrintAnyElement(); |
|
|
|
// Print 'sizes' or 'summary'. |
|
if (getPrintSizes() && getPrintSummary()) |
|
setPrintSizesSummary(); |
|
|
|
// Generic request for printing. |
|
if (getPrintAll() || getPrintAnyElement() || getPrintSizesSummary() || |
|
getPrintWarnings()) |
|
setPrintExecute(); |
|
|
|
// '--reports=all' settings. |
|
if (getReportAll()) { |
|
setReportChildren(); |
|
setReportList(); |
|
setReportParents(); |
|
setReportView(); |
|
} |
|
|
|
// '--report=view' is a shortcut for '--report=parents,children'. |
|
if (getReportView()) { |
|
setReportChildren(); |
|
setReportParents(); |
|
} |
|
|
|
// The report will include: Parents or Children. |
|
if (getReportParents() || getReportChildren() || getReportView()) |
|
setReportAnyView(); |
|
|
|
// The report will include: List or Parents or Children. |
|
if (getReportList() || getReportAnyView()) |
|
setReportExecute(); |
|
|
|
// If a view or element comparison has been requested, the following options |
|
// must be set, in order to get a correct compare: |
|
// 1) Sort the CUs, to get a fast compare. |
|
// 2) Encode template instantiations, so the names include template |
|
// parameter information. |
|
// 3) Include qualified types and their sizes. |
|
// 4) Include any inserted abstract references. |
|
// 5) For added/missing elements add the '+' or '-' tags. |
|
if (getCompareExecute()) { |
|
resetPrintExecute(); |
|
setComparePrint(); |
|
setSortMode(LVSortMode::Line); |
|
setAttributeAdded(); |
|
setAttributeArgument(); |
|
setAttributeEncoded(); |
|
setAttributeInserted(); |
|
setAttributeMissing(); |
|
setAttributeQualified(); |
|
setAttributeSize(); |
|
} |
|
|
|
// Enable formatting for printing (indentation, print children). |
|
setPrintFormatting(); |
|
|
|
// These attributes are dependent on the capture of location information. |
|
if (getAttributeCoverage() || getAttributeGaps() || getAttributeRegister()) |
|
setAttributeLocation(); |
|
|
|
// Location information is only relevant when printing symbols. |
|
if (!getPrintSymbols()) { |
|
resetAttributeCoverage(); |
|
resetAttributeGaps(); |
|
resetAttributeLocation(); |
|
resetAttributeRegister(); |
|
} |
|
|
|
// Quick check for printing any element source information. |
|
if (getAttributeFilename() || getAttributePathname()) |
|
setAttributeAnySource(); |
|
|
|
// Quick check for printing any location information. |
|
if (getAttributeLocation() || getAttributeRange()) |
|
setAttributeAnyLocation(); |
|
|
|
if (getAttributeRange() || getPrintAnyLine()) |
|
setGeneralCollectRanges(); |
|
|
|
calculateIndentationSize(); |
|
|
|
// Print collected command line options. |
|
LLVM_DEBUG({ dump(); }); |
|
} |
|
|
|
void LVOptions::calculateIndentationSize() { |
|
if (getInternalID()) { |
|
std::string String = hexSquareString(0); |
|
IndentationSize += String.length(); |
|
} |
|
if (getCompareExecute() && (getAttributeAdded() || getAttributeMissing())) |
|
++IndentationSize; |
|
if (getAttributeOffset()) { |
|
std::string String = hexSquareString(0); |
|
IndentationSize += String.length(); |
|
} |
|
if (getAttributeLevel()) { |
|
std::stringstream Stream; |
|
Stream.str(std::string()); |
|
Stream << "[" << std::setfill('0') << std::setw(3) << 0 << "]"; |
|
IndentationSize += Stream.tellp(); |
|
} |
|
if (getAttributeGlobal()) |
|
++IndentationSize; |
|
} |
|
|
|
// Print the current values for all the options, after the dependencies |
|
// has been resolved. |
|
void LVOptions::print(raw_ostream &OS) const { |
|
// --attribute |
|
OS << "** Attributes **\n" |
|
<< "All: " << getAttributeAll() << ", " |
|
<< "Argument: " << getAttributeArgument() << ", " |
|
<< "Base: " << getAttributeBase() << ", " |
|
<< "Coverage: " << getAttributeCoverage() << "\n" |
|
<< "Directories: " << getAttributeDirectories() << ", " |
|
<< "Discarded: " << getAttributeDiscarded() << ", " |
|
<< "Discriminator: " << getAttributeDiscriminator() << ", " |
|
<< "Encoded: " << getAttributeEncoded() << "\n" |
|
<< "Extended: " << getAttributeExtended() << ", " |
|
<< "Filename: " << getAttributeFilename() << ", " |
|
<< "Files: " << getAttributeFiles() << ", " |
|
<< "Format: " << getAttributeFormat() << "\n" |
|
<< "Gaps: " << getAttributeGaps() << ", " |
|
<< "Generated: " << getAttributeGenerated() << ", " |
|
<< "Global: " << getAttributeGlobal() << ", " |
|
<< "Inserted: " << getAttributeInserted() << "\n" |
|
<< "Level: " << getAttributeLevel() << ", " |
|
<< "Linkage: " << getAttributeLinkage() << ", " |
|
<< "Local: " << getAttributeLocal() << ", " |
|
<< "Location: " << getAttributeLocation() << "\n" |
|
<< "Offset: " << getAttributeOffset() << ", " |
|
<< "Pathname: " << getAttributePathname() << ", " |
|
<< "Producer: " << getAttributeProducer() << ", " |
|
<< "Publics: " << getAttributePublics() << "\n" |
|
<< "Qualified: " << getAttributeQualified() << ", " |
|
<< "Qualifier: " << getAttributeQualifier() << ", " |
|
<< "Range: " << getAttributeRange() << ", " |
|
<< "Reference: " << getAttributeReference() << "\n" |
|
<< "Register: " << getAttributeRegister() << ", " |
|
<< "Size: " << getAttributeSize() << ", " |
|
<< "Standard: " << getAttributeStandard() << ", " |
|
<< "Subrange: " << getAttributeSubrange() << "\n" |
|
<< "System: " << getAttributeSystem() << ", " |
|
<< "Typename: " << getAttributeTypename() << ", " |
|
<< "Underlying: " << getAttributeUnderlying() << ", " |
|
<< "Zero: " << getAttributeZero() << "\n"; |
|
OS << "Added: " << getAttributeAdded() << ", " |
|
<< "AnyLocation: " << getAttributeAnyLocation() << ", " |
|
<< "AnySource: " << getAttributeAnySource() << ", " |
|
<< "Missing: " << getAttributeMissing() << "\n" |
|
<< "\n"; |
|
|
|
// --compare |
|
OS << "** Compare **\n" |
|
<< "All: " << getCompareAll() << ", " |
|
<< "Lines: " << getCompareLines() << ", " |
|
<< "Scopes: " << getCompareScopes() << ", " |
|
<< "Symbols: " << getCompareSymbols() << ", " |
|
<< "Types: " << getCompareTypes() << "\n"; |
|
OS << "Context: " << getCompareContext() << ", " |
|
<< "Execute: " << getCompareExecute() << ", " |
|
<< "Print: " << getComparePrint() << "\n" |
|
<< "\n"; |
|
|
|
// --print |
|
OS << "** Print **\n" |
|
<< "All: " << getPrintAll() << ", " |
|
<< "Elements: " << getPrintElements() << ", " |
|
<< "Instructions: " << getPrintInstructions() << ", " |
|
<< "Lines: " << getPrintLines() << "\n" |
|
<< "Scopes: " << getPrintScopes() << ", " |
|
<< "Sizes: " << getPrintSizes() << ", " |
|
<< "Summary: " << getPrintSummary() << ", " |
|
<< "Symbols: " << getPrintSymbols() << "\n" |
|
<< "Types: " << getPrintTypes() << ", " |
|
<< "Warnings: " << getPrintWarnings() << "\n"; |
|
OS << "AnyElemeny: " << getPrintAnyElement() << ", " |
|
<< "AnyLine: " << getPrintAnyLine() << ", " |
|
<< "Execute: " << getPrintExecute() << ", " |
|
<< "Formatting: " << getPrintFormatting() << "\n" |
|
<< "Offset: " << getPrintOffset() << ", " |
|
<< "SizesSummary: " << getPrintSizesSummary() << "\n" |
|
<< "\n"; |
|
|
|
// --report |
|
OS << "** Report **\n" |
|
<< "All: " << getReportAll() << ", " |
|
<< "Children: " << getReportChildren() << ", " |
|
<< "List: " << getReportList() << ", " |
|
<< "Parents: " << getReportParents() << ", " |
|
<< "View: " << getReportView() << "\n"; |
|
OS << "AnyView: " << getReportAnyView() << ", " |
|
<< "Execute: " << getReportExecute() << "\n" |
|
<< "\n"; |
|
|
|
// --select |
|
OS << "** Select **\n" |
|
<< "IgnoreCase: " << getSelectIgnoreCase() << ", " |
|
<< "UseRegex: " << getSelectUseRegex() << ", " |
|
<< "Execute: " << getSelectExecute() << ", " |
|
<< "GenericKind: " << getSelectGenericKind() << "\n" |
|
<< "GenericPattern: " << getSelectGenericPattern() << ", " |
|
<< "OffsetPattern: " << getSelectOffsetPattern() << "\n" |
|
<< "\n"; |
|
|
|
// --warning |
|
OS << "** Warning **\n" |
|
<< "All: " << getWarningAll() << ", " |
|
<< "Coverage: " << getWarningCoverages() << ", " |
|
<< "Lines: " << getWarningLines() << ", " |
|
<< "Locations: " << getWarningLocations() << ", " |
|
<< "Ranges: " << getWarningRanges() << "\n" |
|
<< "\n"; |
|
|
|
// --internal |
|
OS << "** Internal **\n" |
|
<< "All: " << Options.getInternalAll() << ", " |
|
<< "Cmdline: " << Options.getInternalCmdline() << ", " |
|
<< "ID: " << Options.getInternalID() << ", " |
|
<< "Integrity: " << Options.getInternalIntegrity() << ", " |
|
<< "None: " << Options.getInternalNone() << "\n" |
|
<< "Tag: " << Options.getInternalTag() << "\n" |
|
<< "\n"; |
|
} |
|
|
|
//===----------------------------------------------------------------------===// |
|
// Logical element selection using patterns. |
|
//===----------------------------------------------------------------------===// |
|
LVPatterns *LVPatterns::getPatterns() { |
|
static LVPatterns Patterns; |
|
return &Patterns; |
|
} |
|
|
|
Error LVPatterns::createMatchEntry(LVMatchInfo &Filters, StringRef Pattern, |
|
bool IgnoreCase, bool UseRegex) { |
|
LVMatch Match; |
|
// Process pattern as regular expression. |
|
if (UseRegex) { |
|
Match.Pattern = std::string(Pattern); |
|
if (Pattern.size()) { |
|
Match.RE = std::make_shared<Regex>(Pattern, IgnoreCase ? Regex::IgnoreCase |
|
: Regex::NoFlags); |
|
std::string Error; |
|
if (!Match.RE->isValid(Error)) |
|
return createStringError(errc::invalid_argument, |
|
"Error in regular expression: %s", |
|
Error.c_str()); |
|
|
|
Match.Mode = LVMatchMode::Regex; |
|
Filters.push_back(Match); |
|
return Error::success(); |
|
} |
|
} |
|
|
|
// Process pattern as an exact string match, depending on the case. |
|
Match.Pattern = std::string(Pattern); |
|
if (Match.Pattern.size()) { |
|
Match.Mode = IgnoreCase ? LVMatchMode::NoCase : LVMatchMode::Match; |
|
Filters.push_back(Match); |
|
} |
|
|
|
return Error::success(); |
|
} |
|
|
|
void LVPatterns::addGenericPatterns(StringSet<> &Patterns) { |
|
addPatterns(Patterns, GenericMatchInfo); |
|
if (GenericMatchInfo.size()) { |
|
options().setSelectGenericPattern(); |
|
options().setSelectExecute(); |
|
} |
|
} |
|
|
|
void LVPatterns::addOffsetPatterns(const LVOffsetSet &Patterns) { |
|
llvm::append_range(OffsetMatchInfo, Patterns); |
|
if (OffsetMatchInfo.size()) { |
|
options().setSelectOffsetPattern(); |
|
options().setSelectExecute(); |
|
} |
|
} |
|
|
|
void LVPatterns::addPatterns(StringSet<> &Patterns, LVMatchInfo &Filters) { |
|
bool IgnoreCase = options().getSelectIgnoreCase(); |
|
bool UseRegex = options().getSelectUseRegex(); |
|
for (const StringSet<>::value_type &Entry : Patterns) { |
|
StringRef Pattern = Entry.first(); |
|
if (Error Err = createMatchEntry(Filters, Pattern, IgnoreCase, UseRegex)) |
|
consumeError(std::move(Err)); |
|
} |
|
|
|
LLVM_DEBUG({ |
|
dbgs() << "\nPattern Information:\n"; |
|
for (LVMatch &Match : Filters) |
|
dbgs() << "Mode: " |
|
<< (Match.Mode == LVMatchMode::Match ? "Match" : "Regex") |
|
<< " Pattern: '" << Match.Pattern << "'\n"; |
|
}); |
|
} |
|
|
|
void LVPatterns::addElement(LVElement *Element) { |
|
// Mark any element that matches a given pattern. |
|
Element->setIsMatched(); |
|
options().setSelectExecute(); |
|
if (options().getReportList()) |
|
getReaderCompileUnit()->addMatched(Element); |
|
if (options().getReportAnyView()) { |
|
getReaderCompileUnit()->addMatched(Element->getIsScope() |
|
? static_cast<LVScope *>(Element) |
|
: Element->getParentScope()); |
|
// Mark element as matched. |
|
if (!Element->getIsScope()) |
|
Element->setHasPattern(); |
|
} |
|
} |
|
|
|
void LVPatterns::updateReportOptions() { |
|
if (ElementRequest.size() || LineRequest.size() || ScopeRequest.size() || |
|
SymbolRequest.size() || TypeRequest.size()) { |
|
options().setSelectGenericKind(); |
|
options().setSelectExecute(); |
|
} |
|
|
|
// If we have selected requests and there are no specified report options, |
|
// assume the 'details' option. |
|
if (options().getSelectExecute() && !options().getReportExecute()) { |
|
options().setReportExecute(); |
|
options().setReportList(); |
|
} |
|
} |
|
|
|
// Match a general pattern. |
|
bool LVPatterns::matchPattern(StringRef Input, const LVMatchInfo &MatchInfo) { |
|
bool Matched = false; |
|
// Do not match an empty 'Input'. |
|
if (Input.empty()) |
|
return Matched; |
|
// Traverse all match specifications. |
|
for (const LVMatch &Match : MatchInfo) { |
|
switch (Match.Mode) { |
|
case LVMatchMode::Match: |
|
Matched = Input == Match.Pattern; |
|
break; |
|
case LVMatchMode::NoCase: |
|
Matched = Input.equals_insensitive(Match.Pattern); |
|
break; |
|
case LVMatchMode::Regex: |
|
Matched = Match.RE->match(Input); |
|
break; |
|
default: |
|
break; |
|
} |
|
// Return if we have a match. |
|
if (Matched) |
|
return true; |
|
} |
|
return Matched; |
|
} |
|
|
|
bool LVPatterns::printElement(const LVLine *Line) const { |
|
return (options().getPrintLines() && Line->getIsLineDebug()) || |
|
(options().getPrintInstructions() && Line->getIsLineAssembler()); |
|
} |
|
|
|
bool LVPatterns::printObject(const LVLocation *Location) const { |
|
if (options().getAttributeAll()) |
|
return true; |
|
bool DoPrint = options().getAttributeAnyLocation(); |
|
// Consider the case of filler locations. |
|
if (DoPrint && Location && Location->getIsGapEntry()) |
|
DoPrint = options().getAttributeGaps(); |
|
return DoPrint; |
|
} |
|
|
|
bool LVPatterns::printElement(const LVScope *Scope) const { |
|
// A scope will be printed depending on the following rules: |
|
// - Request to print scopes. |
|
// - Request to print any of its children. |
|
// - If the scope is Root or CompileUnit: |
|
// Request to print summary, sizes or warnings. |
|
return options().getPrintScopes() || |
|
(options().getPrintSymbols() && Scope->getHasSymbols()) || |
|
(options().getPrintAnyLine() && Scope->getHasLines()) || |
|
(options().getPrintTypes() && Scope->getHasTypes()) || |
|
((options().getPrintSizesSummary() || options().getPrintWarnings()) && |
|
(Scope->getIsRoot() || Scope->getIsCompileUnit())); |
|
} |
|
|
|
bool LVPatterns::printElement(const LVSymbol *Symbol) const { |
|
// Print compiler generated symbols only if command line option. |
|
if (Symbol->getIsArtificial()) |
|
return options().getAttributeGenerated() && options().getPrintSymbols(); |
|
return options().getPrintSymbols(); |
|
} |
|
|
|
bool LVPatterns::printElement(const LVType *Type) const { |
|
// Print array subranges only if print types is requested. |
|
if (Type->getIsSubrange()) |
|
return options().getAttributeSubrange() && options().getPrintTypes(); |
|
return options().getPrintTypes(); |
|
} |
|
|
|
void LVPatterns::print(raw_ostream &OS) const { |
|
OS << "LVPatterns\n"; |
|
LLVM_DEBUG(dbgs() << "Print Patterns\n"); |
|
} |