1 //===-- LVElement.cpp -----------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 // This implements the LVElement class.
11 //===----------------------------------------------------------------------===//
13 #include "llvm/DebugInfo/LogicalView/Core/LVElement.h"
14 #include "llvm/DebugInfo/LogicalView/Core/LVReader.h"
15 #include "llvm/DebugInfo/LogicalView/Core/LVScope.h"
16 #include "llvm/DebugInfo/LogicalView/Core/LVSymbol.h"
17 #include "llvm/DebugInfo/LogicalView/Core/LVType.h"
20 using namespace llvm::codeview
;
21 using namespace llvm::logicalview
;
23 #define DEBUG_TYPE "Element"
25 LVElementDispatch
LVElement::Dispatch
= {
26 {LVElementKind::Discarded
, &LVElement::getIsDiscarded
},
27 {LVElementKind::Global
, &LVElement::getIsGlobalReference
},
28 {LVElementKind::Optimized
, &LVElement::getIsOptimized
}};
30 LVType
*LVElement::getTypeAsType() const {
31 return ElementType
&& ElementType
->getIsType()
32 ? static_cast<LVType
*>(ElementType
)
36 LVScope
*LVElement::getTypeAsScope() const {
37 return ElementType
&& ElementType
->getIsScope()
38 ? static_cast<LVScope
*>(ElementType
)
42 // Set the element type.
43 void LVElement::setGenericType(LVElement
*Element
) {
44 if (!Element
->isTemplateParam()) {
48 // For template parameters, the instance type can be a type or a scope.
49 if (options().getAttributeArgument()) {
50 if (Element
->getIsKindType())
51 setType(Element
->getTypeAsType());
52 else if (Element
->getIsKindScope())
53 setType(Element
->getTypeAsScope());
58 // Discriminator as string.
59 std::string
LVElement::discriminatorAsString() const {
60 uint32_t Discriminator
= getDiscriminator();
62 raw_string_ostream
Stream(String
);
63 if (Discriminator
&& options().getAttributeDiscriminator())
64 Stream
<< "," << Discriminator
;
68 // Get the type as a string.
69 StringRef
LVElement::typeAsString() const {
70 return getHasType() ? getTypeName() : typeVoid();
73 // Get name for element type.
74 StringRef
LVElement::getTypeName() const {
75 return ElementType
? ElementType
->getName() : StringRef();
78 static size_t getStringIndex(StringRef Name
) {
79 // Convert the name to Unified format ('\' have been converted into '/').
80 std::string
Pathname(transformPath(Name
));
82 // Depending on the --attribute=filename and --attribute=pathname command
83 // line options, use the basename or the full pathname as the name.
84 if (!options().getAttributePathname()) {
85 // Get the basename by ignoring any prefix up to the last slash ('/').
86 StringRef Basename
= Pathname
;
87 size_t Pos
= Basename
.rfind('/');
88 if (Pos
!= std::string::npos
)
89 Basename
= Basename
.substr(Pos
+ 1);
90 return getStringPool().getIndex(Basename
);
93 return getStringPool().getIndex(Pathname
);
96 void LVElement::setName(StringRef ElementName
) {
97 // In the case of Root or Compile Unit, get index for the flatted out name.
98 NameIndex
= getTransformName() ? getStringIndex(ElementName
)
99 : getStringPool().getIndex(ElementName
);
102 void LVElement::setFilename(StringRef Filename
) {
103 // Get index for the flattened out filename.
104 FilenameIndex
= getStringIndex(Filename
);
107 void LVElement::setInnerComponent(StringRef Name
) {
109 StringRef InnerComponent
;
110 std::tie(std::ignore
, InnerComponent
) = getInnerComponent(Name
);
111 setName(InnerComponent
);
115 // Return the string representation of a DIE offset.
116 std::string
LVElement::typeOffsetAsString() const {
117 if (options().getAttributeOffset()) {
118 LVElement
*Element
= getType();
119 return hexSquareString(Element
? Element
->getOffset() : 0);
124 StringRef
LVElement::accessibilityString(uint32_t Access
) const {
125 uint32_t Value
= getAccessibilityCode();
126 switch (Value
? Value
: Access
) {
127 case dwarf::DW_ACCESS_public
:
129 case dwarf::DW_ACCESS_protected
:
131 case dwarf::DW_ACCESS_private
:
138 std::optional
<uint32_t> LVElement::getAccessibilityCode(MemberAccess Access
) {
140 case MemberAccess::Private
:
141 return dwarf::DW_ACCESS_private
;
142 case MemberAccess::Protected
:
143 return dwarf::DW_ACCESS_protected
;
144 case MemberAccess::Public
:
145 return dwarf::DW_ACCESS_public
;
151 StringRef
LVElement::externalString() const {
152 return getIsExternal() ? "extern" : StringRef();
155 StringRef
LVElement::inlineCodeString(uint32_t Code
) const {
156 uint32_t Value
= getInlineCode();
157 switch (Value
? Value
: Code
) {
158 case dwarf::DW_INL_not_inlined
:
159 return "not_inlined";
160 case dwarf::DW_INL_inlined
:
162 case dwarf::DW_INL_declared_not_inlined
:
163 return "declared_not_inlined";
164 case dwarf::DW_INL_declared_inlined
:
165 return "declared_inlined";
171 StringRef
LVElement::virtualityString(uint32_t Virtuality
) const {
172 uint32_t Value
= getVirtualityCode();
173 switch (Value
? Value
: Virtuality
) {
174 case dwarf::DW_VIRTUALITY_none
:
176 case dwarf::DW_VIRTUALITY_virtual
:
178 case dwarf::DW_VIRTUALITY_pure_virtual
:
179 return "pure virtual";
185 std::optional
<uint32_t> LVElement::getVirtualityCode(MethodKind Virtuality
) {
186 switch (Virtuality
) {
187 case MethodKind::Virtual
:
188 return dwarf::DW_VIRTUALITY_virtual
;
189 case MethodKind::PureVirtual
:
190 return dwarf::DW_VIRTUALITY_pure_virtual
;
191 case MethodKind::IntroducingVirtual
:
192 case MethodKind::PureIntroducingVirtual
:
193 // No direct equivalents in DWARF. Assume Virtual.
194 return dwarf::DW_VIRTUALITY_virtual
;
200 void LVElement::resolve() {
211 // Set File/Line using the specification element.
212 void LVElement::setFileLine(LVElement
*Specification
) {
213 // In the case of inlined functions, the correct scope must be associated
214 // with the file and line information of the outline version.
216 setLineNumber(Specification
->getLineNumber());
217 setIsLineFromReference();
220 setFilenameIndex(Specification
->getFilenameIndex());
221 setIsFileFromReference();
225 void LVElement::resolveName() {
226 // Set the qualified name if requested.
227 if (options().getAttributeQualified())
228 resolveQualifiedName();
233 // Resolve any parents.
234 void LVElement::resolveParents() {
235 if (isRoot() || isCompileUnit())
238 LVScope
*Parent
= getParentScope();
239 if (Parent
&& !Parent
->getIsCompileUnit())
243 // Generate a name for unnamed elements.
244 void LVElement::generateName(std::string
&Prefix
) const {
245 LVScope
*Scope
= getParentScope();
249 // Use its parent name and any line information.
250 Prefix
.append(std::string(Scope
->getName()));
252 Prefix
.append(isLined() ? lineNumberAsString(/*ShowZero=*/true) : "?");
254 // Remove any whitespaces.
255 llvm::erase_if(Prefix
, ::isspace
);
258 // Generate a name for unnamed elements.
259 void LVElement::generateName() {
264 setIsGeneratedName();
267 void LVElement::updateLevel(LVScope
*Parent
, bool Moved
) {
268 setLevel(Parent
->getLevel() + 1);
273 // Generate the full name for the element, to include special qualifiers.
274 void LVElement::resolveFullname(LVElement
*BaseType
, StringRef Name
) {
275 // For the following sample code,
277 // some compilers do not generate an attribute for the associated type:
282 // $1: DW_TAG_pointer_type
284 // For those cases, generate the implicit 'void' type.
285 StringRef BaseTypename
= BaseType
? BaseType
->getName() : emptyString();
286 bool GetBaseTypename
= false;
287 bool UseBaseTypename
= true;
288 bool UseNameText
= true;
291 case dwarf::DW_TAG_pointer_type
: // "*";
293 BaseTypename
= typeVoid();
295 case dwarf::DW_TAG_const_type
: // "const"
296 case dwarf::DW_TAG_ptr_to_member_type
: // "*"
297 case dwarf::DW_TAG_rvalue_reference_type
: // "&&"
298 case dwarf::DW_TAG_reference_type
: // "&"
299 case dwarf::DW_TAG_restrict_type
: // "restrict"
300 case dwarf::DW_TAG_volatile_type
: // "volatile"
301 case dwarf::DW_TAG_unaligned
: // "unaligned"
303 case dwarf::DW_TAG_base_type
:
304 case dwarf::DW_TAG_compile_unit
:
305 case dwarf::DW_TAG_class_type
:
306 case dwarf::DW_TAG_enumerator
:
307 case dwarf::DW_TAG_namespace
:
308 case dwarf::DW_TAG_skeleton_unit
:
309 case dwarf::DW_TAG_structure_type
:
310 case dwarf::DW_TAG_union_type
:
311 case dwarf::DW_TAG_unspecified_type
:
312 case dwarf::DW_TAG_GNU_template_parameter_pack
:
313 GetBaseTypename
= true;
315 case dwarf::DW_TAG_array_type
:
316 case dwarf::DW_TAG_call_site
:
317 case dwarf::DW_TAG_entry_point
:
318 case dwarf::DW_TAG_enumeration_type
:
319 case dwarf::DW_TAG_GNU_call_site
:
320 case dwarf::DW_TAG_imported_module
:
321 case dwarf::DW_TAG_imported_declaration
:
322 case dwarf::DW_TAG_inlined_subroutine
:
323 case dwarf::DW_TAG_label
:
324 case dwarf::DW_TAG_subprogram
:
325 case dwarf::DW_TAG_subrange_type
:
326 case dwarf::DW_TAG_subroutine_type
:
327 case dwarf::DW_TAG_typedef
:
328 GetBaseTypename
= true;
329 UseBaseTypename
= false;
331 case dwarf::DW_TAG_template_type_parameter
:
332 case dwarf::DW_TAG_template_value_parameter
:
333 UseBaseTypename
= false;
335 case dwarf::DW_TAG_GNU_template_template_param
:
337 case dwarf::DW_TAG_catch_block
:
338 case dwarf::DW_TAG_lexical_block
:
339 case dwarf::DW_TAG_try_block
:
343 llvm_unreachable("Invalid type.");
348 // Overwrite if no given value. 'Name' is empty when resolving for scopes
349 // and symbols. In the case of types, it represents the type base name.
350 if (Name
.empty() && GetBaseTypename
)
353 // Concatenate the elements to get the full type name.
354 // Type will be: base_parent + pre + base + parent + post.
355 std::string Fullname
;
357 if (UseNameText
&& Name
.size())
358 Fullname
.append(std::string(Name
));
359 if (UseBaseTypename
&& BaseTypename
.size()) {
360 if (UseNameText
&& Name
.size())
361 Fullname
.append(" ");
362 Fullname
.append(std::string(BaseTypename
));
365 // For a better and consistent layout, check if the generated name
366 // contains double space sequences.
367 assert((Fullname
.find(" ", 0) == std::string::npos
) &&
368 "Extra double spaces in name.");
370 LLVM_DEBUG({ dbgs() << "Fullname = '" << Fullname
<< "'\n"; });
374 void LVElement::setFile(LVElement
*Reference
) {
375 if (!options().getAttributeAnySource())
378 // At this point, any existing reference to another element, have been
379 // resolved and the file ID extracted from the DI entry.
381 setFileLine(Reference
);
383 // The file information is used to show the source file for any element
384 // and display any new source file in relation to its parent element.
385 // a) Elements that are not inlined.
386 // - We record the DW_AT_decl_line and DW_AT_decl_file.
387 // b) Elements that are inlined.
388 // - We record the DW_AT_decl_line and DW_AT_decl_file.
389 // - We record the DW_AT_call_line and DW_AT_call_file.
390 // For both cases, we use the DW_AT_decl_file value to detect any changes
391 // in the source filename containing the element. Changes on this value
392 // indicates that the element being printed is not contained in the
393 // previous printed filename.
395 // The source files are indexed starting at 0, but DW_AT_decl_file defines
396 // that 0 means no file; a value of 1 means the 0th entry.
399 // An element with no source file information will use the reference
400 // attribute (DW_AT_specification, DW_AT_abstract_origin, DW_AT_extension)
401 // to update its information.
402 if (getIsFileFromReference() && Reference
) {
403 Index
= Reference
->getFilenameIndex();
404 if (Reference
->getInvalidFilename())
405 setInvalidFilename();
406 setFilenameIndex(Index
);
410 // The source files are indexed starting at 0, but DW_AT_decl_file
411 // defines that 0 means no file; a value of 1 means the 0th entry.
412 Index
= getFilenameIndex();
414 StringRef Filename
= getReader().getFilename(this, Index
);
415 Filename
.size() ? setFilename(Filename
) : setInvalidFilename();
419 LVScope
*LVElement::traverseParents(LVScopeGetFunction GetFunction
) const {
420 LVScope
*Parent
= getParentScope();
421 while (Parent
&& !(Parent
->*GetFunction
)())
422 Parent
= Parent
->getParentScope();
426 LVScope
*LVElement::getFunctionParent() const {
427 return traverseParents(&LVScope::getIsFunction
);
430 LVScope
*LVElement::getCompileUnitParent() const {
431 return traverseParents(&LVScope::getIsCompileUnit
);
434 // Resolve the qualified name to include the parent hierarchy names.
435 void LVElement::resolveQualifiedName() {
436 if (!getIsReferencedType() || isBase() || getQualifiedResolved() ||
437 !getIncludeInPrint())
442 // Get the qualified name, excluding the Compile Unit.
443 LVScope
*Parent
= getParentScope();
444 if (Parent
&& !Parent
->getIsRoot()) {
445 while (Parent
&& !Parent
->getIsCompileUnit()) {
446 Name
.insert(0, "::");
447 if (Parent
->isNamed())
448 Name
.insert(0, std::string(Parent
->getName()));
451 Parent
->generateName(Temp
);
452 Name
.insert(0, Temp
);
454 Parent
= Parent
->getParentScope();
459 setQualifiedName(Name
);
460 setQualifiedResolved();
463 dbgs() << "Offset: " << hexSquareString(getOffset())
464 << ", Kind: " << formattedKind(kind())
465 << ", Name: " << formattedName(getName())
466 << ", QualifiedName: " << formattedName(Name
) << "\n";
470 bool LVElement::referenceMatch(const LVElement
*Element
) const {
471 return (getHasReference() && Element
->getHasReference()) ||
472 (!getHasReference() && !Element
->getHasReference());
475 bool LVElement::equals(const LVElement
*Element
) const {
476 // The minimum factors that must be the same for an equality are:
477 // line number, level, name, qualified name and filename.
479 dbgs() << "\n[Element::equals]\n";
480 if (options().getAttributeOffset()) {
481 dbgs() << "Reference: " << hexSquareString(getOffset()) << "\n";
482 dbgs() << "Target : " << hexSquareString(Element
->getOffset()) << "\n";
484 dbgs() << "Reference: "
485 << "Kind = " << formattedKind(kind()) << ", "
486 << "Name = " << formattedName(getName()) << ", "
487 << "Qualified = " << formattedName(getQualifiedName()) << "\n"
489 << "Kind = " << formattedKind(Element
->kind()) << ", "
490 << "Name = " << formattedName(Element
->getName()) << ", "
491 << "Qualified = " << formattedName(Element
->getQualifiedName())
494 << "NameIndex = " << getNameIndex() << ", "
495 << "QualifiedNameIndex = " << getQualifiedNameIndex() << ", "
496 << "FilenameIndex = " << getFilenameIndex() << "\n"
498 << "NameIndex = " << Element
->getNameIndex() << ", "
499 << "QualifiedNameIndex = " << Element
->getQualifiedNameIndex()
501 << "FilenameIndex = " << Element
->getFilenameIndex() << "\n";
503 if ((getLineNumber() != Element
->getLineNumber()) ||
504 (getLevel() != Element
->getLevel()))
507 if ((getQualifiedNameIndex() != Element
->getQualifiedNameIndex()) ||
508 (getNameIndex() != Element
->getNameIndex()) ||
509 (getFilenameIndex() != Element
->getFilenameIndex()))
512 if (!getType() && !Element
->getType())
514 if (getType() && Element
->getType())
515 return getType()->equals(Element
->getType());
519 // Print the FileName Index.
520 void LVElement::printFileIndex(raw_ostream
&OS
, bool Full
) const {
521 if (options().getPrintFormatting() && options().getAttributeAnySource() &&
522 getFilenameIndex()) {
524 // Check if there is a change in the File ID sequence.
525 size_t Index
= getFilenameIndex();
526 if (options().changeFilenameIndex(Index
)) {
527 // Just to keep a nice layout.
529 printAttributes(OS
, /*Full=*/false);
532 if (getInvalidFilename())
533 OS
<< format("[0x%08x]\n", Index
);
535 OS
<< formattedName(getPathname()) << "\n";
540 void LVElement::printReference(raw_ostream
&OS
, bool Full
,
541 LVElement
*Parent
) const {
542 if (options().getPrintFormatting() && options().getAttributeReference())
543 printAttributes(OS
, Full
, "{Reference} ", Parent
,
544 referenceAsString(getLineNumber(), /*Spaces=*/false),
545 /*UseQuotes=*/false, /*PrintRef=*/true);
548 void LVElement::printLinkageName(raw_ostream
&OS
, bool Full
,
549 LVElement
*Parent
) const {
550 if (options().getPrintFormatting() && options().getAttributeLinkage()) {
551 printAttributes(OS
, Full
, "{Linkage} ", Parent
, getLinkageName(),
552 /*UseQuotes=*/true, /*PrintRef=*/false);
556 void LVElement::printLinkageName(raw_ostream
&OS
, bool Full
, LVElement
*Parent
,
557 LVScope
*Scope
) const {
558 if (options().getPrintFormatting() && options().getAttributeLinkage()) {
559 LVSectionIndex SectionIndex
= getReader().getSectionIndex(Scope
);
560 std::string Text
= (Twine(" 0x") + Twine::utohexstr(SectionIndex
) +
561 Twine(" '") + Twine(getLinkageName()) + Twine("'"))
563 printAttributes(OS
, Full
, "{Linkage} ", Parent
, Text
,
564 /*UseQuotes=*/false, /*PrintRef=*/false);