xref: /freebsd/contrib/llvm-project/llvm/lib/DebugInfo/LogicalView/Core/LVOptions.cpp (revision 700637cbb5e582861067a11aaca4d053546871d2)
1 //===-- LVOptions.cpp -----------------------------------------------------===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This implements the LVOptions class.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "llvm/DebugInfo/LogicalView/Core/LVOptions.h"
14 #include "llvm/DebugInfo/LogicalView/Core/LVReader.h"
15 #include "llvm/Support/Errc.h"
16 
17 using namespace llvm;
18 using namespace llvm::logicalview;
19 
20 #define DEBUG_TYPE "Options"
21 
22 //===----------------------------------------------------------------------===//
23 // Options extracted from the command line.
24 //===----------------------------------------------------------------------===//
25 static LVOptions Options;
getOptions()26 LVOptions *LVOptions::getOptions() { return &Options; }
setOptions(LVOptions * CmdOptions)27 void LVOptions::setOptions(LVOptions *CmdOptions) { Options = *CmdOptions; }
28 
resolveDependencies()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();
34 
35     setAttributeBase();
36     setAttributeCoverage();
37     setAttributeDirectories();
38     setAttributeDiscriminator();
39     setAttributeFilename();
40     setAttributeFiles();
41     setAttributeFormat();
42     setAttributeLanguage();
43     setAttributeLevel();
44     setAttributeProducer();
45     setAttributePublics();
46     setAttributeRange();
47     setAttributeReference();
48     setAttributeZero();
49   };
50 
51   // Attributes that are classified as extended options.
52   auto ExtendedAttributes = [&]() {
53     // Set the 'extended' attribute to indicate its associated attributes.
54     setAttributeExtended();
55 
56     setAttributeArgument();
57     setAttributeDiscarded();
58     setAttributeEncoded();
59     setAttributeGaps();
60     setAttributeGenerated();
61     setAttributeGlobal();
62     setAttributeInserted();
63     setAttributeLinkage();
64     setAttributeLocal();
65     setAttributeLocation();
66     setAttributeOffset();
67     setAttributePathname();
68     setAttributeQualified();
69     setAttributeQualifier();
70     setAttributeRegister();
71     setAttributeSize();
72     setAttributeSubrange();
73     setAttributeSystem();
74     setAttributeTypename();
75   };
76 
77   // '--Attribute=standard' settings.
78   if (getAttributeStandard())
79     StandardAttributes();
80 
81   // '--Attribute=extended' settings.
82   if (getAttributeExtended())
83     ExtendedAttributes();
84 
85   // '--Attribute=all' settings.
86   if (getAttributeAll()) {
87     StandardAttributes();
88     ExtendedAttributes();
89   }
90 
91   // '--attribute=pathname' supersedes '--attribute=filename'.
92   if (getAttributePathname())
93     resetAttributeFilename();
94 
95   // Assume '--output=text' as default
96   if (!getOutputText() && !getOutputJson())
97     setOutputText();
98 
99   // '--output=all' settings.
100   if (getOutputAll()) {
101     setOutputJson();
102     setOutputSplit();
103     setOutputText();
104   }
105 
106   // A view split folder was specified.
107   if (getOutputFolder().length())
108     setOutputSplit();
109 
110   // Always use the full pathname with splitted output.
111   if (getOutputSplit())
112     setAttributePathname();
113 
114   // '--print=elements' settings.
115   if (getPrintElements()) {
116     setPrintInstructions();
117     setPrintLines();
118     setPrintScopes();
119     setPrintSymbols();
120     setPrintTypes();
121   }
122 
123   // '--print=all' settings.
124   if (getPrintAll()) {
125     setPrintInstructions();
126     setPrintLines();
127     setPrintScopes();
128     setPrintSizes();
129     setPrintSymbols();
130     setPrintSummary();
131     setPrintTypes();
132     setPrintWarnings();
133   }
134 
135   // '--warning=all' settings.
136   if (getWarningAll()) {
137     setWarningCoverages();
138     setWarningLines();
139     setWarningLocations();
140     setWarningRanges();
141   }
142 
143   // '--internal=all' settings.
144   if (getInternalAll()) {
145     setInternalCmdline();
146     setInternalID();
147     setInternalIntegrity();
148     setInternalNone();
149     setInternalTag();
150   }
151 
152   // '--compare=all' settings.
153   if (getCompareAll()) {
154     setCompareLines();
155     setCompareScopes();
156     setCompareSymbols();
157     setCompareTypes();
158   }
159 
160   // Compare the scopes if a request for compare symbols, types, lines.
161   if (getCompareLines() || getCompareSymbols() || getCompareTypes())
162     setCompareScopes();
163 
164   // Generic request for comparison.
165   if (getCompareScopes())
166     setCompareExecute();
167 
168   // Print any logical line (debug or instruction).
169   if (getPrintInstructions() || getPrintLines())
170     setPrintAnyLine();
171 
172   // Print any logical element (line, scope, symbol or type).
173   if (getPrintAnyLine() || getPrintScopes() || getPrintSymbols() ||
174       getPrintTypes())
175     setPrintAnyElement();
176 
177   // Print 'sizes' or 'summary'.
178   if (getPrintSizes() && getPrintSummary())
179     setPrintSizesSummary();
180 
181   // Generic request for printing.
182   if (getPrintAll() || getPrintAnyElement() || getPrintSizesSummary() ||
183       getPrintWarnings())
184     setPrintExecute();
185 
186   // '--reports=all' settings.
187   if (getReportAll()) {
188     setReportChildren();
189     setReportList();
190     setReportParents();
191     setReportView();
192   }
193 
194   // '--report=view' is a shortcut for '--report=parents,children'.
195   if (getReportView()) {
196     setReportChildren();
197     setReportParents();
198   }
199 
200   // The report will include: Parents or Children.
201   if (getReportParents() || getReportChildren() || getReportView())
202     setReportAnyView();
203 
204   // The report will include: List or Parents or Children.
205   if (getReportList() || getReportAnyView())
206     setReportExecute();
207 
208   // If a view or element comparison has been requested, the following options
209   // must be set, in order to get a correct compare:
210   // 1) Sort the CUs, to get a fast compare.
211   // 2) Encode template instantiations, so the names include template
212   //    parameter information.
213   // 3) Include qualified types and their sizes.
214   // 4) Include any inserted abstract references.
215   // 5) For added/missing elements add the '+' or '-' tags.
216   if (getCompareExecute()) {
217     resetPrintExecute();
218     setComparePrint();
219     setSortMode(LVSortMode::Line);
220     setAttributeAdded();
221     setAttributeArgument();
222     setAttributeEncoded();
223     setAttributeInserted();
224     setAttributeMissing();
225     setAttributeQualified();
226     setAttributeSize();
227   }
228 
229   // Enable formatting for printing (indentation, print children).
230   setPrintFormatting();
231 
232   // These attributes are dependent on the capture of location information.
233   if (getAttributeCoverage() || getAttributeGaps() || getAttributeRegister())
234     setAttributeLocation();
235 
236   // Location information is only relevant when printing symbols.
237   if (!getPrintSymbols()) {
238     resetAttributeCoverage();
239     resetAttributeGaps();
240     resetAttributeLocation();
241     resetAttributeRegister();
242   }
243 
244   // Quick check for printing any element source information.
245   if (getAttributeFilename() || getAttributePathname())
246     setAttributeAnySource();
247 
248   // Quick check for printing any location information.
249   if (getAttributeLocation() || getAttributeRange())
250     setAttributeAnyLocation();
251 
252   if (getAttributeRange() || getPrintAnyLine())
253     setGeneralCollectRanges();
254 
255   calculateIndentationSize();
256 
257   // Print collected command line options.
258   LLVM_DEBUG({ dump(); });
259 }
260 
calculateIndentationSize()261 void LVOptions::calculateIndentationSize() {
262   if (getInternalID()) {
263     std::string String = hexSquareString(0);
264     IndentationSize += String.length();
265   }
266   if (getCompareExecute() && (getAttributeAdded() || getAttributeMissing()))
267     ++IndentationSize;
268   if (getAttributeOffset()) {
269     std::string String = hexSquareString(0);
270     IndentationSize += String.length();
271   }
272   if (getAttributeLevel()) {
273     std::stringstream Stream;
274     Stream.str(std::string());
275     Stream << "[" << std::setfill('0') << std::setw(3) << 0 << "]";
276     IndentationSize += Stream.tellp();
277   }
278   if (getAttributeGlobal())
279     ++IndentationSize;
280 }
281 
282 // Print the current values for all the options, after the dependencies
283 // has been resolved.
print(raw_ostream & OS) const284 void LVOptions::print(raw_ostream &OS) const {
285   // --attribute
286   OS << "** Attributes **\n"
287      << "All:           " << getAttributeAll() << ", "
288      << "Argument:      " << getAttributeArgument() << ", "
289      << "Base:          " << getAttributeBase() << ", "
290      << "Coverage:      " << getAttributeCoverage() << "\n"
291      << "Directories:   " << getAttributeDirectories() << ", "
292      << "Discarded:     " << getAttributeDiscarded() << ", "
293      << "Discriminator: " << getAttributeDiscriminator() << ", "
294      << "Encoded:       " << getAttributeEncoded() << "\n"
295      << "Extended:      " << getAttributeExtended() << ", "
296      << "Filename:      " << getAttributeFilename() << ", "
297      << "Files:         " << getAttributeFiles() << ", "
298      << "Format:        " << getAttributeFormat() << "\n"
299      << "Gaps:          " << getAttributeGaps() << ", "
300      << "Generated:     " << getAttributeGenerated() << ", "
301      << "Global:        " << getAttributeGlobal() << ", "
302      << "Inserted:      " << getAttributeInserted() << "\n"
303      << "Level:         " << getAttributeLevel() << ", "
304      << "Linkage:       " << getAttributeLinkage() << ", "
305      << "Local:         " << getAttributeLocal() << ", "
306      << "Location:      " << getAttributeLocation() << "\n"
307      << "Offset:        " << getAttributeOffset() << ", "
308      << "Pathname:      " << getAttributePathname() << ", "
309      << "Producer:      " << getAttributeProducer() << ", "
310      << "Publics:       " << getAttributePublics() << "\n"
311      << "Qualified:     " << getAttributeQualified() << ", "
312      << "Qualifier:     " << getAttributeQualifier() << ", "
313      << "Range:         " << getAttributeRange() << ", "
314      << "Reference:     " << getAttributeReference() << "\n"
315      << "Register:      " << getAttributeRegister() << ", "
316      << "Size:          " << getAttributeSize() << ", "
317      << "Standard:      " << getAttributeStandard() << ", "
318      << "Subrange:      " << getAttributeSubrange() << "\n"
319      << "System:        " << getAttributeSystem() << ", "
320      << "Typename:      " << getAttributeTypename() << ", "
321      << "Underlying:    " << getAttributeUnderlying() << ", "
322      << "Zero:          " << getAttributeZero() << "\n";
323   OS << "Added:         " << getAttributeAdded() << ", "
324      << "AnyLocation:   " << getAttributeAnyLocation() << ", "
325      << "AnySource:     " << getAttributeAnySource() << ", "
326      << "Missing:       " << getAttributeMissing() << "\n"
327      << "\n";
328 
329   // --compare
330   OS << "** Compare **\n"
331      << "All:     " << getCompareAll() << ", "
332      << "Lines:   " << getCompareLines() << ", "
333      << "Scopes:  " << getCompareScopes() << ", "
334      << "Symbols: " << getCompareSymbols() << ", "
335      << "Types:   " << getCompareTypes() << "\n";
336   OS << "Context: " << getCompareContext() << ", "
337      << "Execute: " << getCompareExecute() << ", "
338      << "Print:   " << getComparePrint() << "\n"
339      << "\n";
340 
341   // --print
342   OS << "** Print **\n"
343      << "All:          " << getPrintAll() << ", "
344      << "Elements:     " << getPrintElements() << ", "
345      << "Instructions: " << getPrintInstructions() << ", "
346      << "Lines:        " << getPrintLines() << "\n"
347      << "Scopes:       " << getPrintScopes() << ", "
348      << "Sizes:        " << getPrintSizes() << ", "
349      << "Summary:      " << getPrintSummary() << ", "
350      << "Symbols:      " << getPrintSymbols() << "\n"
351      << "Types:        " << getPrintTypes() << ", "
352      << "Warnings:     " << getPrintWarnings() << "\n";
353   OS << "AnyElemeny:   " << getPrintAnyElement() << ", "
354      << "AnyLine:      " << getPrintAnyLine() << ", "
355      << "Execute:      " << getPrintExecute() << ", "
356      << "Formatting:   " << getPrintFormatting() << "\n"
357      << "Offset:       " << getPrintOffset() << ", "
358      << "SizesSummary: " << getPrintSizesSummary() << "\n"
359      << "\n";
360 
361   // --report
362   OS << "** Report **\n"
363      << "All:      " << getReportAll() << ", "
364      << "Children: " << getReportChildren() << ", "
365      << "List:     " << getReportList() << ", "
366      << "Parents:  " << getReportParents() << ", "
367      << "View:     " << getReportView() << "\n";
368   OS << "AnyView:  " << getReportAnyView() << ", "
369      << "Execute:  " << getReportExecute() << "\n"
370      << "\n";
371 
372   // --select
373   OS << "** Select **\n"
374      << "IgnoreCase:     " << getSelectIgnoreCase() << ", "
375      << "UseRegex:       " << getSelectUseRegex() << ", "
376      << "Execute:        " << getSelectExecute() << ", "
377      << "GenericKind:    " << getSelectGenericKind() << "\n"
378      << "GenericPattern: " << getSelectGenericPattern() << ", "
379      << "OffsetPattern:  " << getSelectOffsetPattern() << "\n"
380      << "\n";
381 
382   // --warning
383   OS << "** Warning **\n"
384      << "All:       " << getWarningAll() << ", "
385      << "Coverage:  " << getWarningCoverages() << ", "
386      << "Lines:     " << getWarningLines() << ", "
387      << "Locations: " << getWarningLocations() << ", "
388      << "Ranges:    " << getWarningRanges() << "\n"
389      << "\n";
390 
391   // --internal
392   OS << "** Internal **\n"
393      << "All:       " << Options.getInternalAll() << ", "
394      << "Cmdline:   " << Options.getInternalCmdline() << ", "
395      << "ID:        " << Options.getInternalID() << ", "
396      << "Integrity: " << Options.getInternalIntegrity() << ", "
397      << "None:      " << Options.getInternalNone() << "\n"
398      << "Tag:       " << Options.getInternalTag() << "\n"
399      << "\n";
400 }
401 
402 //===----------------------------------------------------------------------===//
403 // Logical element selection using patterns.
404 //===----------------------------------------------------------------------===//
getPatterns()405 LVPatterns *LVPatterns::getPatterns() {
406   static LVPatterns Patterns;
407   return &Patterns;
408 }
409 
createMatchEntry(LVMatchInfo & Filters,StringRef Pattern,bool IgnoreCase,bool UseRegex)410 Error LVPatterns::createMatchEntry(LVMatchInfo &Filters, StringRef Pattern,
411                                    bool IgnoreCase, bool UseRegex) {
412   LVMatch Match;
413   // Process pattern as regular expression.
414   if (UseRegex) {
415     Match.Pattern = std::string(Pattern);
416     if (Pattern.size()) {
417       Match.RE = std::make_shared<Regex>(Pattern, IgnoreCase ? Regex::IgnoreCase
418                                                              : Regex::NoFlags);
419       std::string Error;
420       if (!Match.RE->isValid(Error))
421         return createStringError(errc::invalid_argument,
422                                  "Error in regular expression: %s",
423                                  Error.c_str());
424 
425       Match.Mode = LVMatchMode::Regex;
426       Filters.push_back(Match);
427       return Error::success();
428     }
429   }
430 
431   // Process pattern as an exact string match, depending on the case.
432   Match.Pattern = std::string(Pattern);
433   if (Match.Pattern.size()) {
434     Match.Mode = IgnoreCase ? LVMatchMode::NoCase : LVMatchMode::Match;
435     Filters.push_back(Match);
436   }
437 
438   return Error::success();
439 }
440 
addGenericPatterns(StringSet<> & Patterns)441 void LVPatterns::addGenericPatterns(StringSet<> &Patterns) {
442   addPatterns(Patterns, GenericMatchInfo);
443   if (GenericMatchInfo.size()) {
444     options().setSelectGenericPattern();
445     options().setSelectExecute();
446   }
447 }
448 
addOffsetPatterns(const LVOffsetSet & Patterns)449 void LVPatterns::addOffsetPatterns(const LVOffsetSet &Patterns) {
450   llvm::append_range(OffsetMatchInfo, Patterns);
451   if (OffsetMatchInfo.size()) {
452     options().setSelectOffsetPattern();
453     options().setSelectExecute();
454   }
455 }
456 
addPatterns(StringSet<> & Patterns,LVMatchInfo & Filters)457 void LVPatterns::addPatterns(StringSet<> &Patterns, LVMatchInfo &Filters) {
458   bool IgnoreCase = options().getSelectIgnoreCase();
459   bool UseRegex = options().getSelectUseRegex();
460   for (const StringSet<>::value_type &Entry : Patterns) {
461     StringRef Pattern = Entry.first();
462     if (Error Err = createMatchEntry(Filters, Pattern, IgnoreCase, UseRegex))
463       consumeError(std::move(Err));
464   }
465 
466   LLVM_DEBUG({
467     dbgs() << "\nPattern Information:\n";
468     for (LVMatch &Match : Filters)
469       dbgs() << "Mode: "
470              << (Match.Mode == LVMatchMode::Match ? "Match" : "Regex")
471              << " Pattern: '" << Match.Pattern << "'\n";
472   });
473 }
474 
addElement(LVElement * Element)475 void LVPatterns::addElement(LVElement *Element) {
476   // Mark any element that matches a given pattern.
477   Element->setIsMatched();
478   options().setSelectExecute();
479   if (options().getReportList())
480     getReaderCompileUnit()->addMatched(Element);
481   if (options().getReportAnyView()) {
482     getReaderCompileUnit()->addMatched(Element->getIsScope()
483                                            ? static_cast<LVScope *>(Element)
484                                            : Element->getParentScope());
485     // Mark element as matched.
486     if (!Element->getIsScope())
487       Element->setHasPattern();
488   }
489 }
490 
updateReportOptions()491 void LVPatterns::updateReportOptions() {
492   if (ElementRequest.size() || LineRequest.size() || ScopeRequest.size() ||
493       SymbolRequest.size() || TypeRequest.size()) {
494     options().setSelectGenericKind();
495     options().setSelectExecute();
496   }
497 
498   // If we have selected requests and there are no specified report options,
499   // assume the 'details' option.
500   if (options().getSelectExecute() && !options().getReportExecute()) {
501     options().setReportExecute();
502     options().setReportList();
503   }
504 }
505 
506 // Match a general pattern.
matchPattern(StringRef Input,const LVMatchInfo & MatchInfo)507 bool LVPatterns::matchPattern(StringRef Input, const LVMatchInfo &MatchInfo) {
508   bool Matched = false;
509   // Do not match an empty 'Input'.
510   if (Input.empty())
511     return Matched;
512   // Traverse all match specifications.
513   for (const LVMatch &Match : MatchInfo) {
514     switch (Match.Mode) {
515     case LVMatchMode::Match:
516       Matched = Input == Match.Pattern;
517       break;
518     case LVMatchMode::NoCase:
519       Matched = Input.equals_insensitive(Match.Pattern);
520       break;
521     case LVMatchMode::Regex:
522       Matched = Match.RE->match(Input);
523       break;
524     default:
525       break;
526     }
527     // Return if we have a match.
528     if (Matched)
529       return true;
530   }
531   return Matched;
532 }
533 
printElement(const LVLine * Line) const534 bool LVPatterns::printElement(const LVLine *Line) const {
535   return (options().getPrintLines() && Line->getIsLineDebug()) ||
536          (options().getPrintInstructions() && Line->getIsLineAssembler());
537 }
538 
printObject(const LVLocation * Location) const539 bool LVPatterns::printObject(const LVLocation *Location) const {
540   if (options().getAttributeAll())
541     return true;
542   bool DoPrint = options().getAttributeAnyLocation();
543   // Consider the case of filler locations.
544   if (DoPrint && Location && Location->getIsGapEntry())
545     DoPrint = options().getAttributeGaps();
546   return DoPrint;
547 }
548 
printElement(const LVScope * Scope) const549 bool LVPatterns::printElement(const LVScope *Scope) const {
550   // A scope will be printed depending on the following rules:
551   // - Request to print scopes.
552   // - Request to print any of its children.
553   // - If the scope is Root or CompileUnit:
554   //     Request to print summary, sizes or warnings.
555   return options().getPrintScopes() ||
556          (options().getPrintSymbols() && Scope->getHasSymbols()) ||
557          (options().getPrintAnyLine() && Scope->getHasLines()) ||
558          (options().getPrintTypes() && Scope->getHasTypes()) ||
559          ((options().getPrintSizesSummary() || options().getPrintWarnings()) &&
560           (Scope->getIsRoot() || Scope->getIsCompileUnit()));
561 }
562 
printElement(const LVSymbol * Symbol) const563 bool LVPatterns::printElement(const LVSymbol *Symbol) const {
564   // Print compiler generated symbols only if command line option.
565   if (Symbol->getIsArtificial())
566     return options().getAttributeGenerated() && options().getPrintSymbols();
567   return options().getPrintSymbols();
568 }
569 
printElement(const LVType * Type) const570 bool LVPatterns::printElement(const LVType *Type) const {
571   // Print array subranges only if print types is requested.
572   if (Type->getIsSubrange())
573     return options().getAttributeSubrange() && options().getPrintTypes();
574   return options().getPrintTypes();
575 }
576 
print(raw_ostream & OS) const577 void LVPatterns::print(raw_ostream &OS) const {
578   OS << "LVPatterns\n";
579   LLVM_DEBUG(dbgs() << "Print Patterns\n");
580 }
581