1//===- SyntheticTypeNameBuilder.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#ifndef LLVM_LIB_DWARFLINKER_PARALLEL_SYNTHETICTYPENAMEBUILDER_H
10#define LLVM_LIB_DWARFLINKER_PARALLEL_SYNTHETICTYPENAMEBUILDER_H
11
12#include "DWARFLinkerCompileUnit.h"
13#include "DWARFLinkerGlobalData.h"
14#include "llvm/ADT/SmallString.h"
15#include "llvm/ADT/SmallVector.h"
16
17namespace llvm {
18class DWARFDebugInfoEntry;
19
20namespace dwarf_linker {
21namespace parallel {
22struct LinkContext;
23class TypeTableUnit;
24class CompileUnit;
25
26/// The helper class to build type name based on DIE properties.
27/// It builds synthetic name based on explicit attributes: DW_AT_name,
28/// DW_AT_linkage_name or based on implicit attributes(DW_AT_decl*).
29/// Names for specific DIEs(like subprograms, template classes...) include
30/// additional attributes: subprogram parameters, template parameters,
31/// array ranges. Examples of built name:
32///
33/// class A { } : {8}A
34///
35/// namspace llvm { class A { } } : {1}llvm{8}A
36///
37/// template <int> structure B { } : {F}B<{0}int>
38///
39/// void foo ( int p1, float p3 ) : {a}void foo({0}int, {0}int)
40///
41/// int *ptr; : {c}ptr {0}int
42///
43/// int var; : {d}var
44///
45/// These names is used to refer DIEs describing types.
46class SyntheticTypeNameBuilder {
47public:
48 SyntheticTypeNameBuilder(TypePool &TypePoolRef) : TypePoolRef(TypePoolRef) {}
49
50 /// Create synthetic name for the specified DIE \p InputUnitEntryPair
51 /// and assign created name to the DIE type info. \p ChildIndex is used
52 /// to create name for ordered DIEs(function arguments f.e.).
53 Error assignName(UnitEntryPairTy InputUnitEntryPair,
54 std::optional<std::pair<size_t, size_t>> ChildIndex);
55
56protected:
57 /// Add array type dimension.
58 void addArrayDimension(UnitEntryPairTy InputUnitEntryPair);
59
60 /// Add signature( entry type plus type of parameters plus type of template
61 /// parameters(if \p addTemplateParameters is true).
62 Error addSignature(UnitEntryPairTy InputUnitEntryPair,
63 bool addTemplateParameters);
64
65 /// Add specified \p FunctionParameters to the built name.
66 Error addParamNames(
67 CompileUnit &CU,
68 SmallVector<const DWARFDebugInfoEntry *, 20> &FunctionParameters);
69
70 /// Add specified \p TemplateParameters to the built name.
71 Error addTemplateParamNames(
72 CompileUnit &CU,
73 SmallVector<const DWARFDebugInfoEntry *, 10> &TemplateParameters);
74
75 /// Analyze \p InputUnitEntryPair's ODR attributes and put names
76 /// of the referenced type dies to the built name.
77 Error addReferencedODRDies(UnitEntryPairTy InputUnitEntryPair,
78 bool AssignNameToTypeDescriptor,
79 ArrayRef<dwarf::Attribute> ODRAttrs);
80
81 /// Resolve the DIE that \p Attr of \p InputUnitEntryPair refers to.
82 /// \returns std::nullopt if there is nothing to follow.
83 Expected<std::optional<UnitEntryPairTy>>
84 resolveReference(UnitEntryPairTy InputUnitEntryPair, dwarf::Attribute Attr);
85
86 /// Count a referenced DIE toward the recursion limit. Callers decrement
87 /// RecursionDepth once they are done with it.
88 Error incrementRecursionDepth();
89
90 /// Add names of parent dies to the built name.
91 Error addParentName(UnitEntryPairTy &InputUnitEntryPair);
92
93 /// \returns synthetic name of the specified \p DieEntry.
94 /// The name is constructed from the dwarf::DW_AT_decl_file
95 /// and dwarf::DW_AT_decl_line attributes.
96 void addDieNameFromDeclFileAndDeclLine(UnitEntryPairTy &InputUnitEntryPair,
97 bool &HasDeclFileName);
98
99 /// Add contents of the unnamed type \p InputUnitEntryPair.
100 Error addUnnamedTypeContents(UnitEntryPairTy InputUnitEntryPair);
101
102 /// Add the type \p InputUnitEntryPair refers to, without parent scopes. A
103 /// type nested in an unnamed type would need the name being built.
104 Error addUnqualifiedTypeName(UnitEntryPairTy InputUnitEntryPair);
105
106 /// Add type prefix to the built name.
107 void addTypePrefix(CompileUnit &CU, const DWARFDebugInfoEntry *DieEntry);
108
109 /// Add type name to the built name.
110 Error addTypeName(UnitEntryPairTy InputUnitEntryPair, bool AddParentNames);
111
112 /// Analyze \p InputUnitEntryPair for the type name and possibly assign
113 /// built type name to the DIE's type info.
114 /// NOTE: while analyzing types we may create different kind of names
115 /// for the same type depending on whether the type is part of another type.
116 /// f.e. DW_TAG_formal_parameter would receive "{02}01" name when
117 /// examined alone. Or "{0}int" name when it is a part of a function name:
118 /// {a}void foo({0}int). The \p AssignNameToTypeDescriptor tells whether
119 /// the type name is part of another type name and then should not be assigned
120 /// to DIE type descriptor.
121 Error addDIETypeName(UnitEntryPairTy InputUnitEntryPair,
122 std::optional<std::pair<size_t, size_t>> ChildIndex,
123 bool AssignNameToTypeDescriptor);
124
125 /// Add ordered name to the built name.
126 void addOrderedName(std::pair<size_t, size_t> ChildIdx);
127
128 /// Add value name to the built name.
129 void addValueName(UnitEntryPairTy InputUnitEntryPair, dwarf::Attribute Attr);
130
131 /// Buffer keeping bult name.
132 SmallString<1000> SyntheticName;
133
134 /// Recursion counter
135 size_t RecursionDepth = 0;
136
137 /// Bounds RecursionDepth, which malformed input can make unbounded.
138 static constexpr size_t MaxRecursionDepth = 1000;
139
140 /// Type pool
141 TypePool &TypePoolRef;
142};
143
144/// This class helps to assign indexes for DIE children.
145/// Indexes are used to create type name for children which
146/// should be presented in the original order(function parameters,
147/// array dimensions, enumeration members, class/structure members).
148class OrderedChildrenIndexAssigner {
149public:
150 OrderedChildrenIndexAssigner(CompileUnit &CU,
151 const DWARFDebugInfoEntry *DieEntry);
152
153 /// Returns index of the specified child and width of hexadecimal
154 /// representation.
155 std::optional<std::pair<size_t, size_t>>
156 getChildIndex(CompileUnit &CU, const DWARFDebugInfoEntry *ChildDieEntry);
157
158protected:
159 using OrderedChildrenIndexesArrayTy = std::array<size_t, 8>;
160
161 std::optional<size_t> tagToArrayIndex(CompileUnit &CU,
162 const DWARFDebugInfoEntry *DieEntry);
163
164 bool NeedCountChildren = false;
165 OrderedChildrenIndexesArrayTy OrderedChildIdxs = {0};
166 OrderedChildrenIndexesArrayTy ChildIndexesWidth = {0};
167};
168
169} // end of namespace parallel
170} // end of namespace dwarf_linker
171} // end of namespace llvm
172
173#endif // LLVM_LIB_DWARFLINKER_PARALLEL_SYNTHETICTYPENAMEBUILDER_H
174