xref: /llvm-project/clang/lib/CodeGen/Targets/XCore.cpp (revision cfe26358e3051755961fb1f3b46328dc2c326895)
1992cb984SSergei Barannikov //===- XCore.cpp ----------------------------------------------------------===//
2992cb984SSergei Barannikov //
3992cb984SSergei Barannikov // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4992cb984SSergei Barannikov // See https://llvm.org/LICENSE.txt for license information.
5992cb984SSergei Barannikov // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6992cb984SSergei Barannikov //
7992cb984SSergei Barannikov //===----------------------------------------------------------------------===//
8992cb984SSergei Barannikov 
9992cb984SSergei Barannikov #include "ABIInfoImpl.h"
10992cb984SSergei Barannikov #include "TargetInfo.h"
11992cb984SSergei Barannikov 
12992cb984SSergei Barannikov using namespace clang;
13992cb984SSergei Barannikov using namespace clang::CodeGen;
14992cb984SSergei Barannikov 
15992cb984SSergei Barannikov //===----------------------------------------------------------------------===//
16992cb984SSergei Barannikov // XCore ABI Implementation
17992cb984SSergei Barannikov //===----------------------------------------------------------------------===//
18992cb984SSergei Barannikov 
19992cb984SSergei Barannikov namespace {
20992cb984SSergei Barannikov 
21992cb984SSergei Barannikov /// A SmallStringEnc instance is used to build up the TypeString by passing
22992cb984SSergei Barannikov /// it by reference between functions that append to it.
23992cb984SSergei Barannikov typedef llvm::SmallString<128> SmallStringEnc;
24992cb984SSergei Barannikov 
25992cb984SSergei Barannikov /// TypeStringCache caches the meta encodings of Types.
26992cb984SSergei Barannikov ///
27992cb984SSergei Barannikov /// The reason for caching TypeStrings is two fold:
28992cb984SSergei Barannikov ///   1. To cache a type's encoding for later uses;
29992cb984SSergei Barannikov ///   2. As a means to break recursive member type inclusion.
30992cb984SSergei Barannikov ///
31992cb984SSergei Barannikov /// A cache Entry can have a Status of:
32992cb984SSergei Barannikov ///   NonRecursive:   The type encoding is not recursive;
33992cb984SSergei Barannikov ///   Recursive:      The type encoding is recursive;
34992cb984SSergei Barannikov ///   Incomplete:     An incomplete TypeString;
35992cb984SSergei Barannikov ///   IncompleteUsed: An incomplete TypeString that has been used in a
36992cb984SSergei Barannikov ///                   Recursive type encoding.
37992cb984SSergei Barannikov ///
38992cb984SSergei Barannikov /// A NonRecursive entry will have all of its sub-members expanded as fully
39992cb984SSergei Barannikov /// as possible. Whilst it may contain types which are recursive, the type
40992cb984SSergei Barannikov /// itself is not recursive and thus its encoding may be safely used whenever
41992cb984SSergei Barannikov /// the type is encountered.
42992cb984SSergei Barannikov ///
43992cb984SSergei Barannikov /// A Recursive entry will have all of its sub-members expanded as fully as
44992cb984SSergei Barannikov /// possible. The type itself is recursive and it may contain other types which
45992cb984SSergei Barannikov /// are recursive. The Recursive encoding must not be used during the expansion
46992cb984SSergei Barannikov /// of a recursive type's recursive branch. For simplicity the code uses
47992cb984SSergei Barannikov /// IncompleteCount to reject all usage of Recursive encodings for member types.
48992cb984SSergei Barannikov ///
49992cb984SSergei Barannikov /// An Incomplete entry is always a RecordType and only encodes its
50992cb984SSergei Barannikov /// identifier e.g. "s(S){}". Incomplete 'StubEnc' entries are ephemeral and
51992cb984SSergei Barannikov /// are placed into the cache during type expansion as a means to identify and
52992cb984SSergei Barannikov /// handle recursive inclusion of types as sub-members. If there is recursion
53992cb984SSergei Barannikov /// the entry becomes IncompleteUsed.
54992cb984SSergei Barannikov ///
55992cb984SSergei Barannikov /// During the expansion of a RecordType's members:
56992cb984SSergei Barannikov ///
57992cb984SSergei Barannikov ///   If the cache contains a NonRecursive encoding for the member type, the
58992cb984SSergei Barannikov ///   cached encoding is used;
59992cb984SSergei Barannikov ///
60992cb984SSergei Barannikov ///   If the cache contains a Recursive encoding for the member type, the
61992cb984SSergei Barannikov ///   cached encoding is 'Swapped' out, as it may be incorrect, and...
62992cb984SSergei Barannikov ///
63992cb984SSergei Barannikov ///   If the member is a RecordType, an Incomplete encoding is placed into the
64992cb984SSergei Barannikov ///   cache to break potential recursive inclusion of itself as a sub-member;
65992cb984SSergei Barannikov ///
66992cb984SSergei Barannikov ///   Once a member RecordType has been expanded, its temporary incomplete
67992cb984SSergei Barannikov ///   entry is removed from the cache. If a Recursive encoding was swapped out
68992cb984SSergei Barannikov ///   it is swapped back in;
69992cb984SSergei Barannikov ///
70992cb984SSergei Barannikov ///   If an incomplete entry is used to expand a sub-member, the incomplete
71992cb984SSergei Barannikov ///   entry is marked as IncompleteUsed. The cache keeps count of how many
72992cb984SSergei Barannikov ///   IncompleteUsed entries it currently contains in IncompleteUsedCount;
73992cb984SSergei Barannikov ///
74992cb984SSergei Barannikov ///   If a member's encoding is found to be a NonRecursive or Recursive viz:
75992cb984SSergei Barannikov ///   IncompleteUsedCount==0, the member's encoding is added to the cache.
76992cb984SSergei Barannikov ///   Else the member is part of a recursive type and thus the recursion has
77992cb984SSergei Barannikov ///   been exited too soon for the encoding to be correct for the member.
78992cb984SSergei Barannikov ///
79992cb984SSergei Barannikov class TypeStringCache {
80992cb984SSergei Barannikov   enum Status {NonRecursive, Recursive, Incomplete, IncompleteUsed};
81992cb984SSergei Barannikov   struct Entry {
82992cb984SSergei Barannikov     std::string Str;     // The encoded TypeString for the type.
83992cb984SSergei Barannikov     enum Status State;   // Information about the encoding in 'Str'.
84992cb984SSergei Barannikov     std::string Swapped; // A temporary place holder for a Recursive encoding
85992cb984SSergei Barannikov                          // during the expansion of RecordType's members.
86992cb984SSergei Barannikov   };
87992cb984SSergei Barannikov   std::map<const IdentifierInfo *, struct Entry> Map;
88992cb984SSergei Barannikov   unsigned IncompleteCount;     // Number of Incomplete entries in the Map.
89992cb984SSergei Barannikov   unsigned IncompleteUsedCount; // Number of IncompleteUsed entries in the Map.
90992cb984SSergei Barannikov public:
91992cb984SSergei Barannikov   TypeStringCache() : IncompleteCount(0), IncompleteUsedCount(0) {}
92992cb984SSergei Barannikov   void addIncomplete(const IdentifierInfo *ID, std::string StubEnc);
93992cb984SSergei Barannikov   bool removeIncomplete(const IdentifierInfo *ID);
94992cb984SSergei Barannikov   void addIfComplete(const IdentifierInfo *ID, StringRef Str,
95992cb984SSergei Barannikov                      bool IsRecursive);
96992cb984SSergei Barannikov   StringRef lookupStr(const IdentifierInfo *ID);
97992cb984SSergei Barannikov };
98992cb984SSergei Barannikov 
99992cb984SSergei Barannikov /// TypeString encodings for enum & union fields must be order.
100992cb984SSergei Barannikov /// FieldEncoding is a helper for this ordering process.
101992cb984SSergei Barannikov class FieldEncoding {
102992cb984SSergei Barannikov   bool HasName;
103992cb984SSergei Barannikov   std::string Enc;
104992cb984SSergei Barannikov public:
105992cb984SSergei Barannikov   FieldEncoding(bool b, SmallStringEnc &e) : HasName(b), Enc(e.c_str()) {}
106992cb984SSergei Barannikov   StringRef str() { return Enc; }
107992cb984SSergei Barannikov   bool operator<(const FieldEncoding &rhs) const {
108992cb984SSergei Barannikov     if (HasName != rhs.HasName) return HasName;
109992cb984SSergei Barannikov     return Enc < rhs.Enc;
110992cb984SSergei Barannikov   }
111992cb984SSergei Barannikov };
112992cb984SSergei Barannikov 
113992cb984SSergei Barannikov class XCoreABIInfo : public DefaultABIInfo {
114992cb984SSergei Barannikov public:
115992cb984SSergei Barannikov   XCoreABIInfo(CodeGen::CodeGenTypes &CGT) : DefaultABIInfo(CGT) {}
1166d973b45SMariya Podchishchaeva   RValue EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty,
1176d973b45SMariya Podchishchaeva                    AggValueSlot Slot) const override;
118992cb984SSergei Barannikov };
119992cb984SSergei Barannikov 
120992cb984SSergei Barannikov class XCoreTargetCodeGenInfo : public TargetCodeGenInfo {
121992cb984SSergei Barannikov   mutable TypeStringCache TSC;
122992cb984SSergei Barannikov   void emitTargetMD(const Decl *D, llvm::GlobalValue *GV,
123992cb984SSergei Barannikov                     const CodeGen::CodeGenModule &M) const;
124992cb984SSergei Barannikov 
125992cb984SSergei Barannikov public:
126992cb984SSergei Barannikov   XCoreTargetCodeGenInfo(CodeGenTypes &CGT)
127992cb984SSergei Barannikov       : TargetCodeGenInfo(std::make_unique<XCoreABIInfo>(CGT)) {}
128992cb984SSergei Barannikov   void emitTargetMetadata(CodeGen::CodeGenModule &CGM,
129992cb984SSergei Barannikov                           const llvm::MapVector<GlobalDecl, StringRef>
130992cb984SSergei Barannikov                               &MangledDeclNames) const override;
131992cb984SSergei Barannikov };
132992cb984SSergei Barannikov 
133992cb984SSergei Barannikov } // End anonymous namespace.
134992cb984SSergei Barannikov 
135992cb984SSergei Barannikov // TODO: this implementation is likely now redundant with the default
136992cb984SSergei Barannikov // EmitVAArg.
1376d973b45SMariya Podchishchaeva RValue XCoreABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
1386d973b45SMariya Podchishchaeva                                QualType Ty, AggValueSlot Slot) const {
139992cb984SSergei Barannikov   CGBuilderTy &Builder = CGF.Builder;
140992cb984SSergei Barannikov 
141992cb984SSergei Barannikov   // Get the VAList.
142992cb984SSergei Barannikov   CharUnits SlotSize = CharUnits::fromQuantity(4);
143992cb984SSergei Barannikov   Address AP = Address(Builder.CreateLoad(VAListAddr),
144992cb984SSergei Barannikov                        getVAListElementType(CGF), SlotSize);
145992cb984SSergei Barannikov 
146992cb984SSergei Barannikov   // Handle the argument.
147992cb984SSergei Barannikov   ABIArgInfo AI = classifyArgumentType(Ty);
148992cb984SSergei Barannikov   CharUnits TypeAlign = getContext().getTypeAlignInChars(Ty);
149992cb984SSergei Barannikov   llvm::Type *ArgTy = CGT.ConvertType(Ty);
150992cb984SSergei Barannikov   if (AI.canHaveCoerceToType() && !AI.getCoerceToType())
151992cb984SSergei Barannikov     AI.setCoerceToType(ArgTy);
152992cb984SSergei Barannikov   llvm::Type *ArgPtrTy = llvm::PointerType::getUnqual(ArgTy);
153992cb984SSergei Barannikov 
154992cb984SSergei Barannikov   Address Val = Address::invalid();
155992cb984SSergei Barannikov   CharUnits ArgSize = CharUnits::Zero();
156992cb984SSergei Barannikov   switch (AI.getKind()) {
157992cb984SSergei Barannikov   case ABIArgInfo::Expand:
158992cb984SSergei Barannikov   case ABIArgInfo::CoerceAndExpand:
159992cb984SSergei Barannikov   case ABIArgInfo::InAlloca:
160992cb984SSergei Barannikov     llvm_unreachable("Unsupported ABI kind for va_arg");
161992cb984SSergei Barannikov   case ABIArgInfo::Ignore:
162992cb984SSergei Barannikov     Val = Address(llvm::UndefValue::get(ArgPtrTy), ArgTy, TypeAlign);
163992cb984SSergei Barannikov     ArgSize = CharUnits::Zero();
164992cb984SSergei Barannikov     break;
165992cb984SSergei Barannikov   case ABIArgInfo::Extend:
166992cb984SSergei Barannikov   case ABIArgInfo::Direct:
1675f32baf1SYoungsuk Kim     Val = AP.withElementType(ArgTy);
168992cb984SSergei Barannikov     ArgSize = CharUnits::fromQuantity(
169992cb984SSergei Barannikov         getDataLayout().getTypeAllocSize(AI.getCoerceToType()));
170992cb984SSergei Barannikov     ArgSize = ArgSize.alignTo(SlotSize);
171992cb984SSergei Barannikov     break;
172992cb984SSergei Barannikov   case ABIArgInfo::Indirect:
173992cb984SSergei Barannikov   case ABIArgInfo::IndirectAliased:
1745f32baf1SYoungsuk Kim     Val = AP.withElementType(ArgPtrTy);
175992cb984SSergei Barannikov     Val = Address(Builder.CreateLoad(Val), ArgTy, TypeAlign);
176992cb984SSergei Barannikov     ArgSize = SlotSize;
177992cb984SSergei Barannikov     break;
178992cb984SSergei Barannikov   }
179992cb984SSergei Barannikov 
180992cb984SSergei Barannikov   // Increment the VAList.
181992cb984SSergei Barannikov   if (!ArgSize.isZero()) {
182992cb984SSergei Barannikov     Address APN = Builder.CreateConstInBoundsByteGEP(AP, ArgSize);
18384780af4SAkira Hatanaka     Builder.CreateStore(APN.emitRawPointer(CGF), VAListAddr);
184992cb984SSergei Barannikov   }
185992cb984SSergei Barannikov 
1866d973b45SMariya Podchishchaeva   return CGF.EmitLoadOfAnyValue(CGF.MakeAddrLValue(Val, Ty), Slot);
187992cb984SSergei Barannikov }
188992cb984SSergei Barannikov 
189992cb984SSergei Barannikov /// During the expansion of a RecordType, an incomplete TypeString is placed
190992cb984SSergei Barannikov /// into the cache as a means to identify and break recursion.
191992cb984SSergei Barannikov /// If there is a Recursive encoding in the cache, it is swapped out and will
192992cb984SSergei Barannikov /// be reinserted by removeIncomplete().
193992cb984SSergei Barannikov /// All other types of encoding should have been used rather than arriving here.
194992cb984SSergei Barannikov void TypeStringCache::addIncomplete(const IdentifierInfo *ID,
195992cb984SSergei Barannikov                                     std::string StubEnc) {
196992cb984SSergei Barannikov   if (!ID)
197992cb984SSergei Barannikov     return;
198992cb984SSergei Barannikov   Entry &E = Map[ID];
199992cb984SSergei Barannikov   assert( (E.Str.empty() || E.State == Recursive) &&
200992cb984SSergei Barannikov          "Incorrectly use of addIncomplete");
201992cb984SSergei Barannikov   assert(!StubEnc.empty() && "Passing an empty string to addIncomplete()");
202992cb984SSergei Barannikov   E.Swapped.swap(E.Str); // swap out the Recursive
203992cb984SSergei Barannikov   E.Str.swap(StubEnc);
204992cb984SSergei Barannikov   E.State = Incomplete;
205992cb984SSergei Barannikov   ++IncompleteCount;
206992cb984SSergei Barannikov }
207992cb984SSergei Barannikov 
208992cb984SSergei Barannikov /// Once the RecordType has been expanded, the temporary incomplete TypeString
209992cb984SSergei Barannikov /// must be removed from the cache.
210992cb984SSergei Barannikov /// If a Recursive was swapped out by addIncomplete(), it will be replaced.
211992cb984SSergei Barannikov /// Returns true if the RecordType was defined recursively.
212992cb984SSergei Barannikov bool TypeStringCache::removeIncomplete(const IdentifierInfo *ID) {
213992cb984SSergei Barannikov   if (!ID)
214992cb984SSergei Barannikov     return false;
215992cb984SSergei Barannikov   auto I = Map.find(ID);
216992cb984SSergei Barannikov   assert(I != Map.end() && "Entry not present");
217992cb984SSergei Barannikov   Entry &E = I->second;
218992cb984SSergei Barannikov   assert( (E.State == Incomplete ||
219992cb984SSergei Barannikov            E.State == IncompleteUsed) &&
220992cb984SSergei Barannikov          "Entry must be an incomplete type");
221992cb984SSergei Barannikov   bool IsRecursive = false;
222992cb984SSergei Barannikov   if (E.State == IncompleteUsed) {
223992cb984SSergei Barannikov     // We made use of our Incomplete encoding, thus we are recursive.
224992cb984SSergei Barannikov     IsRecursive = true;
225992cb984SSergei Barannikov     --IncompleteUsedCount;
226992cb984SSergei Barannikov   }
227992cb984SSergei Barannikov   if (E.Swapped.empty())
228992cb984SSergei Barannikov     Map.erase(I);
229992cb984SSergei Barannikov   else {
230992cb984SSergei Barannikov     // Swap the Recursive back.
231992cb984SSergei Barannikov     E.Swapped.swap(E.Str);
232992cb984SSergei Barannikov     E.Swapped.clear();
233992cb984SSergei Barannikov     E.State = Recursive;
234992cb984SSergei Barannikov   }
235992cb984SSergei Barannikov   --IncompleteCount;
236992cb984SSergei Barannikov   return IsRecursive;
237992cb984SSergei Barannikov }
238992cb984SSergei Barannikov 
239992cb984SSergei Barannikov /// Add the encoded TypeString to the cache only if it is NonRecursive or
240992cb984SSergei Barannikov /// Recursive (viz: all sub-members were expanded as fully as possible).
241992cb984SSergei Barannikov void TypeStringCache::addIfComplete(const IdentifierInfo *ID, StringRef Str,
242992cb984SSergei Barannikov                                     bool IsRecursive) {
243992cb984SSergei Barannikov   if (!ID || IncompleteUsedCount)
244992cb984SSergei Barannikov     return; // No key or it is an incomplete sub-type so don't add.
245992cb984SSergei Barannikov   Entry &E = Map[ID];
246992cb984SSergei Barannikov   if (IsRecursive && !E.Str.empty()) {
247992cb984SSergei Barannikov     assert(E.State==Recursive && E.Str.size() == Str.size() &&
248992cb984SSergei Barannikov            "This is not the same Recursive entry");
249992cb984SSergei Barannikov     // The parent container was not recursive after all, so we could have used
250992cb984SSergei Barannikov     // this Recursive sub-member entry after all, but we assumed the worse when
251992cb984SSergei Barannikov     // we started viz: IncompleteCount!=0.
252992cb984SSergei Barannikov     return;
253992cb984SSergei Barannikov   }
254992cb984SSergei Barannikov   assert(E.Str.empty() && "Entry already present");
255992cb984SSergei Barannikov   E.Str = Str.str();
256992cb984SSergei Barannikov   E.State = IsRecursive? Recursive : NonRecursive;
257992cb984SSergei Barannikov }
258992cb984SSergei Barannikov 
259992cb984SSergei Barannikov /// Return a cached TypeString encoding for the ID. If there isn't one, or we
260992cb984SSergei Barannikov /// are recursively expanding a type (IncompleteCount != 0) and the cached
261992cb984SSergei Barannikov /// encoding is Recursive, return an empty StringRef.
262992cb984SSergei Barannikov StringRef TypeStringCache::lookupStr(const IdentifierInfo *ID) {
263992cb984SSergei Barannikov   if (!ID)
264992cb984SSergei Barannikov     return StringRef();   // We have no key.
265992cb984SSergei Barannikov   auto I = Map.find(ID);
266992cb984SSergei Barannikov   if (I == Map.end())
267992cb984SSergei Barannikov     return StringRef();   // We have no encoding.
268992cb984SSergei Barannikov   Entry &E = I->second;
269992cb984SSergei Barannikov   if (E.State == Recursive && IncompleteCount)
270992cb984SSergei Barannikov     return StringRef();   // We don't use Recursive encodings for member types.
271992cb984SSergei Barannikov 
272992cb984SSergei Barannikov   if (E.State == Incomplete) {
273992cb984SSergei Barannikov     // The incomplete type is being used to break out of recursion.
274992cb984SSergei Barannikov     E.State = IncompleteUsed;
275992cb984SSergei Barannikov     ++IncompleteUsedCount;
276992cb984SSergei Barannikov   }
277992cb984SSergei Barannikov   return E.Str;
278992cb984SSergei Barannikov }
279992cb984SSergei Barannikov 
280992cb984SSergei Barannikov /// The XCore ABI includes a type information section that communicates symbol
281992cb984SSergei Barannikov /// type information to the linker. The linker uses this information to verify
282992cb984SSergei Barannikov /// safety/correctness of things such as array bound and pointers et al.
283992cb984SSergei Barannikov /// The ABI only requires C (and XC) language modules to emit TypeStrings.
284992cb984SSergei Barannikov /// This type information (TypeString) is emitted into meta data for all global
285992cb984SSergei Barannikov /// symbols: definitions, declarations, functions & variables.
286992cb984SSergei Barannikov ///
287992cb984SSergei Barannikov /// The TypeString carries type, qualifier, name, size & value details.
288992cb984SSergei Barannikov /// Please see 'Tools Development Guide' section 2.16.2 for format details:
289992cb984SSergei Barannikov /// https://www.xmos.com/download/public/Tools-Development-Guide%28X9114A%29.pdf
290992cb984SSergei Barannikov /// The output is tested by test/CodeGen/xcore-stringtype.c.
291992cb984SSergei Barannikov ///
292992cb984SSergei Barannikov static bool getTypeString(SmallStringEnc &Enc, const Decl *D,
293992cb984SSergei Barannikov                           const CodeGen::CodeGenModule &CGM,
294992cb984SSergei Barannikov                           TypeStringCache &TSC);
295992cb984SSergei Barannikov 
296992cb984SSergei Barannikov /// XCore uses emitTargetMD to emit TypeString metadata for global symbols.
297992cb984SSergei Barannikov void XCoreTargetCodeGenInfo::emitTargetMD(
298992cb984SSergei Barannikov     const Decl *D, llvm::GlobalValue *GV,
299992cb984SSergei Barannikov     const CodeGen::CodeGenModule &CGM) const {
300992cb984SSergei Barannikov   SmallStringEnc Enc;
301992cb984SSergei Barannikov   if (getTypeString(Enc, D, CGM, TSC)) {
302992cb984SSergei Barannikov     llvm::LLVMContext &Ctx = CGM.getModule().getContext();
303992cb984SSergei Barannikov     llvm::Metadata *MDVals[] = {llvm::ConstantAsMetadata::get(GV),
304992cb984SSergei Barannikov                                 llvm::MDString::get(Ctx, Enc.str())};
305992cb984SSergei Barannikov     llvm::NamedMDNode *MD =
306992cb984SSergei Barannikov       CGM.getModule().getOrInsertNamedMetadata("xcore.typestrings");
307992cb984SSergei Barannikov     MD->addOperand(llvm::MDNode::get(Ctx, MDVals));
308992cb984SSergei Barannikov   }
309992cb984SSergei Barannikov }
310992cb984SSergei Barannikov 
311992cb984SSergei Barannikov void XCoreTargetCodeGenInfo::emitTargetMetadata(
312992cb984SSergei Barannikov     CodeGen::CodeGenModule &CGM,
313992cb984SSergei Barannikov     const llvm::MapVector<GlobalDecl, StringRef> &MangledDeclNames) const {
314992cb984SSergei Barannikov   // Warning, new MangledDeclNames may be appended within this loop.
315992cb984SSergei Barannikov   // We rely on MapVector insertions adding new elements to the end
316992cb984SSergei Barannikov   // of the container.
317992cb984SSergei Barannikov   for (unsigned I = 0; I != MangledDeclNames.size(); ++I) {
318992cb984SSergei Barannikov     auto Val = *(MangledDeclNames.begin() + I);
319992cb984SSergei Barannikov     llvm::GlobalValue *GV = CGM.GetGlobalValue(Val.second);
320992cb984SSergei Barannikov     if (GV) {
321992cb984SSergei Barannikov       const Decl *D = Val.first.getDecl()->getMostRecentDecl();
322992cb984SSergei Barannikov       emitTargetMD(D, GV, CGM);
323992cb984SSergei Barannikov     }
324992cb984SSergei Barannikov   }
325992cb984SSergei Barannikov }
326992cb984SSergei Barannikov 
327992cb984SSergei Barannikov static bool appendType(SmallStringEnc &Enc, QualType QType,
328992cb984SSergei Barannikov                        const CodeGen::CodeGenModule &CGM,
329992cb984SSergei Barannikov                        TypeStringCache &TSC);
330992cb984SSergei Barannikov 
331992cb984SSergei Barannikov /// Helper function for appendRecordType().
332992cb984SSergei Barannikov /// Builds a SmallVector containing the encoded field types in declaration
333992cb984SSergei Barannikov /// order.
334992cb984SSergei Barannikov static bool extractFieldType(SmallVectorImpl<FieldEncoding> &FE,
335992cb984SSergei Barannikov                              const RecordDecl *RD,
336992cb984SSergei Barannikov                              const CodeGen::CodeGenModule &CGM,
337992cb984SSergei Barannikov                              TypeStringCache &TSC) {
338992cb984SSergei Barannikov   for (const auto *Field : RD->fields()) {
339992cb984SSergei Barannikov     SmallStringEnc Enc;
340992cb984SSergei Barannikov     Enc += "m(";
341992cb984SSergei Barannikov     Enc += Field->getName();
342992cb984SSergei Barannikov     Enc += "){";
343992cb984SSergei Barannikov     if (Field->isBitField()) {
344992cb984SSergei Barannikov       Enc += "b(";
345992cb984SSergei Barannikov       llvm::raw_svector_ostream OS(Enc);
346*cfe26358STimm Baeder       OS << Field->getBitWidthValue();
347992cb984SSergei Barannikov       Enc += ':';
348992cb984SSergei Barannikov     }
349992cb984SSergei Barannikov     if (!appendType(Enc, Field->getType(), CGM, TSC))
350992cb984SSergei Barannikov       return false;
351992cb984SSergei Barannikov     if (Field->isBitField())
352992cb984SSergei Barannikov       Enc += ')';
353992cb984SSergei Barannikov     Enc += '}';
354992cb984SSergei Barannikov     FE.emplace_back(!Field->getName().empty(), Enc);
355992cb984SSergei Barannikov   }
356992cb984SSergei Barannikov   return true;
357992cb984SSergei Barannikov }
358992cb984SSergei Barannikov 
359992cb984SSergei Barannikov /// Appends structure and union types to Enc and adds encoding to cache.
360992cb984SSergei Barannikov /// Recursively calls appendType (via extractFieldType) for each field.
361992cb984SSergei Barannikov /// Union types have their fields ordered according to the ABI.
362992cb984SSergei Barannikov static bool appendRecordType(SmallStringEnc &Enc, const RecordType *RT,
363992cb984SSergei Barannikov                              const CodeGen::CodeGenModule &CGM,
364992cb984SSergei Barannikov                              TypeStringCache &TSC, const IdentifierInfo *ID) {
365992cb984SSergei Barannikov   // Append the cached TypeString if we have one.
366992cb984SSergei Barannikov   StringRef TypeString = TSC.lookupStr(ID);
367992cb984SSergei Barannikov   if (!TypeString.empty()) {
368992cb984SSergei Barannikov     Enc += TypeString;
369992cb984SSergei Barannikov     return true;
370992cb984SSergei Barannikov   }
371992cb984SSergei Barannikov 
372992cb984SSergei Barannikov   // Start to emit an incomplete TypeString.
373992cb984SSergei Barannikov   size_t Start = Enc.size();
374992cb984SSergei Barannikov   Enc += (RT->isUnionType()? 'u' : 's');
375992cb984SSergei Barannikov   Enc += '(';
376992cb984SSergei Barannikov   if (ID)
377992cb984SSergei Barannikov     Enc += ID->getName();
378992cb984SSergei Barannikov   Enc += "){";
379992cb984SSergei Barannikov 
380992cb984SSergei Barannikov   // We collect all encoded fields and order as necessary.
381992cb984SSergei Barannikov   bool IsRecursive = false;
382992cb984SSergei Barannikov   const RecordDecl *RD = RT->getDecl()->getDefinition();
383992cb984SSergei Barannikov   if (RD && !RD->field_empty()) {
384992cb984SSergei Barannikov     // An incomplete TypeString stub is placed in the cache for this RecordType
385992cb984SSergei Barannikov     // so that recursive calls to this RecordType will use it whilst building a
386992cb984SSergei Barannikov     // complete TypeString for this RecordType.
387992cb984SSergei Barannikov     SmallVector<FieldEncoding, 16> FE;
388992cb984SSergei Barannikov     std::string StubEnc(Enc.substr(Start).str());
389992cb984SSergei Barannikov     StubEnc += '}';  // StubEnc now holds a valid incomplete TypeString.
390992cb984SSergei Barannikov     TSC.addIncomplete(ID, std::move(StubEnc));
391992cb984SSergei Barannikov     if (!extractFieldType(FE, RD, CGM, TSC)) {
392992cb984SSergei Barannikov       (void) TSC.removeIncomplete(ID);
393992cb984SSergei Barannikov       return false;
394992cb984SSergei Barannikov     }
395992cb984SSergei Barannikov     IsRecursive = TSC.removeIncomplete(ID);
396992cb984SSergei Barannikov     // The ABI requires unions to be sorted but not structures.
397992cb984SSergei Barannikov     // See FieldEncoding::operator< for sort algorithm.
398992cb984SSergei Barannikov     if (RT->isUnionType())
399992cb984SSergei Barannikov       llvm::sort(FE);
400992cb984SSergei Barannikov     // We can now complete the TypeString.
401992cb984SSergei Barannikov     unsigned E = FE.size();
402992cb984SSergei Barannikov     for (unsigned I = 0; I != E; ++I) {
403992cb984SSergei Barannikov       if (I)
404992cb984SSergei Barannikov         Enc += ',';
405992cb984SSergei Barannikov       Enc += FE[I].str();
406992cb984SSergei Barannikov     }
407992cb984SSergei Barannikov   }
408992cb984SSergei Barannikov   Enc += '}';
409992cb984SSergei Barannikov   TSC.addIfComplete(ID, Enc.substr(Start), IsRecursive);
410992cb984SSergei Barannikov   return true;
411992cb984SSergei Barannikov }
412992cb984SSergei Barannikov 
413992cb984SSergei Barannikov /// Appends enum types to Enc and adds the encoding to the cache.
414992cb984SSergei Barannikov static bool appendEnumType(SmallStringEnc &Enc, const EnumType *ET,
415992cb984SSergei Barannikov                            TypeStringCache &TSC,
416992cb984SSergei Barannikov                            const IdentifierInfo *ID) {
417992cb984SSergei Barannikov   // Append the cached TypeString if we have one.
418992cb984SSergei Barannikov   StringRef TypeString = TSC.lookupStr(ID);
419992cb984SSergei Barannikov   if (!TypeString.empty()) {
420992cb984SSergei Barannikov     Enc += TypeString;
421992cb984SSergei Barannikov     return true;
422992cb984SSergei Barannikov   }
423992cb984SSergei Barannikov 
424992cb984SSergei Barannikov   size_t Start = Enc.size();
425992cb984SSergei Barannikov   Enc += "e(";
426992cb984SSergei Barannikov   if (ID)
427992cb984SSergei Barannikov     Enc += ID->getName();
428992cb984SSergei Barannikov   Enc += "){";
429992cb984SSergei Barannikov 
430992cb984SSergei Barannikov   // We collect all encoded enumerations and order them alphanumerically.
431992cb984SSergei Barannikov   if (const EnumDecl *ED = ET->getDecl()->getDefinition()) {
432992cb984SSergei Barannikov     SmallVector<FieldEncoding, 16> FE;
433992cb984SSergei Barannikov     for (auto I = ED->enumerator_begin(), E = ED->enumerator_end(); I != E;
434992cb984SSergei Barannikov          ++I) {
435992cb984SSergei Barannikov       SmallStringEnc EnumEnc;
436992cb984SSergei Barannikov       EnumEnc += "m(";
437992cb984SSergei Barannikov       EnumEnc += I->getName();
438992cb984SSergei Barannikov       EnumEnc += "){";
439992cb984SSergei Barannikov       I->getInitVal().toString(EnumEnc);
440992cb984SSergei Barannikov       EnumEnc += '}';
441992cb984SSergei Barannikov       FE.push_back(FieldEncoding(!I->getName().empty(), EnumEnc));
442992cb984SSergei Barannikov     }
443992cb984SSergei Barannikov     llvm::sort(FE);
444992cb984SSergei Barannikov     unsigned E = FE.size();
445992cb984SSergei Barannikov     for (unsigned I = 0; I != E; ++I) {
446992cb984SSergei Barannikov       if (I)
447992cb984SSergei Barannikov         Enc += ',';
448992cb984SSergei Barannikov       Enc += FE[I].str();
449992cb984SSergei Barannikov     }
450992cb984SSergei Barannikov   }
451992cb984SSergei Barannikov   Enc += '}';
452992cb984SSergei Barannikov   TSC.addIfComplete(ID, Enc.substr(Start), false);
453992cb984SSergei Barannikov   return true;
454992cb984SSergei Barannikov }
455992cb984SSergei Barannikov 
456992cb984SSergei Barannikov /// Appends type's qualifier to Enc.
457992cb984SSergei Barannikov /// This is done prior to appending the type's encoding.
458992cb984SSergei Barannikov static void appendQualifier(SmallStringEnc &Enc, QualType QT) {
459992cb984SSergei Barannikov   // Qualifiers are emitted in alphabetical order.
460992cb984SSergei Barannikov   static const char *const Table[]={"","c:","r:","cr:","v:","cv:","rv:","crv:"};
461992cb984SSergei Barannikov   int Lookup = 0;
462992cb984SSergei Barannikov   if (QT.isConstQualified())
463992cb984SSergei Barannikov     Lookup += 1<<0;
464992cb984SSergei Barannikov   if (QT.isRestrictQualified())
465992cb984SSergei Barannikov     Lookup += 1<<1;
466992cb984SSergei Barannikov   if (QT.isVolatileQualified())
467992cb984SSergei Barannikov     Lookup += 1<<2;
468992cb984SSergei Barannikov   Enc += Table[Lookup];
469992cb984SSergei Barannikov }
470992cb984SSergei Barannikov 
471992cb984SSergei Barannikov /// Appends built-in types to Enc.
472992cb984SSergei Barannikov static bool appendBuiltinType(SmallStringEnc &Enc, const BuiltinType *BT) {
473992cb984SSergei Barannikov   const char *EncType;
474992cb984SSergei Barannikov   switch (BT->getKind()) {
475992cb984SSergei Barannikov     case BuiltinType::Void:
476992cb984SSergei Barannikov       EncType = "0";
477992cb984SSergei Barannikov       break;
478992cb984SSergei Barannikov     case BuiltinType::Bool:
479992cb984SSergei Barannikov       EncType = "b";
480992cb984SSergei Barannikov       break;
481992cb984SSergei Barannikov     case BuiltinType::Char_U:
482992cb984SSergei Barannikov       EncType = "uc";
483992cb984SSergei Barannikov       break;
484992cb984SSergei Barannikov     case BuiltinType::UChar:
485992cb984SSergei Barannikov       EncType = "uc";
486992cb984SSergei Barannikov       break;
487992cb984SSergei Barannikov     case BuiltinType::SChar:
488992cb984SSergei Barannikov       EncType = "sc";
489992cb984SSergei Barannikov       break;
490992cb984SSergei Barannikov     case BuiltinType::UShort:
491992cb984SSergei Barannikov       EncType = "us";
492992cb984SSergei Barannikov       break;
493992cb984SSergei Barannikov     case BuiltinType::Short:
494992cb984SSergei Barannikov       EncType = "ss";
495992cb984SSergei Barannikov       break;
496992cb984SSergei Barannikov     case BuiltinType::UInt:
497992cb984SSergei Barannikov       EncType = "ui";
498992cb984SSergei Barannikov       break;
499992cb984SSergei Barannikov     case BuiltinType::Int:
500992cb984SSergei Barannikov       EncType = "si";
501992cb984SSergei Barannikov       break;
502992cb984SSergei Barannikov     case BuiltinType::ULong:
503992cb984SSergei Barannikov       EncType = "ul";
504992cb984SSergei Barannikov       break;
505992cb984SSergei Barannikov     case BuiltinType::Long:
506992cb984SSergei Barannikov       EncType = "sl";
507992cb984SSergei Barannikov       break;
508992cb984SSergei Barannikov     case BuiltinType::ULongLong:
509992cb984SSergei Barannikov       EncType = "ull";
510992cb984SSergei Barannikov       break;
511992cb984SSergei Barannikov     case BuiltinType::LongLong:
512992cb984SSergei Barannikov       EncType = "sll";
513992cb984SSergei Barannikov       break;
514992cb984SSergei Barannikov     case BuiltinType::Float:
515992cb984SSergei Barannikov       EncType = "ft";
516992cb984SSergei Barannikov       break;
517992cb984SSergei Barannikov     case BuiltinType::Double:
518992cb984SSergei Barannikov       EncType = "d";
519992cb984SSergei Barannikov       break;
520992cb984SSergei Barannikov     case BuiltinType::LongDouble:
521992cb984SSergei Barannikov       EncType = "ld";
522992cb984SSergei Barannikov       break;
523992cb984SSergei Barannikov     default:
524992cb984SSergei Barannikov       return false;
525992cb984SSergei Barannikov   }
526992cb984SSergei Barannikov   Enc += EncType;
527992cb984SSergei Barannikov   return true;
528992cb984SSergei Barannikov }
529992cb984SSergei Barannikov 
530992cb984SSergei Barannikov /// Appends a pointer encoding to Enc before calling appendType for the pointee.
531992cb984SSergei Barannikov static bool appendPointerType(SmallStringEnc &Enc, const PointerType *PT,
532992cb984SSergei Barannikov                               const CodeGen::CodeGenModule &CGM,
533992cb984SSergei Barannikov                               TypeStringCache &TSC) {
534992cb984SSergei Barannikov   Enc += "p(";
535992cb984SSergei Barannikov   if (!appendType(Enc, PT->getPointeeType(), CGM, TSC))
536992cb984SSergei Barannikov     return false;
537992cb984SSergei Barannikov   Enc += ')';
538992cb984SSergei Barannikov   return true;
539992cb984SSergei Barannikov }
540992cb984SSergei Barannikov 
541992cb984SSergei Barannikov /// Appends array encoding to Enc before calling appendType for the element.
542992cb984SSergei Barannikov static bool appendArrayType(SmallStringEnc &Enc, QualType QT,
543992cb984SSergei Barannikov                             const ArrayType *AT,
544992cb984SSergei Barannikov                             const CodeGen::CodeGenModule &CGM,
545992cb984SSergei Barannikov                             TypeStringCache &TSC, StringRef NoSizeEnc) {
54649fd28d9SVlad Serebrennikov   if (AT->getSizeModifier() != ArraySizeModifier::Normal)
547992cb984SSergei Barannikov     return false;
548992cb984SSergei Barannikov   Enc += "a(";
549992cb984SSergei Barannikov   if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT))
550992cb984SSergei Barannikov     CAT->getSize().toStringUnsigned(Enc);
551992cb984SSergei Barannikov   else
552992cb984SSergei Barannikov     Enc += NoSizeEnc; // Global arrays use "*", otherwise it is "".
553992cb984SSergei Barannikov   Enc += ':';
554992cb984SSergei Barannikov   // The Qualifiers should be attached to the type rather than the array.
555992cb984SSergei Barannikov   appendQualifier(Enc, QT);
556992cb984SSergei Barannikov   if (!appendType(Enc, AT->getElementType(), CGM, TSC))
557992cb984SSergei Barannikov     return false;
558992cb984SSergei Barannikov   Enc += ')';
559992cb984SSergei Barannikov   return true;
560992cb984SSergei Barannikov }
561992cb984SSergei Barannikov 
562992cb984SSergei Barannikov /// Appends a function encoding to Enc, calling appendType for the return type
563992cb984SSergei Barannikov /// and the arguments.
564992cb984SSergei Barannikov static bool appendFunctionType(SmallStringEnc &Enc, const FunctionType *FT,
565992cb984SSergei Barannikov                              const CodeGen::CodeGenModule &CGM,
566992cb984SSergei Barannikov                              TypeStringCache &TSC) {
567992cb984SSergei Barannikov   Enc += "f{";
568992cb984SSergei Barannikov   if (!appendType(Enc, FT->getReturnType(), CGM, TSC))
569992cb984SSergei Barannikov     return false;
570992cb984SSergei Barannikov   Enc += "}(";
571992cb984SSergei Barannikov   if (const FunctionProtoType *FPT = FT->getAs<FunctionProtoType>()) {
572992cb984SSergei Barannikov     // N.B. we are only interested in the adjusted param types.
573992cb984SSergei Barannikov     auto I = FPT->param_type_begin();
574992cb984SSergei Barannikov     auto E = FPT->param_type_end();
575992cb984SSergei Barannikov     if (I != E) {
576992cb984SSergei Barannikov       do {
577992cb984SSergei Barannikov         if (!appendType(Enc, *I, CGM, TSC))
578992cb984SSergei Barannikov           return false;
579992cb984SSergei Barannikov         ++I;
580992cb984SSergei Barannikov         if (I != E)
581992cb984SSergei Barannikov           Enc += ',';
582992cb984SSergei Barannikov       } while (I != E);
583992cb984SSergei Barannikov       if (FPT->isVariadic())
584992cb984SSergei Barannikov         Enc += ",va";
585992cb984SSergei Barannikov     } else {
586992cb984SSergei Barannikov       if (FPT->isVariadic())
587992cb984SSergei Barannikov         Enc += "va";
588992cb984SSergei Barannikov       else
589992cb984SSergei Barannikov         Enc += '0';
590992cb984SSergei Barannikov     }
591992cb984SSergei Barannikov   }
592992cb984SSergei Barannikov   Enc += ')';
593992cb984SSergei Barannikov   return true;
594992cb984SSergei Barannikov }
595992cb984SSergei Barannikov 
596992cb984SSergei Barannikov /// Handles the type's qualifier before dispatching a call to handle specific
597992cb984SSergei Barannikov /// type encodings.
598992cb984SSergei Barannikov static bool appendType(SmallStringEnc &Enc, QualType QType,
599992cb984SSergei Barannikov                        const CodeGen::CodeGenModule &CGM,
600992cb984SSergei Barannikov                        TypeStringCache &TSC) {
601992cb984SSergei Barannikov 
602992cb984SSergei Barannikov   QualType QT = QType.getCanonicalType();
603992cb984SSergei Barannikov 
604992cb984SSergei Barannikov   if (const ArrayType *AT = QT->getAsArrayTypeUnsafe())
605992cb984SSergei Barannikov     // The Qualifiers should be attached to the type rather than the array.
606992cb984SSergei Barannikov     // Thus we don't call appendQualifier() here.
607992cb984SSergei Barannikov     return appendArrayType(Enc, QT, AT, CGM, TSC, "");
608992cb984SSergei Barannikov 
609992cb984SSergei Barannikov   appendQualifier(Enc, QT);
610992cb984SSergei Barannikov 
611992cb984SSergei Barannikov   if (const BuiltinType *BT = QT->getAs<BuiltinType>())
612992cb984SSergei Barannikov     return appendBuiltinType(Enc, BT);
613992cb984SSergei Barannikov 
614992cb984SSergei Barannikov   if (const PointerType *PT = QT->getAs<PointerType>())
615992cb984SSergei Barannikov     return appendPointerType(Enc, PT, CGM, TSC);
616992cb984SSergei Barannikov 
617992cb984SSergei Barannikov   if (const EnumType *ET = QT->getAs<EnumType>())
618992cb984SSergei Barannikov     return appendEnumType(Enc, ET, TSC, QT.getBaseTypeIdentifier());
619992cb984SSergei Barannikov 
620992cb984SSergei Barannikov   if (const RecordType *RT = QT->getAsStructureType())
621992cb984SSergei Barannikov     return appendRecordType(Enc, RT, CGM, TSC, QT.getBaseTypeIdentifier());
622992cb984SSergei Barannikov 
623992cb984SSergei Barannikov   if (const RecordType *RT = QT->getAsUnionType())
624992cb984SSergei Barannikov     return appendRecordType(Enc, RT, CGM, TSC, QT.getBaseTypeIdentifier());
625992cb984SSergei Barannikov 
626992cb984SSergei Barannikov   if (const FunctionType *FT = QT->getAs<FunctionType>())
627992cb984SSergei Barannikov     return appendFunctionType(Enc, FT, CGM, TSC);
628992cb984SSergei Barannikov 
629992cb984SSergei Barannikov   return false;
630992cb984SSergei Barannikov }
631992cb984SSergei Barannikov 
632992cb984SSergei Barannikov static bool getTypeString(SmallStringEnc &Enc, const Decl *D,
633992cb984SSergei Barannikov                           const CodeGen::CodeGenModule &CGM,
634992cb984SSergei Barannikov                           TypeStringCache &TSC) {
635992cb984SSergei Barannikov   if (!D)
636992cb984SSergei Barannikov     return false;
637992cb984SSergei Barannikov 
638992cb984SSergei Barannikov   if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
639992cb984SSergei Barannikov     if (FD->getLanguageLinkage() != CLanguageLinkage)
640992cb984SSergei Barannikov       return false;
641992cb984SSergei Barannikov     return appendType(Enc, FD->getType(), CGM, TSC);
642992cb984SSergei Barannikov   }
643992cb984SSergei Barannikov 
644992cb984SSergei Barannikov   if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
645992cb984SSergei Barannikov     if (VD->getLanguageLinkage() != CLanguageLinkage)
646992cb984SSergei Barannikov       return false;
647992cb984SSergei Barannikov     QualType QT = VD->getType().getCanonicalType();
648992cb984SSergei Barannikov     if (const ArrayType *AT = QT->getAsArrayTypeUnsafe()) {
649992cb984SSergei Barannikov       // Global ArrayTypes are given a size of '*' if the size is unknown.
650992cb984SSergei Barannikov       // The Qualifiers should be attached to the type rather than the array.
651992cb984SSergei Barannikov       // Thus we don't call appendQualifier() here.
652992cb984SSergei Barannikov       return appendArrayType(Enc, QT, AT, CGM, TSC, "*");
653992cb984SSergei Barannikov     }
654992cb984SSergei Barannikov     return appendType(Enc, QT, CGM, TSC);
655992cb984SSergei Barannikov   }
656992cb984SSergei Barannikov   return false;
657992cb984SSergei Barannikov }
658992cb984SSergei Barannikov 
659992cb984SSergei Barannikov std::unique_ptr<TargetCodeGenInfo>
660992cb984SSergei Barannikov CodeGen::createXCoreTargetCodeGenInfo(CodeGenModule &CGM) {
661992cb984SSergei Barannikov   return std::make_unique<XCoreTargetCodeGenInfo>(CGM.getTypes());
662992cb984SSergei Barannikov }
663