1 //===-- LVType.cpp --------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This implements the LVType class.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #include "llvm/DebugInfo/LogicalView/Core/LVType.h"
14 #include "llvm/DebugInfo/LogicalView/Core/LVCompare.h"
15 #include "llvm/DebugInfo/LogicalView/Core/LVReader.h"
16 #include "llvm/DebugInfo/LogicalView/Core/LVScope.h"
17
18 using namespace llvm;
19 using namespace llvm::logicalview;
20
21 #define DEBUG_TYPE "Type"
22
23 namespace {
24 const char *const KindBaseType = "BaseType";
25 const char *const KindConst = "Const";
26 const char *const KindEnumerator = "Enumerator";
27 const char *const KindImport = "Import";
28 const char *const KindPointer = "Pointer";
29 const char *const KindPointerMember = "PointerMember";
30 const char *const KindReference = "Reference";
31 const char *const KindRestrict = "Restrict";
32 const char *const KindRvalueReference = "RvalueReference";
33 const char *const KindSubrange = "Subrange";
34 const char *const KindTemplateTemplate = "TemplateTemplate";
35 const char *const KindTemplateType = "TemplateType";
36 const char *const KindTemplateValue = "TemplateValue";
37 const char *const KindTypeAlias = "TypeAlias";
38 const char *const KindUndefined = "Undefined";
39 const char *const KindUnaligned = "Unaligned";
40 const char *const KindUnspecified = "Unspecified";
41 const char *const KindVolatile = "Volatile";
42 } // end anonymous namespace
43
44 //===----------------------------------------------------------------------===//
45 // DWARF Type.
46 //===----------------------------------------------------------------------===//
47 // Return a string representation for the type kind.
kind() const48 const char *LVType::kind() const {
49 const char *Kind = KindUndefined;
50 if (getIsBase())
51 Kind = KindBaseType;
52 else if (getIsConst())
53 Kind = KindConst;
54 else if (getIsEnumerator())
55 Kind = KindEnumerator;
56 else if (getIsImport())
57 Kind = KindImport;
58 else if (getIsPointerMember())
59 Kind = KindPointerMember;
60 else if (getIsPointer())
61 Kind = KindPointer;
62 else if (getIsReference())
63 Kind = KindReference;
64 else if (getIsRestrict())
65 Kind = KindRestrict;
66 else if (getIsRvalueReference())
67 Kind = KindRvalueReference;
68 else if (getIsSubrange())
69 Kind = KindSubrange;
70 else if (getIsTemplateTypeParam())
71 Kind = KindTemplateType;
72 else if (getIsTemplateValueParam())
73 Kind = KindTemplateValue;
74 else if (getIsTemplateTemplateParam())
75 Kind = KindTemplateTemplate;
76 else if (getIsTypedef())
77 Kind = KindTypeAlias;
78 else if (getIsUnaligned())
79 Kind = KindUnaligned;
80 else if (getIsUnspecified())
81 Kind = KindUnspecified;
82 else if (getIsVolatile())
83 Kind = KindVolatile;
84 return Kind;
85 }
86
87 LVTypeDispatch LVType::Dispatch = {
88 {LVTypeKind::IsBase, &LVType::getIsBase},
89 {LVTypeKind::IsConst, &LVType::getIsConst},
90 {LVTypeKind::IsEnumerator, &LVType::getIsEnumerator},
91 {LVTypeKind::IsImport, &LVType::getIsImport},
92 {LVTypeKind::IsImportDeclaration, &LVType::getIsImportDeclaration},
93 {LVTypeKind::IsImportModule, &LVType::getIsImportModule},
94 {LVTypeKind::IsPointer, &LVType::getIsPointer},
95 {LVTypeKind::IsPointerMember, &LVType::getIsPointerMember},
96 {LVTypeKind::IsReference, &LVType::getIsReference},
97 {LVTypeKind::IsRestrict, &LVType::getIsRestrict},
98 {LVTypeKind::IsRvalueReference, &LVType::getIsRvalueReference},
99 {LVTypeKind::IsSubrange, &LVType::getIsSubrange},
100 {LVTypeKind::IsTemplateParam, &LVType::getIsTemplateParam},
101 {LVTypeKind::IsTemplateTemplateParam, &LVType::getIsTemplateTemplateParam},
102 {LVTypeKind::IsTemplateTypeParam, &LVType::getIsTemplateTypeParam},
103 {LVTypeKind::IsTemplateValueParam, &LVType::getIsTemplateValueParam},
104 {LVTypeKind::IsTypedef, &LVType::getIsTypedef},
105 {LVTypeKind::IsUnaligned, &LVType::getIsUnaligned},
106 {LVTypeKind::IsUnspecified, &LVType::getIsUnspecified},
107 {LVTypeKind::IsVolatile, &LVType::getIsVolatile}};
108
resolveReferences()109 void LVType::resolveReferences() {
110 // Some DWARF tags are the representation of types. However, we associate
111 // some of them to scopes. The ones associated with types, do not have
112 // any reference tags, such as DW_AT_specification, DW_AT_abstract_origin,
113 // DW_AT_extension.
114
115 // Set the file/line information using the Debug Information entry.
116 setFile(/*Reference=*/nullptr);
117
118 if (LVElement *Element = getType())
119 Element->resolve();
120 }
121
resolveName()122 void LVType::resolveName() {
123 if (getIsResolvedName())
124 return;
125 setIsResolvedName();
126
127 // The templates are recorded as normal DWARF objects relationships;
128 // the template parameters are preserved to show the types used during
129 // the instantiation; however if a compare have been requested, those
130 // parameters needs to be resolved, so no conflicts are generated.
131 // The following DWARF illustrates this issue:
132 //
133 // a) Template Parameters are preserved:
134 // {Class} 'ConstArray<AtomTable>'
135 // {Inherits} -> 'ArrayBase'
136 // {TemplateType} 'taTYPE' -> 'AtomTable'
137 // {Member} 'mData' -> '* taTYPE'
138 //
139 // b) Template Parameters are resolved:
140 // {Class} 'ConstArray<AtomTable>'
141 // {Inherits} -> 'ArrayBase'
142 // {TemplateType} 'taTYPE' -> 'AtomTable'
143 // {Member} 'mData' -> '* AtomTable'
144 //
145 // In (b), the {Member} type have been resolved to use the real type.
146
147 LVElement *BaseType = getType();
148 if (BaseType && options().getAttributeArgument())
149 if (BaseType->isTemplateParam())
150 BaseType = BaseType->getType();
151
152 if (BaseType && !BaseType->getIsResolvedName())
153 BaseType->resolveName();
154 resolveFullname(BaseType, getName());
155
156 // In the case of unnamed types, try to generate a name for it, using
157 // the parents name and the line information. Ignore the template parameters.
158 if (!isNamed() && !getIsTemplateParam())
159 generateName();
160
161 LVElement::resolveName();
162
163 // Resolve any given pattern.
164 patterns().resolvePatternMatch(this);
165 }
166
resolveReferencesChain()167 StringRef LVType::resolveReferencesChain() {
168 // The types do not have a DW_AT_specification or DW_AT_abstract_origin
169 // reference. Just return the type name.
170 return getName();
171 }
172
markMissingParents(const LVTypes * References,const LVTypes * Targets)173 void LVType::markMissingParents(const LVTypes *References,
174 const LVTypes *Targets) {
175 if (!(References && Targets))
176 return;
177
178 LLVM_DEBUG({
179 dbgs() << "\n[LVType::markMissingParents]\n";
180 for (const LVType *Reference : *References)
181 dbgs() << "References: "
182 << "Kind = " << formattedKind(Reference->kind()) << ", "
183 << "Name = " << formattedName(Reference->getName()) << "\n";
184 for (const LVType *Target : *Targets)
185 dbgs() << "Targets : "
186 << "Kind = " << formattedKind(Target->kind()) << ", "
187 << "Name = " << formattedName(Target->getName()) << "\n";
188 });
189
190 for (LVType *Reference : *References) {
191 LLVM_DEBUG({
192 dbgs() << "Search Reference: Name = "
193 << formattedName(Reference->getName()) << "\n";
194 });
195 if (!Reference->findIn(Targets))
196 Reference->markBranchAsMissing();
197 }
198 }
199
findIn(const LVTypes * Targets) const200 LVType *LVType::findIn(const LVTypes *Targets) const {
201 if (!Targets)
202 return nullptr;
203
204 LLVM_DEBUG({
205 dbgs() << "\n[LVType::findIn]\n"
206 << "Reference: "
207 << "Level = " << getLevel() << ", "
208 << "Kind = " << formattedKind(kind()) << ", "
209 << "Name = " << formattedName(getName()) << "\n";
210 for (const LVType *Target : *Targets)
211 dbgs() << "Target : "
212 << "Level = " << Target->getLevel() << ", "
213 << "Kind = " << formattedKind(Target->kind()) << ", "
214 << "Name = " << formattedName(Target->getName()) << "\n";
215 });
216
217 for (LVType *Target : *Targets)
218 if (equals(Target))
219 return Target;
220
221 return nullptr;
222 }
223
224 // Check for a match on the arguments of a function.
parametersMatch(const LVTypes * References,const LVTypes * Targets)225 bool LVType::parametersMatch(const LVTypes *References,
226 const LVTypes *Targets) {
227 if (!References && !Targets)
228 return true;
229 if (References && Targets) {
230 LVTypes ReferenceTypes;
231 LVScopes ReferenceScopes;
232 getParameters(References, &ReferenceTypes, &ReferenceScopes);
233 LVTypes TargetTypes;
234 LVScopes TargetScopes;
235 getParameters(Targets, &TargetTypes, &TargetScopes);
236 if (!LVType::equals(&ReferenceTypes, &TargetTypes) ||
237 !LVScope::equals(&ReferenceScopes, &TargetScopes))
238 return false;
239 return true;
240 }
241 return false;
242 }
243
244 // Return the types which are parameters.
getParameters(const LVTypes * Types,LVTypes * TypesParam,LVScopes * ScopesParam)245 void LVType::getParameters(const LVTypes *Types, LVTypes *TypesParam,
246 LVScopes *ScopesParam) {
247 if (!Types)
248 return;
249
250 // During a compare task, the template parameters are expanded to
251 // point to their real types, to avoid compare conflicts.
252 for (LVType *Type : *Types) {
253 if (!Type->getIsTemplateParam())
254 continue;
255 if (options().getAttributeArgument()) {
256 LVScope *Scope = nullptr;
257 if (Type->getIsKindType())
258 Type = Type->getTypeAsType();
259 else {
260 if (Type->getIsKindScope()) {
261 Scope = Type->getTypeAsScope();
262 Type = nullptr;
263 }
264 }
265 Type ? TypesParam->push_back(Type) : ScopesParam->push_back(Scope);
266 } else
267 TypesParam->push_back(Type);
268 }
269 }
270
equals(const LVType * Type) const271 bool LVType::equals(const LVType *Type) const {
272 return LVElement::equals(Type);
273 }
274
equals(const LVTypes * References,const LVTypes * Targets)275 bool LVType::equals(const LVTypes *References, const LVTypes *Targets) {
276 if (!References && !Targets)
277 return true;
278 if (References && Targets && References->size() == Targets->size()) {
279 for (const LVType *Reference : *References)
280 if (!Reference->findIn(Targets))
281 return false;
282 return true;
283 }
284 return false;
285 }
286
report(LVComparePass Pass)287 void LVType::report(LVComparePass Pass) {
288 getComparator().printItem(this, Pass);
289 }
290
print(raw_ostream & OS,bool Full) const291 void LVType::print(raw_ostream &OS, bool Full) const {
292 if (getIncludeInPrint() &&
293 (getIsReference() || getReader().doPrintType(this))) {
294 getReaderCompileUnit()->incrementPrintedTypes();
295 LVElement::print(OS, Full);
296 printExtra(OS, Full);
297 }
298 }
299
printExtra(raw_ostream & OS,bool Full) const300 void LVType::printExtra(raw_ostream &OS, bool Full) const {
301 OS << formattedKind(kind()) << " " << formattedName(getName()) << "\n";
302 }
303
304 //===----------------------------------------------------------------------===//
305 // DWARF typedef.
306 //===----------------------------------------------------------------------===//
307 // Return the underlying type for a typedef, which can be a type or scope.
getUnderlyingType()308 LVElement *LVTypeDefinition::getUnderlyingType() {
309 LVElement *BaseType = getTypeAsScope();
310 if (BaseType)
311 // Underlying type is a scope.
312 return BaseType;
313
314 LVType *Type = getTypeAsType();
315 assert(Type && "Type definition does not have a type.");
316
317 BaseType = Type;
318 while (Type->getIsTypedef()) {
319 BaseType = Type->getTypeAsScope();
320 if (BaseType)
321 // Underlying type is a scope.
322 return BaseType;
323
324 Type = Type->getTypeAsType();
325 if (Type)
326 BaseType = Type;
327 }
328
329 return BaseType;
330 }
331
resolveExtra()332 void LVTypeDefinition::resolveExtra() {
333 // Set the reference to the typedef type.
334 if (options().getAttributeUnderlying()) {
335 setUnderlyingType(getUnderlyingType());
336 setIsTypedefReduced();
337 if (LVElement *Type = getType()) {
338 Type->resolveName();
339 resolveFullname(Type);
340 }
341 }
342
343 // For the case of typedef'd anonymous structures:
344 // typedef struct { ... } Name;
345 // Propagate the typedef name to the anonymous structure.
346 LVScope *Aggregate = getTypeAsScope();
347 if (Aggregate && Aggregate->getIsAnonymous())
348 Aggregate->setName(getName());
349 }
350
equals(const LVType * Type) const351 bool LVTypeDefinition::equals(const LVType *Type) const {
352 return LVType::equals(Type);
353 }
354
printExtra(raw_ostream & OS,bool Full) const355 void LVTypeDefinition::printExtra(raw_ostream &OS, bool Full) const {
356 OS << formattedKind(kind()) << " " << formattedName(getName()) << " -> "
357 << typeOffsetAsString()
358 << formattedName((getType() ? getType()->getName() : "")) << "\n";
359 }
360
361 //===----------------------------------------------------------------------===//
362 // DWARF enumerator (DW_TAG_enumerator).
363 //===----------------------------------------------------------------------===//
equals(const LVType * Type) const364 bool LVTypeEnumerator::equals(const LVType *Type) const {
365 return LVType::equals(Type);
366 }
367
printExtra(raw_ostream & OS,bool Full) const368 void LVTypeEnumerator::printExtra(raw_ostream &OS, bool Full) const {
369 OS << formattedKind(kind()) << " '" << getName()
370 << "' = " << formattedName(getValue()) << "\n";
371 }
372
373 //===----------------------------------------------------------------------===//
374 // DWARF import (DW_TAG_imported_module / DW_TAG_imported_declaration).
375 //===----------------------------------------------------------------------===//
equals(const LVType * Type) const376 bool LVTypeImport::equals(const LVType *Type) const {
377 return LVType::equals(Type);
378 }
379
printExtra(raw_ostream & OS,bool Full) const380 void LVTypeImport::printExtra(raw_ostream &OS, bool Full) const {
381 std::string Attributes =
382 formatAttributes(virtualityString(), accessibilityString());
383
384 OS << formattedKind(kind()) << " " << typeOffsetAsString() << Attributes
385 << formattedName((getType() ? getType()->getName() : "")) << "\n";
386 }
387
388 //===----------------------------------------------------------------------===//
389 // DWARF Template parameter holder (type or param).
390 //===----------------------------------------------------------------------===//
LVTypeParam()391 LVTypeParam::LVTypeParam() : LVType() {
392 options().getAttributeTypename() ? setIncludeInPrint()
393 : resetIncludeInPrint();
394 }
395
396 // Encode the specific template argument.
encodeTemplateArgument(std::string & Name) const397 void LVTypeParam::encodeTemplateArgument(std::string &Name) const {
398 // The incoming type is a template parameter; we have 3 kinds of parameters:
399 // - type parameter: resolve the instance (type);
400 // - value parameter: resolve the constant value
401 // - template parameter: resolve the name of the template.
402 // If the parameter type is a template instance (STL sample), we need to
403 // expand the type (template template case). For the following variable
404 // declarations:
405 // std::type<float> a_float;
406 // std::type<int> a_int;
407 // We must generate names like:
408 // "std::type<float,std::less<float>,std::allocator<float>,false>"
409 // "std::type<int,std::less<int>,std::allocator<int>,false>"
410 // Instead of the incomplete names:
411 // "type<float,less,allocator,false>"
412 // "type<int,less,allocator,false>"
413
414 if (getIsTemplateTypeParam()) {
415 // Get the type instance recorded in the template type; it can be a
416 // reference to a type or to a scope.
417
418 if (getIsKindType()) {
419 // The argument types always are qualified.
420 Name.append(std::string(getTypeQualifiedName()));
421
422 LVType *ArgType = getTypeAsType();
423 // For template arguments that are typedefs, use the underlying type,
424 // which can be a type or scope.
425 if (ArgType->getIsTypedef()) {
426 LVObject *BaseType = ArgType->getUnderlyingType();
427 Name.append(std::string(BaseType->getName()));
428 } else {
429 Name.append(std::string(ArgType->getName()));
430 }
431 } else {
432 if (getIsKindScope()) {
433 LVScope *ArgScope = getTypeAsScope();
434 // If the scope is a template, we have to resolve that template,
435 // by recursively traversing its arguments.
436 if (ArgScope->getIsTemplate())
437 ArgScope->encodeTemplateArguments(Name);
438 else {
439 // The argument types always are qualified.
440 Name.append(std::string(getTypeQualifiedName()));
441 Name.append(std::string(ArgScope->getName()));
442 }
443 }
444 }
445 } else
446 // Template value parameter or template template parameter.
447 Name.append(getValue());
448 }
449
equals(const LVType * Type) const450 bool LVTypeParam::equals(const LVType *Type) const {
451 if (!LVType::equals(Type))
452 return false;
453
454 // Checks the kind of template argument.
455 if (getIsTemplateTypeParam() && Type->getIsTemplateTypeParam())
456 return getType()->equals(Type->getType());
457
458 if ((getIsTemplateValueParam() && Type->getIsTemplateValueParam()) ||
459 (getIsTemplateTemplateParam() && Type->getIsTemplateTemplateParam()))
460 return getValueIndex() == Type->getValueIndex();
461
462 return false;
463 }
464
printExtra(raw_ostream & OS,bool Full) const465 void LVTypeParam::printExtra(raw_ostream &OS, bool Full) const {
466 OS << formattedKind(kind()) << " " << formattedName(getName()) << " -> "
467 << typeOffsetAsString();
468
469 // Depending on the type of parameter, the print includes different
470 // information: type, value or reference to a template.
471 if (getIsTemplateTypeParam()) {
472 OS << formattedNames(getTypeQualifiedName(), getTypeName()) << "\n";
473 return;
474 }
475 if (getIsTemplateValueParam()) {
476 OS << formattedName(getValue()) << " " << formattedName(getName()) << "\n";
477 return;
478 }
479 if (getIsTemplateTemplateParam())
480 OS << formattedName(getValue()) << "\n";
481 }
482
483 //===----------------------------------------------------------------------===//
484 // DW_TAG_subrange_type
485 //===----------------------------------------------------------------------===//
resolveExtra()486 void LVTypeSubrange::resolveExtra() {
487 // There are 2 cases to represent the bounds information for an array:
488 // 1) DW_TAG_subrange_type
489 // DW_AT_type --> ref_type (type of count)
490 // DW_AT_count --> value (number of elements in subrange)
491
492 // 2) DW_TAG_subrange_type
493 // DW_AT_lower_bound --> value
494 // DW_AT_upper_bound --> value
495
496 // The idea is to represent the bounds as a string, depending on the format:
497 // 1) [count]
498 // 2) [lower..upper]
499
500 // Subrange information.
501 std::string String;
502
503 // Check if we have DW_AT_count subrange style.
504 if (getIsSubrangeCount())
505 // Get count subrange value. Assume 0 if missing.
506 raw_string_ostream(String) << "[" << getCount() << "]";
507 else
508 raw_string_ostream(String)
509 << "[" << getLowerBound() << ".." << getUpperBound() << "]";
510
511 setName(String);
512 }
513
equals(const LVType * Type) const514 bool LVTypeSubrange::equals(const LVType *Type) const {
515 if (!LVType::equals(Type))
516 return false;
517
518 return getTypeName() == Type->getTypeName() && getName() == Type->getName();
519 }
520
printExtra(raw_ostream & OS,bool Full) const521 void LVTypeSubrange::printExtra(raw_ostream &OS, bool Full) const {
522 OS << formattedKind(kind()) << " -> " << typeOffsetAsString()
523 << formattedName(getTypeName()) << " " << formattedName(getName()) << "\n";
524 }
525