1 //===- XCore.cpp ----------------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "ABIInfoImpl.h"
10 #include "TargetInfo.h"
12 using namespace clang
;
13 using namespace clang::CodeGen
;
15 //===----------------------------------------------------------------------===//
16 // XCore ABI Implementation
17 //===----------------------------------------------------------------------===//
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
;
25 /// TypeStringCache caches the meta encodings of Types.
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.
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.
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.
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.
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.
55 /// During the expansion of a RecordType's members:
57 /// If the cache contains a NonRecursive encoding for the member type, the
58 /// cached encoding is used;
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...
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;
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;
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;
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.
79 class TypeStringCache
{
80 enum Status
{NonRecursive
, Recursive
, Incomplete
, IncompleteUsed
};
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.
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.
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
,
96 StringRef
lookupStr(const IdentifierInfo
*ID
);
99 /// TypeString encodings for enum & union fields must be order.
100 /// FieldEncoding is a helper for this ordering process.
101 class FieldEncoding
{
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
;
113 class XCoreABIInfo
: public DefaultABIInfo
{
115 XCoreABIInfo(CodeGen::CodeGenTypes
&CGT
) : DefaultABIInfo(CGT
) {}
116 Address
EmitVAArg(CodeGenFunction
&CGF
, Address VAListAddr
,
117 QualType Ty
) const override
;
120 class XCoreTargetCodeGenInfo
: public TargetCodeGenInfo
{
121 mutable TypeStringCache TSC
;
122 void emitTargetMD(const Decl
*D
, llvm::GlobalValue
*GV
,
123 const CodeGen::CodeGenModule
&M
) const;
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
;
133 } // End anonymous namespace.
135 // TODO: this implementation is likely now redundant with the default
137 Address
XCoreABIInfo::EmitVAArg(CodeGenFunction
&CGF
, Address VAListAddr
,
139 CGBuilderTy
&Builder
= CGF
.Builder
;
142 CharUnits SlotSize
= CharUnits::fromQuantity(4);
143 Address AP
= Address(Builder
.CreateLoad(VAListAddr
),
144 getVAListElementType(CGF
), SlotSize
);
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
);
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();
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
);
172 case ABIArgInfo::Indirect
:
173 case ABIArgInfo::IndirectAliased
:
174 Val
= AP
.withElementType(ArgPtrTy
);
175 Val
= Address(Builder
.CreateLoad(Val
), ArgTy
, TypeAlign
);
180 // Increment the VAList.
181 if (!ArgSize
.isZero()) {
182 Address APN
= Builder
.CreateConstInBoundsByteGEP(AP
, ArgSize
);
183 Builder
.CreateStore(APN
.getPointer(), VAListAddr
);
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
) {
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
204 E
.State
= Incomplete
;
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
) {
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.
225 --IncompleteUsedCount
;
227 if (E
.Swapped
.empty())
230 // Swap the Recursive back.
231 E
.Swapped
.swap(E
.Str
);
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
,
243 if (!ID
|| IncompleteUsedCount
)
244 return; // No key or it is an incomplete sub-type so don't add.
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.
254 assert(E
.Str
.empty() && "Entry already present");
256 E
.State
= IsRecursive
? Recursive
: NonRecursive
;
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
) {
264 return StringRef(); // We have no key.
265 auto I
= Map
.find(ID
);
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.
272 if (E
.State
== Incomplete
) {
273 // The incomplete type is being used to break out of recursion.
274 E
.State
= IncompleteUsed
;
275 ++IncompleteUsedCount
;
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.
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.
292 static bool getTypeString(SmallStringEnc
&Enc
, const Decl
*D
,
293 const CodeGen::CodeGenModule
&CGM
,
294 TypeStringCache
&TSC
);
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 {
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
));
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
317 for (unsigned I
= 0; I
!= MangledDeclNames
.size(); ++I
) {
318 auto Val
= *(MangledDeclNames
.begin() + I
);
319 llvm::GlobalValue
*GV
= CGM
.GetGlobalValue(Val
.second
);
321 const Decl
*D
= Val
.first
.getDecl()->getMostRecentDecl();
322 emitTargetMD(D
, GV
, CGM
);
327 static bool appendType(SmallStringEnc
&Enc
, QualType QType
,
328 const CodeGen::CodeGenModule
&CGM
,
329 TypeStringCache
&TSC
);
331 /// Helper function for appendRecordType().
332 /// Builds a SmallVector containing the encoded field types in declaration
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()) {
341 Enc
+= Field
->getName();
343 if (Field
->isBitField()) {
345 llvm::raw_svector_ostream
OS(Enc
);
346 OS
<< Field
->getBitWidthValue(CGM
.getContext());
349 if (!appendType(Enc
, Field
->getType(), CGM
, TSC
))
351 if (Field
->isBitField())
354 FE
.emplace_back(!Field
->getName().empty(), Enc
);
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()) {
372 // Start to emit an incomplete TypeString.
373 size_t Start
= Enc
.size();
374 Enc
+= (RT
->isUnionType()? 'u' : 's');
377 Enc
+= ID
->getName();
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
);
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())
400 // We can now complete the TypeString.
401 unsigned E
= FE
.size();
402 for (unsigned I
= 0; I
!= E
; ++I
) {
409 TSC
.addIfComplete(ID
, Enc
.substr(Start
), IsRecursive
);
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()) {
424 size_t Start
= Enc
.size();
427 Enc
+= ID
->getName();
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
;
435 SmallStringEnc EnumEnc
;
437 EnumEnc
+= I
->getName();
439 I
->getInitVal().toString(EnumEnc
);
441 FE
.push_back(FieldEncoding(!I
->getName().empty(), EnumEnc
));
444 unsigned E
= FE
.size();
445 for (unsigned I
= 0; I
!= E
; ++I
) {
452 TSC
.addIfComplete(ID
, Enc
.substr(Start
), false);
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:"};
462 if (QT
.isConstQualified())
464 if (QT
.isRestrictQualified())
466 if (QT
.isVolatileQualified())
468 Enc
+= Table
[Lookup
];
471 /// Appends built-in types to Enc.
472 static bool appendBuiltinType(SmallStringEnc
&Enc
, const BuiltinType
*BT
) {
474 switch (BT
->getKind()) {
475 case BuiltinType::Void
:
478 case BuiltinType::Bool
:
481 case BuiltinType::Char_U
:
484 case BuiltinType::UChar
:
487 case BuiltinType::SChar
:
490 case BuiltinType::UShort
:
493 case BuiltinType::Short
:
496 case BuiltinType::UInt
:
499 case BuiltinType::Int
:
502 case BuiltinType::ULong
:
505 case BuiltinType::Long
:
508 case BuiltinType::ULongLong
:
511 case BuiltinType::LongLong
:
514 case BuiltinType::Float
:
517 case BuiltinType::Double
:
520 case BuiltinType::LongDouble
:
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
) {
535 if (!appendType(Enc
, PT
->getPointeeType(), CGM
, TSC
))
541 /// Appends array encoding to Enc before calling appendType for the element.
542 static bool appendArrayType(SmallStringEnc
&Enc
, QualType QT
,
544 const CodeGen::CodeGenModule
&CGM
,
545 TypeStringCache
&TSC
, StringRef NoSizeEnc
) {
546 if (AT
->getSizeModifier() != ArraySizeModifier::Normal
)
549 if (const ConstantArrayType
*CAT
= dyn_cast
<ConstantArrayType
>(AT
))
550 CAT
->getSize().toStringUnsigned(Enc
);
552 Enc
+= NoSizeEnc
; // Global arrays use "*", otherwise it is "".
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
))
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
) {
568 if (!appendType(Enc
, FT
->getReturnType(), CGM
, TSC
))
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();
577 if (!appendType(Enc
, *I
, CGM
, TSC
))
583 if (FPT
->isVariadic())
586 if (FPT
->isVariadic())
596 /// Handles the type's qualifier before dispatching a call to handle specific
598 static bool appendType(SmallStringEnc
&Enc
, QualType QType
,
599 const CodeGen::CodeGenModule
&CGM
,
600 TypeStringCache
&TSC
) {
602 QualType QT
= QType
.getCanonicalType();
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
, "");
609 appendQualifier(Enc
, QT
);
611 if (const BuiltinType
*BT
= QT
->getAs
<BuiltinType
>())
612 return appendBuiltinType(Enc
, BT
);
614 if (const PointerType
*PT
= QT
->getAs
<PointerType
>())
615 return appendPointerType(Enc
, PT
, CGM
, TSC
);
617 if (const EnumType
*ET
= QT
->getAs
<EnumType
>())
618 return appendEnumType(Enc
, ET
, TSC
, QT
.getBaseTypeIdentifier());
620 if (const RecordType
*RT
= QT
->getAsStructureType())
621 return appendRecordType(Enc
, RT
, CGM
, TSC
, QT
.getBaseTypeIdentifier());
623 if (const RecordType
*RT
= QT
->getAsUnionType())
624 return appendRecordType(Enc
, RT
, CGM
, TSC
, QT
.getBaseTypeIdentifier());
626 if (const FunctionType
*FT
= QT
->getAs
<FunctionType
>())
627 return appendFunctionType(Enc
, FT
, CGM
, TSC
);
632 static bool getTypeString(SmallStringEnc
&Enc
, const Decl
*D
,
633 const CodeGen::CodeGenModule
&CGM
,
634 TypeStringCache
&TSC
) {
638 if (const FunctionDecl
*FD
= dyn_cast
<FunctionDecl
>(D
)) {
639 if (FD
->getLanguageLinkage() != CLanguageLinkage
)
641 return appendType(Enc
, FD
->getType(), CGM
, TSC
);
644 if (const VarDecl
*VD
= dyn_cast
<VarDecl
>(D
)) {
645 if (VD
->getLanguageLinkage() != CLanguageLinkage
)
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
, "*");
654 return appendType(Enc
, QT
, CGM
, TSC
);
659 std::unique_ptr
<TargetCodeGenInfo
>
660 CodeGen::createXCoreTargetCodeGenInfo(CodeGenModule
&CGM
) {
661 return std::make_unique
<XCoreTargetCodeGenInfo
>(CGM
.getTypes());