106c3fb27SDimitry Andric //===- XCore.cpp ----------------------------------------------------------===// 206c3fb27SDimitry Andric // 306c3fb27SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 406c3fb27SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 506c3fb27SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 606c3fb27SDimitry Andric // 706c3fb27SDimitry Andric //===----------------------------------------------------------------------===// 806c3fb27SDimitry Andric 906c3fb27SDimitry Andric #include "ABIInfoImpl.h" 1006c3fb27SDimitry Andric #include "TargetInfo.h" 1106c3fb27SDimitry Andric 1206c3fb27SDimitry Andric using namespace clang; 1306c3fb27SDimitry Andric using namespace clang::CodeGen; 1406c3fb27SDimitry Andric 1506c3fb27SDimitry Andric //===----------------------------------------------------------------------===// 1606c3fb27SDimitry Andric // XCore ABI Implementation 1706c3fb27SDimitry Andric //===----------------------------------------------------------------------===// 1806c3fb27SDimitry Andric 1906c3fb27SDimitry Andric namespace { 2006c3fb27SDimitry Andric 2106c3fb27SDimitry Andric /// A SmallStringEnc instance is used to build up the TypeString by passing 2206c3fb27SDimitry Andric /// it by reference between functions that append to it. 2306c3fb27SDimitry Andric typedef llvm::SmallString<128> SmallStringEnc; 2406c3fb27SDimitry Andric 2506c3fb27SDimitry Andric /// TypeStringCache caches the meta encodings of Types. 2606c3fb27SDimitry Andric /// 2706c3fb27SDimitry Andric /// The reason for caching TypeStrings is two fold: 2806c3fb27SDimitry Andric /// 1. To cache a type's encoding for later uses; 2906c3fb27SDimitry Andric /// 2. As a means to break recursive member type inclusion. 3006c3fb27SDimitry Andric /// 3106c3fb27SDimitry Andric /// A cache Entry can have a Status of: 3206c3fb27SDimitry Andric /// NonRecursive: The type encoding is not recursive; 3306c3fb27SDimitry Andric /// Recursive: The type encoding is recursive; 3406c3fb27SDimitry Andric /// Incomplete: An incomplete TypeString; 3506c3fb27SDimitry Andric /// IncompleteUsed: An incomplete TypeString that has been used in a 3606c3fb27SDimitry Andric /// Recursive type encoding. 3706c3fb27SDimitry Andric /// 3806c3fb27SDimitry Andric /// A NonRecursive entry will have all of its sub-members expanded as fully 3906c3fb27SDimitry Andric /// as possible. Whilst it may contain types which are recursive, the type 4006c3fb27SDimitry Andric /// itself is not recursive and thus its encoding may be safely used whenever 4106c3fb27SDimitry Andric /// the type is encountered. 4206c3fb27SDimitry Andric /// 4306c3fb27SDimitry Andric /// A Recursive entry will have all of its sub-members expanded as fully as 4406c3fb27SDimitry Andric /// possible. The type itself is recursive and it may contain other types which 4506c3fb27SDimitry Andric /// are recursive. The Recursive encoding must not be used during the expansion 4606c3fb27SDimitry Andric /// of a recursive type's recursive branch. For simplicity the code uses 4706c3fb27SDimitry Andric /// IncompleteCount to reject all usage of Recursive encodings for member types. 4806c3fb27SDimitry Andric /// 4906c3fb27SDimitry Andric /// An Incomplete entry is always a RecordType and only encodes its 5006c3fb27SDimitry Andric /// identifier e.g. "s(S){}". Incomplete 'StubEnc' entries are ephemeral and 5106c3fb27SDimitry Andric /// are placed into the cache during type expansion as a means to identify and 5206c3fb27SDimitry Andric /// handle recursive inclusion of types as sub-members. If there is recursion 5306c3fb27SDimitry Andric /// the entry becomes IncompleteUsed. 5406c3fb27SDimitry Andric /// 5506c3fb27SDimitry Andric /// During the expansion of a RecordType's members: 5606c3fb27SDimitry Andric /// 5706c3fb27SDimitry Andric /// If the cache contains a NonRecursive encoding for the member type, the 5806c3fb27SDimitry Andric /// cached encoding is used; 5906c3fb27SDimitry Andric /// 6006c3fb27SDimitry Andric /// If the cache contains a Recursive encoding for the member type, the 6106c3fb27SDimitry Andric /// cached encoding is 'Swapped' out, as it may be incorrect, and... 6206c3fb27SDimitry Andric /// 6306c3fb27SDimitry Andric /// If the member is a RecordType, an Incomplete encoding is placed into the 6406c3fb27SDimitry Andric /// cache to break potential recursive inclusion of itself as a sub-member; 6506c3fb27SDimitry Andric /// 6606c3fb27SDimitry Andric /// Once a member RecordType has been expanded, its temporary incomplete 6706c3fb27SDimitry Andric /// entry is removed from the cache. If a Recursive encoding was swapped out 6806c3fb27SDimitry Andric /// it is swapped back in; 6906c3fb27SDimitry Andric /// 7006c3fb27SDimitry Andric /// If an incomplete entry is used to expand a sub-member, the incomplete 7106c3fb27SDimitry Andric /// entry is marked as IncompleteUsed. The cache keeps count of how many 7206c3fb27SDimitry Andric /// IncompleteUsed entries it currently contains in IncompleteUsedCount; 7306c3fb27SDimitry Andric /// 7406c3fb27SDimitry Andric /// If a member's encoding is found to be a NonRecursive or Recursive viz: 7506c3fb27SDimitry Andric /// IncompleteUsedCount==0, the member's encoding is added to the cache. 7606c3fb27SDimitry Andric /// Else the member is part of a recursive type and thus the recursion has 7706c3fb27SDimitry Andric /// been exited too soon for the encoding to be correct for the member. 7806c3fb27SDimitry Andric /// 7906c3fb27SDimitry Andric class TypeStringCache { 8006c3fb27SDimitry Andric enum Status {NonRecursive, Recursive, Incomplete, IncompleteUsed}; 8106c3fb27SDimitry Andric struct Entry { 8206c3fb27SDimitry Andric std::string Str; // The encoded TypeString for the type. 8306c3fb27SDimitry Andric enum Status State; // Information about the encoding in 'Str'. 8406c3fb27SDimitry Andric std::string Swapped; // A temporary place holder for a Recursive encoding 8506c3fb27SDimitry Andric // during the expansion of RecordType's members. 8606c3fb27SDimitry Andric }; 8706c3fb27SDimitry Andric std::map<const IdentifierInfo *, struct Entry> Map; 8806c3fb27SDimitry Andric unsigned IncompleteCount; // Number of Incomplete entries in the Map. 8906c3fb27SDimitry Andric unsigned IncompleteUsedCount; // Number of IncompleteUsed entries in the Map. 9006c3fb27SDimitry Andric public: 9106c3fb27SDimitry Andric TypeStringCache() : IncompleteCount(0), IncompleteUsedCount(0) {} 9206c3fb27SDimitry Andric void addIncomplete(const IdentifierInfo *ID, std::string StubEnc); 9306c3fb27SDimitry Andric bool removeIncomplete(const IdentifierInfo *ID); 9406c3fb27SDimitry Andric void addIfComplete(const IdentifierInfo *ID, StringRef Str, 9506c3fb27SDimitry Andric bool IsRecursive); 9606c3fb27SDimitry Andric StringRef lookupStr(const IdentifierInfo *ID); 9706c3fb27SDimitry Andric }; 9806c3fb27SDimitry Andric 9906c3fb27SDimitry Andric /// TypeString encodings for enum & union fields must be order. 10006c3fb27SDimitry Andric /// FieldEncoding is a helper for this ordering process. 10106c3fb27SDimitry Andric class FieldEncoding { 10206c3fb27SDimitry Andric bool HasName; 10306c3fb27SDimitry Andric std::string Enc; 10406c3fb27SDimitry Andric public: 10506c3fb27SDimitry Andric FieldEncoding(bool b, SmallStringEnc &e) : HasName(b), Enc(e.c_str()) {} 10606c3fb27SDimitry Andric StringRef str() { return Enc; } 10706c3fb27SDimitry Andric bool operator<(const FieldEncoding &rhs) const { 10806c3fb27SDimitry Andric if (HasName != rhs.HasName) return HasName; 10906c3fb27SDimitry Andric return Enc < rhs.Enc; 11006c3fb27SDimitry Andric } 11106c3fb27SDimitry Andric }; 11206c3fb27SDimitry Andric 11306c3fb27SDimitry Andric class XCoreABIInfo : public DefaultABIInfo { 11406c3fb27SDimitry Andric public: 11506c3fb27SDimitry Andric XCoreABIInfo(CodeGen::CodeGenTypes &CGT) : DefaultABIInfo(CGT) {} 116*0fca6ea1SDimitry Andric RValue EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty, 117*0fca6ea1SDimitry Andric AggValueSlot Slot) const override; 11806c3fb27SDimitry Andric }; 11906c3fb27SDimitry Andric 12006c3fb27SDimitry Andric class XCoreTargetCodeGenInfo : public TargetCodeGenInfo { 12106c3fb27SDimitry Andric mutable TypeStringCache TSC; 12206c3fb27SDimitry Andric void emitTargetMD(const Decl *D, llvm::GlobalValue *GV, 12306c3fb27SDimitry Andric const CodeGen::CodeGenModule &M) const; 12406c3fb27SDimitry Andric 12506c3fb27SDimitry Andric public: 12606c3fb27SDimitry Andric XCoreTargetCodeGenInfo(CodeGenTypes &CGT) 12706c3fb27SDimitry Andric : TargetCodeGenInfo(std::make_unique<XCoreABIInfo>(CGT)) {} 12806c3fb27SDimitry Andric void emitTargetMetadata(CodeGen::CodeGenModule &CGM, 12906c3fb27SDimitry Andric const llvm::MapVector<GlobalDecl, StringRef> 13006c3fb27SDimitry Andric &MangledDeclNames) const override; 13106c3fb27SDimitry Andric }; 13206c3fb27SDimitry Andric 13306c3fb27SDimitry Andric } // End anonymous namespace. 13406c3fb27SDimitry Andric 13506c3fb27SDimitry Andric // TODO: this implementation is likely now redundant with the default 13606c3fb27SDimitry Andric // EmitVAArg. 137*0fca6ea1SDimitry Andric RValue XCoreABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, 138*0fca6ea1SDimitry Andric QualType Ty, AggValueSlot Slot) const { 13906c3fb27SDimitry Andric CGBuilderTy &Builder = CGF.Builder; 14006c3fb27SDimitry Andric 14106c3fb27SDimitry Andric // Get the VAList. 14206c3fb27SDimitry Andric CharUnits SlotSize = CharUnits::fromQuantity(4); 14306c3fb27SDimitry Andric Address AP = Address(Builder.CreateLoad(VAListAddr), 14406c3fb27SDimitry Andric getVAListElementType(CGF), SlotSize); 14506c3fb27SDimitry Andric 14606c3fb27SDimitry Andric // Handle the argument. 14706c3fb27SDimitry Andric ABIArgInfo AI = classifyArgumentType(Ty); 14806c3fb27SDimitry Andric CharUnits TypeAlign = getContext().getTypeAlignInChars(Ty); 14906c3fb27SDimitry Andric llvm::Type *ArgTy = CGT.ConvertType(Ty); 15006c3fb27SDimitry Andric if (AI.canHaveCoerceToType() && !AI.getCoerceToType()) 15106c3fb27SDimitry Andric AI.setCoerceToType(ArgTy); 15206c3fb27SDimitry Andric llvm::Type *ArgPtrTy = llvm::PointerType::getUnqual(ArgTy); 15306c3fb27SDimitry Andric 15406c3fb27SDimitry Andric Address Val = Address::invalid(); 15506c3fb27SDimitry Andric CharUnits ArgSize = CharUnits::Zero(); 15606c3fb27SDimitry Andric switch (AI.getKind()) { 15706c3fb27SDimitry Andric case ABIArgInfo::Expand: 15806c3fb27SDimitry Andric case ABIArgInfo::CoerceAndExpand: 15906c3fb27SDimitry Andric case ABIArgInfo::InAlloca: 16006c3fb27SDimitry Andric llvm_unreachable("Unsupported ABI kind for va_arg"); 16106c3fb27SDimitry Andric case ABIArgInfo::Ignore: 16206c3fb27SDimitry Andric Val = Address(llvm::UndefValue::get(ArgPtrTy), ArgTy, TypeAlign); 16306c3fb27SDimitry Andric ArgSize = CharUnits::Zero(); 16406c3fb27SDimitry Andric break; 16506c3fb27SDimitry Andric case ABIArgInfo::Extend: 16606c3fb27SDimitry Andric case ABIArgInfo::Direct: 16706c3fb27SDimitry Andric Val = AP.withElementType(ArgTy); 16806c3fb27SDimitry Andric ArgSize = CharUnits::fromQuantity( 16906c3fb27SDimitry Andric getDataLayout().getTypeAllocSize(AI.getCoerceToType())); 17006c3fb27SDimitry Andric ArgSize = ArgSize.alignTo(SlotSize); 17106c3fb27SDimitry Andric break; 17206c3fb27SDimitry Andric case ABIArgInfo::Indirect: 17306c3fb27SDimitry Andric case ABIArgInfo::IndirectAliased: 17406c3fb27SDimitry Andric Val = AP.withElementType(ArgPtrTy); 17506c3fb27SDimitry Andric Val = Address(Builder.CreateLoad(Val), ArgTy, TypeAlign); 17606c3fb27SDimitry Andric ArgSize = SlotSize; 17706c3fb27SDimitry Andric break; 17806c3fb27SDimitry Andric } 17906c3fb27SDimitry Andric 18006c3fb27SDimitry Andric // Increment the VAList. 18106c3fb27SDimitry Andric if (!ArgSize.isZero()) { 18206c3fb27SDimitry Andric Address APN = Builder.CreateConstInBoundsByteGEP(AP, ArgSize); 183*0fca6ea1SDimitry Andric Builder.CreateStore(APN.emitRawPointer(CGF), VAListAddr); 18406c3fb27SDimitry Andric } 18506c3fb27SDimitry Andric 186*0fca6ea1SDimitry Andric return CGF.EmitLoadOfAnyValue(CGF.MakeAddrLValue(Val, Ty), Slot); 18706c3fb27SDimitry Andric } 18806c3fb27SDimitry Andric 18906c3fb27SDimitry Andric /// During the expansion of a RecordType, an incomplete TypeString is placed 19006c3fb27SDimitry Andric /// into the cache as a means to identify and break recursion. 19106c3fb27SDimitry Andric /// If there is a Recursive encoding in the cache, it is swapped out and will 19206c3fb27SDimitry Andric /// be reinserted by removeIncomplete(). 19306c3fb27SDimitry Andric /// All other types of encoding should have been used rather than arriving here. 19406c3fb27SDimitry Andric void TypeStringCache::addIncomplete(const IdentifierInfo *ID, 19506c3fb27SDimitry Andric std::string StubEnc) { 19606c3fb27SDimitry Andric if (!ID) 19706c3fb27SDimitry Andric return; 19806c3fb27SDimitry Andric Entry &E = Map[ID]; 19906c3fb27SDimitry Andric assert( (E.Str.empty() || E.State == Recursive) && 20006c3fb27SDimitry Andric "Incorrectly use of addIncomplete"); 20106c3fb27SDimitry Andric assert(!StubEnc.empty() && "Passing an empty string to addIncomplete()"); 20206c3fb27SDimitry Andric E.Swapped.swap(E.Str); // swap out the Recursive 20306c3fb27SDimitry Andric E.Str.swap(StubEnc); 20406c3fb27SDimitry Andric E.State = Incomplete; 20506c3fb27SDimitry Andric ++IncompleteCount; 20606c3fb27SDimitry Andric } 20706c3fb27SDimitry Andric 20806c3fb27SDimitry Andric /// Once the RecordType has been expanded, the temporary incomplete TypeString 20906c3fb27SDimitry Andric /// must be removed from the cache. 21006c3fb27SDimitry Andric /// If a Recursive was swapped out by addIncomplete(), it will be replaced. 21106c3fb27SDimitry Andric /// Returns true if the RecordType was defined recursively. 21206c3fb27SDimitry Andric bool TypeStringCache::removeIncomplete(const IdentifierInfo *ID) { 21306c3fb27SDimitry Andric if (!ID) 21406c3fb27SDimitry Andric return false; 21506c3fb27SDimitry Andric auto I = Map.find(ID); 21606c3fb27SDimitry Andric assert(I != Map.end() && "Entry not present"); 21706c3fb27SDimitry Andric Entry &E = I->second; 21806c3fb27SDimitry Andric assert( (E.State == Incomplete || 21906c3fb27SDimitry Andric E.State == IncompleteUsed) && 22006c3fb27SDimitry Andric "Entry must be an incomplete type"); 22106c3fb27SDimitry Andric bool IsRecursive = false; 22206c3fb27SDimitry Andric if (E.State == IncompleteUsed) { 22306c3fb27SDimitry Andric // We made use of our Incomplete encoding, thus we are recursive. 22406c3fb27SDimitry Andric IsRecursive = true; 22506c3fb27SDimitry Andric --IncompleteUsedCount; 22606c3fb27SDimitry Andric } 22706c3fb27SDimitry Andric if (E.Swapped.empty()) 22806c3fb27SDimitry Andric Map.erase(I); 22906c3fb27SDimitry Andric else { 23006c3fb27SDimitry Andric // Swap the Recursive back. 23106c3fb27SDimitry Andric E.Swapped.swap(E.Str); 23206c3fb27SDimitry Andric E.Swapped.clear(); 23306c3fb27SDimitry Andric E.State = Recursive; 23406c3fb27SDimitry Andric } 23506c3fb27SDimitry Andric --IncompleteCount; 23606c3fb27SDimitry Andric return IsRecursive; 23706c3fb27SDimitry Andric } 23806c3fb27SDimitry Andric 23906c3fb27SDimitry Andric /// Add the encoded TypeString to the cache only if it is NonRecursive or 24006c3fb27SDimitry Andric /// Recursive (viz: all sub-members were expanded as fully as possible). 24106c3fb27SDimitry Andric void TypeStringCache::addIfComplete(const IdentifierInfo *ID, StringRef Str, 24206c3fb27SDimitry Andric bool IsRecursive) { 24306c3fb27SDimitry Andric if (!ID || IncompleteUsedCount) 24406c3fb27SDimitry Andric return; // No key or it is an incomplete sub-type so don't add. 24506c3fb27SDimitry Andric Entry &E = Map[ID]; 24606c3fb27SDimitry Andric if (IsRecursive && !E.Str.empty()) { 24706c3fb27SDimitry Andric assert(E.State==Recursive && E.Str.size() == Str.size() && 24806c3fb27SDimitry Andric "This is not the same Recursive entry"); 24906c3fb27SDimitry Andric // The parent container was not recursive after all, so we could have used 25006c3fb27SDimitry Andric // this Recursive sub-member entry after all, but we assumed the worse when 25106c3fb27SDimitry Andric // we started viz: IncompleteCount!=0. 25206c3fb27SDimitry Andric return; 25306c3fb27SDimitry Andric } 25406c3fb27SDimitry Andric assert(E.Str.empty() && "Entry already present"); 25506c3fb27SDimitry Andric E.Str = Str.str(); 25606c3fb27SDimitry Andric E.State = IsRecursive? Recursive : NonRecursive; 25706c3fb27SDimitry Andric } 25806c3fb27SDimitry Andric 25906c3fb27SDimitry Andric /// Return a cached TypeString encoding for the ID. If there isn't one, or we 26006c3fb27SDimitry Andric /// are recursively expanding a type (IncompleteCount != 0) and the cached 26106c3fb27SDimitry Andric /// encoding is Recursive, return an empty StringRef. 26206c3fb27SDimitry Andric StringRef TypeStringCache::lookupStr(const IdentifierInfo *ID) { 26306c3fb27SDimitry Andric if (!ID) 26406c3fb27SDimitry Andric return StringRef(); // We have no key. 26506c3fb27SDimitry Andric auto I = Map.find(ID); 26606c3fb27SDimitry Andric if (I == Map.end()) 26706c3fb27SDimitry Andric return StringRef(); // We have no encoding. 26806c3fb27SDimitry Andric Entry &E = I->second; 26906c3fb27SDimitry Andric if (E.State == Recursive && IncompleteCount) 27006c3fb27SDimitry Andric return StringRef(); // We don't use Recursive encodings for member types. 27106c3fb27SDimitry Andric 27206c3fb27SDimitry Andric if (E.State == Incomplete) { 27306c3fb27SDimitry Andric // The incomplete type is being used to break out of recursion. 27406c3fb27SDimitry Andric E.State = IncompleteUsed; 27506c3fb27SDimitry Andric ++IncompleteUsedCount; 27606c3fb27SDimitry Andric } 27706c3fb27SDimitry Andric return E.Str; 27806c3fb27SDimitry Andric } 27906c3fb27SDimitry Andric 28006c3fb27SDimitry Andric /// The XCore ABI includes a type information section that communicates symbol 28106c3fb27SDimitry Andric /// type information to the linker. The linker uses this information to verify 28206c3fb27SDimitry Andric /// safety/correctness of things such as array bound and pointers et al. 28306c3fb27SDimitry Andric /// The ABI only requires C (and XC) language modules to emit TypeStrings. 28406c3fb27SDimitry Andric /// This type information (TypeString) is emitted into meta data for all global 28506c3fb27SDimitry Andric /// symbols: definitions, declarations, functions & variables. 28606c3fb27SDimitry Andric /// 28706c3fb27SDimitry Andric /// The TypeString carries type, qualifier, name, size & value details. 28806c3fb27SDimitry Andric /// Please see 'Tools Development Guide' section 2.16.2 for format details: 28906c3fb27SDimitry Andric /// https://www.xmos.com/download/public/Tools-Development-Guide%28X9114A%29.pdf 29006c3fb27SDimitry Andric /// The output is tested by test/CodeGen/xcore-stringtype.c. 29106c3fb27SDimitry Andric /// 29206c3fb27SDimitry Andric static bool getTypeString(SmallStringEnc &Enc, const Decl *D, 29306c3fb27SDimitry Andric const CodeGen::CodeGenModule &CGM, 29406c3fb27SDimitry Andric TypeStringCache &TSC); 29506c3fb27SDimitry Andric 29606c3fb27SDimitry Andric /// XCore uses emitTargetMD to emit TypeString metadata for global symbols. 29706c3fb27SDimitry Andric void XCoreTargetCodeGenInfo::emitTargetMD( 29806c3fb27SDimitry Andric const Decl *D, llvm::GlobalValue *GV, 29906c3fb27SDimitry Andric const CodeGen::CodeGenModule &CGM) const { 30006c3fb27SDimitry Andric SmallStringEnc Enc; 30106c3fb27SDimitry Andric if (getTypeString(Enc, D, CGM, TSC)) { 30206c3fb27SDimitry Andric llvm::LLVMContext &Ctx = CGM.getModule().getContext(); 30306c3fb27SDimitry Andric llvm::Metadata *MDVals[] = {llvm::ConstantAsMetadata::get(GV), 30406c3fb27SDimitry Andric llvm::MDString::get(Ctx, Enc.str())}; 30506c3fb27SDimitry Andric llvm::NamedMDNode *MD = 30606c3fb27SDimitry Andric CGM.getModule().getOrInsertNamedMetadata("xcore.typestrings"); 30706c3fb27SDimitry Andric MD->addOperand(llvm::MDNode::get(Ctx, MDVals)); 30806c3fb27SDimitry Andric } 30906c3fb27SDimitry Andric } 31006c3fb27SDimitry Andric 31106c3fb27SDimitry Andric void XCoreTargetCodeGenInfo::emitTargetMetadata( 31206c3fb27SDimitry Andric CodeGen::CodeGenModule &CGM, 31306c3fb27SDimitry Andric const llvm::MapVector<GlobalDecl, StringRef> &MangledDeclNames) const { 31406c3fb27SDimitry Andric // Warning, new MangledDeclNames may be appended within this loop. 31506c3fb27SDimitry Andric // We rely on MapVector insertions adding new elements to the end 31606c3fb27SDimitry Andric // of the container. 31706c3fb27SDimitry Andric for (unsigned I = 0; I != MangledDeclNames.size(); ++I) { 31806c3fb27SDimitry Andric auto Val = *(MangledDeclNames.begin() + I); 31906c3fb27SDimitry Andric llvm::GlobalValue *GV = CGM.GetGlobalValue(Val.second); 32006c3fb27SDimitry Andric if (GV) { 32106c3fb27SDimitry Andric const Decl *D = Val.first.getDecl()->getMostRecentDecl(); 32206c3fb27SDimitry Andric emitTargetMD(D, GV, CGM); 32306c3fb27SDimitry Andric } 32406c3fb27SDimitry Andric } 32506c3fb27SDimitry Andric } 32606c3fb27SDimitry Andric 32706c3fb27SDimitry Andric static bool appendType(SmallStringEnc &Enc, QualType QType, 32806c3fb27SDimitry Andric const CodeGen::CodeGenModule &CGM, 32906c3fb27SDimitry Andric TypeStringCache &TSC); 33006c3fb27SDimitry Andric 33106c3fb27SDimitry Andric /// Helper function for appendRecordType(). 33206c3fb27SDimitry Andric /// Builds a SmallVector containing the encoded field types in declaration 33306c3fb27SDimitry Andric /// order. 33406c3fb27SDimitry Andric static bool extractFieldType(SmallVectorImpl<FieldEncoding> &FE, 33506c3fb27SDimitry Andric const RecordDecl *RD, 33606c3fb27SDimitry Andric const CodeGen::CodeGenModule &CGM, 33706c3fb27SDimitry Andric TypeStringCache &TSC) { 33806c3fb27SDimitry Andric for (const auto *Field : RD->fields()) { 33906c3fb27SDimitry Andric SmallStringEnc Enc; 34006c3fb27SDimitry Andric Enc += "m("; 34106c3fb27SDimitry Andric Enc += Field->getName(); 34206c3fb27SDimitry Andric Enc += "){"; 34306c3fb27SDimitry Andric if (Field->isBitField()) { 34406c3fb27SDimitry Andric Enc += "b("; 34506c3fb27SDimitry Andric llvm::raw_svector_ostream OS(Enc); 34606c3fb27SDimitry Andric OS << Field->getBitWidthValue(CGM.getContext()); 34706c3fb27SDimitry Andric Enc += ':'; 34806c3fb27SDimitry Andric } 34906c3fb27SDimitry Andric if (!appendType(Enc, Field->getType(), CGM, TSC)) 35006c3fb27SDimitry Andric return false; 35106c3fb27SDimitry Andric if (Field->isBitField()) 35206c3fb27SDimitry Andric Enc += ')'; 35306c3fb27SDimitry Andric Enc += '}'; 35406c3fb27SDimitry Andric FE.emplace_back(!Field->getName().empty(), Enc); 35506c3fb27SDimitry Andric } 35606c3fb27SDimitry Andric return true; 35706c3fb27SDimitry Andric } 35806c3fb27SDimitry Andric 35906c3fb27SDimitry Andric /// Appends structure and union types to Enc and adds encoding to cache. 36006c3fb27SDimitry Andric /// Recursively calls appendType (via extractFieldType) for each field. 36106c3fb27SDimitry Andric /// Union types have their fields ordered according to the ABI. 36206c3fb27SDimitry Andric static bool appendRecordType(SmallStringEnc &Enc, const RecordType *RT, 36306c3fb27SDimitry Andric const CodeGen::CodeGenModule &CGM, 36406c3fb27SDimitry Andric TypeStringCache &TSC, const IdentifierInfo *ID) { 36506c3fb27SDimitry Andric // Append the cached TypeString if we have one. 36606c3fb27SDimitry Andric StringRef TypeString = TSC.lookupStr(ID); 36706c3fb27SDimitry Andric if (!TypeString.empty()) { 36806c3fb27SDimitry Andric Enc += TypeString; 36906c3fb27SDimitry Andric return true; 37006c3fb27SDimitry Andric } 37106c3fb27SDimitry Andric 37206c3fb27SDimitry Andric // Start to emit an incomplete TypeString. 37306c3fb27SDimitry Andric size_t Start = Enc.size(); 37406c3fb27SDimitry Andric Enc += (RT->isUnionType()? 'u' : 's'); 37506c3fb27SDimitry Andric Enc += '('; 37606c3fb27SDimitry Andric if (ID) 37706c3fb27SDimitry Andric Enc += ID->getName(); 37806c3fb27SDimitry Andric Enc += "){"; 37906c3fb27SDimitry Andric 38006c3fb27SDimitry Andric // We collect all encoded fields and order as necessary. 38106c3fb27SDimitry Andric bool IsRecursive = false; 38206c3fb27SDimitry Andric const RecordDecl *RD = RT->getDecl()->getDefinition(); 38306c3fb27SDimitry Andric if (RD && !RD->field_empty()) { 38406c3fb27SDimitry Andric // An incomplete TypeString stub is placed in the cache for this RecordType 38506c3fb27SDimitry Andric // so that recursive calls to this RecordType will use it whilst building a 38606c3fb27SDimitry Andric // complete TypeString for this RecordType. 38706c3fb27SDimitry Andric SmallVector<FieldEncoding, 16> FE; 38806c3fb27SDimitry Andric std::string StubEnc(Enc.substr(Start).str()); 38906c3fb27SDimitry Andric StubEnc += '}'; // StubEnc now holds a valid incomplete TypeString. 39006c3fb27SDimitry Andric TSC.addIncomplete(ID, std::move(StubEnc)); 39106c3fb27SDimitry Andric if (!extractFieldType(FE, RD, CGM, TSC)) { 39206c3fb27SDimitry Andric (void) TSC.removeIncomplete(ID); 39306c3fb27SDimitry Andric return false; 39406c3fb27SDimitry Andric } 39506c3fb27SDimitry Andric IsRecursive = TSC.removeIncomplete(ID); 39606c3fb27SDimitry Andric // The ABI requires unions to be sorted but not structures. 39706c3fb27SDimitry Andric // See FieldEncoding::operator< for sort algorithm. 39806c3fb27SDimitry Andric if (RT->isUnionType()) 39906c3fb27SDimitry Andric llvm::sort(FE); 40006c3fb27SDimitry Andric // We can now complete the TypeString. 40106c3fb27SDimitry Andric unsigned E = FE.size(); 40206c3fb27SDimitry Andric for (unsigned I = 0; I != E; ++I) { 40306c3fb27SDimitry Andric if (I) 40406c3fb27SDimitry Andric Enc += ','; 40506c3fb27SDimitry Andric Enc += FE[I].str(); 40606c3fb27SDimitry Andric } 40706c3fb27SDimitry Andric } 40806c3fb27SDimitry Andric Enc += '}'; 40906c3fb27SDimitry Andric TSC.addIfComplete(ID, Enc.substr(Start), IsRecursive); 41006c3fb27SDimitry Andric return true; 41106c3fb27SDimitry Andric } 41206c3fb27SDimitry Andric 41306c3fb27SDimitry Andric /// Appends enum types to Enc and adds the encoding to the cache. 41406c3fb27SDimitry Andric static bool appendEnumType(SmallStringEnc &Enc, const EnumType *ET, 41506c3fb27SDimitry Andric TypeStringCache &TSC, 41606c3fb27SDimitry Andric const IdentifierInfo *ID) { 41706c3fb27SDimitry Andric // Append the cached TypeString if we have one. 41806c3fb27SDimitry Andric StringRef TypeString = TSC.lookupStr(ID); 41906c3fb27SDimitry Andric if (!TypeString.empty()) { 42006c3fb27SDimitry Andric Enc += TypeString; 42106c3fb27SDimitry Andric return true; 42206c3fb27SDimitry Andric } 42306c3fb27SDimitry Andric 42406c3fb27SDimitry Andric size_t Start = Enc.size(); 42506c3fb27SDimitry Andric Enc += "e("; 42606c3fb27SDimitry Andric if (ID) 42706c3fb27SDimitry Andric Enc += ID->getName(); 42806c3fb27SDimitry Andric Enc += "){"; 42906c3fb27SDimitry Andric 43006c3fb27SDimitry Andric // We collect all encoded enumerations and order them alphanumerically. 43106c3fb27SDimitry Andric if (const EnumDecl *ED = ET->getDecl()->getDefinition()) { 43206c3fb27SDimitry Andric SmallVector<FieldEncoding, 16> FE; 43306c3fb27SDimitry Andric for (auto I = ED->enumerator_begin(), E = ED->enumerator_end(); I != E; 43406c3fb27SDimitry Andric ++I) { 43506c3fb27SDimitry Andric SmallStringEnc EnumEnc; 43606c3fb27SDimitry Andric EnumEnc += "m("; 43706c3fb27SDimitry Andric EnumEnc += I->getName(); 43806c3fb27SDimitry Andric EnumEnc += "){"; 43906c3fb27SDimitry Andric I->getInitVal().toString(EnumEnc); 44006c3fb27SDimitry Andric EnumEnc += '}'; 44106c3fb27SDimitry Andric FE.push_back(FieldEncoding(!I->getName().empty(), EnumEnc)); 44206c3fb27SDimitry Andric } 44306c3fb27SDimitry Andric llvm::sort(FE); 44406c3fb27SDimitry Andric unsigned E = FE.size(); 44506c3fb27SDimitry Andric for (unsigned I = 0; I != E; ++I) { 44606c3fb27SDimitry Andric if (I) 44706c3fb27SDimitry Andric Enc += ','; 44806c3fb27SDimitry Andric Enc += FE[I].str(); 44906c3fb27SDimitry Andric } 45006c3fb27SDimitry Andric } 45106c3fb27SDimitry Andric Enc += '}'; 45206c3fb27SDimitry Andric TSC.addIfComplete(ID, Enc.substr(Start), false); 45306c3fb27SDimitry Andric return true; 45406c3fb27SDimitry Andric } 45506c3fb27SDimitry Andric 45606c3fb27SDimitry Andric /// Appends type's qualifier to Enc. 45706c3fb27SDimitry Andric /// This is done prior to appending the type's encoding. 45806c3fb27SDimitry Andric static void appendQualifier(SmallStringEnc &Enc, QualType QT) { 45906c3fb27SDimitry Andric // Qualifiers are emitted in alphabetical order. 46006c3fb27SDimitry Andric static const char *const Table[]={"","c:","r:","cr:","v:","cv:","rv:","crv:"}; 46106c3fb27SDimitry Andric int Lookup = 0; 46206c3fb27SDimitry Andric if (QT.isConstQualified()) 46306c3fb27SDimitry Andric Lookup += 1<<0; 46406c3fb27SDimitry Andric if (QT.isRestrictQualified()) 46506c3fb27SDimitry Andric Lookup += 1<<1; 46606c3fb27SDimitry Andric if (QT.isVolatileQualified()) 46706c3fb27SDimitry Andric Lookup += 1<<2; 46806c3fb27SDimitry Andric Enc += Table[Lookup]; 46906c3fb27SDimitry Andric } 47006c3fb27SDimitry Andric 47106c3fb27SDimitry Andric /// Appends built-in types to Enc. 47206c3fb27SDimitry Andric static bool appendBuiltinType(SmallStringEnc &Enc, const BuiltinType *BT) { 47306c3fb27SDimitry Andric const char *EncType; 47406c3fb27SDimitry Andric switch (BT->getKind()) { 47506c3fb27SDimitry Andric case BuiltinType::Void: 47606c3fb27SDimitry Andric EncType = "0"; 47706c3fb27SDimitry Andric break; 47806c3fb27SDimitry Andric case BuiltinType::Bool: 47906c3fb27SDimitry Andric EncType = "b"; 48006c3fb27SDimitry Andric break; 48106c3fb27SDimitry Andric case BuiltinType::Char_U: 48206c3fb27SDimitry Andric EncType = "uc"; 48306c3fb27SDimitry Andric break; 48406c3fb27SDimitry Andric case BuiltinType::UChar: 48506c3fb27SDimitry Andric EncType = "uc"; 48606c3fb27SDimitry Andric break; 48706c3fb27SDimitry Andric case BuiltinType::SChar: 48806c3fb27SDimitry Andric EncType = "sc"; 48906c3fb27SDimitry Andric break; 49006c3fb27SDimitry Andric case BuiltinType::UShort: 49106c3fb27SDimitry Andric EncType = "us"; 49206c3fb27SDimitry Andric break; 49306c3fb27SDimitry Andric case BuiltinType::Short: 49406c3fb27SDimitry Andric EncType = "ss"; 49506c3fb27SDimitry Andric break; 49606c3fb27SDimitry Andric case BuiltinType::UInt: 49706c3fb27SDimitry Andric EncType = "ui"; 49806c3fb27SDimitry Andric break; 49906c3fb27SDimitry Andric case BuiltinType::Int: 50006c3fb27SDimitry Andric EncType = "si"; 50106c3fb27SDimitry Andric break; 50206c3fb27SDimitry Andric case BuiltinType::ULong: 50306c3fb27SDimitry Andric EncType = "ul"; 50406c3fb27SDimitry Andric break; 50506c3fb27SDimitry Andric case BuiltinType::Long: 50606c3fb27SDimitry Andric EncType = "sl"; 50706c3fb27SDimitry Andric break; 50806c3fb27SDimitry Andric case BuiltinType::ULongLong: 50906c3fb27SDimitry Andric EncType = "ull"; 51006c3fb27SDimitry Andric break; 51106c3fb27SDimitry Andric case BuiltinType::LongLong: 51206c3fb27SDimitry Andric EncType = "sll"; 51306c3fb27SDimitry Andric break; 51406c3fb27SDimitry Andric case BuiltinType::Float: 51506c3fb27SDimitry Andric EncType = "ft"; 51606c3fb27SDimitry Andric break; 51706c3fb27SDimitry Andric case BuiltinType::Double: 51806c3fb27SDimitry Andric EncType = "d"; 51906c3fb27SDimitry Andric break; 52006c3fb27SDimitry Andric case BuiltinType::LongDouble: 52106c3fb27SDimitry Andric EncType = "ld"; 52206c3fb27SDimitry Andric break; 52306c3fb27SDimitry Andric default: 52406c3fb27SDimitry Andric return false; 52506c3fb27SDimitry Andric } 52606c3fb27SDimitry Andric Enc += EncType; 52706c3fb27SDimitry Andric return true; 52806c3fb27SDimitry Andric } 52906c3fb27SDimitry Andric 53006c3fb27SDimitry Andric /// Appends a pointer encoding to Enc before calling appendType for the pointee. 53106c3fb27SDimitry Andric static bool appendPointerType(SmallStringEnc &Enc, const PointerType *PT, 53206c3fb27SDimitry Andric const CodeGen::CodeGenModule &CGM, 53306c3fb27SDimitry Andric TypeStringCache &TSC) { 53406c3fb27SDimitry Andric Enc += "p("; 53506c3fb27SDimitry Andric if (!appendType(Enc, PT->getPointeeType(), CGM, TSC)) 53606c3fb27SDimitry Andric return false; 53706c3fb27SDimitry Andric Enc += ')'; 53806c3fb27SDimitry Andric return true; 53906c3fb27SDimitry Andric } 54006c3fb27SDimitry Andric 54106c3fb27SDimitry Andric /// Appends array encoding to Enc before calling appendType for the element. 54206c3fb27SDimitry Andric static bool appendArrayType(SmallStringEnc &Enc, QualType QT, 54306c3fb27SDimitry Andric const ArrayType *AT, 54406c3fb27SDimitry Andric const CodeGen::CodeGenModule &CGM, 54506c3fb27SDimitry Andric TypeStringCache &TSC, StringRef NoSizeEnc) { 5465f757f3fSDimitry Andric if (AT->getSizeModifier() != ArraySizeModifier::Normal) 54706c3fb27SDimitry Andric return false; 54806c3fb27SDimitry Andric Enc += "a("; 54906c3fb27SDimitry Andric if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT)) 55006c3fb27SDimitry Andric CAT->getSize().toStringUnsigned(Enc); 55106c3fb27SDimitry Andric else 55206c3fb27SDimitry Andric Enc += NoSizeEnc; // Global arrays use "*", otherwise it is "". 55306c3fb27SDimitry Andric Enc += ':'; 55406c3fb27SDimitry Andric // The Qualifiers should be attached to the type rather than the array. 55506c3fb27SDimitry Andric appendQualifier(Enc, QT); 55606c3fb27SDimitry Andric if (!appendType(Enc, AT->getElementType(), CGM, TSC)) 55706c3fb27SDimitry Andric return false; 55806c3fb27SDimitry Andric Enc += ')'; 55906c3fb27SDimitry Andric return true; 56006c3fb27SDimitry Andric } 56106c3fb27SDimitry Andric 56206c3fb27SDimitry Andric /// Appends a function encoding to Enc, calling appendType for the return type 56306c3fb27SDimitry Andric /// and the arguments. 56406c3fb27SDimitry Andric static bool appendFunctionType(SmallStringEnc &Enc, const FunctionType *FT, 56506c3fb27SDimitry Andric const CodeGen::CodeGenModule &CGM, 56606c3fb27SDimitry Andric TypeStringCache &TSC) { 56706c3fb27SDimitry Andric Enc += "f{"; 56806c3fb27SDimitry Andric if (!appendType(Enc, FT->getReturnType(), CGM, TSC)) 56906c3fb27SDimitry Andric return false; 57006c3fb27SDimitry Andric Enc += "}("; 57106c3fb27SDimitry Andric if (const FunctionProtoType *FPT = FT->getAs<FunctionProtoType>()) { 57206c3fb27SDimitry Andric // N.B. we are only interested in the adjusted param types. 57306c3fb27SDimitry Andric auto I = FPT->param_type_begin(); 57406c3fb27SDimitry Andric auto E = FPT->param_type_end(); 57506c3fb27SDimitry Andric if (I != E) { 57606c3fb27SDimitry Andric do { 57706c3fb27SDimitry Andric if (!appendType(Enc, *I, CGM, TSC)) 57806c3fb27SDimitry Andric return false; 57906c3fb27SDimitry Andric ++I; 58006c3fb27SDimitry Andric if (I != E) 58106c3fb27SDimitry Andric Enc += ','; 58206c3fb27SDimitry Andric } while (I != E); 58306c3fb27SDimitry Andric if (FPT->isVariadic()) 58406c3fb27SDimitry Andric Enc += ",va"; 58506c3fb27SDimitry Andric } else { 58606c3fb27SDimitry Andric if (FPT->isVariadic()) 58706c3fb27SDimitry Andric Enc += "va"; 58806c3fb27SDimitry Andric else 58906c3fb27SDimitry Andric Enc += '0'; 59006c3fb27SDimitry Andric } 59106c3fb27SDimitry Andric } 59206c3fb27SDimitry Andric Enc += ')'; 59306c3fb27SDimitry Andric return true; 59406c3fb27SDimitry Andric } 59506c3fb27SDimitry Andric 59606c3fb27SDimitry Andric /// Handles the type's qualifier before dispatching a call to handle specific 59706c3fb27SDimitry Andric /// type encodings. 59806c3fb27SDimitry Andric static bool appendType(SmallStringEnc &Enc, QualType QType, 59906c3fb27SDimitry Andric const CodeGen::CodeGenModule &CGM, 60006c3fb27SDimitry Andric TypeStringCache &TSC) { 60106c3fb27SDimitry Andric 60206c3fb27SDimitry Andric QualType QT = QType.getCanonicalType(); 60306c3fb27SDimitry Andric 60406c3fb27SDimitry Andric if (const ArrayType *AT = QT->getAsArrayTypeUnsafe()) 60506c3fb27SDimitry Andric // The Qualifiers should be attached to the type rather than the array. 60606c3fb27SDimitry Andric // Thus we don't call appendQualifier() here. 60706c3fb27SDimitry Andric return appendArrayType(Enc, QT, AT, CGM, TSC, ""); 60806c3fb27SDimitry Andric 60906c3fb27SDimitry Andric appendQualifier(Enc, QT); 61006c3fb27SDimitry Andric 61106c3fb27SDimitry Andric if (const BuiltinType *BT = QT->getAs<BuiltinType>()) 61206c3fb27SDimitry Andric return appendBuiltinType(Enc, BT); 61306c3fb27SDimitry Andric 61406c3fb27SDimitry Andric if (const PointerType *PT = QT->getAs<PointerType>()) 61506c3fb27SDimitry Andric return appendPointerType(Enc, PT, CGM, TSC); 61606c3fb27SDimitry Andric 61706c3fb27SDimitry Andric if (const EnumType *ET = QT->getAs<EnumType>()) 61806c3fb27SDimitry Andric return appendEnumType(Enc, ET, TSC, QT.getBaseTypeIdentifier()); 61906c3fb27SDimitry Andric 62006c3fb27SDimitry Andric if (const RecordType *RT = QT->getAsStructureType()) 62106c3fb27SDimitry Andric return appendRecordType(Enc, RT, CGM, TSC, QT.getBaseTypeIdentifier()); 62206c3fb27SDimitry Andric 62306c3fb27SDimitry Andric if (const RecordType *RT = QT->getAsUnionType()) 62406c3fb27SDimitry Andric return appendRecordType(Enc, RT, CGM, TSC, QT.getBaseTypeIdentifier()); 62506c3fb27SDimitry Andric 62606c3fb27SDimitry Andric if (const FunctionType *FT = QT->getAs<FunctionType>()) 62706c3fb27SDimitry Andric return appendFunctionType(Enc, FT, CGM, TSC); 62806c3fb27SDimitry Andric 62906c3fb27SDimitry Andric return false; 63006c3fb27SDimitry Andric } 63106c3fb27SDimitry Andric 63206c3fb27SDimitry Andric static bool getTypeString(SmallStringEnc &Enc, const Decl *D, 63306c3fb27SDimitry Andric const CodeGen::CodeGenModule &CGM, 63406c3fb27SDimitry Andric TypeStringCache &TSC) { 63506c3fb27SDimitry Andric if (!D) 63606c3fb27SDimitry Andric return false; 63706c3fb27SDimitry Andric 63806c3fb27SDimitry Andric if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { 63906c3fb27SDimitry Andric if (FD->getLanguageLinkage() != CLanguageLinkage) 64006c3fb27SDimitry Andric return false; 64106c3fb27SDimitry Andric return appendType(Enc, FD->getType(), CGM, TSC); 64206c3fb27SDimitry Andric } 64306c3fb27SDimitry Andric 64406c3fb27SDimitry Andric if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { 64506c3fb27SDimitry Andric if (VD->getLanguageLinkage() != CLanguageLinkage) 64606c3fb27SDimitry Andric return false; 64706c3fb27SDimitry Andric QualType QT = VD->getType().getCanonicalType(); 64806c3fb27SDimitry Andric if (const ArrayType *AT = QT->getAsArrayTypeUnsafe()) { 64906c3fb27SDimitry Andric // Global ArrayTypes are given a size of '*' if the size is unknown. 65006c3fb27SDimitry Andric // The Qualifiers should be attached to the type rather than the array. 65106c3fb27SDimitry Andric // Thus we don't call appendQualifier() here. 65206c3fb27SDimitry Andric return appendArrayType(Enc, QT, AT, CGM, TSC, "*"); 65306c3fb27SDimitry Andric } 65406c3fb27SDimitry Andric return appendType(Enc, QT, CGM, TSC); 65506c3fb27SDimitry Andric } 65606c3fb27SDimitry Andric return false; 65706c3fb27SDimitry Andric } 65806c3fb27SDimitry Andric 65906c3fb27SDimitry Andric std::unique_ptr<TargetCodeGenInfo> 66006c3fb27SDimitry Andric CodeGen::createXCoreTargetCodeGenInfo(CodeGenModule &CGM) { 66106c3fb27SDimitry Andric return std::make_unique<XCoreTargetCodeGenInfo>(CGM.getTypes()); 66206c3fb27SDimitry Andric } 663