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 setAttributeLevel();
43 setAttributeProducer();
44 setAttributePublics();
45 setAttributeRange();
46 setAttributeReference();
47 setAttributeZero();
48 };
49
50 // Attributes that are classified as extended options.
51 auto ExtendedAttributes = [&]() {
52 // Set the 'extended' attribute to indicate its associated attributes.
53 setAttributeExtended();
54
55 setAttributeArgument();
56 setAttributeDiscarded();
57 setAttributeEncoded();
58 setAttributeGaps();
59 setAttributeGenerated();
60 setAttributeGlobal();
61 setAttributeInserted();
62 setAttributeLinkage();
63 setAttributeLocal();
64 setAttributeLocation();
65 setAttributeOffset();
66 setAttributePathname();
67 setAttributeQualified();
68 setAttributeQualifier();
69 setAttributeRegister();
70 setAttributeSubrange();
71 setAttributeSystem();
72 setAttributeTypename();
73 };
74
75 // '--Attribute=standard' settings.
76 if (getAttributeStandard())
77 StandardAttributes();
78
79 // '--Attribute=extended' settings.
80 if (getAttributeExtended())
81 ExtendedAttributes();
82
83 // '--Attribute=all' settings.
84 if (getAttributeAll()) {
85 StandardAttributes();
86 ExtendedAttributes();
87 }
88
89 // '--attribute=pathname' supersedes '--attribute=filename'.
90 if (getAttributePathname())
91 resetAttributeFilename();
92
93 // Assume '--output=text' as default
94 if (!getOutputText() && !getOutputJson())
95 setOutputText();
96
97 // '--output=all' settings.
98 if (getOutputAll()) {
99 setOutputJson();
100 setOutputSplit();
101 setOutputText();
102 }
103
104 // A view split folder was specified.
105 if (getOutputFolder().length())
106 setOutputSplit();
107
108 // Always use the full pathname with splitted output.
109 if (getOutputSplit())
110 setAttributePathname();
111
112 // '--print=elements' settings.
113 if (getPrintElements()) {
114 setPrintInstructions();
115 setPrintLines();
116 setPrintScopes();
117 setPrintSymbols();
118 setPrintTypes();
119 }
120
121 // '--print=all' settings.
122 if (getPrintAll()) {
123 setPrintInstructions();
124 setPrintLines();
125 setPrintScopes();
126 setPrintSizes();
127 setPrintSymbols();
128 setPrintSummary();
129 setPrintTypes();
130 setPrintWarnings();
131 }
132
133 // '--warning=all' settings.
134 if (getWarningAll()) {
135 setWarningCoverages();
136 setWarningLines();
137 setWarningLocations();
138 setWarningRanges();
139 }
140
141 // '--internal=all' settings.
142 if (getInternalAll()) {
143 setInternalCmdline();
144 setInternalID();
145 setInternalIntegrity();
146 setInternalNone();
147 setInternalTag();
148 }
149
150 // '--compare=all' settings.
151 if (getCompareAll()) {
152 setCompareLines();
153 setCompareScopes();
154 setCompareSymbols();
155 setCompareTypes();
156 }
157
158 // Compare the scopes if a request for compare symbols, types, lines.
159 if (getCompareLines() || getCompareSymbols() || getCompareTypes())
160 setCompareScopes();
161
162 // Generic request for comparison.
163 if (getCompareScopes())
164 setCompareExecute();
165
166 // Print any logical line (debug or instruction).
167 if (getPrintInstructions() || getPrintLines())
168 setPrintAnyLine();
169
170 // Print any logical element (line, scope, symbol or type).
171 if (getPrintAnyLine() || getPrintScopes() || getPrintSymbols() ||
172 getPrintTypes())
173 setPrintAnyElement();
174
175 // Print 'sizes' or 'summary'.
176 if (getPrintSizes() && getPrintSummary())
177 setPrintSizesSummary();
178
179 // Generic request for printing.
180 if (getPrintAll() || getPrintAnyElement() || getPrintSizesSummary() ||
181 getPrintWarnings())
182 setPrintExecute();
183
184 // '--reports=all' settings.
185 if (getReportAll()) {
186 setReportChildren();
187 setReportList();
188 setReportParents();
189 setReportView();
190 }
191
192 // '--report=view' is a shortcut for '--report=parents,children'.
193 if (getReportView()) {
194 setReportChildren();
195 setReportParents();
196 }
197
198 // The report will include: Parents or Children.
199 if (getReportParents() || getReportChildren() || getReportView())
200 setReportAnyView();
201
202 // The report will include: List or Parents or Children.
203 if (getReportList() || getReportAnyView())
204 setReportExecute();
205
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()) {
215 resetPrintExecute();
216 setComparePrint();
217 setSortMode(LVSortMode::Line);
218 setAttributeAdded();
219 setAttributeArgument();
220 setAttributeEncoded();
221 setAttributeInserted();
222 setAttributeMissing();
223 setAttributeQualified();
224 }
225
226 // Enable formatting for printing (indentation, print children).
227 setPrintFormatting();
228
229 // These attributes are dependent on the capture of location information.
230 if (getAttributeCoverage() || getAttributeGaps() || getAttributeRegister())
231 setAttributeLocation();
232
233 // Location information is only relevant when printing symbols.
234 if (!getPrintSymbols()) {
235 resetAttributeCoverage();
236 resetAttributeGaps();
237 resetAttributeLocation();
238 resetAttributeRegister();
239 }
240
241 // Quick check for printing any element source information.
242 if (getAttributeFilename() || getAttributePathname())
243 setAttributeAnySource();
244
245 // Quick check for printing any location information.
246 if (getAttributeLocation() || getAttributeRange())
247 setAttributeAnyLocation();
248
249 if (getAttributeRange() || getPrintAnyLine())
250 setGeneralCollectRanges();
251
252 calculateIndentationSize();
253
254 // Print collected command line options.
255 LLVM_DEBUG({ dump(); });
256 }
257
calculateIndentationSize()258 void LVOptions::calculateIndentationSize() {
259 #ifndef NDEBUG
260 if (getInternalID()) {
261 std::string String = hexSquareString(0);
262 IndentationSize += String.length();
263 }
264 #endif
265 if (getCompareExecute() && (getAttributeAdded() || getAttributeMissing()))
266 ++IndentationSize;
267 if (getAttributeOffset()) {
268 std::string String = hexSquareString(0);
269 IndentationSize += String.length();
270 }
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();
276 }
277 if (getAttributeGlobal())
278 ++IndentationSize;
279 }
280
281 // Print the current values for all the options, after the dependencies
282 // has been resolved.
print(raw_ostream & OS) const283 void LVOptions::print(raw_ostream &OS) const {
284 // --attribute
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"
325 << "\n";
326
327 // --compare
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"
337 << "\n";
338
339 // --print
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"
357 << "\n";
358
359 // --report
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"
368 << "\n";
369
370 // --select
371 OS << "** Select **\n"
372 << "IgnoreCase: " << getSelectIgnoreCase() << ", "
373 << "UseRegex: " << getSelectUseRegex() << ", "
374 << "Execute: " << getSelectExecute() << ", "
375 << "GenericKind: " << getSelectGenericKind() << "\n"
376 << "GenericPattern: " << getSelectGenericPattern() << ", "
377 << "OffsetPattern: " << getSelectOffsetPattern() << "\n"
378 << "\n";
379
380 // --warning
381 OS << "** Warning **\n"
382 << "All: " << getWarningAll() << ", "
383 << "Coverage: " << getWarningCoverages() << ", "
384 << "Lines: " << getWarningLines() << ", "
385 << "Locations: " << getWarningLocations() << ", "
386 << "Ranges: " << getWarningRanges() << "\n"
387 << "\n";
388
389 // --internal
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"
397 << "\n";
398 }
399
400 //===----------------------------------------------------------------------===//
401 // Logical element selection using patterns.
402 //===----------------------------------------------------------------------===//
getPatterns()403 LVPatterns *LVPatterns::getPatterns() {
404 static LVPatterns Patterns;
405 return &Patterns;
406 }
407
createMatchEntry(LVMatchInfo & Filters,StringRef Pattern,bool IgnoreCase,bool UseRegex)408 Error LVPatterns::createMatchEntry(LVMatchInfo &Filters, StringRef Pattern,
409 bool IgnoreCase, bool UseRegex) {
410 LVMatch Match;
411 // Process pattern as regular expression.
412 if (UseRegex) {
413 Match.Pattern = std::string(Pattern);
414 if (Pattern.size()) {
415 Match.RE = std::make_shared<Regex>(Pattern, IgnoreCase ? Regex::IgnoreCase
416 : Regex::NoFlags);
417 std::string Error;
418 if (!Match.RE->isValid(Error))
419 return createStringError(errc::invalid_argument,
420 "Error in regular expression: %s",
421 Error.c_str());
422
423 Match.Mode = LVMatchMode::Regex;
424 Filters.push_back(Match);
425 return Error::success();
426 }
427 }
428
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);
434 }
435
436 return Error::success();
437 }
438
addGenericPatterns(StringSet<> & Patterns)439 void LVPatterns::addGenericPatterns(StringSet<> &Patterns) {
440 addPatterns(Patterns, GenericMatchInfo);
441 if (GenericMatchInfo.size()) {
442 options().setSelectGenericPattern();
443 options().setSelectExecute();
444 }
445 }
446
addOffsetPatterns(const LVOffsetSet & Patterns)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();
453 }
454 }
455
addPatterns(StringSet<> & Patterns,LVMatchInfo & Filters)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));
463 }
464
465 LLVM_DEBUG({
466 dbgs() << "\nPattern Information:\n";
467 for (LVMatch &Match : Filters)
468 dbgs() << "Mode: "
469 << (Match.Mode == LVMatchMode::Match ? "Match" : "Regex")
470 << " Pattern: '" << Match.Pattern << "'\n";
471 });
472 }
473
addElement(LVElement * Element)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();
487 }
488 }
489
updateReportOptions()490 void LVPatterns::updateReportOptions() {
491 if (ElementRequest.size() || LineRequest.size() || ScopeRequest.size() ||
492 SymbolRequest.size() || TypeRequest.size()) {
493 options().setSelectGenericKind();
494 options().setSelectExecute();
495 }
496
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();
502 }
503 }
504
505 // Match a general pattern.
matchPattern(StringRef Input,const LVMatchInfo & MatchInfo)506 bool LVPatterns::matchPattern(StringRef Input, const LVMatchInfo &MatchInfo) {
507 bool Matched = false;
508 // Do not match an empty 'Input'.
509 if (Input.empty())
510 return Matched;
511 // Traverse all match specifications.
512 for (const LVMatch &Match : MatchInfo) {
513 switch (Match.Mode) {
514 case LVMatchMode::Match:
515 Matched = Input == Match.Pattern;
516 break;
517 case LVMatchMode::NoCase:
518 Matched = Input.equals_insensitive(Match.Pattern);
519 break;
520 case LVMatchMode::Regex:
521 Matched = Match.RE->match(Input);
522 break;
523 default:
524 break;
525 }
526 // Return if we have a match.
527 if (Matched)
528 return true;
529 }
530 return Matched;
531 }
532
printElement(const LVLine * Line) const533 bool LVPatterns::printElement(const LVLine *Line) const {
534 return (options().getPrintLines() && Line->getIsLineDebug()) ||
535 (options().getPrintInstructions() && Line->getIsLineAssembler());
536 }
537
printObject(const LVLocation * Location) const538 bool LVPatterns::printObject(const LVLocation *Location) const {
539 if (options().getAttributeAll())
540 return true;
541 bool DoPrint = options().getAttributeAnyLocation();
542 // Consider the case of filler locations.
543 if (DoPrint && Location && Location->getIsGapEntry())
544 DoPrint = options().getAttributeGaps();
545 return DoPrint;
546 }
547
printElement(const LVScope * Scope) const548 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()));
560 }
561
printElement(const LVSymbol * Symbol) const562 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();
567 }
568
printElement(const LVType * Type) const569 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();
574 }
575
print(raw_ostream & OS) const576 void LVPatterns::print(raw_ostream &OS) const {
577 OS << "LVPatterns\n";
578 LLVM_DEBUG(dbgs() << "Print Patterns\n");
579 }
580