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