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