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:
TypeStringCache()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:
FieldEncoding(bool b,SmallStringEnc & e)105 FieldEncoding(bool b, SmallStringEnc &e) : HasName(b), Enc(e.c_str()) {}
str()106 StringRef str() { return Enc; }
operator <(const FieldEncoding & rhs) const107 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:
XCoreABIInfo(CodeGen::CodeGenTypes & CGT)115 XCoreABIInfo(CodeGen::CodeGenTypes &CGT) : DefaultABIInfo(CGT) {}
116 RValue EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty,
117 AggValueSlot Slot) 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:
XCoreTargetCodeGenInfo(CodeGenTypes & CGT)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.
EmitVAArg(CodeGenFunction & CGF,Address VAListAddr,QualType Ty,AggValueSlot Slot) const137 RValue XCoreABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
138 QualType Ty, AggValueSlot Slot) 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.emitRawPointer(CGF), VAListAddr);
184 }
185
186 return CGF.EmitLoadOfAnyValue(CGF.MakeAddrLValue(Val, Ty), Slot);
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.
addIncomplete(const IdentifierInfo * ID,std::string StubEnc)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.
removeIncomplete(const IdentifierInfo * ID)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).
addIfComplete(const IdentifierInfo * ID,StringRef Str,bool IsRecursive)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.
lookupStr(const IdentifierInfo * ID)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.
emitTargetMD(const Decl * D,llvm::GlobalValue * GV,const CodeGen::CodeGenModule & CGM) const297 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
emitTargetMetadata(CodeGen::CodeGenModule & CGM,const llvm::MapVector<GlobalDecl,StringRef> & MangledDeclNames) const311 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.
extractFieldType(SmallVectorImpl<FieldEncoding> & FE,const RecordDecl * RD,const CodeGen::CodeGenModule & CGM,TypeStringCache & TSC)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.
appendRecordType(SmallStringEnc & Enc,const RecordType * RT,const CodeGen::CodeGenModule & CGM,TypeStringCache & TSC,const IdentifierInfo * ID)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.
appendEnumType(SmallStringEnc & Enc,const EnumType * ET,TypeStringCache & TSC,const IdentifierInfo * ID)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.
appendQualifier(SmallStringEnc & Enc,QualType QT)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.
appendBuiltinType(SmallStringEnc & Enc,const BuiltinType * BT)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.
appendPointerType(SmallStringEnc & Enc,const PointerType * PT,const CodeGen::CodeGenModule & CGM,TypeStringCache & TSC)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.
appendArrayType(SmallStringEnc & Enc,QualType QT,const ArrayType * AT,const CodeGen::CodeGenModule & CGM,TypeStringCache & TSC,StringRef NoSizeEnc)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() != ArraySizeModifier::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.
appendFunctionType(SmallStringEnc & Enc,const FunctionType * FT,const CodeGen::CodeGenModule & CGM,TypeStringCache & TSC)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.
appendType(SmallStringEnc & Enc,QualType QType,const CodeGen::CodeGenModule & CGM,TypeStringCache & TSC)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
getTypeString(SmallStringEnc & Enc,const Decl * D,const CodeGen::CodeGenModule & CGM,TypeStringCache & TSC)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>
createXCoreTargetCodeGenInfo(CodeGenModule & CGM)660 CodeGen::createXCoreTargetCodeGenInfo(CodeGenModule &CGM) {
661 return std::make_unique<XCoreTargetCodeGenInfo>(CGM.getTypes());
662 }
663