2134 lines · cpp
1//===-- LVScope.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-exception6//7//===----------------------------------------------------------------------===//8//9// This implements the LVScope class.10//11//===----------------------------------------------------------------------===//12 13#include "llvm/DebugInfo/LogicalView/Core/LVScope.h"14#include "llvm/DebugInfo/LogicalView/Core/LVCompare.h"15#include "llvm/DebugInfo/LogicalView/Core/LVLine.h"16#include "llvm/DebugInfo/LogicalView/Core/LVLocation.h"17#include "llvm/DebugInfo/LogicalView/Core/LVRange.h"18#include "llvm/DebugInfo/LogicalView/Core/LVReader.h"19#include "llvm/DebugInfo/LogicalView/Core/LVSymbol.h"20#include "llvm/DebugInfo/LogicalView/Core/LVType.h"21 22using namespace llvm;23using namespace llvm::logicalview;24 25#define DEBUG_TYPE "Scope"26 27namespace {28const char *const KindArray = "Array";29const char *const KindBlock = "Block";30const char *const KindCallSite = "CallSite";31const char *const KindClass = "Class";32const char *const KindCompileUnit = "CompileUnit";33const char *const KindEnumeration = "Enumeration";34const char *const KindFile = "File";35const char *const KindFunction = "Function";36const char *const KindInlinedFunction = "InlinedFunction";37const char *const KindModule = "Module";38const char *const KindNamespace = "Namespace";39const char *const KindStruct = "Struct";40const char *const KindTemplateAlias = "TemplateAlias";41const char *const KindTemplatePack = "TemplatePack";42const char *const KindUndefined = "Undefined";43const char *const KindUnion = "Union";44} // end anonymous namespace45 46//===----------------------------------------------------------------------===//47// DWARF lexical block, such as: namespace, function, compile unit, module, etc.48//===----------------------------------------------------------------------===//49// Return a string representation for the scope kind.50const char *LVScope::kind() const {51 const char *Kind = KindUndefined;52 if (getIsArray())53 Kind = KindArray;54 else if (getIsModule())55 Kind = KindModule;56 else if (getIsBlock())57 Kind = KindBlock;58 else if (getIsCallSite())59 Kind = KindCallSite;60 else if (getIsCompileUnit())61 Kind = KindCompileUnit;62 else if (getIsEnumeration())63 Kind = KindEnumeration;64 else if (getIsInlinedFunction())65 Kind = KindInlinedFunction;66 else if (getIsNamespace())67 Kind = KindNamespace;68 else if (getIsTemplatePack())69 Kind = KindTemplatePack;70 else if (getIsRoot())71 Kind = KindFile;72 else if (getIsTemplateAlias())73 Kind = KindTemplateAlias;74 else if (getIsClass())75 Kind = KindClass;76 else if (getIsFunction())77 Kind = KindFunction;78 else if (getIsStructure())79 Kind = KindStruct;80 else if (getIsUnion())81 Kind = KindUnion;82 return Kind;83}84 85LVScopeDispatch LVScope::Dispatch = {86 {LVScopeKind::IsAggregate, &LVScope::getIsAggregate},87 {LVScopeKind::IsArray, &LVScope::getIsArray},88 {LVScopeKind::IsBlock, &LVScope::getIsBlock},89 {LVScopeKind::IsCallSite, &LVScope::getIsCallSite},90 {LVScopeKind::IsCatchBlock, &LVScope::getIsCatchBlock},91 {LVScopeKind::IsClass, &LVScope::getIsClass},92 {LVScopeKind::IsCompileUnit, &LVScope::getIsCompileUnit},93 {LVScopeKind::IsEntryPoint, &LVScope::getIsEntryPoint},94 {LVScopeKind::IsEnumeration, &LVScope::getIsEnumeration},95 {LVScopeKind::IsFunction, &LVScope::getIsFunction},96 {LVScopeKind::IsFunctionType, &LVScope::getIsFunctionType},97 {LVScopeKind::IsInlinedFunction, &LVScope::getIsInlinedFunction},98 {LVScopeKind::IsLabel, &LVScope::getIsLabel},99 {LVScopeKind::IsLexicalBlock, &LVScope::getIsLexicalBlock},100 {LVScopeKind::IsModule, &LVScope::getIsModule},101 {LVScopeKind::IsNamespace, &LVScope::getIsNamespace},102 {LVScopeKind::IsRoot, &LVScope::getIsRoot},103 {LVScopeKind::IsStructure, &LVScope::getIsStructure},104 {LVScopeKind::IsTemplate, &LVScope::getIsTemplate},105 {LVScopeKind::IsTemplateAlias, &LVScope::getIsTemplateAlias},106 {LVScopeKind::IsTemplatePack, &LVScope::getIsTemplatePack},107 {LVScopeKind::IsTryBlock, &LVScope::getIsTryBlock},108 {LVScopeKind::IsUnion, &LVScope::getIsUnion}};109 110const LVTypes LVScope::EmptyTypes{};111const LVSymbols LVScope::EmptySymbols{};112const LVScopes LVScope::EmptyScopes{};113 114LVElements LVScope::getSortedChildren(LVSortFunction SortFunction) const {115 const auto UnsortedChildren = getChildren();116 LVElements Elements{UnsortedChildren.begin(), UnsortedChildren.end()};117 if (SortFunction)118 llvm::stable_sort(Elements, SortFunction);119 return Elements;120}121 122void LVScope::addElement(LVElement *Element) {123 assert(Element && "Invalid element.");124 if (Element->getIsType())125 addElement(static_cast<LVType *>(Element));126 else if (Element->getIsScope())127 addElement(static_cast<LVScope *>(Element));128 else if (Element->getIsSymbol())129 addElement(static_cast<LVSymbol *>(Element));130 else if (Element->getIsLine())131 addElement(static_cast<LVLine *>(Element));132 else133 llvm_unreachable("Invalid Element.");134}135 136// Adds the line info item to the ones stored in the scope.137void LVScope::addElement(LVLine *Line) {138 assert(Line && "Invalid line.");139 assert(!Line->getParent() && "Line already inserted");140 if (!Lines)141 Lines = std::make_unique<LVLines>();142 143 // Add it to parent.144 Lines->push_back(Line);145 Line->setParent(this);146 147 // Notify the reader about the new element being added.148 getReaderCompileUnit()->addedElement(Line);149 150 // All logical elements added to the children, are sorted by any of the151 // following criterias: offset, name, line number, kind.152 // Do not add the line records to the children, as they represent the153 // logical view for the text section and any sorting will not preserve154 // the original sequence.155 156 // Indicate that this tree branch has lines.157 traverseParents(&LVScope::getHasLines, &LVScope::setHasLines);158}159 160// Add a location.161void LVScope::addObject(LVLocation *Location) {162 assert(Location && "Invalid location.");163 assert(!Location->getParent() && "Location already inserted");164 if (!Ranges)165 Ranges = std::make_unique<LVLocations>();166 167 // Add it to parent.168 Location->setParent(this);169 Location->setOffset(getOffset());170 171 Ranges->push_back(Location);172 setHasRanges();173}174 175// Adds the scope to the child scopes and sets the parent in the child.176void LVScope::addElement(LVScope *Scope) {177 assert(Scope && "Invalid scope.");178 assert(!Scope->getParent() && "Scope already inserted");179 if (!Scopes)180 Scopes = std::make_unique<LVScopes>();181 182 // Add it to parent.183 Scopes->push_back(Scope);184 Scope->setParent(this);185 186 // Notify the reader about the new element being added.187 getReaderCompileUnit()->addedElement(Scope);188 189 // If the element is a global reference, mark its parent as having global190 // references; that information is used, to print only those branches191 // with global references.192 if (Scope->getIsGlobalReference())193 traverseParents(&LVScope::getHasGlobals, &LVScope::setHasGlobals);194 else195 traverseParents(&LVScope::getHasLocals, &LVScope::setHasLocals);196 197 // Indicate that this tree branch has scopes.198 traverseParents(&LVScope::getHasScopes, &LVScope::setHasScopes);199}200 201// Adds a symbol to the ones stored in the scope.202void LVScope::addElement(LVSymbol *Symbol) {203 assert(Symbol && "Invalid symbol.");204 assert(!Symbol->getParent() && "Symbol already inserted");205 if (!Symbols)206 Symbols = std::make_unique<LVSymbols>();207 208 // Add it to parent.209 Symbols->push_back(Symbol);210 Symbol->setParent(this);211 212 // Notify the reader about the new element being added.213 getReaderCompileUnit()->addedElement(Symbol);214 215 // If the element is a global reference, mark its parent as having global216 // references; that information is used, to print only those branches217 // with global references.218 if (Symbol->getIsGlobalReference())219 traverseParents(&LVScope::getHasGlobals, &LVScope::setHasGlobals);220 else221 traverseParents(&LVScope::getHasLocals, &LVScope::setHasLocals);222 223 // Indicate that this tree branch has symbols.224 traverseParents(&LVScope::getHasSymbols, &LVScope::setHasSymbols);225}226 227// Adds a type to the ones stored in the scope.228void LVScope::addElement(LVType *Type) {229 assert(Type && "Invalid type.");230 assert(!Type->getParent() && "Type already inserted");231 if (!Types)232 Types = std::make_unique<LVTypes>();233 234 // Add it to parent.235 Types->push_back(Type);236 Type->setParent(this);237 238 // Notify the reader about the new element being added.239 getReaderCompileUnit()->addedElement(Type);240 241 // If the element is a global reference, mark its parent as having global242 // references; that information is used, to print only those branches243 // with global references.244 if (Type->getIsGlobalReference())245 traverseParents(&LVScope::getHasGlobals, &LVScope::setHasGlobals);246 else247 traverseParents(&LVScope::getHasLocals, &LVScope::setHasLocals);248 249 // Indicate that this tree branch has types.250 traverseParents(&LVScope::getHasTypes, &LVScope::setHasTypes);251}252 253// Add a pair of ranges.254void LVScope::addObject(LVAddress LowerAddress, LVAddress UpperAddress) {255 // Pack the ranges into a Location object.256 LVLocation *Location = getReader().createLocation();257 Location->setLowerAddress(LowerAddress);258 Location->setUpperAddress(UpperAddress);259 Location->setIsAddressRange();260 261 addObject(Location);262}263 264bool LVScope::removeElement(LVElement *Element) {265 auto Predicate = [Element](LVElement *Item) -> bool {266 return Item == Element;267 };268 auto RemoveElement = [Element, Predicate](auto &Container) -> bool {269 auto Iter = llvm::remove_if(*Container, Predicate);270 if (Iter != Container->end()) {271 Container->erase(Iter, Container->end());272 Element->resetParent();273 return true;274 }275 return false;276 };277 278 // As 'children' contains only (scopes, symbols and types), check if the279 // element we are deleting is a line.280 if (Element->getIsLine())281 return RemoveElement(Lines);282 283 if (Element->getIsSymbol())284 return RemoveElement(Symbols);285 if (Element->getIsType())286 return RemoveElement(Types);287 if (Element->getIsScope())288 return RemoveElement(Scopes);289 290 return false;291}292 293void LVScope::addMissingElements(LVScope *Reference) {294 setAddedMissing();295 if (!Reference)296 return;297 298 // Get abstract symbols for the given scope reference.299 const LVSymbols *ReferenceSymbols = Reference->getSymbols();300 if (!ReferenceSymbols)301 return;302 303 LVSymbols References;304 References.append(ReferenceSymbols->begin(), ReferenceSymbols->end());305 306 // Erase abstract symbols already in this scope from the collection of307 // symbols in the referenced scope.308 if (getSymbols())309 for (const LVSymbol *Symbol : *getSymbols())310 if (Symbol->getHasReferenceAbstract())311 llvm::erase(References, Symbol->getReference());312 313 // If we have elements left in 'References', those are the elements that314 // need to be inserted in the current scope.315 if (References.size()) {316 LLVM_DEBUG({317 dbgs() << "Insert Missing Inlined Elements\n"318 << "Offset = " << hexSquareString(getOffset()) << " "319 << "Abstract = " << hexSquareString(Reference->getOffset())320 << "\n";321 });322 for (LVSymbol *Reference : References) {323 LLVM_DEBUG({324 dbgs() << "Missing Offset = " << hexSquareString(Reference->getOffset())325 << "\n";326 });327 // We can't clone the abstract origin reference, as it contain extra328 // information that is incorrect for the element to be inserted.329 // As the symbol being added does not exist in the debug section,330 // use its parent scope offset, to indicate its DIE location.331 LVSymbol *Symbol = getReader().createSymbol();332 addElement(Symbol);333 Symbol->setOffset(getOffset());334 Symbol->setIsOptimized();335 Symbol->setReference(Reference);336 337 // The symbol can be a constant, parameter, variable or unspecified338 // parameters (i.e. `...`).339 if (Reference->getIsConstant())340 Symbol->setIsConstant();341 else if (Reference->getIsParameter())342 Symbol->setIsParameter();343 else if (Reference->getIsVariable())344 Symbol->setIsVariable();345 else if (Reference->getIsUnspecified())346 Symbol->setIsUnspecified();347 else348 llvm_unreachable("Invalid symbol kind.");349 }350 }351}352 353void LVScope::updateLevel(LVScope *Parent, bool Moved) {354 // Update the level for the element itself and all its children, using the355 // given scope parent as reference.356 setLevel(Parent->getLevel() + 1);357 358 // Update the children.359 for (LVElement *Element : getChildren())360 Element->updateLevel(this, Moved);361 362 // Update any lines.363 if (Lines)364 for (LVLine *Line : *Lines)365 Line->updateLevel(this, Moved);366}367 368void LVScope::resolve() {369 if (getIsResolved())370 return;371 372 // Resolve the element itself.373 LVElement::resolve();374 375 // Resolve the children.376 for (LVElement *Element : getChildren()) {377 if (getIsGlobalReference())378 // If the scope is a global reference, mark all its children as well.379 Element->setIsGlobalReference();380 Element->resolve();381 }382}383 384void LVScope::resolveName() {385 if (getIsResolvedName())386 return;387 setIsResolvedName();388 389 // If the scope is a template, resolve the template parameters and get390 // the name for the template with the encoded arguments.391 if (getIsTemplate())392 resolveTemplate();393 else {394 if (LVElement *BaseType = getType()) {395 BaseType->resolveName();396 resolveFullname(BaseType);397 }398 }399 400 // In the case of unnamed scopes, try to generate a name for it, using401 // the parents name and the line information. In the case of compiler402 // generated functions, use its linkage name if is available.403 if (!isNamed()) {404 if (getIsArtificial())405 setName(getLinkageName());406 else407 generateName();408 }409 410 LVElement::resolveName();411 412 // Resolve any given pattern.413 patterns().resolvePatternMatch(this);414}415 416void LVScope::resolveReferences() {417 // The scopes can have the following references to other elements:418 // A type:419 // DW_AT_type -> Type or Scope420 // DW_AT_import -> Type421 // A Reference:422 // DW_AT_specification -> Scope423 // DW_AT_abstract_origin -> Scope424 // DW_AT_extension -> Scope425 426 // Resolve any referenced scope.427 LVScope *Reference = getReference();428 if (Reference) {429 Reference->resolve();430 // Recursively resolve the scope names.431 resolveReferencesChain();432 }433 434 // Set the file/line information using the Debug Information entry.435 setFile(Reference);436 437 // Resolve any referenced type or scope.438 if (LVElement *Element = getType())439 Element->resolve();440}441 442void LVScope::resolveElements() {443 // The current element represents the Root. Traverse each Compile Unit.444 if (!Scopes)445 return;446 447 for (LVScope *Scope : *Scopes) {448 LVScopeCompileUnit *CompileUnit = static_cast<LVScopeCompileUnit *>(Scope);449 getReader().setCompileUnit(CompileUnit);450 CompileUnit->resolve();451 // Propagate any matching information into the scopes tree.452 CompileUnit->propagatePatternMatch();453 }454}455 456StringRef LVScope::resolveReferencesChain() {457 // If the scope has a DW_AT_specification or DW_AT_abstract_origin,458 // follow the chain to resolve the name from those references.459 if (getHasReference() && !isNamed())460 setName(getReference()->resolveReferencesChain());461 462 return getName();463}464 465// Get template parameter types.466bool LVScope::getTemplateParameterTypes(LVTypes &Params) {467 // Traverse the scope types and populate the given container with those468 // types that are template parameters; that container will be used by469 // 'encodeTemplateArguments' to resolve them.470 if (const LVTypes *Types = getTypes())471 for (LVType *Type : *Types)472 if (Type->getIsTemplateParam()) {473 Type->resolve();474 Params.push_back(Type);475 }476 477 return !Params.empty();478}479 480// Resolve the template parameters/arguments relationship.481void LVScope::resolveTemplate() {482 if (getIsTemplateResolved())483 return;484 setIsTemplateResolved();485 486 // Check if we need to encode the template arguments.487 if (options().getAttributeEncoded()) {488 LVTypes Params;489 if (getTemplateParameterTypes(Params)) {490 std::string EncodedArgs;491 // Encode the arguments as part of the template name and update the492 // template name, to reflect the encoded parameters.493 encodeTemplateArguments(EncodedArgs, &Params);494 setEncodedArgs(EncodedArgs);495 }496 }497}498 499// Get the qualified name for the template.500void LVScope::getQualifiedName(std::string &QualifiedName) const {501 if (getIsRoot() || getIsCompileUnit())502 return;503 504 if (LVScope *Parent = getParentScope())505 Parent->getQualifiedName(QualifiedName);506 if (!QualifiedName.empty())507 QualifiedName.append("::");508 QualifiedName.append(std::string(getName()));509}510 511// Encode the template arguments as part of the template name.512void LVScope::encodeTemplateArguments(std::string &Name) const {513 // Qualify only when we are expanding parameters that are template514 // instances; the debugger will assume the current scope symbol as515 // the qualifying tag for the symbol being generated, which gives:516 // namespace std {517 // ...518 // set<float,std::less<float>,std::allocator<float>>519 // ...520 // }521 // The 'set' symbol is assumed to have the qualified tag 'std'.522 523 // We are resolving a template parameter which is another template. If524 // it is already resolved, just get the qualified name and return.525 std::string BaseName;526 getQualifiedName(BaseName);527 if (getIsTemplateResolved())528 Name.append(BaseName);529}530 531void LVScope::encodeTemplateArguments(std::string &Name,532 const LVTypes *Types) const {533 // The encoded string will start with the scope name.534 Name.append("<");535 536 // The list of types are the template parameters.537 if (Types) {538 bool AddComma = false;539 for (const LVType *Type : *Types) {540 if (AddComma)541 Name.append(", ");542 Type->encodeTemplateArgument(Name);543 AddComma = true;544 }545 }546 547 Name.append(">");548}549 550bool LVScope::resolvePrinting() const {551 // The warnings collected during the scope creation as per compile unit.552 // If there is a request for printing warnings, always print its associate553 // Compile Unit.554 if (options().getPrintWarnings() && (getIsRoot() || getIsCompileUnit()))555 return true;556 557 // In selection mode, always print the root scope regardless of the558 // number of matched elements. If no matches, the root by itself will559 // indicate no matches.560 if (options().getSelectExecute()) {561 return getIsRoot() || getIsCompileUnit() || getHasPattern();562 }563 564 bool Globals = options().getAttributeGlobal();565 bool Locals = options().getAttributeLocal();566 if ((Globals && Locals) || (!Globals && !Locals)) {567 // Print both Global and Local.568 } else {569 // Check for Global or Local Objects.570 if ((Globals && !(getHasGlobals() || getIsGlobalReference())) ||571 (Locals && !(getHasLocals() || !getIsGlobalReference())))572 return false;573 }574 575 // For the case of functions, skip it if is compiler generated.576 if (getIsFunction() && getIsArtificial() &&577 !options().getAttributeGenerated())578 return false;579 580 return true;581}582 583Error LVScope::doPrint(bool Split, bool Match, bool Print, raw_ostream &OS,584 bool Full) const {585 // During a view output splitting, use the output stream created by the586 // split context, then switch to the reader output stream.587 raw_ostream *StreamSplit = &OS;588 589 // Ignore the CU generated by the VS toolchain, when compiling to PDB.590 if (getIsSystem() && !options().getAttributeSystem())591 return Error::success();592 593 // If 'Split', we use the scope name (CU name) as the ouput file; the594 // delimiters in the pathname, must be replaced by a normal character.595 if (getIsCompileUnit()) {596 getReader().setCompileUnit(const_cast<LVScope *>(this));597 if (Split) {598 std::string ScopeName(getName());599 if (std::error_code EC =600 getReaderSplitContext().open(ScopeName, ".txt", OS))601 return createStringError(EC, "Unable to create split output file %s",602 ScopeName.c_str());603 StreamSplit = static_cast<raw_ostream *>(&getReaderSplitContext().os());604 }605 }606 607 // Ignore discarded or stripped scopes (functions).608 bool DoPrint = (options().getAttributeDiscarded()) ? true : !getIsDiscarded();609 610 // If we are in compare mode, the only conditions are related to the611 // element being missing. In the case of elements comparison, we print the612 // augmented view, that includes added elements.613 // In print mode, we check other conditions, such as local, global, etc.614 if (DoPrint) {615 DoPrint =616 getIsInCompare() ? options().getReportExecute() : resolvePrinting();617 }618 619 // At this point we have checked for very specific options, to decide if the620 // element will be printed. Include the caller's test for element general621 // print.622 DoPrint = DoPrint && (Print || options().getOutputSplit());623 624 if (DoPrint) {625 // Print the element itself.626 print(*StreamSplit, Full);627 628 // Check if we have reached the requested lexical level specified in the629 // command line options. Input file is level zero and the CU is level 1.630 if ((getIsRoot() || options().getPrintAnyElement()) &&631 options().getPrintFormatting() &&632 getLevel() < options().getOutputLevel()) {633 // Print the children.634 for (const LVElement *Element : getSortedChildren()) {635 if (Match && !Element->getHasPattern())636 continue;637 if (Error Err =638 Element->doPrint(Split, Match, Print, *StreamSplit, Full))639 return Err;640 }641 642 // Print the line records.643 if (Lines)644 for (const LVLine *Line : *Lines) {645 if (Match && !Line->getHasPattern())646 continue;647 if (Error Err =648 Line->doPrint(Split, Match, Print, *StreamSplit, Full))649 return Err;650 }651 652 // Print the warnings.653 if (options().getPrintWarnings())654 printWarnings(*StreamSplit, Full);655 }656 }657 658 // Done printing the compile unit. Print any requested summary and659 // restore the original output context.660 if (getIsCompileUnit()) {661 if (options().getPrintSummary())662 printSummary(*StreamSplit);663 if (options().getPrintSizes())664 printSizes(*StreamSplit);665 if (Split) {666 getReaderSplitContext().close();667 StreamSplit = &getReader().outputStream();668 }669 }670 671 if (getIsRoot() && options().getPrintWarnings()) {672 getReader().printRecords(*StreamSplit);673 }674 675 return Error::success();676}677 678void LVScope::sort() {679 // Preserve the lines order as they are associated with user code.680 LVSortFunction SortFunction = getSortFunction();681 if (SortFunction) {682 std::function<void(LVScope * Parent, LVSortFunction SortFunction)> Sort =683 [&](LVScope *Parent, LVSortFunction SortFunction) {684 auto Traverse = [&](auto &Set, LVSortFunction SortFunction) {685 if (Set)686 llvm::stable_sort(*Set, SortFunction);687 };688 Traverse(Parent->Types, SortFunction);689 Traverse(Parent->Symbols, SortFunction);690 Traverse(Parent->Scopes, SortFunction);691 Traverse(Parent->Ranges, compareRange);692 693 if (Parent->Scopes)694 for (LVScope *Scope : *Parent->Scopes)695 Sort(Scope, SortFunction);696 };697 698 // Start traversing the scopes root and transform the element name.699 Sort(this, SortFunction);700 }701}702 703void LVScope::traverseParents(LVScopeGetFunction GetFunction,704 LVScopeSetFunction SetFunction) {705 // Traverse the parent tree.706 LVScope *Parent = this;707 while (Parent) {708 // Terminates if the 'SetFunction' has been already executed.709 if ((Parent->*GetFunction)())710 break;711 (Parent->*SetFunction)();712 Parent = Parent->getParentScope();713 }714}715 716void LVScope::traverseParentsAndChildren(LVObjectGetFunction GetFunction,717 LVObjectSetFunction SetFunction) {718 if (options().getReportParents()) {719 // First traverse the parent tree.720 LVScope *Parent = this;721 while (Parent) {722 // Terminates if the 'SetFunction' has been already executed.723 if ((Parent->*GetFunction)())724 break;725 (Parent->*SetFunction)();726 Parent = Parent->getParentScope();727 }728 }729 730 std::function<void(LVScope * Scope)> TraverseChildren = [&](LVScope *Scope) {731 auto Traverse = [&](const auto *Set) {732 if (Set)733 for (const auto &Entry : *Set)734 (Entry->*SetFunction)();735 };736 737 (Scope->*SetFunction)();738 739 Traverse(Scope->getTypes());740 Traverse(Scope->getSymbols());741 Traverse(Scope->getLines());742 743 if (const LVScopes *Scopes = Scope->getScopes())744 for (LVScope *Scope : *Scopes)745 TraverseChildren(Scope);746 };747 748 if (options().getReportChildren())749 TraverseChildren(this);750}751 752// Traverse the symbol location ranges and for each range:753// - Apply the 'ValidLocation' validation criteria.754// - Add any failed range to the 'LocationList'.755// - Calculate location coverage.756void LVScope::getLocations(LVLocations &LocationList,757 LVValidLocation ValidLocation, bool RecordInvalid) {758 // Traverse scopes and symbols.759 if (Symbols)760 for (LVSymbol *Symbol : *Symbols)761 Symbol->getLocations(LocationList, ValidLocation, RecordInvalid);762 if (Scopes)763 for (LVScope *Scope : *Scopes)764 Scope->getLocations(LocationList, ValidLocation, RecordInvalid);765}766 767// Traverse the scope ranges and for each range:768// - Apply the 'ValidLocation' validation criteria.769// - Add any failed range to the 'LocationList'.770// - Calculate location coverage.771void LVScope::getRanges(LVLocations &LocationList,772 LVValidLocation ValidLocation, bool RecordInvalid) {773 // Ignore discarded or stripped scopes (functions).774 if (getIsDiscarded())775 return;776 777 // Process the ranges for current scope.778 if (Ranges) {779 for (LVLocation *Location : *Ranges) {780 // Add the invalid location object.781 if (!(Location->*ValidLocation)() && RecordInvalid)782 LocationList.push_back(Location);783 }784 785 // Calculate coverage factor.786 calculateCoverage();787 }788 789 // Traverse the scopes.790 if (Scopes)791 for (LVScope *Scope : *Scopes)792 Scope->getRanges(LocationList, ValidLocation, RecordInvalid);793}794 795// Get all the ranges associated with scopes.796void LVScope::getRanges(LVRange &RangeList) {797 // Ignore discarded or stripped scopes (functions).798 if (getIsDiscarded())799 return;800 801 if (Ranges)802 RangeList.addEntry(this);803 if (Scopes)804 for (LVScope *Scope : *Scopes)805 Scope->getRanges(RangeList);806}807 808LVScope *LVScope::outermostParent(LVAddress Address) {809 LVScope *Parent = this;810 while (Parent) {811 const LVLocations *ParentRanges = Parent->getRanges();812 if (ParentRanges)813 for (const LVLocation *Location : *ParentRanges)814 if (Location->getLowerAddress() <= Address)815 return Parent;816 Parent = Parent->getParentScope();817 }818 return Parent;819}820 821LVScope *LVScope::findIn(const LVScopes *Targets) const {822 if (!Targets)823 return nullptr;824 825 // In the case of overloaded functions, sometimes the DWARF used to826 // describe them, does not give suficient information. Try to find a827 // perfect match or mark them as possible conflicts.828 LVScopes Candidates;829 for (LVScope *Target : *Targets)830 if (LVScope::equals(Target))831 Candidates.push_back(Target);832 833 LLVM_DEBUG({834 if (!Candidates.empty()) {835 dbgs() << "\n[LVScope::findIn]\n"836 << "Reference: "837 << "Offset = " << hexSquareString(getOffset()) << ", "838 << "Level = " << getLevel() << ", "839 << "Kind = " << formattedKind(kind()) << ", "840 << "Name = " << formattedName(getName()) << "\n";841 for (const LVScope *Candidate : Candidates)842 dbgs() << "Candidate: "843 << "Offset = " << hexSquareString(Candidate->getOffset()) << ", "844 << "Level = " << Candidate->getLevel() << ", "845 << "Kind = " << formattedKind(Candidate->kind()) << ", "846 << "Name = " << formattedName(Candidate->getName()) << "\n";847 }848 });849 850 if (!Candidates.empty())851 return (Candidates.size() == 1)852 ? (equals(Candidates[0]) ? Candidates[0] : nullptr)853 : findEqualScope(&Candidates);854 855 return nullptr;856}857 858bool LVScope::equalNumberOfChildren(const LVScope *Scope) const {859 // Same number of children. Take into account which elements are requested860 // to be included in the comparison.861 return !(862 (options().getCompareScopes() && scopeCount() != Scope->scopeCount()) ||863 (options().getCompareSymbols() &&864 symbolCount() != Scope->symbolCount()) ||865 (options().getCompareTypes() && typeCount() != Scope->typeCount()) ||866 (options().getCompareLines() && lineCount() != Scope->lineCount()));867}868 869void LVScope::markMissingParents(const LVScope *Target, bool TraverseChildren) {870 auto SetCompareState = [&](auto &Container) {871 if (Container)872 for (auto *Entry : *Container)873 Entry->setIsInCompare();874 };875 SetCompareState(Types);876 SetCompareState(Symbols);877 SetCompareState(Lines);878 SetCompareState(Scopes);879 880 // At this point, we are ready to start comparing the current scope, once881 // the compare bits have been set.882 if (options().getCompareTypes() && getTypes() && Target->getTypes())883 LVType::markMissingParents(getTypes(), Target->getTypes());884 if (options().getCompareSymbols() && getSymbols() && Target->getSymbols())885 LVSymbol::markMissingParents(getSymbols(), Target->getSymbols());886 if (options().getCompareLines() && getLines() && Target->getLines())887 LVLine::markMissingParents(getLines(), Target->getLines());888 if (getScopes() && Target->getScopes())889 LVScope::markMissingParents(getScopes(), Target->getScopes(),890 TraverseChildren);891}892 893void LVScope::markMissingParents(const LVScopes *References,894 const LVScopes *Targets,895 bool TraverseChildren) {896 if (!(References && Targets))897 return;898 899 LLVM_DEBUG({900 dbgs() << "\n[LVScope::markMissingParents]\n";901 for (const LVScope *Reference : *References)902 dbgs() << "References: "903 << "Offset = " << hexSquareString(Reference->getOffset()) << ", "904 << "Level = " << Reference->getLevel() << ", "905 << "Kind = " << formattedKind(Reference->kind()) << ", "906 << "Name = " << formattedName(Reference->getName()) << "\n";907 for (const LVScope *Target : *Targets)908 dbgs() << "Targets : "909 << "Offset = " << hexSquareString(Target->getOffset()) << ", "910 << "Level = " << Target->getLevel() << ", "911 << "Kind = " << formattedKind(Target->kind()) << ", "912 << "Name = " << formattedName(Target->getName()) << "\n";913 });914 915 for (LVScope *Reference : *References) {916 // Don't process 'Block' scopes, as we can't identify them.917 if (Reference->getIsBlock() || Reference->getIsGeneratedName())918 continue;919 920 LLVM_DEBUG({921 dbgs() << "\nSearch Reference: "922 << "Offset = " << hexSquareString(Reference->getOffset()) << " "923 << "Name = " << formattedName(Reference->getName()) << "\n";924 });925 LVScope *Target = Reference->findIn(Targets);926 if (Target) {927 LLVM_DEBUG({928 dbgs() << "\nFound Target: "929 << "Offset = " << hexSquareString(Target->getOffset()) << " "930 << "Name = " << formattedName(Target->getName()) << "\n";931 });932 if (TraverseChildren)933 Reference->markMissingParents(Target, TraverseChildren);934 } else {935 LLVM_DEBUG({936 dbgs() << "Missing Reference: "937 << "Offset = " << hexSquareString(Reference->getOffset()) << " "938 << "Name = " << formattedName(Reference->getName()) << "\n";939 });940 Reference->markBranchAsMissing();941 }942 }943}944 945bool LVScope::equals(const LVScope *Scope) const {946 if (!LVElement::equals(Scope))947 return false;948 // For lexical scopes, check if their parents are the same.949 if (getIsLexicalBlock() && Scope->getIsLexicalBlock())950 return getParentScope()->equals(Scope->getParentScope());951 return true;952}953 954LVScope *LVScope::findEqualScope(const LVScopes *Scopes) const {955 assert(Scopes && "Scopes must not be nullptr");956 for (LVScope *Scope : *Scopes)957 if (equals(Scope))958 return Scope;959 return nullptr;960}961 962bool LVScope::equals(const LVScopes *References, const LVScopes *Targets) {963 if (!References && !Targets)964 return true;965 if (References && Targets && References->size() == Targets->size()) {966 for (const LVScope *Reference : *References)967 if (!Reference->findIn(Targets))968 return false;969 return true;970 }971 return false;972}973 974void LVScope::report(LVComparePass Pass) {975 getComparator().printItem(this, Pass);976 getComparator().push(this);977 for (LVElement *Element : getSortedChildren())978 Element->report(Pass);979 980 if (Lines)981 for (LVLine *Line : *Lines)982 Line->report(Pass);983 getComparator().pop();984}985 986void LVScope::printActiveRanges(raw_ostream &OS, bool Full) const {987 if (options().getPrintFormatting() && options().getAttributeRange() &&988 Ranges) {989 for (const LVLocation *Location : *Ranges)990 Location->print(OS, Full);991 }992}993 994void LVScope::printEncodedArgs(raw_ostream &OS, bool Full) const {995 if (options().getPrintFormatting() && options().getAttributeEncoded())996 printAttributes(OS, Full, "{Encoded} ", const_cast<LVScope *>(this),997 getEncodedArgs(), /*UseQuotes=*/false, /*PrintRef=*/false);998}999 1000void LVScope::print(raw_ostream &OS, bool Full) const {1001 if (getIncludeInPrint() && getReader().doPrintScope(this)) {1002 // For a summary (printed elements), do not count the scope root.1003 // For a summary (selected elements) do not count a compile unit.1004 if (!(getIsRoot() || (getIsCompileUnit() && options().getSelectExecute())))1005 getReaderCompileUnit()->incrementPrintedScopes();1006 LVElement::print(OS, Full);1007 printExtra(OS, Full);1008 }1009}1010 1011void LVScope::printExtra(raw_ostream &OS, bool Full) const {1012 OS << formattedKind(kind());1013 // Do not print any type or name for a lexical block.1014 if (!getIsBlock()) {1015 OS << " " << formattedName(getName());1016 if (!getIsAggregate()) {1017 OS << " -> " << typeOffsetAsString()1018 << formattedNames(getTypeQualifiedName(), typeAsString());1019 }1020 if (options().getAttributeSize())1021 if (uint32_t Size = getStorageSizeInBytes())1022 OS << " [Size = " << Size << "]";1023 }1024 OS << "\n";1025 1026 // Print any active ranges.1027 if (Full && getIsBlock())1028 printActiveRanges(OS, Full);1029}1030 1031//===----------------------------------------------------------------------===//1032// DWARF Union/Structure/Class.1033//===----------------------------------------------------------------------===//1034bool LVScopeAggregate::equals(const LVScope *Scope) const {1035 if (!LVScope::equals(Scope))1036 return false;1037 1038 if (!equalNumberOfChildren(Scope))1039 return false;1040 1041 // Check if the parameters match in the case of templates.1042 if (!LVType::parametersMatch(getTypes(), Scope->getTypes()))1043 return false;1044 1045 if (!isNamed() && !Scope->isNamed())1046 // In the case of unnamed union/structure/class compare the file name.1047 if (getFilenameIndex() != Scope->getFilenameIndex())1048 return false;1049 1050 return true;1051}1052 1053LVScope *LVScopeAggregate::findEqualScope(const LVScopes *Scopes) const {1054 assert(Scopes && "Scopes must not be nullptr");1055 for (LVScope *Scope : *Scopes)1056 if (equals(Scope))1057 return Scope;1058 return nullptr;1059}1060 1061void LVScopeAggregate::printExtra(raw_ostream &OS, bool Full) const {1062 LVScope::printExtra(OS, Full);1063 if (Full) {1064 if (getIsTemplateResolved())1065 printEncodedArgs(OS, Full);1066 LVScope *Reference = getReference();1067 if (Reference)1068 Reference->printReference(OS, Full, const_cast<LVScopeAggregate *>(this));1069 }1070}1071 1072//===----------------------------------------------------------------------===//1073// DWARF Template alias.1074//===----------------------------------------------------------------------===//1075bool LVScopeAlias::equals(const LVScope *Scope) const {1076 if (!LVScope::equals(Scope))1077 return false;1078 return equalNumberOfChildren(Scope);1079}1080 1081void LVScopeAlias::printExtra(raw_ostream &OS, bool Full) const {1082 OS << formattedKind(kind()) << " " << formattedName(getName()) << " -> "1083 << typeOffsetAsString()1084 << formattedNames(getTypeQualifiedName(), typeAsString()) << "\n";1085}1086 1087//===----------------------------------------------------------------------===//1088// DWARF array (DW_TAG_array_type).1089//===----------------------------------------------------------------------===//1090void LVScopeArray::resolveExtra() {1091 // If the scope is an array, resolve the subrange entries and get those1092 // values encoded and assigned to the scope type.1093 // Encode the array subrange entries as part of the name.1094 if (getIsArrayResolved())1095 return;1096 setIsArrayResolved();1097 1098 // There are 2 cases to represent the bounds information for an array:1099 // 1) DW_TAG_array_type1100 // DW_AT_type --> ref_type1101 // DW_TAG_subrange_type1102 // DW_AT_type --> ref_type (type of object)1103 // DW_AT_count --> value (number of elements in subrange)1104 1105 // 2) DW_TAG_array_type1106 // DW_AT_type --> ref_type1107 // DW_TAG_subrange_type1108 // DW_AT_lower_bound --> value1109 // DW_AT_upper_bound --> value1110 1111 // The idea is to represent the bounds as a string, depending on the format:1112 // 1) [count]1113 // 2) [lower][upper]1114 1115 // Traverse scope types, looking for those types that are subranges.1116 LVTypes Subranges;1117 if (const LVTypes *Types = getTypes())1118 for (LVType *Type : *Types)1119 if (Type->getIsSubrange()) {1120 Type->resolve();1121 Subranges.push_back(Type);1122 }1123 1124 // Use the subrange types to generate the high level name for the array.1125 // Check the type has been fully resolved.1126 if (LVElement *BaseType = getType()) {1127 BaseType->resolveName();1128 resolveFullname(BaseType);1129 }1130 1131 // In 'resolveFullname' a check is done for double spaces in the type name.1132 std::stringstream ArrayInfo;1133 if (ElementType)1134 ArrayInfo << getTypeName().str() << " ";1135 1136 for (const LVType *Type : Subranges) {1137 if (Type->getIsSubrangeCount())1138 // Check if we have DW_AT_count subrange style.1139 ArrayInfo << "[" << Type->getCount() << "]";1140 else {1141 // Get lower and upper subrange values.1142 unsigned LowerBound;1143 unsigned UpperBound;1144 std::tie(LowerBound, UpperBound) = Type->getBounds();1145 1146 // The representation depends on the bound values. If the lower value1147 // is zero, treat the pair as the elements count. Otherwise, just use1148 // the pair, as they are representing arrays in languages other than1149 // C/C++ and the lower limit is not zero.1150 if (LowerBound)1151 ArrayInfo << "[" << LowerBound << ".." << UpperBound << "]";1152 else1153 ArrayInfo << "[" << UpperBound + 1 << "]";1154 }1155 }1156 1157 // Update the scope name, to reflect the encoded subranges.1158 setName(ArrayInfo.str());1159}1160 1161bool LVScopeArray::equals(const LVScope *Scope) const {1162 if (!LVScope::equals(Scope))1163 return false;1164 1165 if (!equalNumberOfChildren(Scope))1166 return false;1167 1168 // Despite the arrays are encoded, to reflect the dimensions, we have to1169 // check the subranges, in order to determine if they are the same.1170 if (!LVType::equals(getTypes(), Scope->getTypes()))1171 return false;1172 1173 return true;1174}1175 1176void LVScopeArray::printExtra(raw_ostream &OS, bool Full) const {1177 OS << formattedKind(kind()) << " " << typeOffsetAsString()1178 << formattedName(getName()) << "\n";1179}1180 1181//===----------------------------------------------------------------------===//1182// An object file (single or multiple CUs).1183//===----------------------------------------------------------------------===//1184void LVScopeCompileUnit::addSize(LVScope *Scope, LVOffset Lower,1185 LVOffset Upper) {1186 LLVM_DEBUG({1187 dbgs() << format(1188 "CU [0x%08" PRIx64 "], Scope [0x%08" PRIx64 "], Range [0x%08" PRIx641189 ":0x%08" PRIx64 "], Size = %" PRId64 "\n",1190 getOffset(), Scope->getOffset(), Lower, Upper, Upper - Lower);1191 });1192 1193 // There is no need to check for a previous entry, as we are traversing the1194 // debug information in sequential order.1195 LVOffset Size = Upper - Lower;1196 Sizes[Scope] = Size;1197 if (this == Scope)1198 // Record contribution size for the compilation unit.1199 CUContributionSize = Size;1200}1201 1202// Update parents and children with pattern information.1203void LVScopeCompileUnit::propagatePatternMatch() {1204 // At this stage, we have finished creating the Scopes tree and we have1205 // a list of elements that match the pattern specified in the command line.1206 // The pattern corresponds to a scope or element; mark parents and/or1207 // children as having that pattern, before any printing is done.1208 if (!options().getSelectExecute())1209 return;1210 1211 if (MatchedScopes.size()) {1212 for (LVScope *Scope : MatchedScopes)1213 Scope->traverseParentsAndChildren(&LVScope::getHasPattern,1214 &LVScope::setHasPattern);1215 } else {1216 // Mark the compile unit as having a pattern to enable any requests to1217 // print sizes and summary as that information is recorded at that level.1218 setHasPattern();1219 }1220}1221 1222void LVScopeCompileUnit::processRangeLocationCoverage(1223 LVValidLocation ValidLocation) {1224 if (options().getAttributeRange()) {1225 // Traverse the scopes to get scopes that have invalid ranges.1226 LVLocations Locations;1227 bool RecordInvalid = options().getWarningRanges();1228 getRanges(Locations, ValidLocation, RecordInvalid);1229 1230 // Validate ranges associated with scopes.1231 if (RecordInvalid)1232 for (LVLocation *Location : Locations)1233 addInvalidRange(Location);1234 }1235 1236 if (options().getAttributeLocation()) {1237 // Traverse the scopes to get locations that have invalid ranges.1238 LVLocations Locations;1239 bool RecordInvalid = options().getWarningLocations();1240 getLocations(Locations, ValidLocation, RecordInvalid);1241 1242 // Validate ranges associated with locations.1243 if (RecordInvalid)1244 for (LVLocation *Location : Locations)1245 addInvalidLocation(Location);1246 }1247}1248 1249void LVScopeCompileUnit::addMapping(LVLine *Line, LVSectionIndex SectionIndex) {1250 LVAddress Address = Line->getOffset();1251 SectionMappings.add(SectionIndex, Address, Line);1252}1253 1254LVLine *LVScopeCompileUnit::lineLowerBound(LVAddress Address,1255 LVScope *Scope) const {1256 LVSectionIndex SectionIndex = getReader().getSectionIndex(Scope);1257 LVAddressToLine *Map = SectionMappings.findMap(SectionIndex);1258 if (!Map || Map->empty())1259 return nullptr;1260 LVAddressToLine::const_iterator Iter = Map->lower_bound(Address);1261 return (Iter != Map->end()) ? Iter->second : nullptr;1262}1263 1264LVLine *LVScopeCompileUnit::lineUpperBound(LVAddress Address,1265 LVScope *Scope) const {1266 LVSectionIndex SectionIndex = getReader().getSectionIndex(Scope);1267 LVAddressToLine *Map = SectionMappings.findMap(SectionIndex);1268 if (!Map || Map->empty())1269 return nullptr;1270 LVAddressToLine::const_iterator Iter = Map->upper_bound(Address);1271 if (Iter != Map->begin())1272 Iter = std::prev(Iter);1273 return Iter->second;1274}1275 1276LVLineRange LVScopeCompileUnit::lineRange(LVLocation *Location) const {1277 // The parent of a location can be a symbol or a scope.1278 LVElement *Element = Location->getParent();1279 LVScope *Parent = Element->getIsScope() ? static_cast<LVScope *>(Element)1280 : Element->getParentScope();1281 LVLine *LowLine = lineLowerBound(Location->getLowerAddress(), Parent);1282 LVLine *HighLine = lineUpperBound(Location->getUpperAddress(), Parent);1283 return LVLineRange(LowLine, HighLine);1284}1285 1286StringRef LVScopeCompileUnit::getFilename(size_t Index) const {1287 if (Index <= 0 || Index > Filenames.size())1288 return StringRef();1289 return getStringPool().getString(Filenames[Index - 1]);1290}1291 1292bool LVScopeCompileUnit::equals(const LVScope *Scope) const {1293 if (!LVScope::equals(Scope))1294 return false;1295 1296 return getNameIndex() == Scope->getNameIndex();1297}1298 1299void LVScopeCompileUnit::incrementPrintedLines() {1300 options().getSelectExecute() ? ++Found.Lines : ++Printed.Lines;1301}1302void LVScopeCompileUnit::incrementPrintedScopes() {1303 options().getSelectExecute() ? ++Found.Scopes : ++Printed.Scopes;1304}1305void LVScopeCompileUnit::incrementPrintedSymbols() {1306 options().getSelectExecute() ? ++Found.Symbols : ++Printed.Symbols;1307}1308void LVScopeCompileUnit::incrementPrintedTypes() {1309 options().getSelectExecute() ? ++Found.Types : ++Printed.Types;1310}1311 1312// Values are used by '--summary' option (allocated).1313void LVScopeCompileUnit::increment(LVLine *Line) {1314 if (Line->getIncludeInPrint())1315 ++Allocated.Lines;1316}1317void LVScopeCompileUnit::increment(LVScope *Scope) {1318 if (Scope->getIncludeInPrint())1319 ++Allocated.Scopes;1320}1321void LVScopeCompileUnit::increment(LVSymbol *Symbol) {1322 if (Symbol->getIncludeInPrint())1323 ++Allocated.Symbols;1324}1325void LVScopeCompileUnit::increment(LVType *Type) {1326 if (Type->getIncludeInPrint())1327 ++Allocated.Types;1328}1329 1330// A new element has been added to the scopes tree. Take the following steps:1331// Increase the added element counters, for printing summary.1332// During comparison notify the Reader of the new element.1333void LVScopeCompileUnit::addedElement(LVLine *Line) {1334 increment(Line);1335 getReader().notifyAddedElement(Line);1336}1337void LVScopeCompileUnit::addedElement(LVScope *Scope) {1338 increment(Scope);1339 getReader().notifyAddedElement(Scope);1340}1341void LVScopeCompileUnit::addedElement(LVSymbol *Symbol) {1342 increment(Symbol);1343 getReader().notifyAddedElement(Symbol);1344}1345void LVScopeCompileUnit::addedElement(LVType *Type) {1346 increment(Type);1347 getReader().notifyAddedElement(Type);1348}1349 1350// Record unsuported DWARF tags.1351void LVScopeCompileUnit::addDebugTag(dwarf::Tag Target, LVOffset Offset) {1352 addItem<LVTagOffsetsMap, dwarf::Tag, LVOffset>(&DebugTags, Target, Offset);1353}1354 1355// Record elements with invalid offsets.1356void LVScopeCompileUnit::addInvalidOffset(LVOffset Offset, LVElement *Element) {1357 if (WarningOffsets.find(Offset) == WarningOffsets.end())1358 WarningOffsets.emplace(Offset, Element);1359}1360 1361// Record symbols with invalid coverage values.1362void LVScopeCompileUnit::addInvalidCoverage(LVSymbol *Symbol) {1363 LVOffset Offset = Symbol->getOffset();1364 if (InvalidCoverages.find(Offset) == InvalidCoverages.end())1365 InvalidCoverages.emplace(Offset, Symbol);1366}1367 1368// Record symbols with invalid locations.1369void LVScopeCompileUnit::addInvalidLocation(LVLocation *Location) {1370 addInvalidLocationOrRange(Location, Location->getParentSymbol(),1371 &InvalidLocations);1372}1373 1374// Record scopes with invalid ranges.1375void LVScopeCompileUnit::addInvalidRange(LVLocation *Location) {1376 addInvalidLocationOrRange(Location, Location->getParentScope(),1377 &InvalidRanges);1378}1379 1380// Record line zero.1381void LVScopeCompileUnit::addLineZero(LVLine *Line) {1382 LVScope *Scope = Line->getParentScope();1383 LVOffset Offset = Scope->getOffset();1384 addInvalidOffset(Offset, Scope);1385 addItem<LVOffsetLinesMap, LVOffset, LVLine *>(&LinesZero, Offset, Line);1386}1387 1388void LVScopeCompileUnit::printLocalNames(raw_ostream &OS, bool Full) const {1389 if (!options().getPrintFormatting())1390 return;1391 1392 // Calculate an indentation value, to preserve a nice layout.1393 size_t Indentation = options().indentationSize() +1394 lineNumberAsString().length() +1395 indentAsString(getLevel() + 1).length() + 3;1396 1397 enum class Option { Directory, File };1398 auto PrintNames = [&](Option Action) {1399 StringRef Kind = Action == Option::Directory ? "Directory" : "File";1400 std::set<std::string> UniqueNames;1401 for (size_t Index : Filenames) {1402 // In the case of missing directory name in the .debug_line table,1403 // the returned string has a leading '/'.1404 StringRef Name = getStringPool().getString(Index);1405 size_t Pos = Name.rfind('/');1406 if (Pos != std::string::npos)1407 Name = (Action == Option::File) ? Name.substr(Pos + 1)1408 : Name.substr(0, Pos);1409 // Collect only unique names.1410 UniqueNames.insert(std::string(Name));1411 }1412 for (const std::string &Name : UniqueNames)1413 OS << std::string(Indentation, ' ') << formattedKind(Kind) << " "1414 << formattedName(Name) << "\n";1415 };1416 1417 if (options().getAttributeDirectories())1418 PrintNames(Option::Directory);1419 if (options().getAttributeFiles())1420 PrintNames(Option::File);1421 if (options().getAttributePublics()) {1422 StringRef Kind = "Public";1423 // The public names are indexed by 'LVScope *'. We want to print1424 // them by logical element address, to show the scopes layout.1425 using OffsetSorted = std::map<LVAddress, LVPublicNames::const_iterator>;1426 OffsetSorted SortedNames;1427 for (LVPublicNames::const_iterator Iter = PublicNames.begin();1428 Iter != PublicNames.end(); ++Iter)1429 SortedNames.emplace(Iter->first->getOffset(), Iter);1430 1431 LVPublicNames::const_iterator Iter;1432 for (OffsetSorted::reference Entry : SortedNames) {1433 Iter = Entry.second;1434 OS << std::string(Indentation, ' ') << formattedKind(Kind) << " "1435 << formattedName((*Iter).first->getName());1436 if (options().getAttributeOffset()) {1437 LVAddress Address = (*Iter).second.first;1438 size_t Size = (*Iter).second.second;1439 OS << " [" << hexString(Address) << ":" << hexString(Address + Size)1440 << "]";1441 }1442 OS << "\n";1443 }1444 }1445}1446 1447void LVScopeCompileUnit::printWarnings(raw_ostream &OS, bool Full) const {1448 auto PrintHeader = [&](const char *Header) { OS << "\n" << Header << ":\n"; };1449 auto PrintFooter = [&](auto &Set) {1450 if (Set.empty())1451 OS << "None\n";1452 };1453 auto PrintOffset = [&](unsigned &Count, LVOffset Offset) {1454 if (Count == 5) {1455 Count = 0;1456 OS << "\n";1457 }1458 ++Count;1459 OS << hexSquareString(Offset) << " ";1460 };1461 auto PrintElement = [&](const LVOffsetElementMap &Map, LVOffset Offset) {1462 LVOffsetElementMap::const_iterator Iter = Map.find(Offset);1463 LVElement *Element = Iter != Map.end() ? Iter->second : nullptr;1464 OS << "[" << hexString(Offset) << "]";1465 if (Element)1466 OS << " " << formattedKind(Element->kind()) << " "1467 << formattedName(Element->getName());1468 OS << "\n";1469 };1470 auto PrintInvalidLocations = [&](const LVOffsetLocationsMap &Map,1471 const char *Header) {1472 PrintHeader(Header);1473 for (LVOffsetLocationsMap::const_reference Entry : Map) {1474 PrintElement(WarningOffsets, Entry.first);1475 for (const LVLocation *Location : Entry.second)1476 OS << hexSquareString(Location->getOffset()) << " "1477 << Location->getIntervalInfo() << "\n";1478 }1479 PrintFooter(Map);1480 };1481 1482 if (options().getInternalTag() && getReader().isBinaryTypeELF()) {1483 PrintHeader("Unsupported DWARF Tags");1484 for (LVTagOffsetsMap::const_reference Entry : DebugTags) {1485 OS << format("\n0x%02x", (unsigned)Entry.first) << ", "1486 << dwarf::TagString(Entry.first) << "\n";1487 unsigned Count = 0;1488 for (const LVOffset &Offset : Entry.second)1489 PrintOffset(Count, Offset);1490 OS << "\n";1491 }1492 PrintFooter(DebugTags);1493 }1494 1495 if (options().getWarningCoverages()) {1496 PrintHeader("Symbols Invalid Coverages");1497 for (LVOffsetSymbolMap::const_reference Entry : InvalidCoverages) {1498 // Symbol basic information.1499 LVSymbol *Symbol = Entry.second;1500 OS << hexSquareString(Entry.first) << " {Coverage} "1501 << format("%.2f%%", Symbol->getCoveragePercentage()) << " "1502 << formattedKind(Symbol->kind()) << " "1503 << formattedName(Symbol->getName()) << "\n";1504 }1505 PrintFooter(InvalidCoverages);1506 }1507 1508 if (options().getWarningLines()) {1509 PrintHeader("Lines Zero References");1510 for (LVOffsetLinesMap::const_reference Entry : LinesZero) {1511 PrintElement(WarningOffsets, Entry.first);1512 unsigned Count = 0;1513 for (const LVLine *Line : Entry.second)1514 PrintOffset(Count, Line->getOffset());1515 OS << "\n";1516 }1517 PrintFooter(LinesZero);1518 }1519 1520 if (options().getWarningLocations())1521 PrintInvalidLocations(InvalidLocations, "Invalid Location Ranges");1522 1523 if (options().getWarningRanges())1524 PrintInvalidLocations(InvalidRanges, "Invalid Code Ranges");1525}1526 1527void LVScopeCompileUnit::printTotals(raw_ostream &OS) const {1528 OS << "\nTotals by lexical level:\n";1529 for (size_t Index = 1; Index <= MaxSeenLevel; ++Index)1530 OS << format("[%03d]: %10d (%6.2f%%)\n", Index, Totals[Index].first,1531 Totals[Index].second);1532}1533 1534void LVScopeCompileUnit::printScopeSize(const LVScope *Scope, raw_ostream &OS) {1535 LVSizesMap::const_iterator Iter = Sizes.find(Scope);1536 if (Iter != Sizes.end()) {1537 LVOffset Size = Iter->second;1538 assert(CUContributionSize && "Invalid CU contribution size.");1539 // Get a percentage rounded to two decimal digits. This avoids1540 // implementation-defined rounding inside printing functions.1541 float Percentage =1542 rint((float(Size) / CUContributionSize) * 100.0 * 100.0) / 100.0;1543 OS << format("%10" PRId64 " (%6.2f%%) : ", Size, Percentage);1544 Scope->print(OS);1545 1546 // Keep record of the total sizes at each lexical level.1547 LVLevel Level = Scope->getLevel();1548 if (Level > MaxSeenLevel)1549 MaxSeenLevel = Level;1550 if (Level >= Totals.size())1551 Totals.resize(2 * Level);1552 Totals[Level].first += Size;1553 Totals[Level].second += Percentage;1554 }1555}1556 1557void LVScopeCompileUnit::printSizes(raw_ostream &OS) const {1558 // Recursively print the contributions for each scope.1559 std::function<void(const LVScope *Scope)> PrintScope =1560 [&](const LVScope *Scope) {1561 // If we have selection criteria, then use only the selected scopes.1562 if (options().getSelectExecute() && options().getReportAnyView()) {1563 for (const LVScope *Scope : MatchedScopes)1564 if (Scope->getLevel() < options().getOutputLevel())1565 printScopeSize(Scope, OS);1566 return;1567 }1568 if (Scope->getLevel() < options().getOutputLevel()) {1569 if (const LVScopes *Scopes = Scope->getScopes())1570 for (const LVScope *Scope : *Scopes) {1571 printScopeSize(Scope, OS);1572 PrintScope(Scope);1573 }1574 }1575 };1576 1577 bool PrintScopes = options().getPrintScopes();1578 if (!PrintScopes)1579 options().setPrintScopes();1580 getReader().setCompileUnit(const_cast<LVScopeCompileUnit *>(this));1581 1582 OS << "\nScope Sizes:\n";1583 options().resetPrintFormatting();1584 options().setPrintOffset();1585 1586 // Print the scopes regardless if the user has requested any scopes1587 // printing. Set the option just to allow printing the contributions.1588 printScopeSize(this, OS);1589 PrintScope(this);1590 1591 // Print total scope sizes by level.1592 printTotals(OS);1593 1594 options().resetPrintOffset();1595 options().setPrintFormatting();1596 1597 if (!PrintScopes)1598 options().resetPrintScopes();1599}1600 1601void LVScopeCompileUnit::printSummary(raw_ostream &OS) const {1602 printSummary(OS, options().getSelectExecute() ? Found : Printed, "Printed");1603}1604 1605// Print summary details for the scopes tree.1606void LVScopeCompileUnit::printSummary(raw_ostream &OS, const LVCounter &Counter,1607 const char *Header) const {1608 std::string Separator = std::string(29, '-');1609 auto PrintSeparator = [&]() { OS << Separator << "\n"; };1610 auto PrintHeadingRow = [&](const char *T, const char *U, const char *V) {1611 OS << format("%-9s%9s %9s\n", T, U, V);1612 };1613 auto PrintDataRow = [&](const char *T, unsigned U, unsigned V) {1614 OS << format("%-9s%9d %9d\n", T, U, V);1615 };1616 1617 OS << "\n";1618 PrintSeparator();1619 PrintHeadingRow("Element", "Total", Header);1620 PrintSeparator();1621 PrintDataRow("Scopes", Allocated.Scopes, Counter.Scopes);1622 PrintDataRow("Symbols", Allocated.Symbols, Counter.Symbols);1623 PrintDataRow("Types", Allocated.Types, Counter.Types);1624 PrintDataRow("Lines", Allocated.Lines, Counter.Lines);1625 PrintSeparator();1626 PrintDataRow(1627 "Total",1628 Allocated.Scopes + Allocated.Symbols + Allocated.Lines + Allocated.Types,1629 Counter.Scopes + Counter.Symbols + Counter.Lines + Counter.Types);1630}1631 1632void LVScopeCompileUnit::printMatchedElements(raw_ostream &OS,1633 bool UseMatchedElements) {1634 LVSortFunction SortFunction = getSortFunction();1635 if (SortFunction)1636 llvm::stable_sort(MatchedElements, SortFunction);1637 1638 // Check the type of elements required to be printed. 'MatchedElements'1639 // contains generic elements (lines, scopes, symbols, types). If we have a1640 // request to print any generic element, then allow the normal printing.1641 if (options().getPrintAnyElement()) {1642 if (UseMatchedElements)1643 OS << "\n";1644 print(OS);1645 1646 if (UseMatchedElements) {1647 // Print the details for the matched elements.1648 for (const LVElement *Element : MatchedElements)1649 Element->print(OS);1650 } else {1651 // Print the view for the matched scopes.1652 for (const LVScope *Scope : MatchedScopes) {1653 Scope->print(OS);1654 for (LVElement *Element : Scope->getSortedChildren())1655 Element->print(OS);1656 }1657 }1658 1659 // Print any requested summary.1660 if (options().getPrintSummary()) {1661 // In the case of '--report=details' the matched elements are1662 // already counted; just proceed to print any requested summary.1663 // Otherwise, count them and print the summary.1664 if (!options().getReportList()) {1665 for (LVElement *Element : MatchedElements) {1666 if (!Element->getIncludeInPrint())1667 continue;1668 if (Element->getIsType())1669 ++Found.Types;1670 else if (Element->getIsSymbol())1671 ++Found.Symbols;1672 else if (Element->getIsScope())1673 ++Found.Scopes;1674 else if (Element->getIsLine())1675 ++Found.Lines;1676 else1677 assert(Element && "Invalid element.");1678 }1679 }1680 printSummary(OS, Found, "Printed");1681 }1682 }1683 1684 // Check if we have a request to print sizes for the matched elements1685 // that are scopes.1686 if (options().getPrintSizes()) {1687 OS << "\n";1688 print(OS);1689 1690 OS << "\nScope Sizes:\n";1691 printScopeSize(this, OS);1692 for (LVElement *Element : MatchedElements)1693 if (Element->getIsScope())1694 // Print sizes only for scopes.1695 printScopeSize(static_cast<LVScope *>(Element), OS);1696 1697 printTotals(OS);1698 }1699}1700 1701void LVScopeCompileUnit::print(raw_ostream &OS, bool Full) const {1702 // Reset counters for printed and found elements.1703 const_cast<LVScopeCompileUnit *>(this)->Found.reset();1704 const_cast<LVScopeCompileUnit *>(this)->Printed.reset();1705 1706 if (getReader().doPrintScope(this) && options().getPrintFormatting())1707 OS << "\n";1708 1709 LVScope::print(OS, Full);1710}1711 1712void LVScopeCompileUnit::printExtra(raw_ostream &OS, bool Full) const {1713 OS << formattedKind(kind()) << " '" << getName() << "'\n";1714 if (options().getPrintFormatting()) {1715 if (options().getAttributeProducer())1716 printAttributes(OS, Full, "{Producer} ",1717 const_cast<LVScopeCompileUnit *>(this), getProducer(),1718 /*UseQuotes=*/true,1719 /*PrintRef=*/false);1720 if (options().getAttributeLanguage())1721 if (auto SL = getSourceLanguage(); SL.isValid())1722 printAttributes(OS, Full, "{Language} ",1723 const_cast<LVScopeCompileUnit *>(this), SL.getName(),1724 /*UseQuotes=*/true,1725 /*PrintRef=*/false);1726 }1727 1728 // Reset file index, to allow its children to print the correct filename.1729 options().resetFilenameIndex();1730 1731 // Print any files, directories, public names and active ranges.1732 if (Full) {1733 printLocalNames(OS, Full);1734 printActiveRanges(OS, Full);1735 }1736}1737 1738//===----------------------------------------------------------------------===//1739// DWARF enumeration (DW_TAG_enumeration_type).1740//===----------------------------------------------------------------------===//1741bool LVScopeEnumeration::equals(const LVScope *Scope) const {1742 if (!LVScope::equals(Scope))1743 return false;1744 return equalNumberOfChildren(Scope);1745}1746 1747void LVScopeEnumeration::printExtra(raw_ostream &OS, bool Full) const {1748 // Print the full type name.1749 OS << formattedKind(kind()) << " " << (getIsEnumClass() ? "class " : "")1750 << formattedName(getName());1751 if (getHasType())1752 OS << " -> " << typeOffsetAsString()1753 << formattedNames(getTypeQualifiedName(), typeAsString());1754 OS << "\n";1755}1756 1757//===----------------------------------------------------------------------===//1758// DWARF formal parameter pack (DW_TAG_GNU_formal_parameter_pack).1759//===----------------------------------------------------------------------===//1760bool LVScopeFormalPack::equals(const LVScope *Scope) const {1761 if (!LVScope::equals(Scope))1762 return false;1763 return equalNumberOfChildren(Scope);1764}1765 1766void LVScopeFormalPack::printExtra(raw_ostream &OS, bool Full) const {1767 OS << formattedKind(kind()) << " " << formattedName(getName()) << "\n";1768}1769 1770//===----------------------------------------------------------------------===//1771// DWARF function.1772//===----------------------------------------------------------------------===//1773void LVScopeFunction::resolveReferences() {1774 // Before we resolve any references to other elements, check if we have1775 // to insert missing elements, that have been stripped, which will help1776 // the logical view comparison.1777 if (options().getAttributeInserted() && getHasReferenceAbstract() &&1778 !getAddedMissing()) {1779 // Add missing elements at the function scope.1780 addMissingElements(getReference());1781 if (Scopes)1782 for (LVScope *Scope : *Scopes)1783 if (Scope->getHasReferenceAbstract() && !Scope->getAddedMissing())1784 Scope->addMissingElements(Scope->getReference());1785 }1786 1787 LVScope::resolveReferences();1788 1789 // The DWARF 'extern' attribute is generated at the class level.1790 // 0000003f DW_TAG_class_type "CLASS"1791 // 00000048 DW_TAG_subprogram "bar"1792 // DW_AT_external DW_FORM_flag_present1793 // 00000070 DW_TAG_subprogram "bar"1794 // DW_AT_specification DW_FORM_ref4 0x000000481795 // CodeView does not include any information at the class level to1796 // mark the member function as external.1797 // If there is a reference linking the declaration and definition, mark1798 // the definition as extern, to facilitate the logical view comparison.1799 if (getHasReferenceSpecification()) {1800 LVScope *Reference = getReference();1801 if (Reference && Reference->getIsExternal()) {1802 Reference->resetIsExternal();1803 setIsExternal();1804 }1805 }1806 1807 // Resolve the function associated type.1808 if (!getType())1809 if (LVScope *Reference = getReference())1810 setType(Reference->getType());1811}1812 1813void LVScopeFunction::setName(StringRef ObjectName) {1814 LVScope::setName(ObjectName);1815 // Check for system generated functions.1816 getReader().isSystemEntry(this, ObjectName);1817}1818 1819void LVScopeFunction::resolveExtra() {1820 // Check if we need to encode the template arguments.1821 if (getIsTemplate())1822 resolveTemplate();1823}1824 1825bool LVScopeFunction::equals(const LVScope *Scope) const {1826 if (!LVScope::equals(Scope))1827 return false;1828 1829 // When comparing logical elements, ignore any difference in the children.1830 if (options().getCompareContext() && !equalNumberOfChildren(Scope))1831 return false;1832 1833 // Check if the linkage name matches.1834 if (getLinkageNameIndex() != Scope->getLinkageNameIndex())1835 return false;1836 1837 // Check if the parameters match in the case of templates.1838 if (!LVType::parametersMatch(getTypes(), Scope->getTypes()))1839 return false;1840 1841 // Check if the arguments match.1842 if (!LVSymbol::parametersMatch(getSymbols(), Scope->getSymbols()))1843 return false;1844 1845 // Check if the lines match.1846 if (options().getCompareLines() &&1847 !LVLine::equals(getLines(), Scope->getLines()))1848 return false;1849 1850 // Check if any reference is the same.1851 if (!referenceMatch(Scope))1852 return false;1853 1854 if (getReference() && !getReference()->equals(Scope->getReference()))1855 return false;1856 1857 return true;1858}1859 1860LVScope *LVScopeFunction::findEqualScope(const LVScopes *Scopes) const {1861 assert(Scopes && "Scopes must not be nullptr");1862 // Go through candidates and try to find a best match.1863 for (LVScope *Scope : *Scopes)1864 // Match arguments, children, lines, references.1865 if (equals(Scope))1866 return Scope;1867 return nullptr;1868}1869 1870void LVScopeFunction::printExtra(raw_ostream &OS, bool Full) const {1871 LVScope *Reference = getReference();1872 1873 // Inline attributes based on the reference element.1874 uint32_t InlineCode =1875 Reference ? Reference->getInlineCode() : getInlineCode();1876 1877 // Accessibility depends on the parent (class, structure).1878 uint32_t AccessCode = 0;1879 if (getIsMember())1880 AccessCode = getParentScope()->getIsClass() ? dwarf::DW_ACCESS_private1881 : dwarf::DW_ACCESS_public;1882 1883 std::string Attributes =1884 getIsCallSite()1885 ? ""1886 : formatAttributes(externalString(), accessibilityString(AccessCode),1887 inlineCodeString(InlineCode), virtualityString());1888 1889 OS << formattedKind(kind()) << " " << Attributes << formattedName(getName())1890 << discriminatorAsString() << " -> " << typeOffsetAsString()1891 << formattedNames(getTypeQualifiedName(), typeAsString()) << "\n";1892 1893 // Print any active ranges.1894 if (Full) {1895 if (getIsTemplateResolved())1896 printEncodedArgs(OS, Full);1897 printActiveRanges(OS, Full);1898 if (getLinkageNameIndex())1899 printLinkageName(OS, Full, const_cast<LVScopeFunction *>(this),1900 const_cast<LVScopeFunction *>(this));1901 if (Reference)1902 Reference->printReference(OS, Full, const_cast<LVScopeFunction *>(this));1903 }1904}1905 1906//===----------------------------------------------------------------------===//1907// DWARF inlined function (DW_TAG_inlined_function).1908//===----------------------------------------------------------------------===//1909void LVScopeFunctionInlined::resolveExtra() {1910 // Check if we need to encode the template arguments.1911 if (getIsTemplate())1912 resolveTemplate();1913}1914 1915bool LVScopeFunctionInlined::equals(const LVScope *Scope) const {1916 if (!LVScopeFunction::equals(Scope))1917 return false;1918 1919 // Check if any reference is the same.1920 if (getHasDiscriminator() && Scope->getHasDiscriminator())1921 if (getDiscriminator() != Scope->getDiscriminator())1922 return false;1923 1924 // Check the call site information.1925 if (getCallFilenameIndex() != Scope->getCallFilenameIndex() ||1926 getCallLineNumber() != Scope->getCallLineNumber())1927 return false;1928 1929 return true;1930}1931 1932LVScope *LVScopeFunctionInlined::findEqualScope(const LVScopes *Scopes) const {1933 return LVScopeFunction::findEqualScope(Scopes);1934}1935 1936void LVScopeFunctionInlined::printExtra(raw_ostream &OS, bool Full) const {1937 LVScopeFunction::printExtra(OS, Full);1938}1939 1940//===----------------------------------------------------------------------===//1941// DWARF subroutine type.1942//===----------------------------------------------------------------------===//1943// Resolve a Subroutine Type (Callback).1944void LVScopeFunctionType::resolveExtra() {1945 if (getIsMemberPointerResolved())1946 return;1947 setIsMemberPointerResolved();1948 1949 // The encoded string has the return type and the formal parameters type.1950 std::string Name(typeAsString());1951 Name.append(" (*)");1952 Name.append("(");1953 1954 // Traverse the scope symbols, looking for those which are parameters.1955 if (const LVSymbols *Symbols = getSymbols()) {1956 bool AddComma = false;1957 for (LVSymbol *Symbol : *Symbols)1958 if (Symbol->getIsParameter()) {1959 Symbol->resolve();1960 if (LVElement *Type = Symbol->getType())1961 Type->resolveName();1962 if (AddComma)1963 Name.append(", ");1964 Name.append(std::string(Symbol->getTypeName()));1965 AddComma = true;1966 }1967 }1968 1969 Name.append(")");1970 1971 // Update the scope name, to reflect the encoded parameters.1972 setName(Name);1973}1974 1975//===----------------------------------------------------------------------===//1976// DWARF module (DW_TAG_module).1977//===----------------------------------------------------------------------===//1978bool LVScopeModule::equals(const LVScope *Scope) const {1979 // For lexical blocks, LVScope::equals() compares the parent scope.1980 return LVScope::equals(Scope) && (Scope->getName() == getName());1981}1982 1983void LVScopeModule::printExtra(raw_ostream &OS, bool Full) const {1984 OS << formattedKind(kind()) << " " << formattedName(getName()) << "\n";1985}1986 1987//===----------------------------------------------------------------------===//1988// DWARF namespace (DW_TAG_namespace).1989//===----------------------------------------------------------------------===//1990bool LVScopeNamespace::equals(const LVScope *Scope) const {1991 if (!LVScope::equals(Scope))1992 return false;1993 1994 if (!equalNumberOfChildren(Scope))1995 return false;1996 1997 // Check if any reference is the same.1998 if (!referenceMatch(Scope))1999 return false;2000 2001 if (getReference() && !getReference()->equals(Scope->getReference()))2002 return false;2003 2004 return true;2005}2006 2007LVScope *LVScopeNamespace::findEqualScope(const LVScopes *Scopes) const {2008 assert(Scopes && "Scopes must not be nullptr");2009 // Go through candidates and try to find a best match.2010 for (LVScope *Scope : *Scopes)2011 if (equals(Scope))2012 return Scope;2013 return nullptr;2014}2015 2016void LVScopeNamespace::printExtra(raw_ostream &OS, bool Full) const {2017 OS << formattedKind(kind()) << " " << formattedName(getName()) << "\n";2018 2019 // Print any active ranges.2020 if (Full) {2021 printActiveRanges(OS, Full);2022 2023 if (LVScope *Reference = getReference())2024 Reference->printReference(OS, Full, const_cast<LVScopeNamespace *>(this));2025 }2026}2027 2028//===----------------------------------------------------------------------===//2029// An object file (single or multiple CUs).2030//===----------------------------------------------------------------------===//2031void LVScopeRoot::processRangeInformation() {2032 if (!options().getAttributeAnyLocation())2033 return;2034 2035 if (Scopes)2036 for (LVScope *Scope : *Scopes) {2037 LVScopeCompileUnit *CompileUnit =2038 static_cast<LVScopeCompileUnit *>(Scope);2039 getReader().setCompileUnit(CompileUnit);2040 CompileUnit->processRangeLocationCoverage();2041 }2042}2043 2044void LVScopeRoot::transformScopedName() {2045 // Recursively transform all names.2046 std::function<void(LVScope * Parent)> TraverseScope = [&](LVScope *Parent) {2047 auto Traverse = [&](const auto *Set) {2048 if (Set)2049 for (const auto &Entry : *Set)2050 Entry->setInnerComponent();2051 };2052 if (const LVScopes *Scopes = Parent->getScopes())2053 for (LVScope *Scope : *Scopes) {2054 Scope->setInnerComponent();2055 TraverseScope(Scope);2056 }2057 Traverse(Parent->getSymbols());2058 Traverse(Parent->getTypes());2059 Traverse(Parent->getLines());2060 };2061 2062 // Start traversing the scopes root and transform the element name.2063 TraverseScope(this);2064}2065 2066bool LVScopeRoot::equals(const LVScope *Scope) const {2067 return LVScope::equals(Scope);2068}2069 2070void LVScopeRoot::print(raw_ostream &OS, bool Full) const {2071 OS << "\nLogical View:\n";2072 LVScope::print(OS, Full);2073}2074 2075void LVScopeRoot::printExtra(raw_ostream &OS, bool Full) const {2076 OS << formattedKind(kind()) << " " << formattedName(getName()) << "";2077 if (options().getAttributeFormat())2078 OS << " -> " << getFileFormatName();2079 OS << "\n";2080}2081 2082Error LVScopeRoot::doPrintMatches(bool Split, raw_ostream &OS,2083 bool UseMatchedElements) const {2084 // During a view output splitting, use the output stream created by the2085 // split context, then switch to the reader output stream.2086 static raw_ostream *StreamSplit = &OS;2087 2088 if (Scopes) {2089 if (UseMatchedElements)2090 options().resetPrintFormatting();2091 print(OS);2092 2093 for (LVScope *Scope : *Scopes) {2094 getReader().setCompileUnit(Scope);2095 2096 // If 'Split', we use the scope name (CU name) as the ouput file; the2097 // delimiters in the pathname, must be replaced by a normal character.2098 if (Split) {2099 std::string ScopeName(Scope->getName());2100 if (std::error_code EC =2101 getReaderSplitContext().open(ScopeName, ".txt", OS))2102 return createStringError(EC, "Unable to create split output file %s",2103 ScopeName.c_str());2104 StreamSplit = static_cast<raw_ostream *>(&getReaderSplitContext().os());2105 }2106 2107 Scope->printMatchedElements(*StreamSplit, UseMatchedElements);2108 2109 // Done printing the compile unit. Restore the original output context.2110 if (Split) {2111 getReaderSplitContext().close();2112 StreamSplit = &getReader().outputStream();2113 }2114 }2115 if (UseMatchedElements)2116 options().setPrintFormatting();2117 }2118 2119 return Error::success();2120}2121 2122//===----------------------------------------------------------------------===//2123// DWARF template parameter pack (DW_TAG_GNU_template_parameter_pack).2124//===----------------------------------------------------------------------===//2125bool LVScopeTemplatePack::equals(const LVScope *Scope) const {2126 if (!LVScope::equals(Scope))2127 return false;2128 return equalNumberOfChildren(Scope);2129}2130 2131void LVScopeTemplatePack::printExtra(raw_ostream &OS, bool Full) const {2132 OS << formattedKind(kind()) << " " << formattedName(getName()) << "\n";2133}2134