xref: /llvm-project/llvm/lib/DebugInfo/LogicalView/Core/LVElement.cpp (revision 0060c54e0da6d1429875da2d30895faa7562b706)
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