1 //===-- LVElement.h ---------------------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file defines the LVElement class, which is used to describe a debug
10 // information element.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVELEMENT_H
15 #define LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVELEMENT_H
16 
17 #include "llvm/DebugInfo/LogicalView/Core/LVObject.h"
18 #include "llvm/Support/Casting.h"
19 #include <map>
20 #include <set>
21 #include <vector>
22 
23 namespace llvm {
24 namespace logicalview {
25 
26 // RTTI Subclasses ID.
27 enum class LVSubclassID : unsigned char {
28   LV_ELEMENT,
29   LV_LINE_FIRST,
30   LV_LINE,
31   LV_LINE_DEBUG,
32   LV_LINE_ASSEMBLER,
33   LV_LINE_LAST,
34   lV_SCOPE_FIRST,
35   LV_SCOPE,
36   LV_SCOPE_AGGREGATE,
37   LV_SCOPE_ALIAS,
38   LV_SCOPE_ARRAY,
39   LV_SCOPE_COMPILE_UNIT,
40   LV_SCOPE_ENUMERATION,
41   LV_SCOPE_FORMAL_PACK,
42   LV_SCOPE_FUNCTION,
43   LV_SCOPE_FUNCTION_INLINED,
44   LV_SCOPE_FUNCTION_TYPE,
45   LV_SCOPE_NAMESPACE,
46   LV_SCOPE_ROOT,
47   LV_SCOPE_TEMPLATE_PACK,
48   LV_SCOPE_LAST,
49   LV_SYMBOL_FIRST,
50   LV_SYMBOL,
51   LV_SYMBOL_LAST,
52   LV_TYPE_FIRST,
53   LV_TYPE,
54   LV_TYPE_DEFINITION,
55   LV_TYPE_ENUMERATOR,
56   LV_TYPE_IMPORT,
57   LV_TYPE_PARAM,
58   LV_TYPE_SUBRANGE,
59   LV_TYPE_LAST
60 };
61 
62 enum class LVElementKind { Discarded, Global, Optimized, LastEntry };
63 using LVElementKindSet = std::set<LVElementKind>;
64 using LVElementDispatch = std::map<LVElementKind, LVElementGetFunction>;
65 using LVElementRequest = std::vector<LVElementGetFunction>;
66 
67 class LVElement : public LVObject {
68   enum class Property {
69     IsLine,   // A logical line.
70     IsScope,  // A logical scope.
71     IsSymbol, // A logical symbol.
72     IsType,   // A logical type.
73     IsEnumClass,
74     IsExternal,
75     HasType,
76     HasAugmentedName,
77     IsTypedefReduced,
78     IsArrayResolved,
79     IsMemberPointerResolved,
80     IsTemplateResolved,
81     IsInlined,
82     IsInlinedAbstract,
83     InvalidFilename,
84     HasReference,
85     HasReferenceAbstract,
86     HasReferenceExtension,
87     HasReferenceSpecification,
88     QualifiedResolved,
89     IncludeInPrint,
90     IsStatic,
91     TransformName,
92     IsScoped,        // CodeView local type.
93     IsNested,        // CodeView nested type.
94     IsScopedAlready, // CodeView nested type inserted in correct scope.
95     IsArtificial,
96     IsReferencedType,
97     IsSystem,
98     OffsetFromTypeIndex,
99     IsAnonymous,
100     LastEntry
101   };
102   // Typed bitvector with properties for this element.
103   LVProperties<Property> Properties;
104   static LVElementDispatch Dispatch;
105 
106   /// RTTI.
107   const LVSubclassID SubclassID;
108 
109   // Indexes in the String Pool.
110   size_t NameIndex = 0;
111   size_t QualifiedNameIndex = 0;
112   size_t FilenameIndex = 0;
113 
114   uint16_t AccessibilityCode : 2; // DW_AT_accessibility.
115   uint16_t InlineCode : 2;        // DW_AT_inline.
116   uint16_t VirtualityCode : 2;    // DW_AT_virtuality.
117 
118   // The given Specification points to an element that is connected via the
119   // DW_AT_specification, DW_AT_abstract_origin or DW_AT_extension attribute.
120   void setFileLine(LVElement *Specification);
121 
122   // Get the qualified name that include its parents name.
123   void resolveQualifiedName();
124 
125 protected:
126   // Type of this element.
127   LVElement *ElementType = nullptr;
128 
129   // Print the FileName Index.
130   void printFileIndex(raw_ostream &OS, bool Full = true) const override;
131 
132 public:
LVElement(LVSubclassID ID)133   LVElement(LVSubclassID ID)
134       : LVObject(), SubclassID(ID), AccessibilityCode(0), InlineCode(0),
135         VirtualityCode(0) {}
136   LVElement(const LVElement &) = delete;
137   LVElement &operator=(const LVElement &) = delete;
138   virtual ~LVElement() = default;
139 
getSubclassID()140   LVSubclassID getSubclassID() const { return SubclassID; }
141 
142   PROPERTY(Property, IsLine);
143   PROPERTY(Property, IsScope);
144   PROPERTY(Property, IsSymbol);
145   PROPERTY(Property, IsType);
146   PROPERTY(Property, IsEnumClass);
147   PROPERTY(Property, IsExternal);
148   PROPERTY(Property, HasType);
149   PROPERTY(Property, HasAugmentedName);
150   PROPERTY(Property, IsTypedefReduced);
151   PROPERTY(Property, IsArrayResolved);
152   PROPERTY(Property, IsMemberPointerResolved);
153   PROPERTY(Property, IsTemplateResolved);
154   PROPERTY(Property, IsInlined);
155   PROPERTY(Property, IsInlinedAbstract);
156   PROPERTY(Property, InvalidFilename);
157   PROPERTY(Property, HasReference);
158   PROPERTY(Property, HasReferenceAbstract);
159   PROPERTY(Property, HasReferenceExtension);
160   PROPERTY(Property, HasReferenceSpecification);
161   PROPERTY(Property, QualifiedResolved);
162   PROPERTY(Property, IncludeInPrint);
163   PROPERTY(Property, IsStatic);
164   PROPERTY(Property, TransformName);
165   PROPERTY(Property, IsScoped);
166   PROPERTY(Property, IsNested);
167   PROPERTY(Property, IsScopedAlready);
168   PROPERTY(Property, IsArtificial);
169   PROPERTY(Property, IsReferencedType);
170   PROPERTY(Property, IsSystem);
171   PROPERTY(Property, OffsetFromTypeIndex);
172   PROPERTY(Property, IsAnonymous);
173 
isNamed()174   bool isNamed() const override { return NameIndex != 0; }
isTyped()175   bool isTyped() const override { return ElementType != nullptr; }
isFiled()176   bool isFiled() const override { return FilenameIndex != 0; }
177 
178   // The Element class type can point to a Type or Scope.
getIsKindType()179   bool getIsKindType() const { return ElementType && ElementType->getIsType(); }
getIsKindScope()180   bool getIsKindScope() const {
181     return ElementType && ElementType->getIsScope();
182   }
183 
getName()184   StringRef getName() const override {
185     return getStringPool().getString(NameIndex);
186   }
187   void setName(StringRef ElementName) override;
188 
189   // Get pathname associated with the Element.
getPathname()190   StringRef getPathname() const {
191     return getStringPool().getString(getFilenameIndex());
192   }
193 
194   // Set filename associated with the Element.
195   void setFilename(StringRef Filename);
196 
197   // Set the Element qualified name.
setQualifiedName(StringRef Name)198   void setQualifiedName(StringRef Name) {
199     QualifiedNameIndex = getStringPool().getIndex(Name);
200   }
getQualifiedName()201   StringRef getQualifiedName() const {
202     return getStringPool().getString(QualifiedNameIndex);
203   }
204 
getNameIndex()205   size_t getNameIndex() const { return NameIndex; }
getQualifiedNameIndex()206   size_t getQualifiedNameIndex() const { return QualifiedNameIndex; }
207 
setInnerComponent()208   void setInnerComponent() { setInnerComponent(getName()); }
209   void setInnerComponent(StringRef Name);
210 
211   // Element type name.
212   StringRef getTypeName() const;
213 
getProducer()214   virtual StringRef getProducer() const { return StringRef(); }
setProducer(StringRef ProducerName)215   virtual void setProducer(StringRef ProducerName) {}
216 
isCompileUnit()217   virtual bool isCompileUnit() const { return false; }
isRoot()218   virtual bool isRoot() const { return false; }
219 
setReference(LVElement * Element)220   virtual void setReference(LVElement *Element) {}
setReference(LVScope * Scope)221   virtual void setReference(LVScope *Scope) {}
setReference(LVSymbol * Symbol)222   virtual void setReference(LVSymbol *Symbol) {}
setReference(LVType * Type)223   virtual void setReference(LVType *Type) {}
224 
setLinkageName(StringRef LinkageName)225   virtual void setLinkageName(StringRef LinkageName) {}
getLinkageName()226   virtual StringRef getLinkageName() const { return StringRef(); }
getLinkageNameIndex()227   virtual size_t getLinkageNameIndex() const { return 0; }
228 
getCallLineNumber()229   virtual uint32_t getCallLineNumber() const { return 0; }
setCallLineNumber(uint32_t Number)230   virtual void setCallLineNumber(uint32_t Number) {}
getCallFilenameIndex()231   virtual size_t getCallFilenameIndex() const { return 0; }
setCallFilenameIndex(size_t Index)232   virtual void setCallFilenameIndex(size_t Index) {}
getFilenameIndex()233   size_t getFilenameIndex() const { return FilenameIndex; }
setFilenameIndex(size_t Index)234   void setFilenameIndex(size_t Index) { FilenameIndex = Index; }
235 
236   // Set the File location for the Element.
237   void setFile(LVElement *Reference = nullptr);
238 
isBase()239   virtual bool isBase() const { return false; }
isTemplateParam()240   virtual bool isTemplateParam() const { return false; }
241 
getBitSize()242   virtual uint32_t getBitSize() const { return 0; }
setBitSize(uint32_t Size)243   virtual void setBitSize(uint32_t Size) {}
244 
getCount()245   virtual int64_t getCount() const { return 0; }
setCount(int64_t Value)246   virtual void setCount(int64_t Value) {}
getLowerBound()247   virtual int64_t getLowerBound() const { return 0; }
setLowerBound(int64_t Value)248   virtual void setLowerBound(int64_t Value) {}
getUpperBound()249   virtual int64_t getUpperBound() const { return 0; }
setUpperBound(int64_t Value)250   virtual void setUpperBound(int64_t Value) {}
getBounds()251   virtual std::pair<unsigned, unsigned> getBounds() const { return {}; }
setBounds(unsigned Lower,unsigned Upper)252   virtual void setBounds(unsigned Lower, unsigned Upper) {}
253 
254   // Access DW_AT_GNU_discriminator attribute.
getDiscriminator()255   virtual uint32_t getDiscriminator() const { return 0; }
setDiscriminator(uint32_t Value)256   virtual void setDiscriminator(uint32_t Value) {}
257 
258   // Process the values for a DW_TAG_enumerator.
getValue()259   virtual StringRef getValue() const { return {}; }
setValue(StringRef Value)260   virtual void setValue(StringRef Value) {}
getValueIndex()261   virtual size_t getValueIndex() const { return 0; }
262 
263   // DWARF Accessibility Codes.
getAccessibilityCode()264   uint32_t getAccessibilityCode() const { return AccessibilityCode; }
setAccessibilityCode(uint32_t Access)265   void setAccessibilityCode(uint32_t Access) { AccessibilityCode = Access; }
266   StringRef
267   accessibilityString(uint32_t Access = dwarf::DW_ACCESS_private) const;
268 
269   // CodeView Accessibility Codes.
270   std::optional<uint32_t> getAccessibilityCode(codeview::MemberAccess Access);
setAccessibilityCode(codeview::MemberAccess Access)271   void setAccessibilityCode(codeview::MemberAccess Access) {
272     if (std::optional<uint32_t> Code = getAccessibilityCode(Access))
273       AccessibilityCode = Code.value();
274   }
275 
276   // DWARF Inline Codes.
getInlineCode()277   uint32_t getInlineCode() const { return InlineCode; }
setInlineCode(uint32_t Code)278   void setInlineCode(uint32_t Code) { InlineCode = Code; }
279   StringRef inlineCodeString(uint32_t Code) const;
280 
281   // DWARF Virtuality Codes.
getVirtualityCode()282   uint32_t getVirtualityCode() const { return VirtualityCode; }
setVirtualityCode(uint32_t Virtuality)283   void setVirtualityCode(uint32_t Virtuality) { VirtualityCode = Virtuality; }
284   StringRef
285   virtualityString(uint32_t Virtuality = dwarf::DW_VIRTUALITY_none) const;
286 
287   // CodeView Virtuality Codes.
288   std::optional<uint32_t> getVirtualityCode(codeview::MethodKind Virtuality);
setVirtualityCode(codeview::MethodKind Virtuality)289   void setVirtualityCode(codeview::MethodKind Virtuality) {
290     if (std::optional<uint32_t> Code = getVirtualityCode(Virtuality))
291       VirtualityCode = Code.value();
292   }
293 
294   // DWARF Extern Codes.
295   StringRef externalString() const;
296 
getType()297   LVElement *getType() const { return ElementType; }
298   LVType *getTypeAsType() const;
299   LVScope *getTypeAsScope() const;
300 
301   void setType(LVElement *Element = nullptr) {
302     ElementType = Element;
303     if (Element) {
304       setHasType();
305       Element->setIsReferencedType();
306     }
307   }
308 
309   // Set the type for the element, handling template parameters.
310   void setGenericType(LVElement *Element);
311 
getTypeQualifiedName()312   StringRef getTypeQualifiedName() const {
313     return ElementType ? ElementType->getQualifiedName() : "";
314   }
315 
316   StringRef typeAsString() const;
317   std::string typeOffsetAsString() const;
318   std::string discriminatorAsString() const;
319 
320   LVScope *traverseParents(LVScopeGetFunction GetFunction) const;
321 
322   LVScope *getFunctionParent() const;
323   virtual LVScope *getCompileUnitParent() const;
324 
325   // Print any referenced element.
326   void printReference(raw_ostream &OS, bool Full, LVElement *Parent) const;
327 
328   // Print the linkage name (Symbols and functions).
329   void printLinkageName(raw_ostream &OS, bool Full, LVElement *Parent,
330                         LVScope *Scope) const;
331   void printLinkageName(raw_ostream &OS, bool Full, LVElement *Parent) const;
332 
333   // Generate the full name for the Element.
334   void resolveFullname(LVElement *BaseType, StringRef Name = emptyString());
335 
336   // Generate a name for unnamed elements.
337   void generateName(std::string &Prefix) const;
338   void generateName();
339 
removeElement(LVElement * Element)340   virtual bool removeElement(LVElement *Element) { return false; }
341   virtual void updateLevel(LVScope *Parent, bool Moved = false);
342 
343   // During the parsing of the debug information, the logical elements are
344   // created with information extracted from its description entries (DIE).
345   // But they are not complete for the logical view concept. A second pass
346   // is executed in order to collect their additional information.
347   // The following functions 'resolve' some of their properties, such as
348   // name, references, parents, extra information based on the element kind.
349   virtual void resolve();
resolveExtra()350   virtual void resolveExtra() {}
351   virtual void resolveName();
resolveReferences()352   virtual void resolveReferences() {}
353   void resolveParents();
354 
355   bool referenceMatch(const LVElement *Element) const;
356 
357   // Returns true if current element is logically equal to the given 'Element'.
358   bool equals(const LVElement *Element) const;
359 
360   // Report the current element as missing or added during comparison.
report(LVComparePass Pass)361   virtual void report(LVComparePass Pass) {}
362 
getDispatch()363   static LVElementDispatch &getDispatch() { return Dispatch; }
364 };
365 
366 } // end namespace logicalview
367 } // end namespace llvm
368 
369 #endif // LLVM_DEBUGINFO_LOGICALVIEW_CORE_LVELEMENT_H
370