1 //===- XCore.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 #include "ABIInfoImpl.h" 10 #include "TargetInfo.h" 11 12 using namespace clang; 13 using namespace clang::CodeGen; 14 15 //===----------------------------------------------------------------------===// 16 // XCore ABI Implementation 17 //===----------------------------------------------------------------------===// 18 19 namespace { 20 21 /// A SmallStringEnc instance is used to build up the TypeString by passing 22 /// it by reference between functions that append to it. 23 typedef llvm::SmallString<128> SmallStringEnc; 24 25 /// TypeStringCache caches the meta encodings of Types. 26 /// 27 /// The reason for caching TypeStrings is two fold: 28 /// 1. To cache a type's encoding for later uses; 29 /// 2. As a means to break recursive member type inclusion. 30 /// 31 /// A cache Entry can have a Status of: 32 /// NonRecursive: The type encoding is not recursive; 33 /// Recursive: The type encoding is recursive; 34 /// Incomplete: An incomplete TypeString; 35 /// IncompleteUsed: An incomplete TypeString that has been used in a 36 /// Recursive type encoding. 37 /// 38 /// A NonRecursive entry will have all of its sub-members expanded as fully 39 /// as possible. Whilst it may contain types which are recursive, the type 40 /// itself is not recursive and thus its encoding may be safely used whenever 41 /// the type is encountered. 42 /// 43 /// A Recursive entry will have all of its sub-members expanded as fully as 44 /// possible. The type itself is recursive and it may contain other types which 45 /// are recursive. The Recursive encoding must not be used during the expansion 46 /// of a recursive type's recursive branch. For simplicity the code uses 47 /// IncompleteCount to reject all usage of Recursive encodings for member types. 48 /// 49 /// An Incomplete entry is always a RecordType and only encodes its 50 /// identifier e.g. "s(S){}". Incomplete 'StubEnc' entries are ephemeral and 51 /// are placed into the cache during type expansion as a means to identify and 52 /// handle recursive inclusion of types as sub-members. If there is recursion 53 /// the entry becomes IncompleteUsed. 54 /// 55 /// During the expansion of a RecordType's members: 56 /// 57 /// If the cache contains a NonRecursive encoding for the member type, the 58 /// cached encoding is used; 59 /// 60 /// If the cache contains a Recursive encoding for the member type, the 61 /// cached encoding is 'Swapped' out, as it may be incorrect, and... 62 /// 63 /// If the member is a RecordType, an Incomplete encoding is placed into the 64 /// cache to break potential recursive inclusion of itself as a sub-member; 65 /// 66 /// Once a member RecordType has been expanded, its temporary incomplete 67 /// entry is removed from the cache. If a Recursive encoding was swapped out 68 /// it is swapped back in; 69 /// 70 /// If an incomplete entry is used to expand a sub-member, the incomplete 71 /// entry is marked as IncompleteUsed. The cache keeps count of how many 72 /// IncompleteUsed entries it currently contains in IncompleteUsedCount; 73 /// 74 /// If a member's encoding is found to be a NonRecursive or Recursive viz: 75 /// IncompleteUsedCount==0, the member's encoding is added to the cache. 76 /// Else the member is part of a recursive type and thus the recursion has 77 /// been exited too soon for the encoding to be correct for the member. 78 /// 79 class TypeStringCache { 80 enum Status {NonRecursive, Recursive, Incomplete, IncompleteUsed}; 81 struct Entry { 82 std::string Str; // The encoded TypeString for the type. 83 enum Status State; // Information about the encoding in 'Str'. 84 std::string Swapped; // A temporary place holder for a Recursive encoding 85 // during the expansion of RecordType's members. 86 }; 87 std::map<const IdentifierInfo *, struct Entry> Map; 88 unsigned IncompleteCount; // Number of Incomplete entries in the Map. 89 unsigned IncompleteUsedCount; // Number of IncompleteUsed entries in the Map. 90 public: 91 TypeStringCache() : IncompleteCount(0), IncompleteUsedCount(0) {} 92 void addIncomplete(const IdentifierInfo *ID, std::string StubEnc); 93 bool removeIncomplete(const IdentifierInfo *ID); 94 void addIfComplete(const IdentifierInfo *ID, StringRef Str, 95 bool IsRecursive); 96 StringRef lookupStr(const IdentifierInfo *ID); 97 }; 98 99 /// TypeString encodings for enum & union fields must be order. 100 /// FieldEncoding is a helper for this ordering process. 101 class FieldEncoding { 102 bool HasName; 103 std::string Enc; 104 public: 105 FieldEncoding(bool b, SmallStringEnc &e) : HasName(b), Enc(e.c_str()) {} 106 StringRef str() { return Enc; } 107 bool operator<(const FieldEncoding &rhs) const { 108 if (HasName != rhs.HasName) return HasName; 109 return Enc < rhs.Enc; 110 } 111 }; 112 113 class XCoreABIInfo : public DefaultABIInfo { 114 public: 115 XCoreABIInfo(CodeGen::CodeGenTypes &CGT) : DefaultABIInfo(CGT) {} 116 Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, 117 QualType Ty) const override; 118 }; 119 120 class XCoreTargetCodeGenInfo : public TargetCodeGenInfo { 121 mutable TypeStringCache TSC; 122 void emitTargetMD(const Decl *D, llvm::GlobalValue *GV, 123 const CodeGen::CodeGenModule &M) const; 124 125 public: 126 XCoreTargetCodeGenInfo(CodeGenTypes &CGT) 127 : TargetCodeGenInfo(std::make_unique<XCoreABIInfo>(CGT)) {} 128 void emitTargetMetadata(CodeGen::CodeGenModule &CGM, 129 const llvm::MapVector<GlobalDecl, StringRef> 130 &MangledDeclNames) const override; 131 }; 132 133 } // End anonymous namespace. 134 135 // TODO: this implementation is likely now redundant with the default 136 // EmitVAArg. 137 Address XCoreABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, 138 QualType Ty) const { 139 CGBuilderTy &Builder = CGF.Builder; 140 141 // Get the VAList. 142 CharUnits SlotSize = CharUnits::fromQuantity(4); 143 Address AP = Address(Builder.CreateLoad(VAListAddr), 144 getVAListElementType(CGF), SlotSize); 145 146 // Handle the argument. 147 ABIArgInfo AI = classifyArgumentType(Ty); 148 CharUnits TypeAlign = getContext().getTypeAlignInChars(Ty); 149 llvm::Type *ArgTy = CGT.ConvertType(Ty); 150 if (AI.canHaveCoerceToType() && !AI.getCoerceToType()) 151 AI.setCoerceToType(ArgTy); 152 llvm::Type *ArgPtrTy = llvm::PointerType::getUnqual(ArgTy); 153 154 Address Val = Address::invalid(); 155 CharUnits ArgSize = CharUnits::Zero(); 156 switch (AI.getKind()) { 157 case ABIArgInfo::Expand: 158 case ABIArgInfo::CoerceAndExpand: 159 case ABIArgInfo::InAlloca: 160 llvm_unreachable("Unsupported ABI kind for va_arg"); 161 case ABIArgInfo::Ignore: 162 Val = Address(llvm::UndefValue::get(ArgPtrTy), ArgTy, TypeAlign); 163 ArgSize = CharUnits::Zero(); 164 break; 165 case ABIArgInfo::Extend: 166 case ABIArgInfo::Direct: 167 Val = AP.withElementType(ArgTy); 168 ArgSize = CharUnits::fromQuantity( 169 getDataLayout().getTypeAllocSize(AI.getCoerceToType())); 170 ArgSize = ArgSize.alignTo(SlotSize); 171 break; 172 case ABIArgInfo::Indirect: 173 case ABIArgInfo::IndirectAliased: 174 Val = AP.withElementType(ArgPtrTy); 175 Val = Address(Builder.CreateLoad(Val), ArgTy, TypeAlign); 176 ArgSize = SlotSize; 177 break; 178 } 179 180 // Increment the VAList. 181 if (!ArgSize.isZero()) { 182 Address APN = Builder.CreateConstInBoundsByteGEP(AP, ArgSize); 183 Builder.CreateStore(APN.getPointer(), VAListAddr); 184 } 185 186 return Val; 187 } 188 189 /// During the expansion of a RecordType, an incomplete TypeString is placed 190 /// into the cache as a means to identify and break recursion. 191 /// If there is a Recursive encoding in the cache, it is swapped out and will 192 /// be reinserted by removeIncomplete(). 193 /// All other types of encoding should have been used rather than arriving here. 194 void TypeStringCache::addIncomplete(const IdentifierInfo *ID, 195 std::string StubEnc) { 196 if (!ID) 197 return; 198 Entry &E = Map[ID]; 199 assert( (E.Str.empty() || E.State == Recursive) && 200 "Incorrectly use of addIncomplete"); 201 assert(!StubEnc.empty() && "Passing an empty string to addIncomplete()"); 202 E.Swapped.swap(E.Str); // swap out the Recursive 203 E.Str.swap(StubEnc); 204 E.State = Incomplete; 205 ++IncompleteCount; 206 } 207 208 /// Once the RecordType has been expanded, the temporary incomplete TypeString 209 /// must be removed from the cache. 210 /// If a Recursive was swapped out by addIncomplete(), it will be replaced. 211 /// Returns true if the RecordType was defined recursively. 212 bool TypeStringCache::removeIncomplete(const IdentifierInfo *ID) { 213 if (!ID) 214 return false; 215 auto I = Map.find(ID); 216 assert(I != Map.end() && "Entry not present"); 217 Entry &E = I->second; 218 assert( (E.State == Incomplete || 219 E.State == IncompleteUsed) && 220 "Entry must be an incomplete type"); 221 bool IsRecursive = false; 222 if (E.State == IncompleteUsed) { 223 // We made use of our Incomplete encoding, thus we are recursive. 224 IsRecursive = true; 225 --IncompleteUsedCount; 226 } 227 if (E.Swapped.empty()) 228 Map.erase(I); 229 else { 230 // Swap the Recursive back. 231 E.Swapped.swap(E.Str); 232 E.Swapped.clear(); 233 E.State = Recursive; 234 } 235 --IncompleteCount; 236 return IsRecursive; 237 } 238 239 /// Add the encoded TypeString to the cache only if it is NonRecursive or 240 /// Recursive (viz: all sub-members were expanded as fully as possible). 241 void TypeStringCache::addIfComplete(const IdentifierInfo *ID, StringRef Str, 242 bool IsRecursive) { 243 if (!ID || IncompleteUsedCount) 244 return; // No key or it is an incomplete sub-type so don't add. 245 Entry &E = Map[ID]; 246 if (IsRecursive && !E.Str.empty()) { 247 assert(E.State==Recursive && E.Str.size() == Str.size() && 248 "This is not the same Recursive entry"); 249 // The parent container was not recursive after all, so we could have used 250 // this Recursive sub-member entry after all, but we assumed the worse when 251 // we started viz: IncompleteCount!=0. 252 return; 253 } 254 assert(E.Str.empty() && "Entry already present"); 255 E.Str = Str.str(); 256 E.State = IsRecursive? Recursive : NonRecursive; 257 } 258 259 /// Return a cached TypeString encoding for the ID. If there isn't one, or we 260 /// are recursively expanding a type (IncompleteCount != 0) and the cached 261 /// encoding is Recursive, return an empty StringRef. 262 StringRef TypeStringCache::lookupStr(const IdentifierInfo *ID) { 263 if (!ID) 264 return StringRef(); // We have no key. 265 auto I = Map.find(ID); 266 if (I == Map.end()) 267 return StringRef(); // We have no encoding. 268 Entry &E = I->second; 269 if (E.State == Recursive && IncompleteCount) 270 return StringRef(); // We don't use Recursive encodings for member types. 271 272 if (E.State == Incomplete) { 273 // The incomplete type is being used to break out of recursion. 274 E.State = IncompleteUsed; 275 ++IncompleteUsedCount; 276 } 277 return E.Str; 278 } 279 280 /// The XCore ABI includes a type information section that communicates symbol 281 /// type information to the linker. The linker uses this information to verify 282 /// safety/correctness of things such as array bound and pointers et al. 283 /// The ABI only requires C (and XC) language modules to emit TypeStrings. 284 /// This type information (TypeString) is emitted into meta data for all global 285 /// symbols: definitions, declarations, functions & variables. 286 /// 287 /// The TypeString carries type, qualifier, name, size & value details. 288 /// Please see 'Tools Development Guide' section 2.16.2 for format details: 289 /// https://www.xmos.com/download/public/Tools-Development-Guide%28X9114A%29.pdf 290 /// The output is tested by test/CodeGen/xcore-stringtype.c. 291 /// 292 static bool getTypeString(SmallStringEnc &Enc, const Decl *D, 293 const CodeGen::CodeGenModule &CGM, 294 TypeStringCache &TSC); 295 296 /// XCore uses emitTargetMD to emit TypeString metadata for global symbols. 297 void XCoreTargetCodeGenInfo::emitTargetMD( 298 const Decl *D, llvm::GlobalValue *GV, 299 const CodeGen::CodeGenModule &CGM) const { 300 SmallStringEnc Enc; 301 if (getTypeString(Enc, D, CGM, TSC)) { 302 llvm::LLVMContext &Ctx = CGM.getModule().getContext(); 303 llvm::Metadata *MDVals[] = {llvm::ConstantAsMetadata::get(GV), 304 llvm::MDString::get(Ctx, Enc.str())}; 305 llvm::NamedMDNode *MD = 306 CGM.getModule().getOrInsertNamedMetadata("xcore.typestrings"); 307 MD->addOperand(llvm::MDNode::get(Ctx, MDVals)); 308 } 309 } 310 311 void XCoreTargetCodeGenInfo::emitTargetMetadata( 312 CodeGen::CodeGenModule &CGM, 313 const llvm::MapVector<GlobalDecl, StringRef> &MangledDeclNames) const { 314 // Warning, new MangledDeclNames may be appended within this loop. 315 // We rely on MapVector insertions adding new elements to the end 316 // of the container. 317 for (unsigned I = 0; I != MangledDeclNames.size(); ++I) { 318 auto Val = *(MangledDeclNames.begin() + I); 319 llvm::GlobalValue *GV = CGM.GetGlobalValue(Val.second); 320 if (GV) { 321 const Decl *D = Val.first.getDecl()->getMostRecentDecl(); 322 emitTargetMD(D, GV, CGM); 323 } 324 } 325 } 326 327 static bool appendType(SmallStringEnc &Enc, QualType QType, 328 const CodeGen::CodeGenModule &CGM, 329 TypeStringCache &TSC); 330 331 /// Helper function for appendRecordType(). 332 /// Builds a SmallVector containing the encoded field types in declaration 333 /// order. 334 static bool extractFieldType(SmallVectorImpl<FieldEncoding> &FE, 335 const RecordDecl *RD, 336 const CodeGen::CodeGenModule &CGM, 337 TypeStringCache &TSC) { 338 for (const auto *Field : RD->fields()) { 339 SmallStringEnc Enc; 340 Enc += "m("; 341 Enc += Field->getName(); 342 Enc += "){"; 343 if (Field->isBitField()) { 344 Enc += "b("; 345 llvm::raw_svector_ostream OS(Enc); 346 OS << Field->getBitWidthValue(CGM.getContext()); 347 Enc += ':'; 348 } 349 if (!appendType(Enc, Field->getType(), CGM, TSC)) 350 return false; 351 if (Field->isBitField()) 352 Enc += ')'; 353 Enc += '}'; 354 FE.emplace_back(!Field->getName().empty(), Enc); 355 } 356 return true; 357 } 358 359 /// Appends structure and union types to Enc and adds encoding to cache. 360 /// Recursively calls appendType (via extractFieldType) for each field. 361 /// Union types have their fields ordered according to the ABI. 362 static bool appendRecordType(SmallStringEnc &Enc, const RecordType *RT, 363 const CodeGen::CodeGenModule &CGM, 364 TypeStringCache &TSC, const IdentifierInfo *ID) { 365 // Append the cached TypeString if we have one. 366 StringRef TypeString = TSC.lookupStr(ID); 367 if (!TypeString.empty()) { 368 Enc += TypeString; 369 return true; 370 } 371 372 // Start to emit an incomplete TypeString. 373 size_t Start = Enc.size(); 374 Enc += (RT->isUnionType()? 'u' : 's'); 375 Enc += '('; 376 if (ID) 377 Enc += ID->getName(); 378 Enc += "){"; 379 380 // We collect all encoded fields and order as necessary. 381 bool IsRecursive = false; 382 const RecordDecl *RD = RT->getDecl()->getDefinition(); 383 if (RD && !RD->field_empty()) { 384 // An incomplete TypeString stub is placed in the cache for this RecordType 385 // so that recursive calls to this RecordType will use it whilst building a 386 // complete TypeString for this RecordType. 387 SmallVector<FieldEncoding, 16> FE; 388 std::string StubEnc(Enc.substr(Start).str()); 389 StubEnc += '}'; // StubEnc now holds a valid incomplete TypeString. 390 TSC.addIncomplete(ID, std::move(StubEnc)); 391 if (!extractFieldType(FE, RD, CGM, TSC)) { 392 (void) TSC.removeIncomplete(ID); 393 return false; 394 } 395 IsRecursive = TSC.removeIncomplete(ID); 396 // The ABI requires unions to be sorted but not structures. 397 // See FieldEncoding::operator< for sort algorithm. 398 if (RT->isUnionType()) 399 llvm::sort(FE); 400 // We can now complete the TypeString. 401 unsigned E = FE.size(); 402 for (unsigned I = 0; I != E; ++I) { 403 if (I) 404 Enc += ','; 405 Enc += FE[I].str(); 406 } 407 } 408 Enc += '}'; 409 TSC.addIfComplete(ID, Enc.substr(Start), IsRecursive); 410 return true; 411 } 412 413 /// Appends enum types to Enc and adds the encoding to the cache. 414 static bool appendEnumType(SmallStringEnc &Enc, const EnumType *ET, 415 TypeStringCache &TSC, 416 const IdentifierInfo *ID) { 417 // Append the cached TypeString if we have one. 418 StringRef TypeString = TSC.lookupStr(ID); 419 if (!TypeString.empty()) { 420 Enc += TypeString; 421 return true; 422 } 423 424 size_t Start = Enc.size(); 425 Enc += "e("; 426 if (ID) 427 Enc += ID->getName(); 428 Enc += "){"; 429 430 // We collect all encoded enumerations and order them alphanumerically. 431 if (const EnumDecl *ED = ET->getDecl()->getDefinition()) { 432 SmallVector<FieldEncoding, 16> FE; 433 for (auto I = ED->enumerator_begin(), E = ED->enumerator_end(); I != E; 434 ++I) { 435 SmallStringEnc EnumEnc; 436 EnumEnc += "m("; 437 EnumEnc += I->getName(); 438 EnumEnc += "){"; 439 I->getInitVal().toString(EnumEnc); 440 EnumEnc += '}'; 441 FE.push_back(FieldEncoding(!I->getName().empty(), EnumEnc)); 442 } 443 llvm::sort(FE); 444 unsigned E = FE.size(); 445 for (unsigned I = 0; I != E; ++I) { 446 if (I) 447 Enc += ','; 448 Enc += FE[I].str(); 449 } 450 } 451 Enc += '}'; 452 TSC.addIfComplete(ID, Enc.substr(Start), false); 453 return true; 454 } 455 456 /// Appends type's qualifier to Enc. 457 /// This is done prior to appending the type's encoding. 458 static void appendQualifier(SmallStringEnc &Enc, QualType QT) { 459 // Qualifiers are emitted in alphabetical order. 460 static const char *const Table[]={"","c:","r:","cr:","v:","cv:","rv:","crv:"}; 461 int Lookup = 0; 462 if (QT.isConstQualified()) 463 Lookup += 1<<0; 464 if (QT.isRestrictQualified()) 465 Lookup += 1<<1; 466 if (QT.isVolatileQualified()) 467 Lookup += 1<<2; 468 Enc += Table[Lookup]; 469 } 470 471 /// Appends built-in types to Enc. 472 static bool appendBuiltinType(SmallStringEnc &Enc, const BuiltinType *BT) { 473 const char *EncType; 474 switch (BT->getKind()) { 475 case BuiltinType::Void: 476 EncType = "0"; 477 break; 478 case BuiltinType::Bool: 479 EncType = "b"; 480 break; 481 case BuiltinType::Char_U: 482 EncType = "uc"; 483 break; 484 case BuiltinType::UChar: 485 EncType = "uc"; 486 break; 487 case BuiltinType::SChar: 488 EncType = "sc"; 489 break; 490 case BuiltinType::UShort: 491 EncType = "us"; 492 break; 493 case BuiltinType::Short: 494 EncType = "ss"; 495 break; 496 case BuiltinType::UInt: 497 EncType = "ui"; 498 break; 499 case BuiltinType::Int: 500 EncType = "si"; 501 break; 502 case BuiltinType::ULong: 503 EncType = "ul"; 504 break; 505 case BuiltinType::Long: 506 EncType = "sl"; 507 break; 508 case BuiltinType::ULongLong: 509 EncType = "ull"; 510 break; 511 case BuiltinType::LongLong: 512 EncType = "sll"; 513 break; 514 case BuiltinType::Float: 515 EncType = "ft"; 516 break; 517 case BuiltinType::Double: 518 EncType = "d"; 519 break; 520 case BuiltinType::LongDouble: 521 EncType = "ld"; 522 break; 523 default: 524 return false; 525 } 526 Enc += EncType; 527 return true; 528 } 529 530 /// Appends a pointer encoding to Enc before calling appendType for the pointee. 531 static bool appendPointerType(SmallStringEnc &Enc, const PointerType *PT, 532 const CodeGen::CodeGenModule &CGM, 533 TypeStringCache &TSC) { 534 Enc += "p("; 535 if (!appendType(Enc, PT->getPointeeType(), CGM, TSC)) 536 return false; 537 Enc += ')'; 538 return true; 539 } 540 541 /// Appends array encoding to Enc before calling appendType for the element. 542 static bool appendArrayType(SmallStringEnc &Enc, QualType QT, 543 const ArrayType *AT, 544 const CodeGen::CodeGenModule &CGM, 545 TypeStringCache &TSC, StringRef NoSizeEnc) { 546 if (AT->getSizeModifier() != ArrayType::Normal) 547 return false; 548 Enc += "a("; 549 if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT)) 550 CAT->getSize().toStringUnsigned(Enc); 551 else 552 Enc += NoSizeEnc; // Global arrays use "*", otherwise it is "". 553 Enc += ':'; 554 // The Qualifiers should be attached to the type rather than the array. 555 appendQualifier(Enc, QT); 556 if (!appendType(Enc, AT->getElementType(), CGM, TSC)) 557 return false; 558 Enc += ')'; 559 return true; 560 } 561 562 /// Appends a function encoding to Enc, calling appendType for the return type 563 /// and the arguments. 564 static bool appendFunctionType(SmallStringEnc &Enc, const FunctionType *FT, 565 const CodeGen::CodeGenModule &CGM, 566 TypeStringCache &TSC) { 567 Enc += "f{"; 568 if (!appendType(Enc, FT->getReturnType(), CGM, TSC)) 569 return false; 570 Enc += "}("; 571 if (const FunctionProtoType *FPT = FT->getAs<FunctionProtoType>()) { 572 // N.B. we are only interested in the adjusted param types. 573 auto I = FPT->param_type_begin(); 574 auto E = FPT->param_type_end(); 575 if (I != E) { 576 do { 577 if (!appendType(Enc, *I, CGM, TSC)) 578 return false; 579 ++I; 580 if (I != E) 581 Enc += ','; 582 } while (I != E); 583 if (FPT->isVariadic()) 584 Enc += ",va"; 585 } else { 586 if (FPT->isVariadic()) 587 Enc += "va"; 588 else 589 Enc += '0'; 590 } 591 } 592 Enc += ')'; 593 return true; 594 } 595 596 /// Handles the type's qualifier before dispatching a call to handle specific 597 /// type encodings. 598 static bool appendType(SmallStringEnc &Enc, QualType QType, 599 const CodeGen::CodeGenModule &CGM, 600 TypeStringCache &TSC) { 601 602 QualType QT = QType.getCanonicalType(); 603 604 if (const ArrayType *AT = QT->getAsArrayTypeUnsafe()) 605 // The Qualifiers should be attached to the type rather than the array. 606 // Thus we don't call appendQualifier() here. 607 return appendArrayType(Enc, QT, AT, CGM, TSC, ""); 608 609 appendQualifier(Enc, QT); 610 611 if (const BuiltinType *BT = QT->getAs<BuiltinType>()) 612 return appendBuiltinType(Enc, BT); 613 614 if (const PointerType *PT = QT->getAs<PointerType>()) 615 return appendPointerType(Enc, PT, CGM, TSC); 616 617 if (const EnumType *ET = QT->getAs<EnumType>()) 618 return appendEnumType(Enc, ET, TSC, QT.getBaseTypeIdentifier()); 619 620 if (const RecordType *RT = QT->getAsStructureType()) 621 return appendRecordType(Enc, RT, CGM, TSC, QT.getBaseTypeIdentifier()); 622 623 if (const RecordType *RT = QT->getAsUnionType()) 624 return appendRecordType(Enc, RT, CGM, TSC, QT.getBaseTypeIdentifier()); 625 626 if (const FunctionType *FT = QT->getAs<FunctionType>()) 627 return appendFunctionType(Enc, FT, CGM, TSC); 628 629 return false; 630 } 631 632 static bool getTypeString(SmallStringEnc &Enc, const Decl *D, 633 const CodeGen::CodeGenModule &CGM, 634 TypeStringCache &TSC) { 635 if (!D) 636 return false; 637 638 if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { 639 if (FD->getLanguageLinkage() != CLanguageLinkage) 640 return false; 641 return appendType(Enc, FD->getType(), CGM, TSC); 642 } 643 644 if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { 645 if (VD->getLanguageLinkage() != CLanguageLinkage) 646 return false; 647 QualType QT = VD->getType().getCanonicalType(); 648 if (const ArrayType *AT = QT->getAsArrayTypeUnsafe()) { 649 // Global ArrayTypes are given a size of '*' if the size is unknown. 650 // The Qualifiers should be attached to the type rather than the array. 651 // Thus we don't call appendQualifier() here. 652 return appendArrayType(Enc, QT, AT, CGM, TSC, "*"); 653 } 654 return appendType(Enc, QT, CGM, TSC); 655 } 656 return false; 657 } 658 659 std::unique_ptr<TargetCodeGenInfo> 660 CodeGen::createXCoreTargetCodeGenInfo(CodeGenModule &CGM) { 661 return std::make_unique<XCoreTargetCodeGenInfo>(CGM.getTypes()); 662 } 663