1 //==-- SwiftCallingConv.h - Swift ABI lowering -----------------------------==// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // Defines constants and types related to Swift ABI lowering. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #ifndef LLVM_CLANG_CODEGEN_SWIFTCALLINGCONV_H 15 #define LLVM_CLANG_CODEGEN_SWIFTCALLINGCONV_H 16 17 #include "clang/AST/CanonicalType.h" 18 #include "clang/AST/CharUnits.h" 19 #include "clang/AST/Type.h" 20 #include "llvm/ADT/FoldingSet.h" 21 #include "llvm/Support/TrailingObjects.h" 22 #include <cassert> 23 24 namespace llvm { 25 class IntegerType; 26 class Type; 27 class StructType; 28 class VectorType; 29 } 30 31 namespace clang { 32 class Decl; 33 class FieldDecl; 34 class ASTRecordLayout; 35 36 namespace CodeGen { 37 class ABIArgInfo; 38 class CodeGenModule; 39 class CGFunctionInfo; 40 41 namespace swiftcall { 42 43 class SwiftAggLowering { 44 CodeGenModule &CGM; 45 46 struct StorageEntry { 47 CharUnits Begin; 48 CharUnits End; 49 llvm::Type *Type; 50 getWidthStorageEntry51 CharUnits getWidth() const { 52 return End - Begin; 53 } 54 }; 55 SmallVector<StorageEntry, 4> Entries; 56 bool Finished = false; 57 58 public: SwiftAggLowering(CodeGenModule & CGM)59 SwiftAggLowering(CodeGenModule &CGM) : CGM(CGM) {} 60 addOpaqueData(CharUnits begin,CharUnits end)61 void addOpaqueData(CharUnits begin, CharUnits end) { 62 addEntry(nullptr, begin, end); 63 } 64 65 void addTypedData(QualType type, CharUnits begin); 66 void addTypedData(const RecordDecl *record, CharUnits begin); 67 void addTypedData(const RecordDecl *record, CharUnits begin, 68 const ASTRecordLayout &layout); 69 void addTypedData(llvm::Type *type, CharUnits begin); 70 void addTypedData(llvm::Type *type, CharUnits begin, CharUnits end); 71 72 void finish(); 73 74 /// Does this lowering require passing any data? empty()75 bool empty() const { 76 assert(Finished && "didn't finish lowering before calling empty()"); 77 return Entries.empty(); 78 } 79 80 /// According to the target Swift ABI, should a value with this lowering 81 /// be passed indirectly? 82 /// 83 /// Note that this decision is based purely on the data layout of the 84 /// value and does not consider whether the type is address-only, 85 /// must be passed indirectly to match a function abstraction pattern, or 86 /// anything else that is expected to be handled by high-level lowering. 87 /// 88 /// \param asReturnValue - if true, answer whether it should be passed 89 /// indirectly as a return value; if false, answer whether it should be 90 /// passed indirectly as an argument 91 bool shouldPassIndirectly(bool asReturnValue) const; 92 93 using EnumerationCallback = 94 llvm::function_ref<void(CharUnits offset, llvm::Type *type)>; 95 96 /// Enumerate the expanded components of this type. 97 /// 98 /// The component types will always be legal vector, floating-point, 99 /// integer, or pointer types. 100 void enumerateComponents(EnumerationCallback callback) const; 101 102 /// Return the types for a coerce-and-expand operation. 103 /// 104 /// The first type matches the memory layout of the data that's been 105 /// added to this structure, including explicit [N x i8] arrays for any 106 /// internal padding. 107 /// 108 /// The second type removes any internal padding members and, if only 109 /// one element remains, is simply that element type. 110 std::pair<llvm::StructType*, llvm::Type*> getCoerceAndExpandTypes() const; 111 112 private: 113 void addBitFieldData(const FieldDecl *field, CharUnits begin, 114 uint64_t bitOffset); 115 void addLegalTypedData(llvm::Type *type, CharUnits begin, CharUnits end); 116 void addEntry(llvm::Type *type, CharUnits begin, CharUnits end); 117 void splitVectorEntry(unsigned index); 118 }; 119 120 /// Return the maximum voluntary integer size for the current target. 121 CharUnits getMaximumVoluntaryIntegerSize(CodeGenModule &CGM); 122 123 /// Return the Swift CC's notion of the natural alignment of a type. 124 CharUnits getNaturalAlignment(CodeGenModule &CGM, llvm::Type *type); 125 126 /// Is the given integer type "legal" for Swift's perspective on the 127 /// current platform? 128 bool isLegalIntegerType(CodeGenModule &CGM, llvm::IntegerType *type); 129 130 /// Is the given vector type "legal" for Swift's perspective on the 131 /// current platform? 132 bool isLegalVectorType(CodeGenModule &CGM, CharUnits vectorSize, 133 llvm::VectorType *vectorTy); 134 bool isLegalVectorType(CodeGenModule &CGM, CharUnits vectorSize, 135 llvm::Type *eltTy, unsigned numElts); 136 137 /// Minimally split a legal vector type. 138 std::pair<llvm::Type*, unsigned> 139 splitLegalVectorType(CodeGenModule &CGM, CharUnits vectorSize, 140 llvm::VectorType *vectorTy); 141 142 /// Turn a vector type in a sequence of legal component vector types. 143 /// 144 /// The caller may assume that the sum of the data sizes of the resulting 145 /// types will equal the data size of the vector type. 146 void legalizeVectorType(CodeGenModule &CGM, CharUnits vectorSize, 147 llvm::VectorType *vectorTy, 148 llvm::SmallVectorImpl<llvm::Type*> &types); 149 150 /// Should a C++ record type be passed and returned indirectly? 151 bool shouldPassCXXRecordIndirectly(CodeGenModule &CGM, 152 const CXXRecordDecl *record); 153 154 /// Classify the rules for how to return a particular type. 155 ABIArgInfo classifyReturnType(CodeGenModule &CGM, CanQualType type); 156 157 /// Classify the rules for how to pass a particular type. 158 ABIArgInfo classifyArgumentType(CodeGenModule &CGM, CanQualType type); 159 160 /// Compute the ABI information of a swiftcall function. This is a 161 /// private interface for Clang. 162 void computeABIInfo(CodeGenModule &CGM, CGFunctionInfo &FI); 163 164 } // end namespace swiftcall 165 } // end namespace CodeGen 166 } // end namespace clang 167 168 #endif 169