blob: 265237ee21dc28fe472390b5ea6defe7389acc25 [file] [log] [blame]
//===-- 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();
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();
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.
// 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();
}
// 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() {
#ifndef NDEBUG
if (getInternalID()) {
std::string String = hexSquareString(0);
IndentationSize += String.length();
}
#endif
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() << ", "
<< "Standard: " << getAttributeStandard() << ", "
<< "Subrange: " << getAttributeSubrange() << ", "
<< "System: " << getAttributeSystem() << "\n"
<< "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) {
for (const LVOffset &Entry : Patterns)
OffsetMatchInfo.push_back(Entry);
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.equals(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");
}