clang 22.0.0git
XCore.cpp
Go to the documentation of this file.
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
12using namespace clang;
13using namespace clang::CodeGen;
14
15//===----------------------------------------------------------------------===//
16// XCore ABI Implementation
17//===----------------------------------------------------------------------===//
18
19namespace {
20
21/// A SmallStringEnc instance is used to build up the TypeString by passing
22/// it by reference between functions that append to it.
23typedef 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///
79class 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.
90public:
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.
101class FieldEncoding {
102 bool HasName;
103 std::string Enc;
104public:
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
113class XCoreABIInfo : public DefaultABIInfo {
114public:
115 XCoreABIInfo(CodeGen::CodeGenTypes &CGT) : DefaultABIInfo(CGT) {}
116 RValue EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty,
117 AggValueSlot Slot) const override;
118};
119
120class XCoreTargetCodeGenInfo : public TargetCodeGenInfo {
121 mutable TypeStringCache TSC;
122 void emitTargetMD(const Decl *D, llvm::GlobalValue *GV,
123 const CodeGen::CodeGenModule &M) const;
124
125public:
126 XCoreTargetCodeGenInfo(CodeGenTypes &CGT)
127 : TargetCodeGenInfo(std::make_unique<XCoreABIInfo>(CGT)) {}
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.
137RValue XCoreABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
138 QualType Ty, AggValueSlot Slot) const {
139 CGBuilderTy &Builder = CGF.Builder;
140
141 // Get the VAList.
143 Address AP = Address(Builder.CreateLoad(VAListAddr),
144 getVAListElementType(CGF), SlotSize);
145
146 // Handle the argument.
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->getContext());
153
155 CharUnits ArgSize = CharUnits::Zero();
156 switch (AI.getKind()) {
161 llvm_unreachable("Unsupported ABI kind for va_arg");
163 Val = Address(llvm::UndefValue::get(ArgPtrTy), ArgTy, TypeAlign);
164 ArgSize = CharUnits::Zero();
165 break;
168 Val = AP.withElementType(ArgTy);
169 ArgSize = CharUnits::fromQuantity(
170 getDataLayout().getTypeAllocSize(AI.getCoerceToType()));
171 ArgSize = ArgSize.alignTo(SlotSize);
172 break;
175 Val = AP.withElementType(ArgPtrTy);
176 Val = Address(Builder.CreateLoad(Val), ArgTy, TypeAlign);
177 ArgSize = SlotSize;
178 break;
179 }
180
181 // Increment the VAList.
182 if (!ArgSize.isZero()) {
183 Address APN = Builder.CreateConstInBoundsByteGEP(AP, ArgSize);
184 Builder.CreateStore(APN.emitRawPointer(CGF), VAListAddr);
185 }
186
187 return CGF.EmitLoadOfAnyValue(CGF.MakeAddrLValue(Val, Ty), Slot);
188}
189
190/// During the expansion of a RecordType, an incomplete TypeString is placed
191/// into the cache as a means to identify and break recursion.
192/// If there is a Recursive encoding in the cache, it is swapped out and will
193/// be reinserted by removeIncomplete().
194/// All other types of encoding should have been used rather than arriving here.
195void TypeStringCache::addIncomplete(const IdentifierInfo *ID,
196 std::string StubEnc) {
197 if (!ID)
198 return;
199 Entry &E = Map[ID];
200 assert( (E.Str.empty() || E.State == Recursive) &&
201 "Incorrectly use of addIncomplete");
202 assert(!StubEnc.empty() && "Passing an empty string to addIncomplete()");
203 E.Swapped.swap(E.Str); // swap out the Recursive
204 E.Str.swap(StubEnc);
205 E.State = Incomplete;
206 ++IncompleteCount;
207}
208
209/// Once the RecordType has been expanded, the temporary incomplete TypeString
210/// must be removed from the cache.
211/// If a Recursive was swapped out by addIncomplete(), it will be replaced.
212/// Returns true if the RecordType was defined recursively.
213bool TypeStringCache::removeIncomplete(const IdentifierInfo *ID) {
214 if (!ID)
215 return false;
216 auto I = Map.find(ID);
217 assert(I != Map.end() && "Entry not present");
218 Entry &E = I->second;
219 assert( (E.State == Incomplete ||
220 E.State == IncompleteUsed) &&
221 "Entry must be an incomplete type");
222 bool IsRecursive = false;
223 if (E.State == IncompleteUsed) {
224 // We made use of our Incomplete encoding, thus we are recursive.
225 IsRecursive = true;
226 --IncompleteUsedCount;
227 }
228 if (E.Swapped.empty())
229 Map.erase(I);
230 else {
231 // Swap the Recursive back.
232 E.Swapped.swap(E.Str);
233 E.Swapped.clear();
234 E.State = Recursive;
235 }
236 --IncompleteCount;
237 return IsRecursive;
238}
239
240/// Add the encoded TypeString to the cache only if it is NonRecursive or
241/// Recursive (viz: all sub-members were expanded as fully as possible).
242void TypeStringCache::addIfComplete(const IdentifierInfo *ID, StringRef Str,
243 bool IsRecursive) {
244 if (!ID || IncompleteUsedCount)
245 return; // No key or it is an incomplete sub-type so don't add.
246 Entry &E = Map[ID];
247 if (IsRecursive && !E.Str.empty()) {
248 assert(E.State==Recursive && E.Str.size() == Str.size() &&
249 "This is not the same Recursive entry");
250 // The parent container was not recursive after all, so we could have used
251 // this Recursive sub-member entry after all, but we assumed the worse when
252 // we started viz: IncompleteCount!=0.
253 return;
254 }
255 assert(E.Str.empty() && "Entry already present");
256 E.Str = Str.str();
257 E.State = IsRecursive? Recursive : NonRecursive;
258}
259
260/// Return a cached TypeString encoding for the ID. If there isn't one, or we
261/// are recursively expanding a type (IncompleteCount != 0) and the cached
262/// encoding is Recursive, return an empty StringRef.
263StringRef TypeStringCache::lookupStr(const IdentifierInfo *ID) {
264 if (!ID)
265 return StringRef(); // We have no key.
266 auto I = Map.find(ID);
267 if (I == Map.end())
268 return StringRef(); // We have no encoding.
269 Entry &E = I->second;
270 if (E.State == Recursive && IncompleteCount)
271 return StringRef(); // We don't use Recursive encodings for member types.
272
273 if (E.State == Incomplete) {
274 // The incomplete type is being used to break out of recursion.
275 E.State = IncompleteUsed;
276 ++IncompleteUsedCount;
277 }
278 return E.Str;
279}
280
281/// The XCore ABI includes a type information section that communicates symbol
282/// type information to the linker. The linker uses this information to verify
283/// safety/correctness of things such as array bound and pointers et al.
284/// The ABI only requires C (and XC) language modules to emit TypeStrings.
285/// This type information (TypeString) is emitted into meta data for all global
286/// symbols: definitions, declarations, functions & variables.
287///
288/// The TypeString carries type, qualifier, name, size & value details.
289/// Please see 'Tools Development Guide' section 2.16.2 for format details:
290/// https://www.xmos.com/download/public/Tools-Development-Guide%28X9114A%29.pdf
291/// The output is tested by test/CodeGen/xcore-stringtype.c.
292///
293static bool getTypeString(SmallStringEnc &Enc, const Decl *D,
294 const CodeGen::CodeGenModule &CGM,
295 TypeStringCache &TSC);
296
297/// XCore uses emitTargetMD to emit TypeString metadata for global symbols.
298void XCoreTargetCodeGenInfo::emitTargetMD(
299 const Decl *D, llvm::GlobalValue *GV,
300 const CodeGen::CodeGenModule &CGM) const {
301 SmallStringEnc Enc;
302 if (getTypeString(Enc, D, CGM, TSC)) {
303 llvm::LLVMContext &Ctx = CGM.getModule().getContext();
304 llvm::Metadata *MDVals[] = {llvm::ConstantAsMetadata::get(GV),
305 llvm::MDString::get(Ctx, Enc.str())};
306 llvm::NamedMDNode *MD =
307 CGM.getModule().getOrInsertNamedMetadata("xcore.typestrings");
308 MD->addOperand(llvm::MDNode::get(Ctx, MDVals));
309 }
310}
311
312void XCoreTargetCodeGenInfo::emitTargetMetadata(
314 const llvm::MapVector<GlobalDecl, StringRef> &MangledDeclNames) const {
315 // Warning, new MangledDeclNames may be appended within this loop.
316 // We rely on MapVector insertions adding new elements to the end
317 // of the container.
318 for (unsigned I = 0; I != MangledDeclNames.size(); ++I) {
319 auto Val = *(MangledDeclNames.begin() + I);
320 llvm::GlobalValue *GV = CGM.GetGlobalValue(Val.second);
321 if (GV) {
322 const Decl *D = Val.first.getDecl()->getMostRecentDecl();
323 emitTargetMD(D, GV, CGM);
324 }
325 }
326}
327
328static bool appendType(SmallStringEnc &Enc, QualType QType,
329 const CodeGen::CodeGenModule &CGM,
330 TypeStringCache &TSC);
331
332/// Helper function for appendRecordType().
333/// Builds a SmallVector containing the encoded field types in declaration
334/// order.
336 const RecordDecl *RD,
337 const CodeGen::CodeGenModule &CGM,
338 TypeStringCache &TSC) {
339 for (const auto *Field : RD->fields()) {
340 SmallStringEnc Enc;
341 Enc += "m(";
342 Enc += Field->getName();
343 Enc += "){";
344 if (Field->isBitField()) {
345 Enc += "b(";
346 llvm::raw_svector_ostream OS(Enc);
347 OS << Field->getBitWidthValue();
348 Enc += ':';
349 }
350 if (!appendType(Enc, Field->getType(), CGM, TSC))
351 return false;
352 if (Field->isBitField())
353 Enc += ')';
354 Enc += '}';
355 FE.emplace_back(!Field->getName().empty(), Enc);
356 }
357 return true;
358}
359
360/// Appends structure and union types to Enc and adds encoding to cache.
361/// Recursively calls appendType (via extractFieldType) for each field.
362/// Union types have their fields ordered according to the ABI.
363static bool appendRecordType(SmallStringEnc &Enc, const RecordType *RT,
364 const CodeGen::CodeGenModule &CGM,
365 TypeStringCache &TSC, const IdentifierInfo *ID) {
366 // Append the cached TypeString if we have one.
367 StringRef TypeString = TSC.lookupStr(ID);
368 if (!TypeString.empty()) {
369 Enc += TypeString;
370 return true;
371 }
372
373 // Start to emit an incomplete TypeString.
374 size_t Start = Enc.size();
375 Enc += (RT->isUnionType()? 'u' : 's');
376 Enc += '(';
377 if (ID)
378 Enc += ID->getName();
379 Enc += "){";
380
381 // We collect all encoded fields and order as necessary.
382 bool IsRecursive = false;
383 const RecordDecl *RD = RT->getOriginalDecl()->getDefinition();
384 if (RD && !RD->field_empty()) {
385 // An incomplete TypeString stub is placed in the cache for this RecordType
386 // so that recursive calls to this RecordType will use it whilst building a
387 // complete TypeString for this RecordType.
389 std::string StubEnc(Enc.substr(Start).str());
390 StubEnc += '}'; // StubEnc now holds a valid incomplete TypeString.
391 TSC.addIncomplete(ID, std::move(StubEnc));
392 if (!extractFieldType(FE, RD, CGM, TSC)) {
393 (void) TSC.removeIncomplete(ID);
394 return false;
395 }
396 IsRecursive = TSC.removeIncomplete(ID);
397 // The ABI requires unions to be sorted but not structures.
398 // See FieldEncoding::operator< for sort algorithm.
399 if (RT->isUnionType())
400 llvm::sort(FE);
401 // We can now complete the TypeString.
402 unsigned E = FE.size();
403 for (unsigned I = 0; I != E; ++I) {
404 if (I)
405 Enc += ',';
406 Enc += FE[I].str();
407 }
408 }
409 Enc += '}';
410 TSC.addIfComplete(ID, Enc.substr(Start), IsRecursive);
411 return true;
412}
413
414/// Appends enum types to Enc and adds the encoding to the cache.
415static bool appendEnumType(SmallStringEnc &Enc, const EnumType *ET,
416 TypeStringCache &TSC,
417 const IdentifierInfo *ID) {
418 // Append the cached TypeString if we have one.
419 StringRef TypeString = TSC.lookupStr(ID);
420 if (!TypeString.empty()) {
421 Enc += TypeString;
422 return true;
423 }
424
425 size_t Start = Enc.size();
426 Enc += "e(";
427 if (ID)
428 Enc += ID->getName();
429 Enc += "){";
430
431 // We collect all encoded enumerations and order them alphanumerically.
432 if (const EnumDecl *ED = ET->getOriginalDecl()->getDefinition()) {
434 for (auto I = ED->enumerator_begin(), E = ED->enumerator_end(); I != E;
435 ++I) {
436 SmallStringEnc EnumEnc;
437 EnumEnc += "m(";
438 EnumEnc += I->getName();
439 EnumEnc += "){";
440 I->getInitVal().toString(EnumEnc);
441 EnumEnc += '}';
442 FE.push_back(FieldEncoding(!I->getName().empty(), EnumEnc));
443 }
444 llvm::sort(FE);
445 unsigned E = FE.size();
446 for (unsigned I = 0; I != E; ++I) {
447 if (I)
448 Enc += ',';
449 Enc += FE[I].str();
450 }
451 }
452 Enc += '}';
453 TSC.addIfComplete(ID, Enc.substr(Start), false);
454 return true;
455}
456
457/// Appends type's qualifier to Enc.
458/// This is done prior to appending the type's encoding.
459static void appendQualifier(SmallStringEnc &Enc, QualType QT) {
460 // Qualifiers are emitted in alphabetical order.
461 static const char *const Table[]={"","c:","r:","cr:","v:","cv:","rv:","crv:"};
462 int Lookup = 0;
463 if (QT.isConstQualified())
464 Lookup += 1<<0;
465 if (QT.isRestrictQualified())
466 Lookup += 1<<1;
467 if (QT.isVolatileQualified())
468 Lookup += 1<<2;
469 Enc += Table[Lookup];
470}
471
472/// Appends built-in types to Enc.
473static bool appendBuiltinType(SmallStringEnc &Enc, const BuiltinType *BT) {
474 const char *EncType;
475 switch (BT->getKind()) {
476 case BuiltinType::Void:
477 EncType = "0";
478 break;
479 case BuiltinType::Bool:
480 EncType = "b";
481 break;
482 case BuiltinType::Char_U:
483 EncType = "uc";
484 break;
485 case BuiltinType::UChar:
486 EncType = "uc";
487 break;
488 case BuiltinType::SChar:
489 EncType = "sc";
490 break;
491 case BuiltinType::UShort:
492 EncType = "us";
493 break;
494 case BuiltinType::Short:
495 EncType = "ss";
496 break;
497 case BuiltinType::UInt:
498 EncType = "ui";
499 break;
500 case BuiltinType::Int:
501 EncType = "si";
502 break;
503 case BuiltinType::ULong:
504 EncType = "ul";
505 break;
506 case BuiltinType::Long:
507 EncType = "sl";
508 break;
509 case BuiltinType::ULongLong:
510 EncType = "ull";
511 break;
512 case BuiltinType::LongLong:
513 EncType = "sll";
514 break;
515 case BuiltinType::Float:
516 EncType = "ft";
517 break;
518 case BuiltinType::Double:
519 EncType = "d";
520 break;
521 case BuiltinType::LongDouble:
522 EncType = "ld";
523 break;
524 default:
525 return false;
526 }
527 Enc += EncType;
528 return true;
529}
530
531/// Appends a pointer encoding to Enc before calling appendType for the pointee.
532static bool appendPointerType(SmallStringEnc &Enc, const PointerType *PT,
533 const CodeGen::CodeGenModule &CGM,
534 TypeStringCache &TSC) {
535 Enc += "p(";
536 if (!appendType(Enc, PT->getPointeeType(), CGM, TSC))
537 return false;
538 Enc += ')';
539 return true;
540}
541
542/// Appends array encoding to Enc before calling appendType for the element.
543static bool appendArrayType(SmallStringEnc &Enc, QualType QT,
544 const ArrayType *AT,
545 const CodeGen::CodeGenModule &CGM,
546 TypeStringCache &TSC, StringRef NoSizeEnc) {
547 if (AT->getSizeModifier() != ArraySizeModifier::Normal)
548 return false;
549 Enc += "a(";
550 if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT))
551 CAT->getSize().toStringUnsigned(Enc);
552 else
553 Enc += NoSizeEnc; // Global arrays use "*", otherwise it is "".
554 Enc += ':';
555 // The Qualifiers should be attached to the type rather than the array.
556 appendQualifier(Enc, QT);
557 if (!appendType(Enc, AT->getElementType(), CGM, TSC))
558 return false;
559 Enc += ')';
560 return true;
561}
562
563/// Appends a function encoding to Enc, calling appendType for the return type
564/// and the arguments.
565static bool appendFunctionType(SmallStringEnc &Enc, const FunctionType *FT,
566 const CodeGen::CodeGenModule &CGM,
567 TypeStringCache &TSC) {
568 Enc += "f{";
569 if (!appendType(Enc, FT->getReturnType(), CGM, TSC))
570 return false;
571 Enc += "}(";
572 if (const FunctionProtoType *FPT = FT->getAs<FunctionProtoType>()) {
573 // N.B. we are only interested in the adjusted param types.
574 auto I = FPT->param_type_begin();
575 auto E = FPT->param_type_end();
576 if (I != E) {
577 do {
578 if (!appendType(Enc, *I, CGM, TSC))
579 return false;
580 ++I;
581 if (I != E)
582 Enc += ',';
583 } while (I != E);
584 if (FPT->isVariadic())
585 Enc += ",va";
586 } else {
587 if (FPT->isVariadic())
588 Enc += "va";
589 else
590 Enc += '0';
591 }
592 }
593 Enc += ')';
594 return true;
595}
596
597/// Handles the type's qualifier before dispatching a call to handle specific
598/// type encodings.
599static bool appendType(SmallStringEnc &Enc, QualType QType,
600 const CodeGen::CodeGenModule &CGM,
601 TypeStringCache &TSC) {
602
603 QualType QT = QType.getCanonicalType();
604
605 if (const ArrayType *AT = QT->getAsArrayTypeUnsafe())
606 // The Qualifiers should be attached to the type rather than the array.
607 // Thus we don't call appendQualifier() here.
608 return appendArrayType(Enc, QT, AT, CGM, TSC, "");
609
610 appendQualifier(Enc, QT);
611
612 if (const BuiltinType *BT = QT->getAs<BuiltinType>())
613 return appendBuiltinType(Enc, BT);
614
615 if (const PointerType *PT = QT->getAs<PointerType>())
616 return appendPointerType(Enc, PT, CGM, TSC);
617
618 if (const EnumType *ET = QT->getAsCanonical<EnumType>())
619 return appendEnumType(Enc, ET, TSC, QT.getBaseTypeIdentifier());
620
621 if (const RecordType *RT = QT->getAsCanonical<RecordType>())
622 return appendRecordType(Enc, RT, CGM, TSC, QT.getBaseTypeIdentifier());
623
624 if (const FunctionType *FT = QT->getAs<FunctionType>())
625 return appendFunctionType(Enc, FT, CGM, TSC);
626
627 return false;
628}
629
630static bool getTypeString(SmallStringEnc &Enc, const Decl *D,
631 const CodeGen::CodeGenModule &CGM,
632 TypeStringCache &TSC) {
633 if (!D)
634 return false;
635
636 if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
637 if (FD->getLanguageLinkage() != CLanguageLinkage)
638 return false;
639 return appendType(Enc, FD->getType(), CGM, TSC);
640 }
641
642 if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
643 if (VD->getLanguageLinkage() != CLanguageLinkage)
644 return false;
645 QualType QT = VD->getType().getCanonicalType();
646 if (const ArrayType *AT = QT->getAsArrayTypeUnsafe()) {
647 // Global ArrayTypes are given a size of '*' if the size is unknown.
648 // The Qualifiers should be attached to the type rather than the array.
649 // Thus we don't call appendQualifier() here.
650 return appendArrayType(Enc, QT, AT, CGM, TSC, "*");
651 }
652 return appendType(Enc, QT, CGM, TSC);
653 }
654 return false;
655}
656
657std::unique_ptr<TargetCodeGenInfo>
659 return std::make_unique<XCoreTargetCodeGenInfo>(CGM.getTypes());
660}
const Decl * D
Expr * E
static bool appendRecordType(SmallStringEnc &Enc, const RecordType *RT, const CodeGen::CodeGenModule &CGM, TypeStringCache &TSC, const IdentifierInfo *ID)
Appends structure and union types to Enc and adds encoding to cache.
Definition: XCore.cpp:363
static bool appendBuiltinType(SmallStringEnc &Enc, const BuiltinType *BT)
Appends built-in types to Enc.
Definition: XCore.cpp:473
static bool extractFieldType(SmallVectorImpl< FieldEncoding > &FE, const RecordDecl *RD, const CodeGen::CodeGenModule &CGM, TypeStringCache &TSC)
Helper function for appendRecordType().
Definition: XCore.cpp:335
static bool appendPointerType(SmallStringEnc &Enc, const PointerType *PT, const CodeGen::CodeGenModule &CGM, TypeStringCache &TSC)
Appends a pointer encoding to Enc before calling appendType for the pointee.
Definition: XCore.cpp:532
static bool appendFunctionType(SmallStringEnc &Enc, const FunctionType *FT, const CodeGen::CodeGenModule &CGM, TypeStringCache &TSC)
Appends a function encoding to Enc, calling appendType for the return type and the arguments.
Definition: XCore.cpp:565
static bool getTypeString(SmallStringEnc &Enc, const Decl *D, const CodeGen::CodeGenModule &CGM, TypeStringCache &TSC)
The XCore ABI includes a type information section that communicates symbol type information to the li...
Definition: XCore.cpp:630
static void appendQualifier(SmallStringEnc &Enc, QualType QT)
Appends type's qualifier to Enc.
Definition: XCore.cpp:459
static bool appendType(SmallStringEnc &Enc, QualType QType, const CodeGen::CodeGenModule &CGM, TypeStringCache &TSC)
Handles the type's qualifier before dispatching a call to handle specific type encodings.
Definition: XCore.cpp:599
static bool appendEnumType(SmallStringEnc &Enc, const EnumType *ET, TypeStringCache &TSC, const IdentifierInfo *ID)
Appends enum types to Enc and adds the encoding to the cache.
Definition: XCore.cpp:415
static bool appendArrayType(SmallStringEnc &Enc, QualType QT, const ArrayType *AT, const CodeGen::CodeGenModule &CGM, TypeStringCache &TSC, StringRef NoSizeEnc)
Appends array encoding to Enc before calling appendType for the element.
Definition: XCore.cpp:543
static CharUnits getTypeAllocSize(CodeGenModule &CGM, llvm::Type *type)
__device__ __2f16 b
Represents an array type, per C99 6.7.5.2 - Array Declarators.
Definition: TypeBase.h:3738
ArraySizeModifier getSizeModifier() const
Definition: TypeBase.h:3752
QualType getElementType() const
Definition: TypeBase.h:3750
This class is used for builtin types like 'int'.
Definition: TypeBase.h:3182
Kind getKind() const
Definition: TypeBase.h:3230
CharUnits - This is an opaque type for sizes expressed in character units.
Definition: CharUnits.h:38
bool isZero() const
isZero - Test whether the quantity equals zero.
Definition: CharUnits.h:122
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
Definition: CharUnits.h:63
CharUnits alignTo(const CharUnits &Align) const
alignTo - Returns the next integer (mod 2**64) that is greater than or equal to this quantity and is ...
Definition: CharUnits.h:201
static CharUnits Zero()
Zero - Construct a CharUnits quantity of zero.
Definition: CharUnits.h:53
ABIArgInfo - Helper class to encapsulate information about how a specific C type should be passed to ...
void setCoerceToType(llvm::Type *T)
@ Extend
Extend - Valid only for integer argument types.
@ Ignore
Ignore - Ignore the argument (treat as void).
@ IndirectAliased
IndirectAliased - Similar to Indirect, but the pointer may be to an object that is otherwise referenc...
@ Expand
Expand - Only valid for aggregate argument types.
@ TargetSpecific
TargetSpecific - Some argument types are passed as target specific types such as RISC-V's tuple type,...
@ InAlloca
InAlloca - Pass the argument directly using the LLVM inalloca attribute.
@ Indirect
Indirect - Pass the argument indirectly via a hidden pointer with the specified alignment (0 indicate...
@ CoerceAndExpand
CoerceAndExpand - Only valid for aggregate argument types.
@ Direct
Direct - Pass the argument directly using the normal converted LLVM type, or by coercing to another s...
llvm::Type * getCoerceToType() const
Like RawAddress, an abstract representation of an aligned address, but the pointer contained in this ...
Definition: Address.h:128
static Address invalid()
Definition: Address.h:176
llvm::Value * emitRawPointer(CodeGenFunction &CGF) const
Return the pointer contained in this class after authenticating it and adding offset to it if necessa...
Definition: Address.h:253
Address withElementType(llvm::Type *ElemTy) const
Return address with different element type, but same pointer and alignment.
Definition: Address.h:276
An aggregate value slot.
Definition: CGValue.h:504
CodeGenFunction - This class organizes the per-function state that is used while generating LLVM code...
RValue EmitLoadOfAnyValue(LValue V, AggValueSlot Slot=AggValueSlot::ignored(), SourceLocation Loc={})
Like EmitLoadOfLValue but also handles complex and aggregate types.
Definition: CGExpr.cpp:2318
LValue MakeAddrLValue(Address Addr, QualType T, AlignmentSource Source=AlignmentSource::Type)
This class organizes the cross-function state that is used while generating LLVM code.
llvm::Module & getModule() const
llvm::GlobalValue * GetGlobalValue(StringRef Ref)
This class organizes the cross-module state that is used while lowering AST types to LLVM types.
Definition: CodeGenTypes.h:54
DefaultABIInfo - The default implementation for ABI specific details.
Definition: ABIInfoImpl.h:21
RValue EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty, AggValueSlot Slot) const override
EmitVAArg - Emit the target dependent code to load a value of.
Definition: ABIInfoImpl.cpp:77
RValue - This trivial value class is used to represent the result of an expression that is evaluated.
Definition: CGValue.h:42
TargetCodeGenInfo - This class organizes various target-specific codegeneration issues,...
Definition: TargetInfo.h:47
virtual void emitTargetMetadata(CodeGen::CodeGenModule &CGM, const llvm::MapVector< GlobalDecl, StringRef > &MangledDeclNames) const
emitTargetMetadata - Provides a convenient hook to handle extra target-specific metadata for the give...
Definition: TargetInfo.h:85
Represents the canonical version of C arrays with a specified constant size.
Definition: TypeBase.h:3776
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:86
Represents an enum.
Definition: Decl.h:4004
EnumDecl * getDefinition() const
Definition: Decl.h:4107
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of enums.
Definition: TypeBase.h:6522
EnumDecl * getOriginalDecl() const
Definition: TypeBase.h:6529
Represents a function declaration or definition.
Definition: Decl.h:1999
Represents a prototype with parameter type info, e.g.
Definition: TypeBase.h:5282
FunctionType - C99 6.7.5.3 - Function Declarators.
Definition: TypeBase.h:4478
QualType getReturnType() const
Definition: TypeBase.h:4818
One of these records is kept for each identifier that is lexed.
PointerType - C99 6.7.5.1 - Pointer Declarators.
Definition: TypeBase.h:3346
QualType getPointeeType() const
Definition: TypeBase.h:3356
A (possibly-)qualified type.
Definition: TypeBase.h:937
bool isVolatileQualified() const
Determine whether this type is volatile-qualified.
Definition: TypeBase.h:8427
bool isRestrictQualified() const
Determine whether this type is restrict-qualified.
Definition: TypeBase.h:8421
const IdentifierInfo * getBaseTypeIdentifier() const
Retrieves a pointer to the name of the base type.
Definition: Type.cpp:109
QualType getCanonicalType() const
Definition: TypeBase.h:8395
bool isConstQualified() const
Determine whether this type is const-qualified.
Definition: TypeBase.h:8416
Represents a struct/union/class.
Definition: Decl.h:4309
field_range fields() const
Definition: Decl.h:4512
RecordDecl * getDefinition() const
Returns the RecordDecl that actually defines this struct/union/class.
Definition: Decl.h:4493
bool field_empty() const
Definition: Decl.h:4520
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
Definition: TypeBase.h:6502
RecordDecl * getOriginalDecl() const
Definition: TypeBase.h:6509
const ArrayType * getAsArrayTypeUnsafe() const
A variant of getAs<> for array types which silently discards qualifiers from the outermost type.
Definition: TypeBase.h:9212
const T * getAsCanonical() const
If this type is canonically the specified type, return its canonical type cast to that specified type...
Definition: TypeBase.h:2939
const T * getAs() const
Member-template getAs<specific type>'.
Definition: TypeBase.h:9159
bool isUnionType() const
Definition: Type.cpp:718
Represents a variable declaration or definition.
Definition: Decl.h:925
ABIArgInfo classifyArgumentType(CodeGenModule &CGM, CanQualType type)
Classify the rules for how to pass a particular type.
llvm::Type * getVAListElementType(CodeGenFunction &CGF)
std::unique_ptr< TargetCodeGenInfo > createXCoreTargetCodeGenInfo(CodeGenModule &CGM)
Definition: XCore.cpp:658
The JSON file list parser is used to communicate input to InstallAPI.
bool operator<(DeclarationName LHS, DeclarationName RHS)
Ordering on two declaration names.
@ CLanguageLinkage
Definition: Linkage.h:64
@ Incomplete
Template argument deduction did not deduce a value for every template parameter.