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 17using namespace llvm; 18using namespace llvm::logicalview; 19 20#define DEBUG_TYPE "Options" 21 22//===----------------------------------------------------------------------===// 23// Options extracted from the command line. 24//===----------------------------------------------------------------------===// 25static LVOptions Options; 26LVOptions *LVOptions::getOptions() { return &Options; } 27void LVOptions::setOptions(LVOptions *CmdOptions) { Options = *CmdOptions; } 28 29void 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 258void 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. 283void 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//===----------------------------------------------------------------------===// 403LVPatterns *LVPatterns::getPatterns() { 404 static LVPatterns Patterns; 405 return &Patterns; 406} 407 408Error 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 439void LVPatterns::addGenericPatterns(StringSet<> &Patterns) { 440 addPatterns(Patterns, GenericMatchInfo); 441 if (GenericMatchInfo.size()) { 442 options().setSelectGenericPattern(); 443 options().setSelectExecute(); 444 } 445} 446 447void 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 456void 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 474void 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 490void 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. 506bool 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.equals(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 533bool LVPatterns::printElement(const LVLine *Line) const { 534 return (options().getPrintLines() && Line->getIsLineDebug()) || 535 (options().getPrintInstructions() && Line->getIsLineAssembler()); 536} 537 538bool 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 548bool 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 562bool 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 569bool 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 576void LVPatterns::print(raw_ostream &OS) const { 577 OS << "LVPatterns\n"; 578 LLVM_DEBUG(dbgs() << "Print Patterns\n"); 579} 580