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