1bdd1243dSDimitry Andric //===-- LVScope.h -----------------------------------------------*- C++ -*-===// 2bdd1243dSDimitry Andric // 3bdd1243dSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4bdd1243dSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5bdd1243dSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6bdd1243dSDimitry Andric // 7bdd1243dSDimitry Andric //===----------------------------------------------------------------------===// 8bdd1243dSDimitry Andric // 9bdd1243dSDimitry Andric // This file defines the LVScope class, which is used to describe a debug 10bdd1243dSDimitry Andric // information scope. 11bdd1243dSDimitry Andric // 12bdd1243dSDimitry Andric //===----------------------------------------------------------------------===// 13bdd1243dSDimitry Andric 14bdd1243dSDimitry Andric #ifndef LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVSCOPE_H 15bdd1243dSDimitry Andric #define LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVSCOPE_H 16bdd1243dSDimitry Andric 17bdd1243dSDimitry Andric #include "llvm/DebugInfo/LogicalView/Core/LVElement.h" 18bdd1243dSDimitry Andric #include "llvm/DebugInfo/LogicalView/Core/LVLocation.h" 19bdd1243dSDimitry Andric #include "llvm/DebugInfo/LogicalView/Core/LVSort.h" 20bdd1243dSDimitry Andric #include "llvm/Object/ObjectFile.h" 21bdd1243dSDimitry Andric #include <list> 22bdd1243dSDimitry Andric #include <map> 23bdd1243dSDimitry Andric #include <set> 24bdd1243dSDimitry Andric 25bdd1243dSDimitry Andric namespace llvm { 26bdd1243dSDimitry Andric namespace logicalview { 27bdd1243dSDimitry Andric 28bdd1243dSDimitry Andric // Name address, Code size. 29bdd1243dSDimitry Andric using LVNameInfo = std::pair<LVAddress, uint64_t>; 30bdd1243dSDimitry Andric using LVPublicNames = std::map<LVScope *, LVNameInfo>; 31bdd1243dSDimitry Andric using LVPublicAddresses = std::map<LVAddress, LVNameInfo>; 32bdd1243dSDimitry Andric 33bdd1243dSDimitry Andric class LVRange; 34bdd1243dSDimitry Andric 35bdd1243dSDimitry Andric enum class LVScopeKind { 36bdd1243dSDimitry Andric IsAggregate, 37bdd1243dSDimitry Andric IsArray, 38bdd1243dSDimitry Andric IsBlock, 39bdd1243dSDimitry Andric IsCallSite, 40bdd1243dSDimitry Andric IsCatchBlock, 41bdd1243dSDimitry Andric IsClass, 42bdd1243dSDimitry Andric IsCompileUnit, 43bdd1243dSDimitry Andric IsEntryPoint, 44bdd1243dSDimitry Andric IsEnumeration, 45bdd1243dSDimitry Andric IsFunction, 46bdd1243dSDimitry Andric IsFunctionType, 47bdd1243dSDimitry Andric IsInlinedFunction, 48bdd1243dSDimitry Andric IsLabel, 49bdd1243dSDimitry Andric IsLexicalBlock, 50bdd1243dSDimitry Andric IsMember, 51bdd1243dSDimitry Andric IsNamespace, 52bdd1243dSDimitry Andric IsRoot, 53bdd1243dSDimitry Andric IsStructure, 54bdd1243dSDimitry Andric IsSubprogram, 55bdd1243dSDimitry Andric IsTemplate, 56bdd1243dSDimitry Andric IsTemplateAlias, 57bdd1243dSDimitry Andric IsTemplatePack, 58bdd1243dSDimitry Andric IsTryBlock, 59bdd1243dSDimitry Andric IsUnion, 60bdd1243dSDimitry Andric LastEntry 61bdd1243dSDimitry Andric }; 62bdd1243dSDimitry Andric using LVScopeKindSet = std::set<LVScopeKind>; 63bdd1243dSDimitry Andric using LVScopeDispatch = std::map<LVScopeKind, LVScopeGetFunction>; 64bdd1243dSDimitry Andric using LVScopeRequest = std::vector<LVScopeGetFunction>; 65bdd1243dSDimitry Andric 66bdd1243dSDimitry Andric using LVOffsetElementMap = std::map<LVOffset, LVElement *>; 67*06c3fb27SDimitry Andric using LVOffsetLinesMap = std::map<LVOffset, LVLines>; 68*06c3fb27SDimitry Andric using LVOffsetLocationsMap = std::map<LVOffset, LVLocations>; 69bdd1243dSDimitry Andric using LVOffsetSymbolMap = std::map<LVOffset, LVSymbol *>; 70*06c3fb27SDimitry Andric using LVTagOffsetsMap = std::map<dwarf::Tag, LVOffsets>; 71bdd1243dSDimitry Andric 72bdd1243dSDimitry Andric // Class to represent a DWARF Scope. 73bdd1243dSDimitry Andric class LVScope : public LVElement { 74bdd1243dSDimitry Andric enum class Property { 75bdd1243dSDimitry Andric HasDiscriminator, 76bdd1243dSDimitry Andric CanHaveRanges, 77bdd1243dSDimitry Andric CanHaveLines, 78bdd1243dSDimitry Andric HasGlobals, 79bdd1243dSDimitry Andric HasLocals, 80bdd1243dSDimitry Andric HasLines, 81bdd1243dSDimitry Andric HasScopes, 82bdd1243dSDimitry Andric HasSymbols, 83bdd1243dSDimitry Andric HasTypes, 84bdd1243dSDimitry Andric IsComdat, 85bdd1243dSDimitry Andric HasComdatScopes, // Compile Unit has comdat functions. 86bdd1243dSDimitry Andric HasRanges, 87bdd1243dSDimitry Andric AddedMissing, // Added missing referenced symbols. 88bdd1243dSDimitry Andric LastEntry 89bdd1243dSDimitry Andric }; 90bdd1243dSDimitry Andric 91bdd1243dSDimitry Andric // Typed bitvector with kinds and properties for this scope. 92bdd1243dSDimitry Andric LVProperties<LVScopeKind> Kinds; 93bdd1243dSDimitry Andric LVProperties<Property> Properties; 94bdd1243dSDimitry Andric static LVScopeDispatch Dispatch; 95bdd1243dSDimitry Andric 96bdd1243dSDimitry Andric // Coverage factor in units (bytes). 97bdd1243dSDimitry Andric unsigned CoverageFactor = 0; 98bdd1243dSDimitry Andric 99bdd1243dSDimitry Andric // Calculate coverage factor. calculateCoverage()100bdd1243dSDimitry Andric void calculateCoverage() { 101bdd1243dSDimitry Andric float CoveragePercentage = 0; 102*06c3fb27SDimitry Andric LVLocation::calculateCoverage(Ranges.get(), CoverageFactor, 103*06c3fb27SDimitry Andric CoveragePercentage); 104bdd1243dSDimitry Andric } 105bdd1243dSDimitry Andric 106bdd1243dSDimitry Andric // Decide if the scope will be printed, using some conditions given by: 107bdd1243dSDimitry Andric // only-globals, only-locals, a-pattern. 108bdd1243dSDimitry Andric bool resolvePrinting() const; 109bdd1243dSDimitry Andric 110bdd1243dSDimitry Andric // Find the current scope in the given 'Targets'. 111bdd1243dSDimitry Andric LVScope *findIn(const LVScopes *Targets) const; 112bdd1243dSDimitry Andric 113bdd1243dSDimitry Andric // Traverse the scope parent tree, executing the given callback function 114bdd1243dSDimitry Andric // on each scope. 115bdd1243dSDimitry Andric void traverseParents(LVScopeGetFunction GetFunction, 116bdd1243dSDimitry Andric LVScopeSetFunction SetFunction); 117bdd1243dSDimitry Andric 118bdd1243dSDimitry Andric protected: 119bdd1243dSDimitry Andric // Types, Symbols, Scopes, Lines, Locations in this scope. 120*06c3fb27SDimitry Andric std::unique_ptr<LVTypes> Types; 121*06c3fb27SDimitry Andric std::unique_ptr<LVSymbols> Symbols; 122*06c3fb27SDimitry Andric std::unique_ptr<LVScopes> Scopes; 123*06c3fb27SDimitry Andric std::unique_ptr<LVLines> Lines; 124*06c3fb27SDimitry Andric std::unique_ptr<LVLocations> Ranges; 125bdd1243dSDimitry Andric 126bdd1243dSDimitry Andric // Vector of elements (types, scopes and symbols). 127bdd1243dSDimitry Andric // It is the union of (*Types, *Symbols and *Scopes) to be used for 128bdd1243dSDimitry Andric // the following reasons: 129bdd1243dSDimitry Andric // - Preserve the order the logical elements are read in. 130bdd1243dSDimitry Andric // - To have a single container with all the logical elements, when 131bdd1243dSDimitry Andric // the traversal does not require any specific element kind. 132*06c3fb27SDimitry Andric std::unique_ptr<LVElements> Children; 133bdd1243dSDimitry Andric 134bdd1243dSDimitry Andric // Resolve the template parameters/arguments relationship. 135bdd1243dSDimitry Andric void resolveTemplate(); 136bdd1243dSDimitry Andric void printEncodedArgs(raw_ostream &OS, bool Full) const; 137bdd1243dSDimitry Andric 138bdd1243dSDimitry Andric void printActiveRanges(raw_ostream &OS, bool Full = true) const; printSizes(raw_ostream & OS)139bdd1243dSDimitry Andric virtual void printSizes(raw_ostream &OS) const {} printSummary(raw_ostream & OS)140bdd1243dSDimitry Andric virtual void printSummary(raw_ostream &OS) const {} 141bdd1243dSDimitry Andric 142bdd1243dSDimitry Andric // Encoded template arguments. getEncodedArgs()143bdd1243dSDimitry Andric virtual StringRef getEncodedArgs() const { return StringRef(); } setEncodedArgs(StringRef EncodedArgs)144bdd1243dSDimitry Andric virtual void setEncodedArgs(StringRef EncodedArgs) {} 145bdd1243dSDimitry Andric 146bdd1243dSDimitry Andric public: LVScope()147bdd1243dSDimitry Andric LVScope() : LVElement(LVSubclassID::LV_SCOPE) { 148bdd1243dSDimitry Andric setIsScope(); 149bdd1243dSDimitry Andric setIncludeInPrint(); 150bdd1243dSDimitry Andric } 151bdd1243dSDimitry Andric LVScope(const LVScope &) = delete; 152bdd1243dSDimitry Andric LVScope &operator=(const LVScope &) = delete; 153*06c3fb27SDimitry Andric virtual ~LVScope() = default; 154bdd1243dSDimitry Andric classof(const LVElement * Element)155bdd1243dSDimitry Andric static bool classof(const LVElement *Element) { 156bdd1243dSDimitry Andric return Element->getSubclassID() == LVSubclassID::LV_SCOPE; 157bdd1243dSDimitry Andric } 158bdd1243dSDimitry Andric 159bdd1243dSDimitry Andric KIND(LVScopeKind, IsAggregate); 160bdd1243dSDimitry Andric KIND(LVScopeKind, IsArray); 161bdd1243dSDimitry Andric KIND_2(LVScopeKind, IsBlock, CanHaveRanges, CanHaveLines); 162bdd1243dSDimitry Andric KIND_1(LVScopeKind, IsCallSite, IsFunction); 163bdd1243dSDimitry Andric KIND_1(LVScopeKind, IsCatchBlock, IsBlock); 164bdd1243dSDimitry Andric KIND_1(LVScopeKind, IsClass, IsAggregate); 165bdd1243dSDimitry Andric KIND_3(LVScopeKind, IsCompileUnit, CanHaveRanges, CanHaveLines, 166bdd1243dSDimitry Andric TransformName); 167bdd1243dSDimitry Andric KIND_1(LVScopeKind, IsEntryPoint, IsFunction); 168bdd1243dSDimitry Andric KIND(LVScopeKind, IsEnumeration); 169bdd1243dSDimitry Andric KIND_2(LVScopeKind, IsFunction, CanHaveRanges, CanHaveLines); 170bdd1243dSDimitry Andric KIND_1(LVScopeKind, IsFunctionType, IsFunction); 171bdd1243dSDimitry Andric KIND_2(LVScopeKind, IsInlinedFunction, IsFunction, IsInlined); 172bdd1243dSDimitry Andric KIND_1(LVScopeKind, IsLabel, IsFunction); 173bdd1243dSDimitry Andric KIND_1(LVScopeKind, IsLexicalBlock, IsBlock); 174bdd1243dSDimitry Andric KIND(LVScopeKind, IsMember); 175bdd1243dSDimitry Andric KIND(LVScopeKind, IsNamespace); 176bdd1243dSDimitry Andric KIND_1(LVScopeKind, IsRoot, TransformName); 177bdd1243dSDimitry Andric KIND_1(LVScopeKind, IsStructure, IsAggregate); 178bdd1243dSDimitry Andric KIND_1(LVScopeKind, IsSubprogram, IsFunction); 179bdd1243dSDimitry Andric KIND(LVScopeKind, IsTemplate); 180bdd1243dSDimitry Andric KIND(LVScopeKind, IsTemplateAlias); 181bdd1243dSDimitry Andric KIND(LVScopeKind, IsTemplatePack); 182bdd1243dSDimitry Andric KIND_1(LVScopeKind, IsTryBlock, IsBlock); 183bdd1243dSDimitry Andric KIND_1(LVScopeKind, IsUnion, IsAggregate); 184bdd1243dSDimitry Andric 185bdd1243dSDimitry Andric PROPERTY(Property, HasDiscriminator); 186bdd1243dSDimitry Andric PROPERTY(Property, CanHaveRanges); 187bdd1243dSDimitry Andric PROPERTY(Property, CanHaveLines); 188bdd1243dSDimitry Andric PROPERTY(Property, HasGlobals); 189bdd1243dSDimitry Andric PROPERTY(Property, HasLocals); 190bdd1243dSDimitry Andric PROPERTY(Property, HasLines); 191bdd1243dSDimitry Andric PROPERTY(Property, HasScopes); 192bdd1243dSDimitry Andric PROPERTY(Property, HasSymbols); 193bdd1243dSDimitry Andric PROPERTY(Property, HasTypes); 194bdd1243dSDimitry Andric PROPERTY(Property, IsComdat); 195bdd1243dSDimitry Andric PROPERTY(Property, HasComdatScopes); 196bdd1243dSDimitry Andric PROPERTY(Property, HasRanges); 197bdd1243dSDimitry Andric PROPERTY(Property, AddedMissing); 198bdd1243dSDimitry Andric isCompileUnit()199bdd1243dSDimitry Andric bool isCompileUnit() const override { return getIsCompileUnit(); } isRoot()200bdd1243dSDimitry Andric bool isRoot() const override { return getIsRoot(); } 201bdd1243dSDimitry Andric 202bdd1243dSDimitry Andric const char *kind() const override; 203bdd1243dSDimitry Andric 204bdd1243dSDimitry Andric // Get the specific children. getLines()205*06c3fb27SDimitry Andric const LVLines *getLines() const { return Lines.get(); } getRanges()206*06c3fb27SDimitry Andric const LVLocations *getRanges() const { return Ranges.get(); } getScopes()207*06c3fb27SDimitry Andric const LVScopes *getScopes() const { return Scopes.get(); } getSymbols()208*06c3fb27SDimitry Andric const LVSymbols *getSymbols() const { return Symbols.get(); } getTypes()209*06c3fb27SDimitry Andric const LVTypes *getTypes() const { return Types.get(); } getChildren()210*06c3fb27SDimitry Andric const LVElements *getChildren() const { return Children.get(); } 211bdd1243dSDimitry Andric 212bdd1243dSDimitry Andric void addElement(LVElement *Element); 213bdd1243dSDimitry Andric void addElement(LVLine *Line); 214bdd1243dSDimitry Andric void addElement(LVScope *Scope); 215bdd1243dSDimitry Andric void addElement(LVSymbol *Symbol); 216bdd1243dSDimitry Andric void addElement(LVType *Type); 217bdd1243dSDimitry Andric void addObject(LVLocation *Location); 218bdd1243dSDimitry Andric void addObject(LVAddress LowerAddress, LVAddress UpperAddress); 219bdd1243dSDimitry Andric void addToChildren(LVElement *Element); 220bdd1243dSDimitry Andric 221bdd1243dSDimitry Andric // Add the missing elements from the given 'Reference', which is the 222bdd1243dSDimitry Andric // scope associated with any DW_AT_specification, DW_AT_abstract_origin. 223bdd1243dSDimitry Andric void addMissingElements(LVScope *Reference); 224bdd1243dSDimitry Andric 225bdd1243dSDimitry Andric // Traverse the scope parent tree and the children, executing the given 226bdd1243dSDimitry Andric // callback function on each element. 227bdd1243dSDimitry Andric void traverseParentsAndChildren(LVObjectGetFunction GetFunction, 228bdd1243dSDimitry Andric LVObjectSetFunction SetFunction); 229bdd1243dSDimitry Andric 230bdd1243dSDimitry Andric // Get the size of specific children. lineCount()231bdd1243dSDimitry Andric size_t lineCount() const { return Lines ? Lines->size() : 0; } rangeCount()232bdd1243dSDimitry Andric size_t rangeCount() const { return Ranges ? Ranges->size() : 0; } scopeCount()233bdd1243dSDimitry Andric size_t scopeCount() const { return Scopes ? Scopes->size() : 0; } symbolCount()234bdd1243dSDimitry Andric size_t symbolCount() const { return Symbols ? Symbols->size() : 0; } typeCount()235bdd1243dSDimitry Andric size_t typeCount() const { return Types ? Types->size() : 0; } 236bdd1243dSDimitry Andric 237bdd1243dSDimitry Andric // Find containing parent for the given address. 238bdd1243dSDimitry Andric LVScope *outermostParent(LVAddress Address); 239bdd1243dSDimitry Andric 240bdd1243dSDimitry Andric // Get all the locations associated with symbols. 241bdd1243dSDimitry Andric void getLocations(LVLocations &LocationList, LVValidLocation ValidLocation, 242bdd1243dSDimitry Andric bool RecordInvalid = false); 243bdd1243dSDimitry Andric void getRanges(LVLocations &LocationList, LVValidLocation ValidLocation, 244bdd1243dSDimitry Andric bool RecordInvalid = false); 245bdd1243dSDimitry Andric void getRanges(LVRange &RangeList); 246bdd1243dSDimitry Andric getCoverageFactor()247bdd1243dSDimitry Andric unsigned getCoverageFactor() const { return CoverageFactor; } 248bdd1243dSDimitry Andric 249bdd1243dSDimitry Andric Error doPrint(bool Split, bool Match, bool Print, raw_ostream &OS, 250bdd1243dSDimitry Andric bool Full = true) const override; 251bdd1243dSDimitry Andric // Sort the logical elements using the criteria specified by the 252bdd1243dSDimitry Andric // command line option '--output-sort'. 253bdd1243dSDimitry Andric void sort(); 254bdd1243dSDimitry Andric 255bdd1243dSDimitry Andric // Get template parameter types. 256bdd1243dSDimitry Andric bool getTemplateParameterTypes(LVTypes &Params); 257bdd1243dSDimitry Andric 258bdd1243dSDimitry Andric // DW_AT_specification, DW_AT_abstract_origin, DW_AT_extension. getReference()259bdd1243dSDimitry Andric virtual LVScope *getReference() const { return nullptr; } 260bdd1243dSDimitry Andric getCompileUnitParent()261bdd1243dSDimitry Andric LVScope *getCompileUnitParent() const override { 262bdd1243dSDimitry Andric return LVElement::getCompileUnitParent(); 263bdd1243dSDimitry Andric } 264bdd1243dSDimitry Andric 265bdd1243dSDimitry Andric // Follow a chain of references given by DW_AT_abstract_origin and/or 266bdd1243dSDimitry Andric // DW_AT_specification and update the scope name. 267bdd1243dSDimitry Andric StringRef resolveReferencesChain(); 268bdd1243dSDimitry Andric 269bdd1243dSDimitry Andric bool removeElement(LVElement *Element) override; 270bdd1243dSDimitry Andric void updateLevel(LVScope *Parent, bool Moved) override; 271bdd1243dSDimitry Andric 272bdd1243dSDimitry Andric void resolve() override; 273bdd1243dSDimitry Andric void resolveName() override; 274bdd1243dSDimitry Andric void resolveReferences() override; 275bdd1243dSDimitry Andric 276bdd1243dSDimitry Andric // Return the chain of parents as a string. 277bdd1243dSDimitry Andric void getQualifiedName(std::string &QualifiedName) const; 278bdd1243dSDimitry Andric // Encode the template arguments. 279bdd1243dSDimitry Andric void encodeTemplateArguments(std::string &Name) const; 280bdd1243dSDimitry Andric void encodeTemplateArguments(std::string &Name, const LVTypes *Types) const; 281bdd1243dSDimitry Andric 282bdd1243dSDimitry Andric void resolveElements(); 283bdd1243dSDimitry Andric 284bdd1243dSDimitry Andric // Iterate through the 'References' set and check that all its elements 285bdd1243dSDimitry Andric // are present in the 'Targets' set. For a missing element, mark its 286bdd1243dSDimitry Andric // parents as missing. 287bdd1243dSDimitry Andric static void markMissingParents(const LVScopes *References, 288bdd1243dSDimitry Andric const LVScopes *Targets, 289bdd1243dSDimitry Andric bool TraverseChildren); 290bdd1243dSDimitry Andric 291bdd1243dSDimitry Andric // Checks if the current scope is contained within the target scope. 292bdd1243dSDimitry Andric // Depending on the result, the callback may be performed. 293bdd1243dSDimitry Andric virtual void markMissingParents(const LVScope *Target, bool TraverseChildren); 294bdd1243dSDimitry Andric 295bdd1243dSDimitry Andric // Returns true if the current scope and the given 'Scope' have the 296bdd1243dSDimitry Andric // same number of children. 297bdd1243dSDimitry Andric virtual bool equalNumberOfChildren(const LVScope *Scope) const; 298bdd1243dSDimitry Andric 299bdd1243dSDimitry Andric // Returns true if current scope is logically equal to the given 'Scope'. 300bdd1243dSDimitry Andric virtual bool equals(const LVScope *Scope) const; 301bdd1243dSDimitry Andric 302bdd1243dSDimitry Andric // Returns true if the given 'References' are logically equal to the 303bdd1243dSDimitry Andric // given 'Targets'. 304bdd1243dSDimitry Andric static bool equals(const LVScopes *References, const LVScopes *Targets); 305bdd1243dSDimitry Andric 306bdd1243dSDimitry Andric // For the given 'Scopes' returns a scope that is logically equal 307bdd1243dSDimitry Andric // to the current scope; otherwise 'nullptr'. 308bdd1243dSDimitry Andric virtual LVScope *findEqualScope(const LVScopes *Scopes) const; 309bdd1243dSDimitry Andric 310bdd1243dSDimitry Andric // Report the current scope as missing or added during comparison. 311bdd1243dSDimitry Andric void report(LVComparePass Pass) override; 312bdd1243dSDimitry Andric getDispatch()313bdd1243dSDimitry Andric static LVScopeDispatch &getDispatch() { return Dispatch; } 314bdd1243dSDimitry Andric 315bdd1243dSDimitry Andric void print(raw_ostream &OS, bool Full = true) const override; 316bdd1243dSDimitry Andric void printExtra(raw_ostream &OS, bool Full = true) const override; 317bdd1243dSDimitry Andric virtual void printWarnings(raw_ostream &OS, bool Full = true) const {} printMatchedElements(raw_ostream & OS,bool UseMatchedElements)318bdd1243dSDimitry Andric virtual void printMatchedElements(raw_ostream &OS, bool UseMatchedElements) {} 319bdd1243dSDimitry Andric 320bdd1243dSDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) dump()321bdd1243dSDimitry Andric void dump() const override { print(dbgs()); } 322bdd1243dSDimitry Andric #endif 323bdd1243dSDimitry Andric }; 324bdd1243dSDimitry Andric 325bdd1243dSDimitry Andric // Class to represent a DWARF Union/Structure/Class. 326bdd1243dSDimitry Andric class LVScopeAggregate final : public LVScope { 327bdd1243dSDimitry Andric LVScope *Reference = nullptr; // DW_AT_specification, DW_AT_abstract_origin. 328bdd1243dSDimitry Andric size_t EncodedArgsIndex = 0; // Template encoded arguments. 329bdd1243dSDimitry Andric 330bdd1243dSDimitry Andric public: LVScopeAggregate()331bdd1243dSDimitry Andric LVScopeAggregate() : LVScope() {} 332bdd1243dSDimitry Andric LVScopeAggregate(const LVScopeAggregate &) = delete; 333bdd1243dSDimitry Andric LVScopeAggregate &operator=(const LVScopeAggregate &) = delete; 334bdd1243dSDimitry Andric ~LVScopeAggregate() = default; 335bdd1243dSDimitry Andric 336bdd1243dSDimitry Andric // DW_AT_specification, DW_AT_abstract_origin. getReference()337bdd1243dSDimitry Andric LVScope *getReference() const override { return Reference; } setReference(LVScope * Scope)338bdd1243dSDimitry Andric void setReference(LVScope *Scope) override { 339bdd1243dSDimitry Andric Reference = Scope; 340bdd1243dSDimitry Andric setHasReference(); 341bdd1243dSDimitry Andric } setReference(LVElement * Element)342bdd1243dSDimitry Andric void setReference(LVElement *Element) override { 343bdd1243dSDimitry Andric setReference(static_cast<LVScope *>(Element)); 344bdd1243dSDimitry Andric } 345bdd1243dSDimitry Andric getEncodedArgs()346bdd1243dSDimitry Andric StringRef getEncodedArgs() const override { 347bdd1243dSDimitry Andric return getStringPool().getString(EncodedArgsIndex); 348bdd1243dSDimitry Andric } setEncodedArgs(StringRef EncodedArgs)349bdd1243dSDimitry Andric void setEncodedArgs(StringRef EncodedArgs) override { 350bdd1243dSDimitry Andric EncodedArgsIndex = getStringPool().getIndex(EncodedArgs); 351bdd1243dSDimitry Andric } 352bdd1243dSDimitry Andric 353bdd1243dSDimitry Andric // Returns true if current scope is logically equal to the given 'Scope'. 354bdd1243dSDimitry Andric bool equals(const LVScope *Scope) const override; 355bdd1243dSDimitry Andric 356bdd1243dSDimitry Andric // For the given 'Scopes' returns a scope that is logically equal 357bdd1243dSDimitry Andric // to the current scope; otherwise 'nullptr'. 358bdd1243dSDimitry Andric LVScope *findEqualScope(const LVScopes *Scopes) const override; 359bdd1243dSDimitry Andric 360bdd1243dSDimitry Andric void printExtra(raw_ostream &OS, bool Full = true) const override; 361bdd1243dSDimitry Andric }; 362bdd1243dSDimitry Andric 363bdd1243dSDimitry Andric // Class to represent a DWARF Template alias. 364bdd1243dSDimitry Andric class LVScopeAlias final : public LVScope { 365bdd1243dSDimitry Andric public: LVScopeAlias()366bdd1243dSDimitry Andric LVScopeAlias() : LVScope() { 367bdd1243dSDimitry Andric setIsTemplateAlias(); 368bdd1243dSDimitry Andric setIsTemplate(); 369bdd1243dSDimitry Andric } 370bdd1243dSDimitry Andric LVScopeAlias(const LVScopeAlias &) = delete; 371bdd1243dSDimitry Andric LVScopeAlias &operator=(const LVScopeAlias &) = delete; 372bdd1243dSDimitry Andric ~LVScopeAlias() = default; 373bdd1243dSDimitry Andric 374bdd1243dSDimitry Andric // Returns true if current scope is logically equal to the given 'Scope'. 375bdd1243dSDimitry Andric bool equals(const LVScope *Scope) const override; 376bdd1243dSDimitry Andric 377bdd1243dSDimitry Andric void printExtra(raw_ostream &OS, bool Full = true) const override; 378bdd1243dSDimitry Andric }; 379bdd1243dSDimitry Andric 380bdd1243dSDimitry Andric // Class to represent a DWARF array (DW_TAG_array_type). 381bdd1243dSDimitry Andric class LVScopeArray final : public LVScope { 382bdd1243dSDimitry Andric public: LVScopeArray()383bdd1243dSDimitry Andric LVScopeArray() : LVScope() { setIsArray(); } 384bdd1243dSDimitry Andric LVScopeArray(const LVScopeArray &) = delete; 385bdd1243dSDimitry Andric LVScopeArray &operator=(const LVScopeArray &) = delete; 386bdd1243dSDimitry Andric ~LVScopeArray() = default; 387bdd1243dSDimitry Andric 388bdd1243dSDimitry Andric void resolveExtra() override; 389bdd1243dSDimitry Andric 390bdd1243dSDimitry Andric // Returns true if current scope is logically equal to the given 'Scope'. 391bdd1243dSDimitry Andric bool equals(const LVScope *Scope) const override; 392bdd1243dSDimitry Andric 393bdd1243dSDimitry Andric void printExtra(raw_ostream &OS, bool Full = true) const override; 394bdd1243dSDimitry Andric }; 395bdd1243dSDimitry Andric 396bdd1243dSDimitry Andric // Class to represent a DWARF Compilation Unit (CU). 397bdd1243dSDimitry Andric class LVScopeCompileUnit final : public LVScope { 398bdd1243dSDimitry Andric // Names (files and directories) used by the Compile Unit. 399bdd1243dSDimitry Andric std::vector<size_t> Filenames; 400bdd1243dSDimitry Andric 401bdd1243dSDimitry Andric // As the .debug_pubnames section has been removed in DWARF5, we have a 402bdd1243dSDimitry Andric // similar functionality, which is used by the decoded functions. We use 403bdd1243dSDimitry Andric // the low-pc and high-pc for those scopes that are marked as public, in 404bdd1243dSDimitry Andric // order to support DWARF and CodeView. 405bdd1243dSDimitry Andric LVPublicNames PublicNames; 406bdd1243dSDimitry Andric 407bdd1243dSDimitry Andric // Toolchain producer. 408bdd1243dSDimitry Andric size_t ProducerIndex = 0; 409bdd1243dSDimitry Andric 410bdd1243dSDimitry Andric // Compilation directory name. 411bdd1243dSDimitry Andric size_t CompilationDirectoryIndex = 0; 412bdd1243dSDimitry Andric 413*06c3fb27SDimitry Andric // Used by the CodeView Reader. 414*06c3fb27SDimitry Andric codeview::CPUType CompilationCPUType = codeview::CPUType::X64; 415*06c3fb27SDimitry Andric 416bdd1243dSDimitry Andric // Keep record of elements. They are needed at the compilation unit level 417bdd1243dSDimitry Andric // to print the summary at the end of the printing. 418bdd1243dSDimitry Andric LVCounter Allocated; 419bdd1243dSDimitry Andric LVCounter Found; 420bdd1243dSDimitry Andric LVCounter Printed; 421bdd1243dSDimitry Andric 422bdd1243dSDimitry Andric // Elements that match a given command line pattern. 423bdd1243dSDimitry Andric LVElements MatchedElements; 424bdd1243dSDimitry Andric LVScopes MatchedScopes; 425bdd1243dSDimitry Andric 426bdd1243dSDimitry Andric // It records the mapping between logical lines representing a debug line 427bdd1243dSDimitry Andric // entry and its address in the text section. It is used to find a line 428bdd1243dSDimitry Andric // giving its exact or closest address. To support comdat functions, all 429bdd1243dSDimitry Andric // addresses for the same section are recorded in the same map. 430bdd1243dSDimitry Andric using LVAddressToLine = std::map<LVAddress, LVLine *>; 431bdd1243dSDimitry Andric LVDoubleMap<LVSectionIndex, LVAddress, LVLine *> SectionMappings; 432bdd1243dSDimitry Andric 433bdd1243dSDimitry Andric // DWARF Tags (Tag, Element list). 434bdd1243dSDimitry Andric LVTagOffsetsMap DebugTags; 435bdd1243dSDimitry Andric 436bdd1243dSDimitry Andric // Offsets associated with objects being flagged as having invalid data 437bdd1243dSDimitry Andric // (ranges, locations, lines zero or coverages). 438bdd1243dSDimitry Andric LVOffsetElementMap WarningOffsets; 439bdd1243dSDimitry Andric 440bdd1243dSDimitry Andric // Symbols with invalid locations. (Symbol, Location List). 441bdd1243dSDimitry Andric LVOffsetLocationsMap InvalidLocations; 442bdd1243dSDimitry Andric 443bdd1243dSDimitry Andric // Symbols with invalid coverage values. 444bdd1243dSDimitry Andric LVOffsetSymbolMap InvalidCoverages; 445bdd1243dSDimitry Andric 446bdd1243dSDimitry Andric // Scopes with invalid ranges (Scope, Range list). 447bdd1243dSDimitry Andric LVOffsetLocationsMap InvalidRanges; 448bdd1243dSDimitry Andric 449bdd1243dSDimitry Andric // Scopes with lines zero (Scope, Line list). 450bdd1243dSDimitry Andric LVOffsetLinesMap LinesZero; 451bdd1243dSDimitry Andric 452bdd1243dSDimitry Andric // Record scopes contribution in bytes to the debug information. 453bdd1243dSDimitry Andric using LVSizesMap = std::map<const LVScope *, LVOffset>; 454bdd1243dSDimitry Andric LVSizesMap Sizes; 455bdd1243dSDimitry Andric LVOffset CUContributionSize = 0; 456bdd1243dSDimitry Andric 457bdd1243dSDimitry Andric // Helper function to add an invalid location/range. addInvalidLocationOrRange(LVLocation * Location,LVElement * Element,LVOffsetLocationsMap * Map)458bdd1243dSDimitry Andric void addInvalidLocationOrRange(LVLocation *Location, LVElement *Element, 459bdd1243dSDimitry Andric LVOffsetLocationsMap *Map) { 460bdd1243dSDimitry Andric LVOffset Offset = Element->getOffset(); 461bdd1243dSDimitry Andric addInvalidOffset(Offset, Element); 462*06c3fb27SDimitry Andric addItem<LVOffsetLocationsMap, LVOffset, LVLocation *>(Map, Offset, 463*06c3fb27SDimitry Andric Location); 464bdd1243dSDimitry Andric } 465bdd1243dSDimitry Andric 466bdd1243dSDimitry Andric // Record scope sizes indexed by lexical level. 467bdd1243dSDimitry Andric // Setting an initial size that will cover a very deep nested scopes. 468bdd1243dSDimitry Andric const size_t TotalInitialSize = 8; 469bdd1243dSDimitry Andric using LVTotalsEntry = std::pair<unsigned, float>; 470bdd1243dSDimitry Andric SmallVector<LVTotalsEntry> Totals; 471bdd1243dSDimitry Andric // Maximum seen lexical level. It is used to control how many entries 472bdd1243dSDimitry Andric // in the 'Totals' vector are valid values. 473bdd1243dSDimitry Andric LVLevel MaxSeenLevel = 0; 474bdd1243dSDimitry Andric 475bdd1243dSDimitry Andric // Get the line located at the given address. 476bdd1243dSDimitry Andric LVLine *lineLowerBound(LVAddress Address, LVScope *Scope) const; 477bdd1243dSDimitry Andric LVLine *lineUpperBound(LVAddress Address, LVScope *Scope) const; 478bdd1243dSDimitry Andric 479bdd1243dSDimitry Andric void printScopeSize(const LVScope *Scope, raw_ostream &OS); printScopeSize(const LVScope * Scope,raw_ostream & OS)480bdd1243dSDimitry Andric void printScopeSize(const LVScope *Scope, raw_ostream &OS) const { 481bdd1243dSDimitry Andric (const_cast<LVScopeCompileUnit *>(this))->printScopeSize(Scope, OS); 482bdd1243dSDimitry Andric } 483bdd1243dSDimitry Andric void printTotals(raw_ostream &OS) const; 484bdd1243dSDimitry Andric 485bdd1243dSDimitry Andric protected: 486bdd1243dSDimitry Andric void printSizes(raw_ostream &OS) const override; 487bdd1243dSDimitry Andric void printSummary(raw_ostream &OS) const override; 488bdd1243dSDimitry Andric 489bdd1243dSDimitry Andric public: LVScopeCompileUnit()490bdd1243dSDimitry Andric LVScopeCompileUnit() : LVScope(), Totals(TotalInitialSize, {0, 0.0}) { 491bdd1243dSDimitry Andric setIsCompileUnit(); 492bdd1243dSDimitry Andric } 493bdd1243dSDimitry Andric LVScopeCompileUnit(const LVScopeCompileUnit &) = delete; 494bdd1243dSDimitry Andric LVScopeCompileUnit &operator=(const LVScopeCompileUnit &) = delete; 495*06c3fb27SDimitry Andric ~LVScopeCompileUnit() = default; 496bdd1243dSDimitry Andric getCompileUnitParent()497bdd1243dSDimitry Andric LVScope *getCompileUnitParent() const override { 498bdd1243dSDimitry Andric return static_cast<LVScope *>(const_cast<LVScopeCompileUnit *>(this)); 499bdd1243dSDimitry Andric } 500bdd1243dSDimitry Andric 501bdd1243dSDimitry Andric // Add line to address mapping. 502bdd1243dSDimitry Andric void addMapping(LVLine *Line, LVSectionIndex SectionIndex); 503bdd1243dSDimitry Andric LVLineRange lineRange(LVLocation *Location) const; 504bdd1243dSDimitry Andric 505bdd1243dSDimitry Andric LVNameInfo NameNone = {UINT64_MAX, 0}; addPublicName(LVScope * Scope,LVAddress LowPC,LVAddress HighPC)506bdd1243dSDimitry Andric void addPublicName(LVScope *Scope, LVAddress LowPC, LVAddress HighPC) { 507bdd1243dSDimitry Andric PublicNames.emplace(std::piecewise_construct, std::forward_as_tuple(Scope), 508bdd1243dSDimitry Andric std::forward_as_tuple(LowPC, HighPC - LowPC)); 509bdd1243dSDimitry Andric } findPublicName(LVScope * Scope)510bdd1243dSDimitry Andric const LVNameInfo &findPublicName(LVScope *Scope) { 511bdd1243dSDimitry Andric LVPublicNames::iterator Iter = PublicNames.find(Scope); 512bdd1243dSDimitry Andric return (Iter != PublicNames.end()) ? Iter->second : NameNone; 513bdd1243dSDimitry Andric } getPublicNames()514bdd1243dSDimitry Andric const LVPublicNames &getPublicNames() const { return PublicNames; } 515bdd1243dSDimitry Andric 516bdd1243dSDimitry Andric // The base address of the scope for any of the debugging information 517bdd1243dSDimitry Andric // entries listed, is given by either the DW_AT_low_pc attribute or the 518bdd1243dSDimitry Andric // first address in the first range entry in the list of ranges given by 519bdd1243dSDimitry Andric // the DW_AT_ranges attribute. getBaseAddress()520bdd1243dSDimitry Andric LVAddress getBaseAddress() const { 521bdd1243dSDimitry Andric return Ranges ? Ranges->front()->getLowerAddress() : 0; 522bdd1243dSDimitry Andric } 523bdd1243dSDimitry Andric getCompilationDirectory()524bdd1243dSDimitry Andric StringRef getCompilationDirectory() const { 525bdd1243dSDimitry Andric return getStringPool().getString(CompilationDirectoryIndex); 526bdd1243dSDimitry Andric } setCompilationDirectory(StringRef CompilationDirectory)527bdd1243dSDimitry Andric void setCompilationDirectory(StringRef CompilationDirectory) { 528bdd1243dSDimitry Andric CompilationDirectoryIndex = getStringPool().getIndex(CompilationDirectory); 529bdd1243dSDimitry Andric } 530bdd1243dSDimitry Andric 531bdd1243dSDimitry Andric StringRef getFilename(size_t Index) const; addFilename(StringRef Name)532bdd1243dSDimitry Andric void addFilename(StringRef Name) { 533bdd1243dSDimitry Andric Filenames.push_back(getStringPool().getIndex(Name)); 534bdd1243dSDimitry Andric } 535bdd1243dSDimitry Andric getProducer()536bdd1243dSDimitry Andric StringRef getProducer() const override { 537bdd1243dSDimitry Andric return getStringPool().getString(ProducerIndex); 538bdd1243dSDimitry Andric } setProducer(StringRef ProducerName)539bdd1243dSDimitry Andric void setProducer(StringRef ProducerName) override { 540bdd1243dSDimitry Andric ProducerIndex = getStringPool().getIndex(ProducerName); 541bdd1243dSDimitry Andric } 542bdd1243dSDimitry Andric setCPUType(codeview::CPUType Type)543*06c3fb27SDimitry Andric void setCPUType(codeview::CPUType Type) { CompilationCPUType = Type; } getCPUType()544*06c3fb27SDimitry Andric codeview::CPUType getCPUType() { return CompilationCPUType; } 545*06c3fb27SDimitry Andric 546bdd1243dSDimitry Andric // Record DWARF tags. 547bdd1243dSDimitry Andric void addDebugTag(dwarf::Tag Target, LVOffset Offset); 548bdd1243dSDimitry Andric // Record elements with invalid offsets. 549bdd1243dSDimitry Andric void addInvalidOffset(LVOffset Offset, LVElement *Element); 550bdd1243dSDimitry Andric // Record symbols with invalid coverage values. 551bdd1243dSDimitry Andric void addInvalidCoverage(LVSymbol *Symbol); 552bdd1243dSDimitry Andric // Record symbols with invalid locations. 553bdd1243dSDimitry Andric void addInvalidLocation(LVLocation *Location); 554bdd1243dSDimitry Andric // Record scopes with invalid ranges. 555bdd1243dSDimitry Andric void addInvalidRange(LVLocation *Location); 556bdd1243dSDimitry Andric // Record line zero. 557bdd1243dSDimitry Andric void addLineZero(LVLine *Line); 558bdd1243dSDimitry Andric getDebugTags()559bdd1243dSDimitry Andric const LVTagOffsetsMap &getDebugTags() const { return DebugTags; } getWarningOffsets()560bdd1243dSDimitry Andric const LVOffsetElementMap &getWarningOffsets() const { return WarningOffsets; } getInvalidLocations()561bdd1243dSDimitry Andric const LVOffsetLocationsMap &getInvalidLocations() const { 562bdd1243dSDimitry Andric return InvalidLocations; 563bdd1243dSDimitry Andric } getInvalidCoverages()564bdd1243dSDimitry Andric const LVOffsetSymbolMap &getInvalidCoverages() const { 565bdd1243dSDimitry Andric return InvalidCoverages; 566bdd1243dSDimitry Andric } getInvalidRanges()567bdd1243dSDimitry Andric const LVOffsetLocationsMap &getInvalidRanges() const { return InvalidRanges; } getLinesZero()568bdd1243dSDimitry Andric const LVOffsetLinesMap &getLinesZero() const { return LinesZero; } 569bdd1243dSDimitry Andric 570bdd1243dSDimitry Andric // Process ranges, locations and calculate coverage. 571bdd1243dSDimitry Andric void processRangeLocationCoverage( 572bdd1243dSDimitry Andric LVValidLocation ValidLocation = &LVLocation::validateRanges); 573bdd1243dSDimitry Andric 574bdd1243dSDimitry Andric // Add matched element. addMatched(LVElement * Element)575bdd1243dSDimitry Andric void addMatched(LVElement *Element) { MatchedElements.push_back(Element); } addMatched(LVScope * Scope)576bdd1243dSDimitry Andric void addMatched(LVScope *Scope) { MatchedScopes.push_back(Scope); } 577bdd1243dSDimitry Andric void propagatePatternMatch(); 578bdd1243dSDimitry Andric getMatchedElements()579bdd1243dSDimitry Andric const LVElements &getMatchedElements() const { return MatchedElements; } getMatchedScopes()580bdd1243dSDimitry Andric const LVScopes &getMatchedScopes() const { return MatchedScopes; } 581bdd1243dSDimitry Andric 582bdd1243dSDimitry Andric void printLocalNames(raw_ostream &OS, bool Full = true) const; 583bdd1243dSDimitry Andric void printSummary(raw_ostream &OS, const LVCounter &Counter, 584bdd1243dSDimitry Andric const char *Header) const; 585bdd1243dSDimitry Andric 586bdd1243dSDimitry Andric void incrementPrintedLines(); 587bdd1243dSDimitry Andric void incrementPrintedScopes(); 588bdd1243dSDimitry Andric void incrementPrintedSymbols(); 589bdd1243dSDimitry Andric void incrementPrintedTypes(); 590bdd1243dSDimitry Andric 591bdd1243dSDimitry Andric // Values are used by '--summary' option (allocated). 592bdd1243dSDimitry Andric void increment(LVLine *Line); 593bdd1243dSDimitry Andric void increment(LVScope *Scope); 594bdd1243dSDimitry Andric void increment(LVSymbol *Symbol); 595bdd1243dSDimitry Andric void increment(LVType *Type); 596bdd1243dSDimitry Andric 597bdd1243dSDimitry Andric // A new element has been added to the scopes tree. Take the following steps: 598bdd1243dSDimitry Andric // Increase the added element counters, for printing summary. 599bdd1243dSDimitry Andric // During comparison notify the Reader of the new element. 600bdd1243dSDimitry Andric void addedElement(LVLine *Line); 601bdd1243dSDimitry Andric void addedElement(LVScope *Scope); 602bdd1243dSDimitry Andric void addedElement(LVSymbol *Symbol); 603bdd1243dSDimitry Andric void addedElement(LVType *Type); 604bdd1243dSDimitry Andric 605bdd1243dSDimitry Andric void addSize(LVScope *Scope, LVOffset Lower, LVOffset Upper); 606bdd1243dSDimitry Andric 607bdd1243dSDimitry Andric // Returns true if current scope is logically equal to the given 'Scope'. 608bdd1243dSDimitry Andric bool equals(const LVScope *Scope) const override; 609bdd1243dSDimitry Andric 610bdd1243dSDimitry Andric void print(raw_ostream &OS, bool Full = true) const override; 611bdd1243dSDimitry Andric void printExtra(raw_ostream &OS, bool Full = true) const override; 612bdd1243dSDimitry Andric void printWarnings(raw_ostream &OS, bool Full = true) const override; 613bdd1243dSDimitry Andric void printMatchedElements(raw_ostream &OS, bool UseMatchedElements) override; 614bdd1243dSDimitry Andric }; 615bdd1243dSDimitry Andric 616bdd1243dSDimitry Andric // Class to represent a DWARF enumerator (DW_TAG_enumeration_type). 617bdd1243dSDimitry Andric class LVScopeEnumeration final : public LVScope { 618bdd1243dSDimitry Andric public: LVScopeEnumeration()619bdd1243dSDimitry Andric LVScopeEnumeration() : LVScope() { setIsEnumeration(); } 620bdd1243dSDimitry Andric LVScopeEnumeration(const LVScopeEnumeration &) = delete; 621bdd1243dSDimitry Andric LVScopeEnumeration &operator=(const LVScopeEnumeration &) = delete; 622bdd1243dSDimitry Andric ~LVScopeEnumeration() = default; 623bdd1243dSDimitry Andric 624bdd1243dSDimitry Andric // Returns true if current scope is logically equal to the given 'Scope'. 625bdd1243dSDimitry Andric bool equals(const LVScope *Scope) const override; 626bdd1243dSDimitry Andric 627bdd1243dSDimitry Andric void printExtra(raw_ostream &OS, bool Full = true) const override; 628bdd1243dSDimitry Andric }; 629bdd1243dSDimitry Andric 630bdd1243dSDimitry Andric // Class to represent a DWARF formal parameter pack 631bdd1243dSDimitry Andric // (DW_TAG_GNU_formal_parameter_pack). 632bdd1243dSDimitry Andric class LVScopeFormalPack final : public LVScope { 633bdd1243dSDimitry Andric public: LVScopeFormalPack()634bdd1243dSDimitry Andric LVScopeFormalPack() : LVScope() { setIsTemplatePack(); } 635bdd1243dSDimitry Andric LVScopeFormalPack(const LVScopeFormalPack &) = delete; 636bdd1243dSDimitry Andric LVScopeFormalPack &operator=(const LVScopeFormalPack &) = delete; 637bdd1243dSDimitry Andric ~LVScopeFormalPack() = default; 638bdd1243dSDimitry Andric 639bdd1243dSDimitry Andric // Returns true if current scope is logically equal to the given 'Scope'. 640bdd1243dSDimitry Andric bool equals(const LVScope *Scope) const override; 641bdd1243dSDimitry Andric 642bdd1243dSDimitry Andric void printExtra(raw_ostream &OS, bool Full = true) const override; 643bdd1243dSDimitry Andric }; 644bdd1243dSDimitry Andric 645bdd1243dSDimitry Andric // Class to represent a DWARF Function. 646bdd1243dSDimitry Andric class LVScopeFunction : public LVScope { 647bdd1243dSDimitry Andric LVScope *Reference = nullptr; // DW_AT_specification, DW_AT_abstract_origin. 648bdd1243dSDimitry Andric size_t LinkageNameIndex = 0; // Function DW_AT_linkage_name attribute. 649bdd1243dSDimitry Andric size_t EncodedArgsIndex = 0; // Template encoded arguments. 650bdd1243dSDimitry Andric 651bdd1243dSDimitry Andric public: LVScopeFunction()652bdd1243dSDimitry Andric LVScopeFunction() : LVScope() {} 653bdd1243dSDimitry Andric LVScopeFunction(const LVScopeFunction &) = delete; 654bdd1243dSDimitry Andric LVScopeFunction &operator=(const LVScopeFunction &) = delete; 655bdd1243dSDimitry Andric virtual ~LVScopeFunction() = default; 656bdd1243dSDimitry Andric 657bdd1243dSDimitry Andric // DW_AT_specification, DW_AT_abstract_origin. getReference()658bdd1243dSDimitry Andric LVScope *getReference() const override { return Reference; } setReference(LVScope * Scope)659bdd1243dSDimitry Andric void setReference(LVScope *Scope) override { 660bdd1243dSDimitry Andric Reference = Scope; 661bdd1243dSDimitry Andric setHasReference(); 662bdd1243dSDimitry Andric } setReference(LVElement * Element)663bdd1243dSDimitry Andric void setReference(LVElement *Element) override { 664bdd1243dSDimitry Andric setReference(static_cast<LVScope *>(Element)); 665bdd1243dSDimitry Andric } 666bdd1243dSDimitry Andric getEncodedArgs()667bdd1243dSDimitry Andric StringRef getEncodedArgs() const override { 668bdd1243dSDimitry Andric return getStringPool().getString(EncodedArgsIndex); 669bdd1243dSDimitry Andric } setEncodedArgs(StringRef EncodedArgs)670bdd1243dSDimitry Andric void setEncodedArgs(StringRef EncodedArgs) override { 671bdd1243dSDimitry Andric EncodedArgsIndex = getStringPool().getIndex(EncodedArgs); 672bdd1243dSDimitry Andric } 673bdd1243dSDimitry Andric setLinkageName(StringRef LinkageName)674bdd1243dSDimitry Andric void setLinkageName(StringRef LinkageName) override { 675bdd1243dSDimitry Andric LinkageNameIndex = getStringPool().getIndex(LinkageName); 676bdd1243dSDimitry Andric } getLinkageName()677bdd1243dSDimitry Andric StringRef getLinkageName() const override { 678bdd1243dSDimitry Andric return getStringPool().getString(LinkageNameIndex); 679bdd1243dSDimitry Andric } getLinkageNameIndex()680bdd1243dSDimitry Andric size_t getLinkageNameIndex() const override { return LinkageNameIndex; } 681bdd1243dSDimitry Andric 682bdd1243dSDimitry Andric void setName(StringRef ObjectName) override; 683bdd1243dSDimitry Andric 684bdd1243dSDimitry Andric void resolveExtra() override; 685bdd1243dSDimitry Andric void resolveReferences() override; 686bdd1243dSDimitry Andric 687bdd1243dSDimitry Andric // Returns true if current scope is logically equal to the given 'Scope'. 688bdd1243dSDimitry Andric bool equals(const LVScope *Scope) const override; 689bdd1243dSDimitry Andric 690bdd1243dSDimitry Andric // For the given 'Scopes' returns a scope that is logically equal 691bdd1243dSDimitry Andric // to the current scope; otherwise 'nullptr'. 692bdd1243dSDimitry Andric LVScope *findEqualScope(const LVScopes *Scopes) const override; 693bdd1243dSDimitry Andric 694bdd1243dSDimitry Andric void printExtra(raw_ostream &OS, bool Full = true) const override; 695bdd1243dSDimitry Andric }; 696bdd1243dSDimitry Andric 697bdd1243dSDimitry Andric // Class to represent a DWARF inlined function. 698bdd1243dSDimitry Andric class LVScopeFunctionInlined final : public LVScopeFunction { 699bdd1243dSDimitry Andric size_t CallFilenameIndex = 0; 700bdd1243dSDimitry Andric uint32_t CallLineNumber = 0; 701bdd1243dSDimitry Andric uint32_t Discriminator = 0; 702bdd1243dSDimitry Andric 703bdd1243dSDimitry Andric public: LVScopeFunctionInlined()704bdd1243dSDimitry Andric LVScopeFunctionInlined() : LVScopeFunction() { setIsInlinedFunction(); } 705bdd1243dSDimitry Andric LVScopeFunctionInlined(const LVScopeFunctionInlined &) = delete; 706bdd1243dSDimitry Andric LVScopeFunctionInlined &operator=(const LVScopeFunctionInlined &) = delete; 707bdd1243dSDimitry Andric ~LVScopeFunctionInlined() = default; 708bdd1243dSDimitry Andric getDiscriminator()709bdd1243dSDimitry Andric uint32_t getDiscriminator() const override { return Discriminator; } setDiscriminator(uint32_t Value)710bdd1243dSDimitry Andric void setDiscriminator(uint32_t Value) override { 711bdd1243dSDimitry Andric Discriminator = Value; 712bdd1243dSDimitry Andric setHasDiscriminator(); 713bdd1243dSDimitry Andric } 714bdd1243dSDimitry Andric getCallLineNumber()715bdd1243dSDimitry Andric uint32_t getCallLineNumber() const override { return CallLineNumber; } setCallLineNumber(uint32_t Number)716bdd1243dSDimitry Andric void setCallLineNumber(uint32_t Number) override { CallLineNumber = Number; } getCallFilenameIndex()717bdd1243dSDimitry Andric size_t getCallFilenameIndex() const override { return CallFilenameIndex; } setCallFilenameIndex(size_t Index)718bdd1243dSDimitry Andric void setCallFilenameIndex(size_t Index) override { 719bdd1243dSDimitry Andric CallFilenameIndex = Index; 720bdd1243dSDimitry Andric } 721bdd1243dSDimitry Andric 722bdd1243dSDimitry Andric // Line number for display; in the case of Inlined Functions, we use the 723bdd1243dSDimitry Andric // DW_AT_call_line attribute; otherwise use DW_AT_decl_line attribute. 724bdd1243dSDimitry Andric std::string lineNumberAsString(bool ShowZero = false) const override { 725bdd1243dSDimitry Andric return lineAsString(getCallLineNumber(), getDiscriminator(), ShowZero); 726bdd1243dSDimitry Andric } 727bdd1243dSDimitry Andric 728bdd1243dSDimitry Andric void resolveExtra() override; 729bdd1243dSDimitry Andric 730bdd1243dSDimitry Andric // Returns true if current scope is logically equal to the given 'Scope'. 731bdd1243dSDimitry Andric bool equals(const LVScope *Scope) const override; 732bdd1243dSDimitry Andric 733bdd1243dSDimitry Andric // For the given 'Scopes' returns a scope that is logically equal 734bdd1243dSDimitry Andric // to the current scope; otherwise 'nullptr'. 735bdd1243dSDimitry Andric LVScope *findEqualScope(const LVScopes *Scopes) const override; 736bdd1243dSDimitry Andric 737bdd1243dSDimitry Andric void printExtra(raw_ostream &OS, bool Full = true) const override; 738bdd1243dSDimitry Andric }; 739bdd1243dSDimitry Andric 740bdd1243dSDimitry Andric // Class to represent a DWARF subroutine type. 741bdd1243dSDimitry Andric class LVScopeFunctionType final : public LVScopeFunction { 742bdd1243dSDimitry Andric public: LVScopeFunctionType()743bdd1243dSDimitry Andric LVScopeFunctionType() : LVScopeFunction() { setIsFunctionType(); } 744bdd1243dSDimitry Andric LVScopeFunctionType(const LVScopeFunctionType &) = delete; 745bdd1243dSDimitry Andric LVScopeFunctionType &operator=(const LVScopeFunctionType &) = delete; 746bdd1243dSDimitry Andric ~LVScopeFunctionType() = default; 747bdd1243dSDimitry Andric 748bdd1243dSDimitry Andric void resolveExtra() override; 749bdd1243dSDimitry Andric }; 750bdd1243dSDimitry Andric 751bdd1243dSDimitry Andric // Class to represent a DWARF Namespace. 752bdd1243dSDimitry Andric class LVScopeNamespace final : public LVScope { 753bdd1243dSDimitry Andric LVScope *Reference = nullptr; // Reference to DW_AT_extension attribute. 754bdd1243dSDimitry Andric 755bdd1243dSDimitry Andric public: LVScopeNamespace()756bdd1243dSDimitry Andric LVScopeNamespace() : LVScope() { setIsNamespace(); } 757bdd1243dSDimitry Andric LVScopeNamespace(const LVScopeNamespace &) = delete; 758bdd1243dSDimitry Andric LVScopeNamespace &operator=(const LVScopeNamespace &) = delete; 759bdd1243dSDimitry Andric ~LVScopeNamespace() = default; 760bdd1243dSDimitry Andric 761bdd1243dSDimitry Andric // Access DW_AT_extension reference. getReference()762bdd1243dSDimitry Andric LVScope *getReference() const override { return Reference; } setReference(LVScope * Scope)763bdd1243dSDimitry Andric void setReference(LVScope *Scope) override { 764bdd1243dSDimitry Andric Reference = Scope; 765bdd1243dSDimitry Andric setHasReference(); 766bdd1243dSDimitry Andric } setReference(LVElement * Element)767bdd1243dSDimitry Andric void setReference(LVElement *Element) override { 768bdd1243dSDimitry Andric setReference(static_cast<LVScope *>(Element)); 769bdd1243dSDimitry Andric } 770bdd1243dSDimitry Andric 771bdd1243dSDimitry Andric // Returns true if current scope is logically equal to the given 'Scope'. 772bdd1243dSDimitry Andric bool equals(const LVScope *Scope) const override; 773bdd1243dSDimitry Andric 774bdd1243dSDimitry Andric // For the given 'Scopes' returns a scope that is logically equal 775bdd1243dSDimitry Andric // to the current scope; otherwise 'nullptr'. 776bdd1243dSDimitry Andric LVScope *findEqualScope(const LVScopes *Scopes) const override; 777bdd1243dSDimitry Andric 778bdd1243dSDimitry Andric void printExtra(raw_ostream &OS, bool Full = true) const override; 779bdd1243dSDimitry Andric }; 780bdd1243dSDimitry Andric 781bdd1243dSDimitry Andric // Class to represent the binary file being analyzed. 782bdd1243dSDimitry Andric class LVScopeRoot final : public LVScope { 783bdd1243dSDimitry Andric size_t FileFormatNameIndex = 0; 784bdd1243dSDimitry Andric 785bdd1243dSDimitry Andric public: LVScopeRoot()786bdd1243dSDimitry Andric LVScopeRoot() : LVScope() { setIsRoot(); } 787bdd1243dSDimitry Andric LVScopeRoot(const LVScopeRoot &) = delete; 788bdd1243dSDimitry Andric LVScopeRoot &operator=(const LVScopeRoot &) = delete; 789bdd1243dSDimitry Andric ~LVScopeRoot() = default; 790bdd1243dSDimitry Andric getFileFormatName()791bdd1243dSDimitry Andric StringRef getFileFormatName() const { 792bdd1243dSDimitry Andric return getStringPool().getString(FileFormatNameIndex); 793bdd1243dSDimitry Andric } setFileFormatName(StringRef FileFormatName)794bdd1243dSDimitry Andric void setFileFormatName(StringRef FileFormatName) { 795bdd1243dSDimitry Andric FileFormatNameIndex = getStringPool().getIndex(FileFormatName); 796bdd1243dSDimitry Andric } 797bdd1243dSDimitry Andric 798*06c3fb27SDimitry Andric // The CodeView Reader uses scoped names. Recursively transform the 799*06c3fb27SDimitry Andric // element name to use just the most inner component. 800*06c3fb27SDimitry Andric void transformScopedName(); 801*06c3fb27SDimitry Andric 802bdd1243dSDimitry Andric // Process the collected location, ranges and calculate coverage. 803bdd1243dSDimitry Andric void processRangeInformation(); 804bdd1243dSDimitry Andric 805bdd1243dSDimitry Andric // Returns true if current scope is logically equal to the given 'Scope'. 806bdd1243dSDimitry Andric bool equals(const LVScope *Scope) const override; 807bdd1243dSDimitry Andric 808bdd1243dSDimitry Andric void print(raw_ostream &OS, bool Full = true) const override; 809bdd1243dSDimitry Andric void printExtra(raw_ostream &OS, bool Full = true) const override; 810bdd1243dSDimitry Andric Error doPrintMatches(bool Split, raw_ostream &OS, 811bdd1243dSDimitry Andric bool UseMatchedElements) const; 812bdd1243dSDimitry Andric }; 813bdd1243dSDimitry Andric 814bdd1243dSDimitry Andric // Class to represent a DWARF template parameter pack 815bdd1243dSDimitry Andric // (DW_TAG_GNU_template_parameter_pack). 816bdd1243dSDimitry Andric class LVScopeTemplatePack final : public LVScope { 817bdd1243dSDimitry Andric public: LVScopeTemplatePack()818bdd1243dSDimitry Andric LVScopeTemplatePack() : LVScope() { setIsTemplatePack(); } 819bdd1243dSDimitry Andric LVScopeTemplatePack(const LVScopeTemplatePack &) = delete; 820bdd1243dSDimitry Andric LVScopeTemplatePack &operator=(const LVScopeTemplatePack &) = delete; 821bdd1243dSDimitry Andric ~LVScopeTemplatePack() = default; 822bdd1243dSDimitry Andric 823bdd1243dSDimitry Andric // Returns true if current scope is logically equal to the given 'Scope'. 824bdd1243dSDimitry Andric bool equals(const LVScope *Scope) const override; 825bdd1243dSDimitry Andric 826bdd1243dSDimitry Andric void printExtra(raw_ostream &OS, bool Full = true) const override; 827bdd1243dSDimitry Andric }; 828bdd1243dSDimitry Andric 829bdd1243dSDimitry Andric } // end namespace logicalview 830bdd1243dSDimitry Andric } // end namespace llvm 831bdd1243dSDimitry Andric 832bdd1243dSDimitry Andric #endif // LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVSCOPE_H 833