| //===-- LVScope.h -----------------------------------------------*- C++ -*-===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This file defines the LVScope class, which is used to describe a debug |
| // information scope. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVSCOPE_H |
| #define LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVSCOPE_H |
| |
| #include "llvm/DebugInfo/LogicalView/Core/LVElement.h" |
| #include "llvm/DebugInfo/LogicalView/Core/LVLocation.h" |
| #include "llvm/DebugInfo/LogicalView/Core/LVSort.h" |
| #include "llvm/Object/ObjectFile.h" |
| #include <list> |
| #include <map> |
| #include <set> |
| |
| namespace llvm { |
| namespace logicalview { |
| |
| // Name address, Code size. |
| using LVNameInfo = std::pair<LVAddress, uint64_t>; |
| using LVPublicNames = std::map<LVScope *, LVNameInfo>; |
| using LVPublicAddresses = std::map<LVAddress, LVNameInfo>; |
| |
| class LVRange; |
| |
| enum class LVScopeKind { |
| IsAggregate, |
| IsArray, |
| IsBlock, |
| IsCallSite, |
| IsCatchBlock, |
| IsClass, |
| IsCompileUnit, |
| IsEntryPoint, |
| IsEnumeration, |
| IsFunction, |
| IsFunctionType, |
| IsInlinedFunction, |
| IsLabel, |
| IsLexicalBlock, |
| IsMember, |
| IsNamespace, |
| IsRoot, |
| IsStructure, |
| IsSubprogram, |
| IsTemplate, |
| IsTemplateAlias, |
| IsTemplatePack, |
| IsTryBlock, |
| IsUnion, |
| LastEntry |
| }; |
| using LVScopeKindSet = std::set<LVScopeKind>; |
| using LVScopeDispatch = std::map<LVScopeKind, LVScopeGetFunction>; |
| using LVScopeRequest = std::vector<LVScopeGetFunction>; |
| |
| using LVOffsetList = std::list<LVOffset>; |
| using LVOffsetElementMap = std::map<LVOffset, LVElement *>; |
| using LVOffsetLinesMap = std::map<LVOffset, LVLines *>; |
| using LVOffsetLocationsMap = std::map<LVOffset, LVLocations *>; |
| using LVOffsetSymbolMap = std::map<LVOffset, LVSymbol *>; |
| using LVTagOffsetsMap = std::map<dwarf::Tag, LVOffsetList *>; |
| |
| // Class to represent a DWARF Scope. |
| class LVScope : public LVElement { |
| enum class Property { |
| HasDiscriminator, |
| CanHaveRanges, |
| CanHaveLines, |
| HasGlobals, |
| HasLocals, |
| HasLines, |
| HasScopes, |
| HasSymbols, |
| HasTypes, |
| IsComdat, |
| HasComdatScopes, // Compile Unit has comdat functions. |
| HasRanges, |
| AddedMissing, // Added missing referenced symbols. |
| LastEntry |
| }; |
| |
| // Typed bitvector with kinds and properties for this scope. |
| LVProperties<LVScopeKind> Kinds; |
| LVProperties<Property> Properties; |
| static LVScopeDispatch Dispatch; |
| |
| // Coverage factor in units (bytes). |
| unsigned CoverageFactor = 0; |
| |
| // Calculate coverage factor. |
| void calculateCoverage() { |
| float CoveragePercentage = 0; |
| LVLocation::calculateCoverage(Ranges, CoverageFactor, CoveragePercentage); |
| } |
| |
| // Decide if the scope will be printed, using some conditions given by: |
| // only-globals, only-locals, a-pattern. |
| bool resolvePrinting() const; |
| |
| // Find the current scope in the given 'Targets'. |
| LVScope *findIn(const LVScopes *Targets) const; |
| |
| // Traverse the scope parent tree, executing the given callback function |
| // on each scope. |
| void traverseParents(LVScopeGetFunction GetFunction, |
| LVScopeSetFunction SetFunction); |
| |
| protected: |
| // Types, Symbols, Scopes, Lines, Locations in this scope. |
| LVAutoTypes *Types = nullptr; |
| LVAutoSymbols *Symbols = nullptr; |
| LVAutoScopes *Scopes = nullptr; |
| LVAutoLines *Lines = nullptr; |
| LVAutoLocations *Ranges = nullptr; |
| |
| // Vector of elements (types, scopes and symbols). |
| // It is the union of (*Types, *Symbols and *Scopes) to be used for |
| // the following reasons: |
| // - Preserve the order the logical elements are read in. |
| // - To have a single container with all the logical elements, when |
| // the traversal does not require any specific element kind. |
| LVElements *Children = nullptr; |
| |
| // Resolve the template parameters/arguments relationship. |
| void resolveTemplate(); |
| void printEncodedArgs(raw_ostream &OS, bool Full) const; |
| |
| void printActiveRanges(raw_ostream &OS, bool Full = true) const; |
| virtual void printSizes(raw_ostream &OS) const {} |
| virtual void printSummary(raw_ostream &OS) const {} |
| |
| // Encoded template arguments. |
| virtual StringRef getEncodedArgs() const { return StringRef(); } |
| virtual void setEncodedArgs(StringRef EncodedArgs) {} |
| |
| public: |
| LVScope() : LVElement(LVSubclassID::LV_SCOPE) { |
| setIsScope(); |
| setIncludeInPrint(); |
| } |
| LVScope(const LVScope &) = delete; |
| LVScope &operator=(const LVScope &) = delete; |
| virtual ~LVScope(); |
| |
| static bool classof(const LVElement *Element) { |
| return Element->getSubclassID() == LVSubclassID::LV_SCOPE; |
| } |
| |
| KIND(LVScopeKind, IsAggregate); |
| KIND(LVScopeKind, IsArray); |
| KIND_2(LVScopeKind, IsBlock, CanHaveRanges, CanHaveLines); |
| KIND_1(LVScopeKind, IsCallSite, IsFunction); |
| KIND_1(LVScopeKind, IsCatchBlock, IsBlock); |
| KIND_1(LVScopeKind, IsClass, IsAggregate); |
| KIND_3(LVScopeKind, IsCompileUnit, CanHaveRanges, CanHaveLines, |
| TransformName); |
| KIND_1(LVScopeKind, IsEntryPoint, IsFunction); |
| KIND(LVScopeKind, IsEnumeration); |
| KIND_2(LVScopeKind, IsFunction, CanHaveRanges, CanHaveLines); |
| KIND_1(LVScopeKind, IsFunctionType, IsFunction); |
| KIND_2(LVScopeKind, IsInlinedFunction, IsFunction, IsInlined); |
| KIND_1(LVScopeKind, IsLabel, IsFunction); |
| KIND_1(LVScopeKind, IsLexicalBlock, IsBlock); |
| KIND(LVScopeKind, IsMember); |
| KIND(LVScopeKind, IsNamespace); |
| KIND_1(LVScopeKind, IsRoot, TransformName); |
| KIND_1(LVScopeKind, IsStructure, IsAggregate); |
| KIND_1(LVScopeKind, IsSubprogram, IsFunction); |
| KIND(LVScopeKind, IsTemplate); |
| KIND(LVScopeKind, IsTemplateAlias); |
| KIND(LVScopeKind, IsTemplatePack); |
| KIND_1(LVScopeKind, IsTryBlock, IsBlock); |
| KIND_1(LVScopeKind, IsUnion, IsAggregate); |
| |
| PROPERTY(Property, HasDiscriminator); |
| PROPERTY(Property, CanHaveRanges); |
| PROPERTY(Property, CanHaveLines); |
| PROPERTY(Property, HasGlobals); |
| PROPERTY(Property, HasLocals); |
| PROPERTY(Property, HasLines); |
| PROPERTY(Property, HasScopes); |
| PROPERTY(Property, HasSymbols); |
| PROPERTY(Property, HasTypes); |
| PROPERTY(Property, IsComdat); |
| PROPERTY(Property, HasComdatScopes); |
| PROPERTY(Property, HasRanges); |
| PROPERTY(Property, AddedMissing); |
| |
| bool isCompileUnit() const override { return getIsCompileUnit(); } |
| bool isRoot() const override { return getIsRoot(); } |
| |
| const char *kind() const override; |
| |
| // Get the specific children. |
| const LVLines *getLines() const { return Lines; } |
| const LVLocations *getRanges() const { return Ranges; } |
| const LVScopes *getScopes() const { return Scopes; } |
| const LVSymbols *getSymbols() const { return Symbols; } |
| const LVTypes *getTypes() const { return Types; } |
| const LVElements *getChildren() const { return Children; } |
| |
| void addElement(LVElement *Element); |
| void addElement(LVLine *Line); |
| void addElement(LVScope *Scope); |
| void addElement(LVSymbol *Symbol); |
| void addElement(LVType *Type); |
| void addObject(LVLocation *Location); |
| void addObject(LVAddress LowerAddress, LVAddress UpperAddress); |
| void addToChildren(LVElement *Element); |
| |
| // Add the missing elements from the given 'Reference', which is the |
| // scope associated with any DW_AT_specification, DW_AT_abstract_origin. |
| void addMissingElements(LVScope *Reference); |
| |
| // Traverse the scope parent tree and the children, executing the given |
| // callback function on each element. |
| void traverseParentsAndChildren(LVObjectGetFunction GetFunction, |
| LVObjectSetFunction SetFunction); |
| |
| // Get the size of specific children. |
| size_t lineCount() const { return Lines ? Lines->size() : 0; } |
| size_t rangeCount() const { return Ranges ? Ranges->size() : 0; } |
| size_t scopeCount() const { return Scopes ? Scopes->size() : 0; } |
| size_t symbolCount() const { return Symbols ? Symbols->size() : 0; } |
| size_t typeCount() const { return Types ? Types->size() : 0; } |
| |
| // Find containing parent for the given address. |
| LVScope *outermostParent(LVAddress Address); |
| |
| // Get all the locations associated with symbols. |
| void getLocations(LVLocations &LocationList, LVValidLocation ValidLocation, |
| bool RecordInvalid = false); |
| void getRanges(LVLocations &LocationList, LVValidLocation ValidLocation, |
| bool RecordInvalid = false); |
| void getRanges(LVRange &RangeList); |
| |
| unsigned getCoverageFactor() const { return CoverageFactor; } |
| |
| Error doPrint(bool Split, bool Match, bool Print, raw_ostream &OS, |
| bool Full = true) const override; |
| // Sort the logical elements using the criteria specified by the |
| // command line option '--output-sort'. |
| void sort(); |
| |
| // Get template parameter types. |
| bool getTemplateParameterTypes(LVTypes &Params); |
| |
| // DW_AT_specification, DW_AT_abstract_origin, DW_AT_extension. |
| virtual LVScope *getReference() const { return nullptr; } |
| |
| LVScope *getCompileUnitParent() const override { |
| return LVElement::getCompileUnitParent(); |
| } |
| |
| // Follow a chain of references given by DW_AT_abstract_origin and/or |
| // DW_AT_specification and update the scope name. |
| StringRef resolveReferencesChain(); |
| |
| bool removeElement(LVElement *Element) override; |
| void updateLevel(LVScope *Parent, bool Moved) override; |
| |
| void resolve() override; |
| void resolveName() override; |
| void resolveReferences() override; |
| |
| // Return the chain of parents as a string. |
| void getQualifiedName(std::string &QualifiedName) const; |
| // Encode the template arguments. |
| void encodeTemplateArguments(std::string &Name) const; |
| void encodeTemplateArguments(std::string &Name, const LVTypes *Types) const; |
| |
| void resolveElements(); |
| |
| // Iterate through the 'References' set and check that all its elements |
| // are present in the 'Targets' set. For a missing element, mark its |
| // parents as missing. |
| static void markMissingParents(const LVScopes *References, |
| const LVScopes *Targets, |
| bool TraverseChildren); |
| |
| // Checks if the current scope is contained within the target scope. |
| // Depending on the result, the callback may be performed. |
| virtual void markMissingParents(const LVScope *Target, bool TraverseChildren); |
| |
| // Returns true if the current scope and the given 'Scope' have the |
| // same number of children. |
| virtual bool equalNumberOfChildren(const LVScope *Scope) const; |
| |
| // Returns true if current scope is logically equal to the given 'Scope'. |
| virtual bool equals(const LVScope *Scope) const; |
| |
| // Returns true if the given 'References' are logically equal to the |
| // given 'Targets'. |
| static bool equals(const LVScopes *References, const LVScopes *Targets); |
| |
| // For the given 'Scopes' returns a scope that is logically equal |
| // to the current scope; otherwise 'nullptr'. |
| virtual LVScope *findEqualScope(const LVScopes *Scopes) const; |
| |
| // Report the current scope as missing or added during comparison. |
| void report(LVComparePass Pass) override; |
| |
| static LVScopeDispatch &getDispatch() { return Dispatch; } |
| |
| void print(raw_ostream &OS, bool Full = true) const override; |
| void printExtra(raw_ostream &OS, bool Full = true) const override; |
| virtual void printWarnings(raw_ostream &OS, bool Full = true) const {} |
| virtual void printMatchedElements(raw_ostream &OS, bool UseMatchedElements) {} |
| |
| #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) |
| void dump() const override { print(dbgs()); } |
| #endif |
| }; |
| |
| // Class to represent a DWARF Union/Structure/Class. |
| class LVScopeAggregate final : public LVScope { |
| LVScope *Reference = nullptr; // DW_AT_specification, DW_AT_abstract_origin. |
| size_t EncodedArgsIndex = 0; // Template encoded arguments. |
| |
| public: |
| LVScopeAggregate() : LVScope() {} |
| LVScopeAggregate(const LVScopeAggregate &) = delete; |
| LVScopeAggregate &operator=(const LVScopeAggregate &) = delete; |
| ~LVScopeAggregate() = default; |
| |
| // DW_AT_specification, DW_AT_abstract_origin. |
| LVScope *getReference() const override { return Reference; } |
| void setReference(LVScope *Scope) override { |
| Reference = Scope; |
| setHasReference(); |
| } |
| void setReference(LVElement *Element) override { |
| setReference(static_cast<LVScope *>(Element)); |
| } |
| |
| StringRef getEncodedArgs() const override { |
| return getStringPool().getString(EncodedArgsIndex); |
| } |
| void setEncodedArgs(StringRef EncodedArgs) override { |
| EncodedArgsIndex = getStringPool().getIndex(EncodedArgs); |
| } |
| |
| // Returns true if current scope is logically equal to the given 'Scope'. |
| bool equals(const LVScope *Scope) const override; |
| |
| // For the given 'Scopes' returns a scope that is logically equal |
| // to the current scope; otherwise 'nullptr'. |
| LVScope *findEqualScope(const LVScopes *Scopes) const override; |
| |
| void printExtra(raw_ostream &OS, bool Full = true) const override; |
| }; |
| |
| // Class to represent a DWARF Template alias. |
| class LVScopeAlias final : public LVScope { |
| public: |
| LVScopeAlias() : LVScope() { |
| setIsTemplateAlias(); |
| setIsTemplate(); |
| } |
| LVScopeAlias(const LVScopeAlias &) = delete; |
| LVScopeAlias &operator=(const LVScopeAlias &) = delete; |
| ~LVScopeAlias() = default; |
| |
| // Returns true if current scope is logically equal to the given 'Scope'. |
| bool equals(const LVScope *Scope) const override; |
| |
| void printExtra(raw_ostream &OS, bool Full = true) const override; |
| }; |
| |
| // Class to represent a DWARF array (DW_TAG_array_type). |
| class LVScopeArray final : public LVScope { |
| public: |
| LVScopeArray() : LVScope() { setIsArray(); } |
| LVScopeArray(const LVScopeArray &) = delete; |
| LVScopeArray &operator=(const LVScopeArray &) = delete; |
| ~LVScopeArray() = default; |
| |
| void resolveExtra() override; |
| |
| // Returns true if current scope is logically equal to the given 'Scope'. |
| bool equals(const LVScope *Scope) const override; |
| |
| void printExtra(raw_ostream &OS, bool Full = true) const override; |
| }; |
| |
| // Class to represent a DWARF Compilation Unit (CU). |
| class LVScopeCompileUnit final : public LVScope { |
| // Names (files and directories) used by the Compile Unit. |
| std::vector<size_t> Filenames; |
| |
| // As the .debug_pubnames section has been removed in DWARF5, we have a |
| // similar functionality, which is used by the decoded functions. We use |
| // the low-pc and high-pc for those scopes that are marked as public, in |
| // order to support DWARF and CodeView. |
| LVPublicNames PublicNames; |
| |
| // Toolchain producer. |
| size_t ProducerIndex = 0; |
| |
| // Compilation directory name. |
| size_t CompilationDirectoryIndex = 0; |
| |
| // Keep record of elements. They are needed at the compilation unit level |
| // to print the summary at the end of the printing. |
| LVCounter Allocated; |
| LVCounter Found; |
| LVCounter Printed; |
| |
| // Elements that match a given command line pattern. |
| LVElements MatchedElements; |
| LVScopes MatchedScopes; |
| |
| // It records the mapping between logical lines representing a debug line |
| // entry and its address in the text section. It is used to find a line |
| // giving its exact or closest address. To support comdat functions, all |
| // addresses for the same section are recorded in the same map. |
| using LVAddressToLine = std::map<LVAddress, LVLine *>; |
| LVDoubleMap<LVSectionIndex, LVAddress, LVLine *> SectionMappings; |
| |
| // DWARF Tags (Tag, Element list). |
| LVTagOffsetsMap DebugTags; |
| |
| // Offsets associated with objects being flagged as having invalid data |
| // (ranges, locations, lines zero or coverages). |
| LVOffsetElementMap WarningOffsets; |
| |
| // Symbols with invalid locations. (Symbol, Location List). |
| LVOffsetLocationsMap InvalidLocations; |
| |
| // Symbols with invalid coverage values. |
| LVOffsetSymbolMap InvalidCoverages; |
| |
| // Scopes with invalid ranges (Scope, Range list). |
| LVOffsetLocationsMap InvalidRanges; |
| |
| // Scopes with lines zero (Scope, Line list). |
| LVOffsetLinesMap LinesZero; |
| |
| // Record scopes contribution in bytes to the debug information. |
| using LVSizesMap = std::map<const LVScope *, LVOffset>; |
| LVSizesMap Sizes; |
| LVOffset CUContributionSize = 0; |
| |
| // Helper function to add an invalid location/range. |
| void addInvalidLocationOrRange(LVLocation *Location, LVElement *Element, |
| LVOffsetLocationsMap *Map) { |
| LVOffset Offset = Element->getOffset(); |
| addInvalidOffset(Offset, Element); |
| addItem<LVOffsetLocationsMap, LVLocations, LVOffset, LVLocation *>( |
| Map, Offset, Location); |
| } |
| |
| // Record scope sizes indexed by lexical level. |
| // Setting an initial size that will cover a very deep nested scopes. |
| const size_t TotalInitialSize = 8; |
| using LVTotalsEntry = std::pair<unsigned, float>; |
| SmallVector<LVTotalsEntry> Totals; |
| // Maximum seen lexical level. It is used to control how many entries |
| // in the 'Totals' vector are valid values. |
| LVLevel MaxSeenLevel = 0; |
| |
| // Get the line located at the given address. |
| LVLine *lineLowerBound(LVAddress Address, LVScope *Scope) const; |
| LVLine *lineUpperBound(LVAddress Address, LVScope *Scope) const; |
| |
| void printScopeSize(const LVScope *Scope, raw_ostream &OS); |
| void printScopeSize(const LVScope *Scope, raw_ostream &OS) const { |
| (const_cast<LVScopeCompileUnit *>(this))->printScopeSize(Scope, OS); |
| } |
| void printTotals(raw_ostream &OS) const; |
| |
| protected: |
| void printSizes(raw_ostream &OS) const override; |
| void printSummary(raw_ostream &OS) const override; |
| |
| public: |
| LVScopeCompileUnit() : LVScope(), Totals(TotalInitialSize, {0, 0.0}) { |
| setIsCompileUnit(); |
| } |
| LVScopeCompileUnit(const LVScopeCompileUnit &) = delete; |
| LVScopeCompileUnit &operator=(const LVScopeCompileUnit &) = delete; |
| ~LVScopeCompileUnit() { |
| deleteList<LVTagOffsetsMap>(DebugTags); |
| deleteList<LVOffsetLocationsMap>(InvalidLocations); |
| deleteList<LVOffsetLocationsMap>(InvalidRanges); |
| deleteList<LVOffsetLinesMap>(LinesZero); |
| } |
| |
| LVScope *getCompileUnitParent() const override { |
| return static_cast<LVScope *>(const_cast<LVScopeCompileUnit *>(this)); |
| } |
| |
| // Add line to address mapping. |
| void addMapping(LVLine *Line, LVSectionIndex SectionIndex); |
| LVLineRange lineRange(LVLocation *Location) const; |
| |
| LVNameInfo NameNone = {UINT64_MAX, 0}; |
| void addPublicName(LVScope *Scope, LVAddress LowPC, LVAddress HighPC) { |
| PublicNames.emplace(std::piecewise_construct, std::forward_as_tuple(Scope), |
| std::forward_as_tuple(LowPC, HighPC - LowPC)); |
| } |
| const LVNameInfo &findPublicName(LVScope *Scope) { |
| LVPublicNames::iterator Iter = PublicNames.find(Scope); |
| return (Iter != PublicNames.end()) ? Iter->second : NameNone; |
| } |
| const LVPublicNames &getPublicNames() const { return PublicNames; } |
| |
| // The base address of the scope for any of the debugging information |
| // entries listed, is given by either the DW_AT_low_pc attribute or the |
| // first address in the first range entry in the list of ranges given by |
| // the DW_AT_ranges attribute. |
| LVAddress getBaseAddress() const { |
| return Ranges ? Ranges->front()->getLowerAddress() : 0; |
| } |
| |
| StringRef getCompilationDirectory() const { |
| return getStringPool().getString(CompilationDirectoryIndex); |
| } |
| void setCompilationDirectory(StringRef CompilationDirectory) { |
| CompilationDirectoryIndex = getStringPool().getIndex(CompilationDirectory); |
| } |
| |
| StringRef getFilename(size_t Index) const; |
| void addFilename(StringRef Name) { |
| Filenames.push_back(getStringPool().getIndex(Name)); |
| } |
| |
| StringRef getProducer() const override { |
| return getStringPool().getString(ProducerIndex); |
| } |
| void setProducer(StringRef ProducerName) override { |
| ProducerIndex = getStringPool().getIndex(ProducerName); |
| } |
| |
| // Record DWARF tags. |
| void addDebugTag(dwarf::Tag Target, LVOffset Offset); |
| // Record elements with invalid offsets. |
| void addInvalidOffset(LVOffset Offset, LVElement *Element); |
| // Record symbols with invalid coverage values. |
| void addInvalidCoverage(LVSymbol *Symbol); |
| // Record symbols with invalid locations. |
| void addInvalidLocation(LVLocation *Location); |
| // Record scopes with invalid ranges. |
| void addInvalidRange(LVLocation *Location); |
| // Record line zero. |
| void addLineZero(LVLine *Line); |
| |
| const LVTagOffsetsMap &getDebugTags() const { return DebugTags; } |
| const LVOffsetElementMap &getWarningOffsets() const { return WarningOffsets; } |
| const LVOffsetLocationsMap &getInvalidLocations() const { |
| return InvalidLocations; |
| } |
| const LVOffsetSymbolMap &getInvalidCoverages() const { |
| return InvalidCoverages; |
| } |
| const LVOffsetLocationsMap &getInvalidRanges() const { return InvalidRanges; } |
| const LVOffsetLinesMap &getLinesZero() const { return LinesZero; } |
| |
| // Process ranges, locations and calculate coverage. |
| void processRangeLocationCoverage( |
| LVValidLocation ValidLocation = &LVLocation::validateRanges); |
| |
| // Add matched element. |
| void addMatched(LVElement *Element) { MatchedElements.push_back(Element); } |
| void addMatched(LVScope *Scope) { MatchedScopes.push_back(Scope); } |
| void propagatePatternMatch(); |
| |
| const LVElements &getMatchedElements() const { return MatchedElements; } |
| const LVScopes &getMatchedScopes() const { return MatchedScopes; } |
| |
| void printLocalNames(raw_ostream &OS, bool Full = true) const; |
| void printSummary(raw_ostream &OS, const LVCounter &Counter, |
| const char *Header) const; |
| |
| void incrementPrintedLines(); |
| void incrementPrintedScopes(); |
| void incrementPrintedSymbols(); |
| void incrementPrintedTypes(); |
| |
| // Values are used by '--summary' option (allocated). |
| void increment(LVLine *Line); |
| void increment(LVScope *Scope); |
| void increment(LVSymbol *Symbol); |
| void increment(LVType *Type); |
| |
| // A new element has been added to the scopes tree. Take the following steps: |
| // Increase the added element counters, for printing summary. |
| // During comparison notify the Reader of the new element. |
| void addedElement(LVLine *Line); |
| void addedElement(LVScope *Scope); |
| void addedElement(LVSymbol *Symbol); |
| void addedElement(LVType *Type); |
| |
| void addSize(LVScope *Scope, LVOffset Lower, LVOffset Upper); |
| |
| // Returns true if current scope is logically equal to the given 'Scope'. |
| bool equals(const LVScope *Scope) const override; |
| |
| void print(raw_ostream &OS, bool Full = true) const override; |
| void printExtra(raw_ostream &OS, bool Full = true) const override; |
| void printWarnings(raw_ostream &OS, bool Full = true) const override; |
| void printMatchedElements(raw_ostream &OS, bool UseMatchedElements) override; |
| }; |
| |
| // Class to represent a DWARF enumerator (DW_TAG_enumeration_type). |
| class LVScopeEnumeration final : public LVScope { |
| public: |
| LVScopeEnumeration() : LVScope() { setIsEnumeration(); } |
| LVScopeEnumeration(const LVScopeEnumeration &) = delete; |
| LVScopeEnumeration &operator=(const LVScopeEnumeration &) = delete; |
| ~LVScopeEnumeration() = default; |
| |
| // Returns true if current scope is logically equal to the given 'Scope'. |
| bool equals(const LVScope *Scope) const override; |
| |
| void printExtra(raw_ostream &OS, bool Full = true) const override; |
| }; |
| |
| // Class to represent a DWARF formal parameter pack |
| // (DW_TAG_GNU_formal_parameter_pack). |
| class LVScopeFormalPack final : public LVScope { |
| public: |
| LVScopeFormalPack() : LVScope() { setIsTemplatePack(); } |
| LVScopeFormalPack(const LVScopeFormalPack &) = delete; |
| LVScopeFormalPack &operator=(const LVScopeFormalPack &) = delete; |
| ~LVScopeFormalPack() = default; |
| |
| // Returns true if current scope is logically equal to the given 'Scope'. |
| bool equals(const LVScope *Scope) const override; |
| |
| void printExtra(raw_ostream &OS, bool Full = true) const override; |
| }; |
| |
| // Class to represent a DWARF Function. |
| class LVScopeFunction : public LVScope { |
| LVScope *Reference = nullptr; // DW_AT_specification, DW_AT_abstract_origin. |
| size_t LinkageNameIndex = 0; // Function DW_AT_linkage_name attribute. |
| size_t EncodedArgsIndex = 0; // Template encoded arguments. |
| |
| public: |
| LVScopeFunction() : LVScope() {} |
| LVScopeFunction(const LVScopeFunction &) = delete; |
| LVScopeFunction &operator=(const LVScopeFunction &) = delete; |
| virtual ~LVScopeFunction() = default; |
| |
| // DW_AT_specification, DW_AT_abstract_origin. |
| LVScope *getReference() const override { return Reference; } |
| void setReference(LVScope *Scope) override { |
| Reference = Scope; |
| setHasReference(); |
| } |
| void setReference(LVElement *Element) override { |
| setReference(static_cast<LVScope *>(Element)); |
| } |
| |
| StringRef getEncodedArgs() const override { |
| return getStringPool().getString(EncodedArgsIndex); |
| } |
| void setEncodedArgs(StringRef EncodedArgs) override { |
| EncodedArgsIndex = getStringPool().getIndex(EncodedArgs); |
| } |
| |
| void setLinkageName(StringRef LinkageName) override { |
| LinkageNameIndex = getStringPool().getIndex(LinkageName); |
| } |
| StringRef getLinkageName() const override { |
| return getStringPool().getString(LinkageNameIndex); |
| } |
| size_t getLinkageNameIndex() const override { return LinkageNameIndex; } |
| |
| void setName(StringRef ObjectName) override; |
| |
| void resolveExtra() override; |
| void resolveReferences() override; |
| |
| // Returns true if current scope is logically equal to the given 'Scope'. |
| bool equals(const LVScope *Scope) const override; |
| |
| // For the given 'Scopes' returns a scope that is logically equal |
| // to the current scope; otherwise 'nullptr'. |
| LVScope *findEqualScope(const LVScopes *Scopes) const override; |
| |
| void printExtra(raw_ostream &OS, bool Full = true) const override; |
| }; |
| |
| // Class to represent a DWARF inlined function. |
| class LVScopeFunctionInlined final : public LVScopeFunction { |
| size_t CallFilenameIndex = 0; |
| uint32_t CallLineNumber = 0; |
| uint32_t Discriminator = 0; |
| |
| public: |
| LVScopeFunctionInlined() : LVScopeFunction() { setIsInlinedFunction(); } |
| LVScopeFunctionInlined(const LVScopeFunctionInlined &) = delete; |
| LVScopeFunctionInlined &operator=(const LVScopeFunctionInlined &) = delete; |
| ~LVScopeFunctionInlined() = default; |
| |
| uint32_t getDiscriminator() const override { return Discriminator; } |
| void setDiscriminator(uint32_t Value) override { |
| Discriminator = Value; |
| setHasDiscriminator(); |
| } |
| |
| uint32_t getCallLineNumber() const override { return CallLineNumber; } |
| void setCallLineNumber(uint32_t Number) override { CallLineNumber = Number; } |
| size_t getCallFilenameIndex() const override { return CallFilenameIndex; } |
| void setCallFilenameIndex(size_t Index) override { |
| CallFilenameIndex = Index; |
| } |
| |
| // Line number for display; in the case of Inlined Functions, we use the |
| // DW_AT_call_line attribute; otherwise use DW_AT_decl_line attribute. |
| std::string lineNumberAsString(bool ShowZero = false) const override { |
| return lineAsString(getCallLineNumber(), getDiscriminator(), ShowZero); |
| } |
| |
| void resolveExtra() override; |
| |
| // Returns true if current scope is logically equal to the given 'Scope'. |
| bool equals(const LVScope *Scope) const override; |
| |
| // For the given 'Scopes' returns a scope that is logically equal |
| // to the current scope; otherwise 'nullptr'. |
| LVScope *findEqualScope(const LVScopes *Scopes) const override; |
| |
| void printExtra(raw_ostream &OS, bool Full = true) const override; |
| }; |
| |
| // Class to represent a DWARF subroutine type. |
| class LVScopeFunctionType final : public LVScopeFunction { |
| public: |
| LVScopeFunctionType() : LVScopeFunction() { setIsFunctionType(); } |
| LVScopeFunctionType(const LVScopeFunctionType &) = delete; |
| LVScopeFunctionType &operator=(const LVScopeFunctionType &) = delete; |
| ~LVScopeFunctionType() = default; |
| |
| void resolveExtra() override; |
| }; |
| |
| // Class to represent a DWARF Namespace. |
| class LVScopeNamespace final : public LVScope { |
| LVScope *Reference = nullptr; // Reference to DW_AT_extension attribute. |
| |
| public: |
| LVScopeNamespace() : LVScope() { setIsNamespace(); } |
| LVScopeNamespace(const LVScopeNamespace &) = delete; |
| LVScopeNamespace &operator=(const LVScopeNamespace &) = delete; |
| ~LVScopeNamespace() = default; |
| |
| // Access DW_AT_extension reference. |
| LVScope *getReference() const override { return Reference; } |
| void setReference(LVScope *Scope) override { |
| Reference = Scope; |
| setHasReference(); |
| } |
| void setReference(LVElement *Element) override { |
| setReference(static_cast<LVScope *>(Element)); |
| } |
| |
| // Returns true if current scope is logically equal to the given 'Scope'. |
| bool equals(const LVScope *Scope) const override; |
| |
| // For the given 'Scopes' returns a scope that is logically equal |
| // to the current scope; otherwise 'nullptr'. |
| LVScope *findEqualScope(const LVScopes *Scopes) const override; |
| |
| void printExtra(raw_ostream &OS, bool Full = true) const override; |
| }; |
| |
| // Class to represent the binary file being analyzed. |
| class LVScopeRoot final : public LVScope { |
| size_t FileFormatNameIndex = 0; |
| |
| public: |
| LVScopeRoot() : LVScope() { setIsRoot(); } |
| LVScopeRoot(const LVScopeRoot &) = delete; |
| LVScopeRoot &operator=(const LVScopeRoot &) = delete; |
| ~LVScopeRoot() = default; |
| |
| StringRef getFileFormatName() const { |
| return getStringPool().getString(FileFormatNameIndex); |
| } |
| void setFileFormatName(StringRef FileFormatName) { |
| FileFormatNameIndex = getStringPool().getIndex(FileFormatName); |
| } |
| |
| // Process the collected location, ranges and calculate coverage. |
| void processRangeInformation(); |
| |
| // Returns true if current scope is logically equal to the given 'Scope'. |
| bool equals(const LVScope *Scope) const override; |
| |
| void print(raw_ostream &OS, bool Full = true) const override; |
| void printExtra(raw_ostream &OS, bool Full = true) const override; |
| Error doPrintMatches(bool Split, raw_ostream &OS, |
| bool UseMatchedElements) const; |
| }; |
| |
| // Class to represent a DWARF template parameter pack |
| // (DW_TAG_GNU_template_parameter_pack). |
| class LVScopeTemplatePack final : public LVScope { |
| public: |
| LVScopeTemplatePack() : LVScope() { setIsTemplatePack(); } |
| LVScopeTemplatePack(const LVScopeTemplatePack &) = delete; |
| LVScopeTemplatePack &operator=(const LVScopeTemplatePack &) = delete; |
| ~LVScopeTemplatePack() = default; |
| |
| // Returns true if current scope is logically equal to the given 'Scope'. |
| bool equals(const LVScope *Scope) const override; |
| |
| void printExtra(raw_ostream &OS, bool Full = true) const override; |
| }; |
| |
| } // end namespace logicalview |
| } // end namespace llvm |
| |
| #endif // LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVSCOPE_H |