1e28b9357SCarlos Alberto Enciso //===-- LVElement.cpp -----------------------------------------------------===// 2e28b9357SCarlos Alberto Enciso // 3e28b9357SCarlos Alberto Enciso // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4e28b9357SCarlos Alberto Enciso // See https://llvm.org/LICENSE.txt for license information. 5e28b9357SCarlos Alberto Enciso // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6e28b9357SCarlos Alberto Enciso // 7e28b9357SCarlos Alberto Enciso //===----------------------------------------------------------------------===// 8e28b9357SCarlos Alberto Enciso // 9e28b9357SCarlos Alberto Enciso // This implements the LVElement class. 10e28b9357SCarlos Alberto Enciso // 11e28b9357SCarlos Alberto Enciso //===----------------------------------------------------------------------===// 12e28b9357SCarlos Alberto Enciso 13e28b9357SCarlos Alberto Enciso #include "llvm/DebugInfo/LogicalView/Core/LVElement.h" 14e28b9357SCarlos Alberto Enciso #include "llvm/DebugInfo/LogicalView/Core/LVReader.h" 15e28b9357SCarlos Alberto Enciso #include "llvm/DebugInfo/LogicalView/Core/LVScope.h" 16e28b9357SCarlos Alberto Enciso #include "llvm/DebugInfo/LogicalView/Core/LVType.h" 17e28b9357SCarlos Alberto Enciso 18e28b9357SCarlos Alberto Enciso using namespace llvm; 19e7950fceSCarlos Alberto Enciso using namespace llvm::codeview; 20e28b9357SCarlos Alberto Enciso using namespace llvm::logicalview; 21e28b9357SCarlos Alberto Enciso 22e28b9357SCarlos Alberto Enciso #define DEBUG_TYPE "Element" 23e28b9357SCarlos Alberto Enciso 240332a8e7SCarlos Alberto Enciso LVElementDispatch LVElement::Dispatch = { 250332a8e7SCarlos Alberto Enciso {LVElementKind::Discarded, &LVElement::getIsDiscarded}, 260332a8e7SCarlos Alberto Enciso {LVElementKind::Global, &LVElement::getIsGlobalReference}, 270332a8e7SCarlos Alberto Enciso {LVElementKind::Optimized, &LVElement::getIsOptimized}}; 280332a8e7SCarlos Alberto Enciso 29e28b9357SCarlos Alberto Enciso LVType *LVElement::getTypeAsType() const { 30e28b9357SCarlos Alberto Enciso return ElementType && ElementType->getIsType() 31e28b9357SCarlos Alberto Enciso ? static_cast<LVType *>(ElementType) 32e28b9357SCarlos Alberto Enciso : nullptr; 33e28b9357SCarlos Alberto Enciso } 34e28b9357SCarlos Alberto Enciso 35e28b9357SCarlos Alberto Enciso LVScope *LVElement::getTypeAsScope() const { 36e28b9357SCarlos Alberto Enciso return ElementType && ElementType->getIsScope() 37e28b9357SCarlos Alberto Enciso ? static_cast<LVScope *>(ElementType) 38e28b9357SCarlos Alberto Enciso : nullptr; 39e28b9357SCarlos Alberto Enciso } 40e28b9357SCarlos Alberto Enciso 41e28b9357SCarlos Alberto Enciso // Set the element type. 42e28b9357SCarlos Alberto Enciso void LVElement::setGenericType(LVElement *Element) { 43e28b9357SCarlos Alberto Enciso if (!Element->isTemplateParam()) { 44e28b9357SCarlos Alberto Enciso setType(Element); 45e28b9357SCarlos Alberto Enciso return; 46e28b9357SCarlos Alberto Enciso } 47e28b9357SCarlos Alberto Enciso // For template parameters, the instance type can be a type or a scope. 48e28b9357SCarlos Alberto Enciso if (options().getAttributeArgument()) { 49e28b9357SCarlos Alberto Enciso if (Element->getIsKindType()) 50e28b9357SCarlos Alberto Enciso setType(Element->getTypeAsType()); 51e28b9357SCarlos Alberto Enciso else if (Element->getIsKindScope()) 52e28b9357SCarlos Alberto Enciso setType(Element->getTypeAsScope()); 53e28b9357SCarlos Alberto Enciso } else 54e28b9357SCarlos Alberto Enciso setType(Element); 55e28b9357SCarlos Alberto Enciso } 56e28b9357SCarlos Alberto Enciso 57e28b9357SCarlos Alberto Enciso // Discriminator as string. 58e28b9357SCarlos Alberto Enciso std::string LVElement::discriminatorAsString() const { 59e28b9357SCarlos Alberto Enciso uint32_t Discriminator = getDiscriminator(); 60e28b9357SCarlos Alberto Enciso std::string String; 61e28b9357SCarlos Alberto Enciso raw_string_ostream Stream(String); 62e28b9357SCarlos Alberto Enciso if (Discriminator && options().getAttributeDiscriminator()) 63e28b9357SCarlos Alberto Enciso Stream << "," << Discriminator; 64e28b9357SCarlos Alberto Enciso return String; 65e28b9357SCarlos Alberto Enciso } 66e28b9357SCarlos Alberto Enciso 67e28b9357SCarlos Alberto Enciso // Get the type as a string. 68e28b9357SCarlos Alberto Enciso StringRef LVElement::typeAsString() const { 69e28b9357SCarlos Alberto Enciso return getHasType() ? getTypeName() : typeVoid(); 70e28b9357SCarlos Alberto Enciso } 71e28b9357SCarlos Alberto Enciso 72e28b9357SCarlos Alberto Enciso // Get name for element type. 73e28b9357SCarlos Alberto Enciso StringRef LVElement::getTypeName() const { 74e28b9357SCarlos Alberto Enciso return ElementType ? ElementType->getName() : StringRef(); 75e28b9357SCarlos Alberto Enciso } 76e28b9357SCarlos Alberto Enciso 77e28b9357SCarlos Alberto Enciso static size_t getStringIndex(StringRef Name) { 78e28b9357SCarlos Alberto Enciso // Convert the name to Unified format ('\' have been converted into '/'). 79e28b9357SCarlos Alberto Enciso std::string Pathname(transformPath(Name)); 80e28b9357SCarlos Alberto Enciso 81e28b9357SCarlos Alberto Enciso // Depending on the --attribute=filename and --attribute=pathname command 82e28b9357SCarlos Alberto Enciso // line options, use the basename or the full pathname as the name. 83e28b9357SCarlos Alberto Enciso if (!options().getAttributePathname()) { 84e28b9357SCarlos Alberto Enciso // Get the basename by ignoring any prefix up to the last slash ('/'). 85e28b9357SCarlos Alberto Enciso StringRef Basename = Pathname; 86e28b9357SCarlos Alberto Enciso size_t Pos = Basename.rfind('/'); 87e28b9357SCarlos Alberto Enciso if (Pos != std::string::npos) 88e28b9357SCarlos Alberto Enciso Basename = Basename.substr(Pos + 1); 89e28b9357SCarlos Alberto Enciso return getStringPool().getIndex(Basename); 90e28b9357SCarlos Alberto Enciso } 91e28b9357SCarlos Alberto Enciso 92e28b9357SCarlos Alberto Enciso return getStringPool().getIndex(Pathname); 93e28b9357SCarlos Alberto Enciso } 94e28b9357SCarlos Alberto Enciso 95e28b9357SCarlos Alberto Enciso void LVElement::setName(StringRef ElementName) { 96e28b9357SCarlos Alberto Enciso // In the case of Root or Compile Unit, get index for the flatted out name. 97e28b9357SCarlos Alberto Enciso NameIndex = getTransformName() ? getStringIndex(ElementName) 98e28b9357SCarlos Alberto Enciso : getStringPool().getIndex(ElementName); 99e28b9357SCarlos Alberto Enciso } 100e28b9357SCarlos Alberto Enciso 101e28b9357SCarlos Alberto Enciso void LVElement::setFilename(StringRef Filename) { 102e28b9357SCarlos Alberto Enciso // Get index for the flattened out filename. 103e28b9357SCarlos Alberto Enciso FilenameIndex = getStringIndex(Filename); 104e28b9357SCarlos Alberto Enciso } 105e28b9357SCarlos Alberto Enciso 106e7950fceSCarlos Alberto Enciso void LVElement::setInnerComponent(StringRef Name) { 107e7950fceSCarlos Alberto Enciso if (Name.size()) { 108e7950fceSCarlos Alberto Enciso StringRef InnerComponent; 109e7950fceSCarlos Alberto Enciso std::tie(std::ignore, InnerComponent) = getInnerComponent(Name); 110e7950fceSCarlos Alberto Enciso setName(InnerComponent); 111e7950fceSCarlos Alberto Enciso } 112e7950fceSCarlos Alberto Enciso } 113e7950fceSCarlos Alberto Enciso 114e28b9357SCarlos Alberto Enciso // Return the string representation of a DIE offset. 115e28b9357SCarlos Alberto Enciso std::string LVElement::typeOffsetAsString() const { 116e28b9357SCarlos Alberto Enciso if (options().getAttributeOffset()) { 117e28b9357SCarlos Alberto Enciso LVElement *Element = getType(); 118e28b9357SCarlos Alberto Enciso return hexSquareString(Element ? Element->getOffset() : 0); 119e28b9357SCarlos Alberto Enciso } 120e28b9357SCarlos Alberto Enciso return {}; 121e28b9357SCarlos Alberto Enciso } 122e28b9357SCarlos Alberto Enciso 123e28b9357SCarlos Alberto Enciso StringRef LVElement::accessibilityString(uint32_t Access) const { 124e28b9357SCarlos Alberto Enciso uint32_t Value = getAccessibilityCode(); 125e28b9357SCarlos Alberto Enciso switch (Value ? Value : Access) { 126e28b9357SCarlos Alberto Enciso case dwarf::DW_ACCESS_public: 127e28b9357SCarlos Alberto Enciso return "public"; 128e28b9357SCarlos Alberto Enciso case dwarf::DW_ACCESS_protected: 129e28b9357SCarlos Alberto Enciso return "protected"; 130e28b9357SCarlos Alberto Enciso case dwarf::DW_ACCESS_private: 131e28b9357SCarlos Alberto Enciso return "private"; 132e28b9357SCarlos Alberto Enciso default: 133e28b9357SCarlos Alberto Enciso return StringRef(); 134e28b9357SCarlos Alberto Enciso } 135e28b9357SCarlos Alberto Enciso } 136e28b9357SCarlos Alberto Enciso 137e7950fceSCarlos Alberto Enciso std::optional<uint32_t> LVElement::getAccessibilityCode(MemberAccess Access) { 138e7950fceSCarlos Alberto Enciso switch (Access) { 139e7950fceSCarlos Alberto Enciso case MemberAccess::Private: 140e7950fceSCarlos Alberto Enciso return dwarf::DW_ACCESS_private; 141e7950fceSCarlos Alberto Enciso case MemberAccess::Protected: 142e7950fceSCarlos Alberto Enciso return dwarf::DW_ACCESS_protected; 143e7950fceSCarlos Alberto Enciso case MemberAccess::Public: 144e7950fceSCarlos Alberto Enciso return dwarf::DW_ACCESS_public; 145e7950fceSCarlos Alberto Enciso default: 146e7950fceSCarlos Alberto Enciso return std::nullopt; 147e7950fceSCarlos Alberto Enciso } 148e7950fceSCarlos Alberto Enciso } 149e7950fceSCarlos Alberto Enciso 150e28b9357SCarlos Alberto Enciso StringRef LVElement::externalString() const { 151e28b9357SCarlos Alberto Enciso return getIsExternal() ? "extern" : StringRef(); 152e28b9357SCarlos Alberto Enciso } 153e28b9357SCarlos Alberto Enciso 154e28b9357SCarlos Alberto Enciso StringRef LVElement::inlineCodeString(uint32_t Code) const { 155e28b9357SCarlos Alberto Enciso uint32_t Value = getInlineCode(); 156e28b9357SCarlos Alberto Enciso switch (Value ? Value : Code) { 157e28b9357SCarlos Alberto Enciso case dwarf::DW_INL_not_inlined: 158e28b9357SCarlos Alberto Enciso return "not_inlined"; 159e28b9357SCarlos Alberto Enciso case dwarf::DW_INL_inlined: 160e28b9357SCarlos Alberto Enciso return "inlined"; 161e28b9357SCarlos Alberto Enciso case dwarf::DW_INL_declared_not_inlined: 162e28b9357SCarlos Alberto Enciso return "declared_not_inlined"; 163e28b9357SCarlos Alberto Enciso case dwarf::DW_INL_declared_inlined: 164e28b9357SCarlos Alberto Enciso return "declared_inlined"; 165e28b9357SCarlos Alberto Enciso default: 166e28b9357SCarlos Alberto Enciso return StringRef(); 167e28b9357SCarlos Alberto Enciso } 168e28b9357SCarlos Alberto Enciso } 169e28b9357SCarlos Alberto Enciso 170e28b9357SCarlos Alberto Enciso StringRef LVElement::virtualityString(uint32_t Virtuality) const { 171e28b9357SCarlos Alberto Enciso uint32_t Value = getVirtualityCode(); 172e28b9357SCarlos Alberto Enciso switch (Value ? Value : Virtuality) { 173e28b9357SCarlos Alberto Enciso case dwarf::DW_VIRTUALITY_none: 174e28b9357SCarlos Alberto Enciso return StringRef(); 175e28b9357SCarlos Alberto Enciso case dwarf::DW_VIRTUALITY_virtual: 176e28b9357SCarlos Alberto Enciso return "virtual"; 177e28b9357SCarlos Alberto Enciso case dwarf::DW_VIRTUALITY_pure_virtual: 178e28b9357SCarlos Alberto Enciso return "pure virtual"; 179e28b9357SCarlos Alberto Enciso default: 180e28b9357SCarlos Alberto Enciso return StringRef(); 181e28b9357SCarlos Alberto Enciso } 182e28b9357SCarlos Alberto Enciso } 183e28b9357SCarlos Alberto Enciso 184e7950fceSCarlos Alberto Enciso std::optional<uint32_t> LVElement::getVirtualityCode(MethodKind Virtuality) { 185e7950fceSCarlos Alberto Enciso switch (Virtuality) { 186e7950fceSCarlos Alberto Enciso case MethodKind::Virtual: 187e7950fceSCarlos Alberto Enciso return dwarf::DW_VIRTUALITY_virtual; 188e7950fceSCarlos Alberto Enciso case MethodKind::PureVirtual: 189e7950fceSCarlos Alberto Enciso return dwarf::DW_VIRTUALITY_pure_virtual; 190e7950fceSCarlos Alberto Enciso case MethodKind::IntroducingVirtual: 191e7950fceSCarlos Alberto Enciso case MethodKind::PureIntroducingVirtual: 192e7950fceSCarlos Alberto Enciso // No direct equivalents in DWARF. Assume Virtual. 193e7950fceSCarlos Alberto Enciso return dwarf::DW_VIRTUALITY_virtual; 194e7950fceSCarlos Alberto Enciso default: 195e7950fceSCarlos Alberto Enciso return std::nullopt; 196e7950fceSCarlos Alberto Enciso } 197e7950fceSCarlos Alberto Enciso } 198e7950fceSCarlos Alberto Enciso 199e28b9357SCarlos Alberto Enciso void LVElement::resolve() { 200e28b9357SCarlos Alberto Enciso if (getIsResolved()) 201e28b9357SCarlos Alberto Enciso return; 202e28b9357SCarlos Alberto Enciso setIsResolved(); 203e28b9357SCarlos Alberto Enciso 204e28b9357SCarlos Alberto Enciso resolveReferences(); 205e28b9357SCarlos Alberto Enciso resolveParents(); 206e28b9357SCarlos Alberto Enciso resolveExtra(); 207e28b9357SCarlos Alberto Enciso resolveName(); 208e28b9357SCarlos Alberto Enciso } 209e28b9357SCarlos Alberto Enciso 210e28b9357SCarlos Alberto Enciso // Set File/Line using the specification element. 211e28b9357SCarlos Alberto Enciso void LVElement::setFileLine(LVElement *Specification) { 212e28b9357SCarlos Alberto Enciso // In the case of inlined functions, the correct scope must be associated 213e28b9357SCarlos Alberto Enciso // with the file and line information of the outline version. 214e28b9357SCarlos Alberto Enciso if (!isLined()) { 215e28b9357SCarlos Alberto Enciso setLineNumber(Specification->getLineNumber()); 216e28b9357SCarlos Alberto Enciso setIsLineFromReference(); 217e28b9357SCarlos Alberto Enciso } 218e28b9357SCarlos Alberto Enciso if (!isFiled()) { 219e28b9357SCarlos Alberto Enciso setFilenameIndex(Specification->getFilenameIndex()); 220e28b9357SCarlos Alberto Enciso setIsFileFromReference(); 221e28b9357SCarlos Alberto Enciso } 222e28b9357SCarlos Alberto Enciso } 223e28b9357SCarlos Alberto Enciso 224e28b9357SCarlos Alberto Enciso void LVElement::resolveName() { 225e28b9357SCarlos Alberto Enciso // Set the qualified name if requested. 226e28b9357SCarlos Alberto Enciso if (options().getAttributeQualified()) 227e28b9357SCarlos Alberto Enciso resolveQualifiedName(); 228e28b9357SCarlos Alberto Enciso 229e28b9357SCarlos Alberto Enciso setIsResolvedName(); 230e28b9357SCarlos Alberto Enciso } 231e28b9357SCarlos Alberto Enciso 232e28b9357SCarlos Alberto Enciso // Resolve any parents. 233e28b9357SCarlos Alberto Enciso void LVElement::resolveParents() { 234e28b9357SCarlos Alberto Enciso if (isRoot() || isCompileUnit()) 235e28b9357SCarlos Alberto Enciso return; 236e28b9357SCarlos Alberto Enciso 237e28b9357SCarlos Alberto Enciso LVScope *Parent = getParentScope(); 238e28b9357SCarlos Alberto Enciso if (Parent && !Parent->getIsCompileUnit()) 239e28b9357SCarlos Alberto Enciso Parent->resolve(); 240e28b9357SCarlos Alberto Enciso } 241e28b9357SCarlos Alberto Enciso 242e28b9357SCarlos Alberto Enciso // Generate a name for unnamed elements. 243e28b9357SCarlos Alberto Enciso void LVElement::generateName(std::string &Prefix) const { 244e28b9357SCarlos Alberto Enciso LVScope *Scope = getParentScope(); 245e28b9357SCarlos Alberto Enciso if (!Scope) 246e28b9357SCarlos Alberto Enciso return; 247e28b9357SCarlos Alberto Enciso 248e28b9357SCarlos Alberto Enciso // Use its parent name and any line information. 249e28b9357SCarlos Alberto Enciso Prefix.append(std::string(Scope->getName())); 250e28b9357SCarlos Alberto Enciso Prefix.append("::"); 251e28b9357SCarlos Alberto Enciso Prefix.append(isLined() ? lineNumberAsString(/*ShowZero=*/true) : "?"); 252e28b9357SCarlos Alberto Enciso 253e28b9357SCarlos Alberto Enciso // Remove any whitespaces. 254*dc271b59SKazu Hirata llvm::erase_if(Prefix, ::isspace); 255e28b9357SCarlos Alberto Enciso } 256e28b9357SCarlos Alberto Enciso 257e28b9357SCarlos Alberto Enciso // Generate a name for unnamed elements. 258e28b9357SCarlos Alberto Enciso void LVElement::generateName() { 259e28b9357SCarlos Alberto Enciso setIsAnonymous(); 260e28b9357SCarlos Alberto Enciso std::string Name; 261e28b9357SCarlos Alberto Enciso generateName(Name); 262e28b9357SCarlos Alberto Enciso setName(Name); 263e28b9357SCarlos Alberto Enciso setIsGeneratedName(); 264e28b9357SCarlos Alberto Enciso } 265e28b9357SCarlos Alberto Enciso 266e28b9357SCarlos Alberto Enciso void LVElement::updateLevel(LVScope *Parent, bool Moved) { 267e28b9357SCarlos Alberto Enciso setLevel(Parent->getLevel() + 1); 268e28b9357SCarlos Alberto Enciso if (Moved) 269e28b9357SCarlos Alberto Enciso setHasMoved(); 270e28b9357SCarlos Alberto Enciso } 271e28b9357SCarlos Alberto Enciso 272e28b9357SCarlos Alberto Enciso // Generate the full name for the element, to include special qualifiers. 273e28b9357SCarlos Alberto Enciso void LVElement::resolveFullname(LVElement *BaseType, StringRef Name) { 274e28b9357SCarlos Alberto Enciso // For the following sample code, 275e28b9357SCarlos Alberto Enciso // void *p; 276e28b9357SCarlos Alberto Enciso // some compilers do not generate an attribute for the associated type: 277e28b9357SCarlos Alberto Enciso // DW_TAG_variable 278e28b9357SCarlos Alberto Enciso // DW_AT_name 'p' 279e28b9357SCarlos Alberto Enciso // DW_AT_type $1 280e28b9357SCarlos Alberto Enciso // ... 281e28b9357SCarlos Alberto Enciso // $1: DW_TAG_pointer_type 282e28b9357SCarlos Alberto Enciso // ... 283e28b9357SCarlos Alberto Enciso // For those cases, generate the implicit 'void' type. 284e28b9357SCarlos Alberto Enciso StringRef BaseTypename = BaseType ? BaseType->getName() : emptyString(); 285e28b9357SCarlos Alberto Enciso bool GetBaseTypename = false; 286e28b9357SCarlos Alberto Enciso bool UseBaseTypename = true; 287e28b9357SCarlos Alberto Enciso bool UseNameText = true; 288e28b9357SCarlos Alberto Enciso 289e28b9357SCarlos Alberto Enciso switch (getTag()) { 290e28b9357SCarlos Alberto Enciso case dwarf::DW_TAG_pointer_type: // "*"; 291e28b9357SCarlos Alberto Enciso if (!BaseType) 292e28b9357SCarlos Alberto Enciso BaseTypename = typeVoid(); 293e28b9357SCarlos Alberto Enciso break; 294e28b9357SCarlos Alberto Enciso case dwarf::DW_TAG_const_type: // "const" 295e28b9357SCarlos Alberto Enciso case dwarf::DW_TAG_ptr_to_member_type: // "*" 296e28b9357SCarlos Alberto Enciso case dwarf::DW_TAG_rvalue_reference_type: // "&&" 297e28b9357SCarlos Alberto Enciso case dwarf::DW_TAG_reference_type: // "&" 298e28b9357SCarlos Alberto Enciso case dwarf::DW_TAG_restrict_type: // "restrict" 299e28b9357SCarlos Alberto Enciso case dwarf::DW_TAG_volatile_type: // "volatile" 300e28b9357SCarlos Alberto Enciso case dwarf::DW_TAG_unaligned: // "unaligned" 301e28b9357SCarlos Alberto Enciso break; 302e28b9357SCarlos Alberto Enciso case dwarf::DW_TAG_base_type: 303e28b9357SCarlos Alberto Enciso case dwarf::DW_TAG_compile_unit: 304e28b9357SCarlos Alberto Enciso case dwarf::DW_TAG_class_type: 305e28b9357SCarlos Alberto Enciso case dwarf::DW_TAG_enumerator: 306e28b9357SCarlos Alberto Enciso case dwarf::DW_TAG_namespace: 307e28b9357SCarlos Alberto Enciso case dwarf::DW_TAG_skeleton_unit: 308e28b9357SCarlos Alberto Enciso case dwarf::DW_TAG_structure_type: 309e28b9357SCarlos Alberto Enciso case dwarf::DW_TAG_union_type: 310e28b9357SCarlos Alberto Enciso case dwarf::DW_TAG_unspecified_type: 311e28b9357SCarlos Alberto Enciso case dwarf::DW_TAG_GNU_template_parameter_pack: 312e28b9357SCarlos Alberto Enciso GetBaseTypename = true; 313e28b9357SCarlos Alberto Enciso break; 314e28b9357SCarlos Alberto Enciso case dwarf::DW_TAG_array_type: 315e28b9357SCarlos Alberto Enciso case dwarf::DW_TAG_call_site: 316e28b9357SCarlos Alberto Enciso case dwarf::DW_TAG_entry_point: 317e28b9357SCarlos Alberto Enciso case dwarf::DW_TAG_enumeration_type: 318e28b9357SCarlos Alberto Enciso case dwarf::DW_TAG_GNU_call_site: 319e28b9357SCarlos Alberto Enciso case dwarf::DW_TAG_imported_module: 320e28b9357SCarlos Alberto Enciso case dwarf::DW_TAG_imported_declaration: 321e28b9357SCarlos Alberto Enciso case dwarf::DW_TAG_inlined_subroutine: 322e28b9357SCarlos Alberto Enciso case dwarf::DW_TAG_label: 323e28b9357SCarlos Alberto Enciso case dwarf::DW_TAG_subprogram: 324e28b9357SCarlos Alberto Enciso case dwarf::DW_TAG_subrange_type: 325e28b9357SCarlos Alberto Enciso case dwarf::DW_TAG_subroutine_type: 326e28b9357SCarlos Alberto Enciso case dwarf::DW_TAG_typedef: 327e28b9357SCarlos Alberto Enciso GetBaseTypename = true; 328e28b9357SCarlos Alberto Enciso UseBaseTypename = false; 329e28b9357SCarlos Alberto Enciso break; 330e28b9357SCarlos Alberto Enciso case dwarf::DW_TAG_template_type_parameter: 331e28b9357SCarlos Alberto Enciso case dwarf::DW_TAG_template_value_parameter: 332e28b9357SCarlos Alberto Enciso UseBaseTypename = false; 333e28b9357SCarlos Alberto Enciso break; 334e28b9357SCarlos Alberto Enciso case dwarf::DW_TAG_GNU_template_template_param: 335e28b9357SCarlos Alberto Enciso break; 336e28b9357SCarlos Alberto Enciso case dwarf::DW_TAG_catch_block: 337e28b9357SCarlos Alberto Enciso case dwarf::DW_TAG_lexical_block: 338e28b9357SCarlos Alberto Enciso case dwarf::DW_TAG_try_block: 339e28b9357SCarlos Alberto Enciso UseNameText = false; 340e28b9357SCarlos Alberto Enciso break; 341e28b9357SCarlos Alberto Enciso default: 342e28b9357SCarlos Alberto Enciso llvm_unreachable("Invalid type."); 343e28b9357SCarlos Alberto Enciso return; 344e28b9357SCarlos Alberto Enciso break; 345e28b9357SCarlos Alberto Enciso } 346e28b9357SCarlos Alberto Enciso 347e28b9357SCarlos Alberto Enciso // Overwrite if no given value. 'Name' is empty when resolving for scopes 348e28b9357SCarlos Alberto Enciso // and symbols. In the case of types, it represents the type base name. 349e28b9357SCarlos Alberto Enciso if (Name.empty() && GetBaseTypename) 350e28b9357SCarlos Alberto Enciso Name = getName(); 351e28b9357SCarlos Alberto Enciso 352e28b9357SCarlos Alberto Enciso // Concatenate the elements to get the full type name. 353e28b9357SCarlos Alberto Enciso // Type will be: base_parent + pre + base + parent + post. 354e28b9357SCarlos Alberto Enciso std::string Fullname; 355e28b9357SCarlos Alberto Enciso 356e28b9357SCarlos Alberto Enciso if (UseNameText && Name.size()) 357e28b9357SCarlos Alberto Enciso Fullname.append(std::string(Name)); 358e28b9357SCarlos Alberto Enciso if (UseBaseTypename && BaseTypename.size()) { 359e28b9357SCarlos Alberto Enciso if (UseNameText && Name.size()) 360e28b9357SCarlos Alberto Enciso Fullname.append(" "); 361e28b9357SCarlos Alberto Enciso Fullname.append(std::string(BaseTypename)); 362e28b9357SCarlos Alberto Enciso } 363e28b9357SCarlos Alberto Enciso 364e28b9357SCarlos Alberto Enciso // For a better and consistent layout, check if the generated name 365e28b9357SCarlos Alberto Enciso // contains double space sequences. 366e28b9357SCarlos Alberto Enciso assert((Fullname.find(" ", 0) == std::string::npos) && 367e28b9357SCarlos Alberto Enciso "Extra double spaces in name."); 368e28b9357SCarlos Alberto Enciso 369e28b9357SCarlos Alberto Enciso LLVM_DEBUG({ dbgs() << "Fullname = '" << Fullname << "'\n"; }); 370d22f050eSGregory Alfonso setName(Fullname); 371e28b9357SCarlos Alberto Enciso } 372e28b9357SCarlos Alberto Enciso 373e28b9357SCarlos Alberto Enciso void LVElement::setFile(LVElement *Reference) { 374e28b9357SCarlos Alberto Enciso if (!options().getAttributeAnySource()) 375e28b9357SCarlos Alberto Enciso return; 376e28b9357SCarlos Alberto Enciso 377e28b9357SCarlos Alberto Enciso // At this point, any existing reference to another element, have been 378e28b9357SCarlos Alberto Enciso // resolved and the file ID extracted from the DI entry. 379e28b9357SCarlos Alberto Enciso if (Reference) 380e28b9357SCarlos Alberto Enciso setFileLine(Reference); 381e28b9357SCarlos Alberto Enciso 382e28b9357SCarlos Alberto Enciso // The file information is used to show the source file for any element 383e28b9357SCarlos Alberto Enciso // and display any new source file in relation to its parent element. 384e28b9357SCarlos Alberto Enciso // a) Elements that are not inlined. 385e28b9357SCarlos Alberto Enciso // - We record the DW_AT_decl_line and DW_AT_decl_file. 386e28b9357SCarlos Alberto Enciso // b) Elements that are inlined. 387e28b9357SCarlos Alberto Enciso // - We record the DW_AT_decl_line and DW_AT_decl_file. 388e28b9357SCarlos Alberto Enciso // - We record the DW_AT_call_line and DW_AT_call_file. 389e28b9357SCarlos Alberto Enciso // For both cases, we use the DW_AT_decl_file value to detect any changes 390e28b9357SCarlos Alberto Enciso // in the source filename containing the element. Changes on this value 391e28b9357SCarlos Alberto Enciso // indicates that the element being printed is not contained in the 392e28b9357SCarlos Alberto Enciso // previous printed filename. 393e28b9357SCarlos Alberto Enciso 394e28b9357SCarlos Alberto Enciso // The source files are indexed starting at 0, but DW_AT_decl_file defines 395e28b9357SCarlos Alberto Enciso // that 0 means no file; a value of 1 means the 0th entry. 396e28b9357SCarlos Alberto Enciso size_t Index = 0; 397e28b9357SCarlos Alberto Enciso 398e28b9357SCarlos Alberto Enciso // An element with no source file information will use the reference 399e28b9357SCarlos Alberto Enciso // attribute (DW_AT_specification, DW_AT_abstract_origin, DW_AT_extension) 400e28b9357SCarlos Alberto Enciso // to update its information. 401e28b9357SCarlos Alberto Enciso if (getIsFileFromReference() && Reference) { 402e28b9357SCarlos Alberto Enciso Index = Reference->getFilenameIndex(); 403e28b9357SCarlos Alberto Enciso if (Reference->getInvalidFilename()) 404e28b9357SCarlos Alberto Enciso setInvalidFilename(); 405e28b9357SCarlos Alberto Enciso setFilenameIndex(Index); 406e28b9357SCarlos Alberto Enciso return; 407e28b9357SCarlos Alberto Enciso } 408e28b9357SCarlos Alberto Enciso 409e28b9357SCarlos Alberto Enciso // The source files are indexed starting at 0, but DW_AT_decl_file 410e28b9357SCarlos Alberto Enciso // defines that 0 means no file; a value of 1 means the 0th entry. 411e28b9357SCarlos Alberto Enciso Index = getFilenameIndex(); 412e28b9357SCarlos Alberto Enciso if (Index) { 413e28b9357SCarlos Alberto Enciso StringRef Filename = getReader().getFilename(this, Index); 414e28b9357SCarlos Alberto Enciso Filename.size() ? setFilename(Filename) : setInvalidFilename(); 415e28b9357SCarlos Alberto Enciso } 416e28b9357SCarlos Alberto Enciso } 417e28b9357SCarlos Alberto Enciso 418e28b9357SCarlos Alberto Enciso LVScope *LVElement::traverseParents(LVScopeGetFunction GetFunction) const { 419e28b9357SCarlos Alberto Enciso LVScope *Parent = getParentScope(); 420e28b9357SCarlos Alberto Enciso while (Parent && !(Parent->*GetFunction)()) 421e28b9357SCarlos Alberto Enciso Parent = Parent->getParentScope(); 422e28b9357SCarlos Alberto Enciso return Parent; 423e28b9357SCarlos Alberto Enciso } 424e28b9357SCarlos Alberto Enciso 425e28b9357SCarlos Alberto Enciso LVScope *LVElement::getFunctionParent() const { 426e28b9357SCarlos Alberto Enciso return traverseParents(&LVScope::getIsFunction); 427e28b9357SCarlos Alberto Enciso } 428e28b9357SCarlos Alberto Enciso 429e28b9357SCarlos Alberto Enciso LVScope *LVElement::getCompileUnitParent() const { 430e28b9357SCarlos Alberto Enciso return traverseParents(&LVScope::getIsCompileUnit); 431e28b9357SCarlos Alberto Enciso } 432e28b9357SCarlos Alberto Enciso 433e28b9357SCarlos Alberto Enciso // Resolve the qualified name to include the parent hierarchy names. 434e28b9357SCarlos Alberto Enciso void LVElement::resolveQualifiedName() { 435e28b9357SCarlos Alberto Enciso if (!getIsReferencedType() || isBase() || getQualifiedResolved() || 436e28b9357SCarlos Alberto Enciso !getIncludeInPrint()) 437e28b9357SCarlos Alberto Enciso return; 438e28b9357SCarlos Alberto Enciso 439e28b9357SCarlos Alberto Enciso std::string Name; 440e28b9357SCarlos Alberto Enciso 441e28b9357SCarlos Alberto Enciso // Get the qualified name, excluding the Compile Unit. 442e28b9357SCarlos Alberto Enciso LVScope *Parent = getParentScope(); 443e28b9357SCarlos Alberto Enciso if (Parent && !Parent->getIsRoot()) { 444e28b9357SCarlos Alberto Enciso while (Parent && !Parent->getIsCompileUnit()) { 445e28b9357SCarlos Alberto Enciso Name.insert(0, "::"); 446e28b9357SCarlos Alberto Enciso if (Parent->isNamed()) 447e28b9357SCarlos Alberto Enciso Name.insert(0, std::string(Parent->getName())); 448e28b9357SCarlos Alberto Enciso else { 449e28b9357SCarlos Alberto Enciso std::string Temp; 450e28b9357SCarlos Alberto Enciso Parent->generateName(Temp); 451e28b9357SCarlos Alberto Enciso Name.insert(0, Temp); 452e28b9357SCarlos Alberto Enciso } 453e28b9357SCarlos Alberto Enciso Parent = Parent->getParentScope(); 454e28b9357SCarlos Alberto Enciso } 455e28b9357SCarlos Alberto Enciso } 456e28b9357SCarlos Alberto Enciso 457e28b9357SCarlos Alberto Enciso if (Name.size()) { 458e28b9357SCarlos Alberto Enciso setQualifiedName(Name); 459e28b9357SCarlos Alberto Enciso setQualifiedResolved(); 460e28b9357SCarlos Alberto Enciso } 461e28b9357SCarlos Alberto Enciso LLVM_DEBUG({ 462e28b9357SCarlos Alberto Enciso dbgs() << "Offset: " << hexSquareString(getOffset()) 463e28b9357SCarlos Alberto Enciso << ", Kind: " << formattedKind(kind()) 464e28b9357SCarlos Alberto Enciso << ", Name: " << formattedName(getName()) 465e28b9357SCarlos Alberto Enciso << ", QualifiedName: " << formattedName(Name) << "\n"; 466e28b9357SCarlos Alberto Enciso }); 467e28b9357SCarlos Alberto Enciso } 468e28b9357SCarlos Alberto Enciso 469e98a4c5aSCarlos Alberto Enciso bool LVElement::referenceMatch(const LVElement *Element) const { 470e98a4c5aSCarlos Alberto Enciso return (getHasReference() && Element->getHasReference()) || 471e98a4c5aSCarlos Alberto Enciso (!getHasReference() && !Element->getHasReference()); 472e98a4c5aSCarlos Alberto Enciso } 473e98a4c5aSCarlos Alberto Enciso 474e98a4c5aSCarlos Alberto Enciso bool LVElement::equals(const LVElement *Element) const { 475e98a4c5aSCarlos Alberto Enciso // The minimum factors that must be the same for an equality are: 476e98a4c5aSCarlos Alberto Enciso // line number, level, name, qualified name and filename. 477e98a4c5aSCarlos Alberto Enciso LLVM_DEBUG({ 478e98a4c5aSCarlos Alberto Enciso dbgs() << "\n[Element::equals]\n"; 479e98a4c5aSCarlos Alberto Enciso if (options().getAttributeOffset()) { 480e98a4c5aSCarlos Alberto Enciso dbgs() << "Reference: " << hexSquareString(getOffset()) << "\n"; 481e98a4c5aSCarlos Alberto Enciso dbgs() << "Target : " << hexSquareString(Element->getOffset()) << "\n"; 482e98a4c5aSCarlos Alberto Enciso } 483e98a4c5aSCarlos Alberto Enciso dbgs() << "Reference: " 484e98a4c5aSCarlos Alberto Enciso << "Kind = " << formattedKind(kind()) << ", " 485e98a4c5aSCarlos Alberto Enciso << "Name = " << formattedName(getName()) << ", " 486e98a4c5aSCarlos Alberto Enciso << "Qualified = " << formattedName(getQualifiedName()) << "\n" 487e98a4c5aSCarlos Alberto Enciso << "Target : " 488e98a4c5aSCarlos Alberto Enciso << "Kind = " << formattedKind(Element->kind()) << ", " 489e98a4c5aSCarlos Alberto Enciso << "Name = " << formattedName(Element->getName()) << ", " 490e98a4c5aSCarlos Alberto Enciso << "Qualified = " << formattedName(Element->getQualifiedName()) 491e98a4c5aSCarlos Alberto Enciso << "\n" 492e98a4c5aSCarlos Alberto Enciso << "Reference: " 493e98a4c5aSCarlos Alberto Enciso << "NameIndex = " << getNameIndex() << ", " 494e98a4c5aSCarlos Alberto Enciso << "QualifiedNameIndex = " << getQualifiedNameIndex() << ", " 495e98a4c5aSCarlos Alberto Enciso << "FilenameIndex = " << getFilenameIndex() << "\n" 496e98a4c5aSCarlos Alberto Enciso << "Target : " 497e98a4c5aSCarlos Alberto Enciso << "NameIndex = " << Element->getNameIndex() << ", " 498e98a4c5aSCarlos Alberto Enciso << "QualifiedNameIndex = " << Element->getQualifiedNameIndex() 499e98a4c5aSCarlos Alberto Enciso << ", " 500e98a4c5aSCarlos Alberto Enciso << "FilenameIndex = " << Element->getFilenameIndex() << "\n"; 501e98a4c5aSCarlos Alberto Enciso }); 502e98a4c5aSCarlos Alberto Enciso if ((getLineNumber() != Element->getLineNumber()) || 503e98a4c5aSCarlos Alberto Enciso (getLevel() != Element->getLevel())) 504e98a4c5aSCarlos Alberto Enciso return false; 505e98a4c5aSCarlos Alberto Enciso 506e98a4c5aSCarlos Alberto Enciso if ((getQualifiedNameIndex() != Element->getQualifiedNameIndex()) || 507e98a4c5aSCarlos Alberto Enciso (getNameIndex() != Element->getNameIndex()) || 508e98a4c5aSCarlos Alberto Enciso (getFilenameIndex() != Element->getFilenameIndex())) 509e98a4c5aSCarlos Alberto Enciso return false; 510e98a4c5aSCarlos Alberto Enciso 511e98a4c5aSCarlos Alberto Enciso if (!getType() && !Element->getType()) 512e98a4c5aSCarlos Alberto Enciso return true; 513e98a4c5aSCarlos Alberto Enciso if (getType() && Element->getType()) 514e98a4c5aSCarlos Alberto Enciso return getType()->equals(Element->getType()); 515e98a4c5aSCarlos Alberto Enciso return false; 516e98a4c5aSCarlos Alberto Enciso } 517e98a4c5aSCarlos Alberto Enciso 518e28b9357SCarlos Alberto Enciso // Print the FileName Index. 519e28b9357SCarlos Alberto Enciso void LVElement::printFileIndex(raw_ostream &OS, bool Full) const { 520e28b9357SCarlos Alberto Enciso if (options().getPrintFormatting() && options().getAttributeAnySource() && 521e28b9357SCarlos Alberto Enciso getFilenameIndex()) { 522e28b9357SCarlos Alberto Enciso 523e28b9357SCarlos Alberto Enciso // Check if there is a change in the File ID sequence. 524e28b9357SCarlos Alberto Enciso size_t Index = getFilenameIndex(); 525e28b9357SCarlos Alberto Enciso if (options().changeFilenameIndex(Index)) { 526e28b9357SCarlos Alberto Enciso // Just to keep a nice layout. 527e28b9357SCarlos Alberto Enciso OS << "\n"; 528e28b9357SCarlos Alberto Enciso printAttributes(OS, /*Full=*/false); 529e28b9357SCarlos Alberto Enciso 530e28b9357SCarlos Alberto Enciso OS << " {Source} "; 531e28b9357SCarlos Alberto Enciso if (getInvalidFilename()) 532e28b9357SCarlos Alberto Enciso OS << format("[0x%08x]\n", Index); 533e28b9357SCarlos Alberto Enciso else 534e28b9357SCarlos Alberto Enciso OS << formattedName(getPathname()) << "\n"; 535e28b9357SCarlos Alberto Enciso } 536e28b9357SCarlos Alberto Enciso } 537e28b9357SCarlos Alberto Enciso } 538e28b9357SCarlos Alberto Enciso 539e28b9357SCarlos Alberto Enciso void LVElement::printReference(raw_ostream &OS, bool Full, 540e28b9357SCarlos Alberto Enciso LVElement *Parent) const { 541e28b9357SCarlos Alberto Enciso if (options().getPrintFormatting() && options().getAttributeReference()) 542e28b9357SCarlos Alberto Enciso printAttributes(OS, Full, "{Reference} ", Parent, 543e28b9357SCarlos Alberto Enciso referenceAsString(getLineNumber(), /*Spaces=*/false), 544e28b9357SCarlos Alberto Enciso /*UseQuotes=*/false, /*PrintRef=*/true); 545e28b9357SCarlos Alberto Enciso } 546e28b9357SCarlos Alberto Enciso 547e28b9357SCarlos Alberto Enciso void LVElement::printLinkageName(raw_ostream &OS, bool Full, 548e28b9357SCarlos Alberto Enciso LVElement *Parent) const { 549e28b9357SCarlos Alberto Enciso if (options().getPrintFormatting() && options().getAttributeLinkage()) { 550e28b9357SCarlos Alberto Enciso printAttributes(OS, Full, "{Linkage} ", Parent, getLinkageName(), 551e28b9357SCarlos Alberto Enciso /*UseQuotes=*/true, /*PrintRef=*/false); 552e28b9357SCarlos Alberto Enciso } 553e28b9357SCarlos Alberto Enciso } 5544f06d46fSCarlos Alberto Enciso 5554f06d46fSCarlos Alberto Enciso void LVElement::printLinkageName(raw_ostream &OS, bool Full, LVElement *Parent, 5564f06d46fSCarlos Alberto Enciso LVScope *Scope) const { 5574f06d46fSCarlos Alberto Enciso if (options().getPrintFormatting() && options().getAttributeLinkage()) { 5584f06d46fSCarlos Alberto Enciso LVSectionIndex SectionIndex = getReader().getSectionIndex(Scope); 5594f06d46fSCarlos Alberto Enciso std::string Text = (Twine(" 0x") + Twine::utohexstr(SectionIndex) + 5604f06d46fSCarlos Alberto Enciso Twine(" '") + Twine(getLinkageName()) + Twine("'")) 5614f06d46fSCarlos Alberto Enciso .str(); 5624f06d46fSCarlos Alberto Enciso printAttributes(OS, Full, "{Linkage} ", Parent, Text, 5634f06d46fSCarlos Alberto Enciso /*UseQuotes=*/false, /*PrintRef=*/false); 5644f06d46fSCarlos Alberto Enciso } 5654f06d46fSCarlos Alberto Enciso } 566