xref: /freebsd/contrib/llvm-project/clang/lib/CodeGen/Targets/XCore.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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