1 //===-- LVOptions.cpp -----------------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This implements the LVOptions class.
11 //===----------------------------------------------------------------------===//
13 #include "llvm/DebugInfo/LogicalView/Core/LVOptions.h"
14 #include "llvm/DebugInfo/LogicalView/Core/LVReader.h"
15 #include "llvm/Support/Errc.h"
18 using namespace llvm::logicalview
;
20 #define DEBUG_TYPE "Options"
22 //===----------------------------------------------------------------------===//
23 // Options extracted from the command line.
24 //===----------------------------------------------------------------------===//
25 static LVOptions Options
;
26 LVOptions
*LVOptions::getOptions() { return &Options
; }
27 void LVOptions::setOptions(LVOptions
*CmdOptions
) { Options
= *CmdOptions
; }
29 void LVOptions::resolveDependencies() {
30 // Attributes that are classified as standard options.
31 auto StandardAttributes
= [&]() {
32 // Set the 'standard' attribute to indicate its associated attributes.
33 setAttributeStandard();
36 setAttributeCoverage();
37 setAttributeDirectories();
38 setAttributeDiscriminator();
39 setAttributeFilename();
43 setAttributeProducer();
44 setAttributePublics();
46 setAttributeReference();
50 // Attributes that are classified as extended options.
51 auto ExtendedAttributes
= [&]() {
52 // Set the 'extended' attribute to indicate its associated attributes.
53 setAttributeExtended();
55 setAttributeArgument();
56 setAttributeDiscarded();
57 setAttributeEncoded();
59 setAttributeGenerated();
61 setAttributeInserted();
62 setAttributeLinkage();
64 setAttributeLocation();
66 setAttributePathname();
67 setAttributeQualified();
68 setAttributeQualifier();
69 setAttributeRegister();
70 setAttributeSubrange();
72 setAttributeTypename();
75 // '--Attribute=standard' settings.
76 if (getAttributeStandard())
79 // '--Attribute=extended' settings.
80 if (getAttributeExtended())
83 // '--Attribute=all' settings.
84 if (getAttributeAll()) {
89 // '--attribute=pathname' supersedes '--attribute=filename'.
90 if (getAttributePathname())
91 resetAttributeFilename();
93 // Assume '--output=text' as default
94 if (!getOutputText() && !getOutputJson())
97 // '--output=all' settings.
104 // A view split folder was specified.
105 if (getOutputFolder().length())
108 // Always use the full pathname with splitted output.
109 if (getOutputSplit())
110 setAttributePathname();
112 // '--print=elements' settings.
113 if (getPrintElements()) {
114 setPrintInstructions();
121 // '--print=all' settings.
123 setPrintInstructions();
133 // '--warning=all' settings.
134 if (getWarningAll()) {
135 setWarningCoverages();
137 setWarningLocations();
141 // '--internal=all' settings.
142 if (getInternalAll()) {
143 setInternalCmdline();
145 setInternalIntegrity();
150 // '--compare=all' settings.
151 if (getCompareAll()) {
158 // Compare the scopes if a request for compare symbols, types, lines.
159 if (getCompareLines() || getCompareSymbols() || getCompareTypes())
162 // Generic request for comparison.
163 if (getCompareScopes())
166 // Print any logical line (debug or instruction).
167 if (getPrintInstructions() || getPrintLines())
170 // Print any logical element (line, scope, symbol or type).
171 if (getPrintAnyLine() || getPrintScopes() || getPrintSymbols() ||
173 setPrintAnyElement();
175 // Print 'sizes' or 'summary'.
176 if (getPrintSizes() && getPrintSummary())
177 setPrintSizesSummary();
179 // Generic request for printing.
180 if (getPrintAll() || getPrintAnyElement() || getPrintSizesSummary() ||
184 // '--reports=all' settings.
185 if (getReportAll()) {
192 // '--report=view' is a shortcut for '--report=parents,children'.
193 if (getReportView()) {
198 // The report will include: Parents or Children.
199 if (getReportParents() || getReportChildren() || getReportView())
202 // The report will include: List or Parents or Children.
203 if (getReportList() || getReportAnyView())
206 // If a view or element comparison has been requested, the following options
207 // must be set, in order to get a correct compare:
208 // 1) Sort the CUs, to get a fast compare.
209 // 2) Encode template instantiations, so the names include template
210 // parameter information.
211 // 3) Include qualified types.
212 // 4) Include any inserted abstract references.
213 // 5) For added/missing elements add the '+' or '-' tags.
214 if (getCompareExecute()) {
217 setSortMode(LVSortMode::Line
);
219 setAttributeArgument();
220 setAttributeEncoded();
221 setAttributeInserted();
222 setAttributeMissing();
223 setAttributeQualified();
226 // Enable formatting for printing (indentation, print children).
227 setPrintFormatting();
229 // These attributes are dependent on the capture of location information.
230 if (getAttributeCoverage() || getAttributeGaps() || getAttributeRegister())
231 setAttributeLocation();
233 // Location information is only relevant when printing symbols.
234 if (!getPrintSymbols()) {
235 resetAttributeCoverage();
236 resetAttributeGaps();
237 resetAttributeLocation();
238 resetAttributeRegister();
241 // Quick check for printing any element source information.
242 if (getAttributeFilename() || getAttributePathname())
243 setAttributeAnySource();
245 // Quick check for printing any location information.
246 if (getAttributeLocation() || getAttributeRange())
247 setAttributeAnyLocation();
249 if (getAttributeRange() || getPrintAnyLine())
250 setGeneralCollectRanges();
252 calculateIndentationSize();
254 // Print collected command line options.
255 LLVM_DEBUG({ dump(); });
258 void LVOptions::calculateIndentationSize() {
260 if (getInternalID()) {
261 std::string String
= hexSquareString(0);
262 IndentationSize
+= String
.length();
265 if (getCompareExecute() && (getAttributeAdded() || getAttributeMissing()))
267 if (getAttributeOffset()) {
268 std::string String
= hexSquareString(0);
269 IndentationSize
+= String
.length();
271 if (getAttributeLevel()) {
272 std::stringstream Stream
;
273 Stream
.str(std::string());
274 Stream
<< "[" << std::setfill('0') << std::setw(3) << 0 << "]";
275 IndentationSize
+= Stream
.tellp();
277 if (getAttributeGlobal())
281 // Print the current values for all the options, after the dependencies
282 // has been resolved.
283 void LVOptions::print(raw_ostream
&OS
) const {
285 OS
<< "** Attributes **\n"
286 << "All: " << getAttributeAll() << ", "
287 << "Argument: " << getAttributeArgument() << ", "
288 << "Base: " << getAttributeBase() << ", "
289 << "Coverage: " << getAttributeCoverage() << "\n"
290 << "Directories: " << getAttributeDirectories() << ", "
291 << "Discarded: " << getAttributeDiscarded() << ", "
292 << "Discriminator: " << getAttributeDiscriminator() << ", "
293 << "Encoded: " << getAttributeEncoded() << "\n"
294 << "Extended: " << getAttributeExtended() << ", "
295 << "Filename: " << getAttributeFilename() << ", "
296 << "Files: " << getAttributeFiles() << ", "
297 << "Format: " << getAttributeFormat() << "\n"
298 << "Gaps: " << getAttributeGaps() << ", "
299 << "Generated: " << getAttributeGenerated() << ", "
300 << "Global: " << getAttributeGlobal() << ", "
301 << "Inserted: " << getAttributeInserted() << "\n"
302 << "Level: " << getAttributeLevel() << ", "
303 << "Linkage: " << getAttributeLinkage() << ", "
304 << "Local: " << getAttributeLocal() << ", "
305 << "Location: " << getAttributeLocation() << "\n"
306 << "Offset: " << getAttributeOffset() << ", "
307 << "Pathname: " << getAttributePathname() << ", "
308 << "Producer: " << getAttributeProducer() << ", "
309 << "Publics: " << getAttributePublics() << "\n"
310 << "Qualified: " << getAttributeQualified() << ", "
311 << "Qualifier: " << getAttributeQualifier() << ", "
312 << "Range: " << getAttributeRange() << ", "
313 << "Reference: " << getAttributeReference() << "\n"
314 << "Register: " << getAttributeRegister() << ", "
315 << "Standard: " << getAttributeStandard() << ", "
316 << "Subrange: " << getAttributeSubrange() << ", "
317 << "System: " << getAttributeSystem() << "\n"
318 << "Typename: " << getAttributeTypename() << ", "
319 << "Underlying: " << getAttributeUnderlying() << ", "
320 << "Zero: " << getAttributeZero() << "\n";
321 OS
<< "Added: " << getAttributeAdded() << ", "
322 << "AnyLocation: " << getAttributeAnyLocation() << ", "
323 << "AnySource: " << getAttributeAnySource() << ", "
324 << "Missing: " << getAttributeMissing() << "\n"
328 OS
<< "** Compare **\n"
329 << "All: " << getCompareAll() << ", "
330 << "Lines: " << getCompareLines() << ", "
331 << "Scopes: " << getCompareScopes() << ", "
332 << "Symbols: " << getCompareSymbols() << ", "
333 << "Types: " << getCompareTypes() << "\n";
334 OS
<< "Context: " << getCompareContext() << ", "
335 << "Execute: " << getCompareExecute() << ", "
336 << "Print: " << getComparePrint() << "\n"
340 OS
<< "** Print **\n"
341 << "All: " << getPrintAll() << ", "
342 << "Elements: " << getPrintElements() << ", "
343 << "Instructions: " << getPrintInstructions() << ", "
344 << "Lines: " << getPrintLines() << "\n"
345 << "Scopes: " << getPrintScopes() << ", "
346 << "Sizes: " << getPrintSizes() << ", "
347 << "Summary: " << getPrintSummary() << ", "
348 << "Symbols: " << getPrintSymbols() << "\n"
349 << "Types: " << getPrintTypes() << ", "
350 << "Warnings: " << getPrintWarnings() << "\n";
351 OS
<< "AnyElemeny: " << getPrintAnyElement() << ", "
352 << "AnyLine: " << getPrintAnyLine() << ", "
353 << "Execute: " << getPrintExecute() << ", "
354 << "Formatting: " << getPrintFormatting() << "\n"
355 << "Offset: " << getPrintOffset() << ", "
356 << "SizesSummary: " << getPrintSizesSummary() << "\n"
360 OS
<< "** Report **\n"
361 << "All: " << getReportAll() << ", "
362 << "Children: " << getReportChildren() << ", "
363 << "List: " << getReportList() << ", "
364 << "Parents: " << getReportParents() << ", "
365 << "View: " << getReportView() << "\n";
366 OS
<< "AnyView: " << getReportAnyView() << ", "
367 << "Execute: " << getReportExecute() << "\n"
371 OS
<< "** Select **\n"
372 << "IgnoreCase: " << getSelectIgnoreCase() << ", "
373 << "UseRegex: " << getSelectUseRegex() << ", "
374 << "Execute: " << getSelectExecute() << ", "
375 << "GenericKind: " << getSelectGenericKind() << "\n"
376 << "GenericPattern: " << getSelectGenericPattern() << ", "
377 << "OffsetPattern: " << getSelectOffsetPattern() << "\n"
381 OS
<< "** Warning **\n"
382 << "All: " << getWarningAll() << ", "
383 << "Coverage: " << getWarningCoverages() << ", "
384 << "Lines: " << getWarningLines() << ", "
385 << "Locations: " << getWarningLocations() << ", "
386 << "Ranges: " << getWarningRanges() << "\n"
390 OS
<< "** Internal **\n"
391 << "All: " << Options
.getInternalAll() << ", "
392 << "Cmdline: " << Options
.getInternalCmdline() << ", "
393 << "ID: " << Options
.getInternalID() << ", "
394 << "Integrity: " << Options
.getInternalIntegrity() << ", "
395 << "None: " << Options
.getInternalNone() << "\n"
396 << "Tag: " << Options
.getInternalTag() << "\n"
400 //===----------------------------------------------------------------------===//
401 // Logical element selection using patterns.
402 //===----------------------------------------------------------------------===//
403 LVPatterns
*LVPatterns::getPatterns() {
404 static LVPatterns Patterns
;
408 Error
LVPatterns::createMatchEntry(LVMatchInfo
&Filters
, StringRef Pattern
,
409 bool IgnoreCase
, bool UseRegex
) {
411 // Process pattern as regular expression.
413 Match
.Pattern
= std::string(Pattern
);
414 if (Pattern
.size()) {
415 Match
.RE
= std::make_shared
<Regex
>(Pattern
, IgnoreCase
? Regex::IgnoreCase
418 if (!Match
.RE
->isValid(Error
))
419 return createStringError(errc::invalid_argument
,
420 "Error in regular expression: %s",
423 Match
.Mode
= LVMatchMode::Regex
;
424 Filters
.push_back(Match
);
425 return Error::success();
429 // Process pattern as an exact string match, depending on the case.
430 Match
.Pattern
= std::string(Pattern
);
431 if (Match
.Pattern
.size()) {
432 Match
.Mode
= IgnoreCase
? LVMatchMode::NoCase
: LVMatchMode::Match
;
433 Filters
.push_back(Match
);
436 return Error::success();
439 void LVPatterns::addGenericPatterns(StringSet
<> &Patterns
) {
440 addPatterns(Patterns
, GenericMatchInfo
);
441 if (GenericMatchInfo
.size()) {
442 options().setSelectGenericPattern();
443 options().setSelectExecute();
447 void LVPatterns::addOffsetPatterns(const LVOffsetSet
&Patterns
) {
448 for (const LVOffset
&Entry
: Patterns
)
449 OffsetMatchInfo
.push_back(Entry
);
450 if (OffsetMatchInfo
.size()) {
451 options().setSelectOffsetPattern();
452 options().setSelectExecute();
456 void LVPatterns::addPatterns(StringSet
<> &Patterns
, LVMatchInfo
&Filters
) {
457 bool IgnoreCase
= options().getSelectIgnoreCase();
458 bool UseRegex
= options().getSelectUseRegex();
459 for (const StringSet
<>::value_type
&Entry
: Patterns
) {
460 StringRef Pattern
= Entry
.first();
461 if (Error Err
= createMatchEntry(Filters
, Pattern
, IgnoreCase
, UseRegex
))
462 consumeError(std::move(Err
));
466 dbgs() << "\nPattern Information:\n";
467 for (LVMatch
&Match
: Filters
)
469 << (Match
.Mode
== LVMatchMode::Match
? "Match" : "Regex")
470 << " Pattern: '" << Match
.Pattern
<< "'\n";
474 void LVPatterns::addElement(LVElement
*Element
) {
475 // Mark any element that matches a given pattern.
476 Element
->setIsMatched();
477 options().setSelectExecute();
478 if (options().getReportList())
479 getReaderCompileUnit()->addMatched(Element
);
480 if (options().getReportAnyView()) {
481 getReaderCompileUnit()->addMatched(Element
->getIsScope()
482 ? static_cast<LVScope
*>(Element
)
483 : Element
->getParentScope());
484 // Mark element as matched.
485 if (!Element
->getIsScope())
486 Element
->setHasPattern();
490 void LVPatterns::updateReportOptions() {
491 if (ElementRequest
.size() || LineRequest
.size() || ScopeRequest
.size() ||
492 SymbolRequest
.size() || TypeRequest
.size()) {
493 options().setSelectGenericKind();
494 options().setSelectExecute();
497 // If we have selected requests and there are no specified report options,
498 // assume the 'details' option.
499 if (options().getSelectExecute() && !options().getReportExecute()) {
500 options().setReportExecute();
501 options().setReportList();
505 // Match a general pattern.
506 bool LVPatterns::matchPattern(StringRef Input
, const LVMatchInfo
&MatchInfo
) {
507 bool Matched
= false;
508 // Do not match an empty 'Input'.
511 // Traverse all match specifications.
512 for (const LVMatch
&Match
: MatchInfo
) {
513 switch (Match
.Mode
) {
514 case LVMatchMode::Match
:
515 Matched
= Input
== Match
.Pattern
;
517 case LVMatchMode::NoCase
:
518 Matched
= Input
.equals_insensitive(Match
.Pattern
);
520 case LVMatchMode::Regex
:
521 Matched
= Match
.RE
->match(Input
);
526 // Return if we have a match.
533 bool LVPatterns::printElement(const LVLine
*Line
) const {
534 return (options().getPrintLines() && Line
->getIsLineDebug()) ||
535 (options().getPrintInstructions() && Line
->getIsLineAssembler());
538 bool LVPatterns::printObject(const LVLocation
*Location
) const {
539 if (options().getAttributeAll())
541 bool DoPrint
= options().getAttributeAnyLocation();
542 // Consider the case of filler locations.
543 if (DoPrint
&& Location
&& Location
->getIsGapEntry())
544 DoPrint
= options().getAttributeGaps();
548 bool LVPatterns::printElement(const LVScope
*Scope
) const {
549 // A scope will be printed depending on the following rules:
550 // - Request to print scopes.
551 // - Request to print any of its children.
552 // - If the scope is Root or CompileUnit:
553 // Request to print summary, sizes or warnings.
554 return options().getPrintScopes() ||
555 (options().getPrintSymbols() && Scope
->getHasSymbols()) ||
556 (options().getPrintAnyLine() && Scope
->getHasLines()) ||
557 (options().getPrintTypes() && Scope
->getHasTypes()) ||
558 ((options().getPrintSizesSummary() || options().getPrintWarnings()) &&
559 (Scope
->getIsRoot() || Scope
->getIsCompileUnit()));
562 bool LVPatterns::printElement(const LVSymbol
*Symbol
) const {
563 // Print compiler generated symbols only if command line option.
564 if (Symbol
->getIsArtificial())
565 return options().getAttributeGenerated() && options().getPrintSymbols();
566 return options().getPrintSymbols();
569 bool LVPatterns::printElement(const LVType
*Type
) const {
570 // Print array subranges only if print types is requested.
571 if (Type
->getIsSubrange())
572 return options().getAttributeSubrange() && options().getPrintTypes();
573 return options().getPrintTypes();
576 void LVPatterns::print(raw_ostream
&OS
) const {
577 OS
<< "LVPatterns\n";
578 LLVM_DEBUG(dbgs() << "Print Patterns\n");