xref: /freebsd/contrib/llvm-project/llvm/lib/DebugInfo/LogicalView/Core/LVType.cpp (revision 700637cbb5e582861067a11aaca4d053546871d2)
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       if (Type->getIsKindType())
257         TypesParam->push_back(Type->getTypeAsType());
258       else if (Type->getIsKindScope())
259         ScopesParam->push_back(Type->getTypeAsScope());
260     } else
261       TypesParam->push_back(Type);
262   }
263 }
264 
equals(const LVType * Type) const265 bool LVType::equals(const LVType *Type) const {
266   return LVElement::equals(Type);
267 }
268 
equals(const LVTypes * References,const LVTypes * Targets)269 bool LVType::equals(const LVTypes *References, const LVTypes *Targets) {
270   if (!References && !Targets)
271     return true;
272   if (References && Targets && References->size() == Targets->size()) {
273     for (const LVType *Reference : *References)
274       if (!Reference->findIn(Targets))
275         return false;
276     return true;
277   }
278   return false;
279 }
280 
report(LVComparePass Pass)281 void LVType::report(LVComparePass Pass) {
282   getComparator().printItem(this, Pass);
283 }
284 
print(raw_ostream & OS,bool Full) const285 void LVType::print(raw_ostream &OS, bool Full) const {
286   if (getIncludeInPrint() &&
287       (getIsReference() || getReader().doPrintType(this))) {
288     getReaderCompileUnit()->incrementPrintedTypes();
289     LVElement::print(OS, Full);
290     printExtra(OS, Full);
291   }
292 }
293 
printExtra(raw_ostream & OS,bool Full) const294 void LVType::printExtra(raw_ostream &OS, bool Full) const {
295   OS << formattedKind(kind()) << " " << formattedName(getName());
296   if (options().getAttributeSize())
297     if (uint32_t Size = getStorageSizeInBytes())
298       OS << " [Size = " << Size << "]";
299   OS << "\n";
300 }
301 
302 //===----------------------------------------------------------------------===//
303 // DWARF typedef.
304 //===----------------------------------------------------------------------===//
305 // Return the underlying type for a typedef, which can be a type or scope.
getUnderlyingType()306 LVElement *LVTypeDefinition::getUnderlyingType() {
307   LVElement *BaseType = getTypeAsScope();
308   if (BaseType)
309     // Underlying type is a scope.
310     return BaseType;
311 
312   LVType *Type = getTypeAsType();
313   assert(Type && "Type definition does not have a type.");
314 
315   BaseType = Type;
316   while (Type->getIsTypedef()) {
317     BaseType = Type->getTypeAsScope();
318     if (BaseType)
319       // Underlying type is a scope.
320       return BaseType;
321 
322     Type = Type->getTypeAsType();
323     if (Type)
324       BaseType = Type;
325   }
326 
327   return BaseType;
328 }
329 
resolveExtra()330 void LVTypeDefinition::resolveExtra() {
331   // In the case of CodeView, the MSVC toolset generates a series of typedefs
332   // that refer to internal runtime structures, that we do not process. Those
333   // typedefs are marked as 'system'. They have an associated logical type,
334   // but the underlying type always is null.
335   if (getIsSystem())
336     return;
337 
338   // Set the reference to the typedef type.
339   if (options().getAttributeUnderlying()) {
340     setUnderlyingType(getUnderlyingType());
341     setIsTypedefReduced();
342     if (LVElement *Type = getType()) {
343       Type->resolveName();
344       resolveFullname(Type);
345     }
346   }
347 
348   // For the case of typedef'd anonymous structures:
349   //   typedef struct { ... } Name;
350   // Propagate the typedef name to the anonymous structure.
351   LVScope *Aggregate = getTypeAsScope();
352   if (Aggregate && Aggregate->getIsAnonymous())
353     Aggregate->setName(getName());
354 }
355 
equals(const LVType * Type) const356 bool LVTypeDefinition::equals(const LVType *Type) const {
357   return LVType::equals(Type);
358 }
359 
printExtra(raw_ostream & OS,bool Full) const360 void LVTypeDefinition::printExtra(raw_ostream &OS, bool Full) const {
361   OS << formattedKind(kind()) << " " << formattedName(getName()) << " -> "
362      << typeOffsetAsString()
363      << formattedName((getType() ? getType()->getName() : "")) << "\n";
364 }
365 
366 //===----------------------------------------------------------------------===//
367 // DWARF enumerator (DW_TAG_enumerator).
368 //===----------------------------------------------------------------------===//
equals(const LVType * Type) const369 bool LVTypeEnumerator::equals(const LVType *Type) const {
370   return LVType::equals(Type);
371 }
372 
printExtra(raw_ostream & OS,bool Full) const373 void LVTypeEnumerator::printExtra(raw_ostream &OS, bool Full) const {
374   OS << formattedKind(kind()) << " '" << getName()
375      << "' = " << formattedName(getValue()) << "\n";
376 }
377 
378 //===----------------------------------------------------------------------===//
379 // DWARF import (DW_TAG_imported_module / DW_TAG_imported_declaration).
380 //===----------------------------------------------------------------------===//
equals(const LVType * Type) const381 bool LVTypeImport::equals(const LVType *Type) const {
382   return LVType::equals(Type);
383 }
384 
printExtra(raw_ostream & OS,bool Full) const385 void LVTypeImport::printExtra(raw_ostream &OS, bool Full) const {
386   std::string Attributes =
387       formatAttributes(virtualityString(), accessibilityString());
388 
389   OS << formattedKind(kind()) << " " << typeOffsetAsString() << Attributes
390      << formattedName((getType() ? getType()->getName() : "")) << "\n";
391 }
392 
393 //===----------------------------------------------------------------------===//
394 // DWARF Template parameter holder (type or param).
395 //===----------------------------------------------------------------------===//
LVTypeParam()396 LVTypeParam::LVTypeParam() : LVType() {
397   options().getAttributeTypename() ? setIncludeInPrint()
398                                    : resetIncludeInPrint();
399 }
400 
401 // Encode the specific template argument.
encodeTemplateArgument(std::string & Name) const402 void LVTypeParam::encodeTemplateArgument(std::string &Name) const {
403   // The incoming type is a template parameter; we have 3 kinds of parameters:
404   // - type parameter: resolve the instance (type);
405   // - value parameter: resolve the constant value
406   // - template parameter: resolve the name of the template.
407   // If the parameter type is a template instance (STL sample), we need to
408   // expand the type (template template case). For the following variable
409   // declarations:
410   //   std::type<float> a_float;
411   //   std::type<int> a_int;
412   // We must generate names like:
413   //   "std::type<float,std::less<float>,std::allocator<float>,false>"
414   //   "std::type<int,std::less<int>,std::allocator<int>,false>"
415   // Instead of the incomplete names:
416   //   "type<float,less,allocator,false>"
417   //   "type<int,less,allocator,false>"
418 
419   if (getIsTemplateTypeParam()) {
420     // Get the type instance recorded in the template type; it can be a
421     // reference to a type or to a scope.
422 
423     if (getIsKindType()) {
424       // The argument types always are qualified.
425       Name.append(std::string(getTypeQualifiedName()));
426 
427       LVType *ArgType = getTypeAsType();
428       // For template arguments that are typedefs, use the underlying type,
429       // which can be a type or scope.
430       if (ArgType->getIsTypedef()) {
431         LVObject *BaseType = ArgType->getUnderlyingType();
432         Name.append(std::string(BaseType->getName()));
433       } else {
434         Name.append(std::string(ArgType->getName()));
435       }
436     } else {
437       if (getIsKindScope()) {
438         LVScope *ArgScope = getTypeAsScope();
439         // If the scope is a template, we have to resolve that template,
440         // by recursively traversing its arguments.
441         if (ArgScope->getIsTemplate())
442           ArgScope->encodeTemplateArguments(Name);
443         else {
444           // The argument types always are qualified.
445           Name.append(std::string(getTypeQualifiedName()));
446           Name.append(std::string(ArgScope->getName()));
447         }
448       }
449     }
450   } else
451     // Template value parameter or template template parameter.
452     Name.append(getValue());
453 }
454 
equals(const LVType * Type) const455 bool LVTypeParam::equals(const LVType *Type) const {
456   if (!LVType::equals(Type))
457     return false;
458 
459   // Checks the kind of template argument.
460   if (getIsTemplateTypeParam() && Type->getIsTemplateTypeParam())
461     return getType()->equals(Type->getType());
462 
463   if ((getIsTemplateValueParam() && Type->getIsTemplateValueParam()) ||
464       (getIsTemplateTemplateParam() && Type->getIsTemplateTemplateParam()))
465     return getValueIndex() == Type->getValueIndex();
466 
467   return false;
468 }
469 
printExtra(raw_ostream & OS,bool Full) const470 void LVTypeParam::printExtra(raw_ostream &OS, bool Full) const {
471   OS << formattedKind(kind()) << " " << formattedName(getName()) << " -> "
472      << typeOffsetAsString();
473 
474   // Depending on the type of parameter, the print includes different
475   // information: type, value or reference to a template.
476   if (getIsTemplateTypeParam()) {
477     OS << formattedNames(getTypeQualifiedName(), getTypeName()) << "\n";
478     return;
479   }
480   if (getIsTemplateValueParam()) {
481     OS << formattedName(getValue()) << " " << formattedName(getName()) << "\n";
482     return;
483   }
484   if (getIsTemplateTemplateParam())
485     OS << formattedName(getValue()) << "\n";
486 }
487 
488 //===----------------------------------------------------------------------===//
489 // DW_TAG_subrange_type
490 //===----------------------------------------------------------------------===//
resolveExtra()491 void LVTypeSubrange::resolveExtra() {
492   // There are 2 cases to represent the bounds information for an array:
493   // 1) DW_TAG_subrange_type
494   //      DW_AT_type --> ref_type (type of count)
495   //      DW_AT_count --> value (number of elements in subrange)
496 
497   // 2) DW_TAG_subrange_type
498   //      DW_AT_lower_bound --> value
499   //      DW_AT_upper_bound --> value
500 
501   // The idea is to represent the bounds as a string, depending on the format:
502   // 1) [count]
503   // 2) [lower..upper]
504 
505   // Subrange information.
506   std::string String;
507 
508   // Check if we have DW_AT_count subrange style.
509   if (getIsSubrangeCount())
510     // Get count subrange value. Assume 0 if missing.
511     raw_string_ostream(String) << "[" << getCount() << "]";
512   else
513     raw_string_ostream(String)
514         << "[" << getLowerBound() << ".." << getUpperBound() << "]";
515 
516   setName(String);
517 }
518 
equals(const LVType * Type) const519 bool LVTypeSubrange::equals(const LVType *Type) const {
520   if (!LVType::equals(Type))
521     return false;
522 
523   return getTypeName() == Type->getTypeName() && getName() == Type->getName();
524 }
525 
printExtra(raw_ostream & OS,bool Full) const526 void LVTypeSubrange::printExtra(raw_ostream &OS, bool Full) const {
527   OS << formattedKind(kind()) << " -> " << typeOffsetAsString()
528      << formattedName(getTypeName()) << " " << formattedName(getName()) << "\n";
529 }
530