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