1 //==-- SwiftCallingConv.h - Swift ABI lowering ------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // Defines constants and types related to Swift ABI lowering. The same ABI 10 // lowering applies to both sync and async functions. 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/Support/TrailingObjects.h" 21 #include <cassert> 22 23 namespace llvm { 24 class IntegerType; 25 class Type; 26 class StructType; 27 class VectorType; 28 } 29 30 namespace clang { 31 class Decl; 32 class FieldDecl; 33 class ASTRecordLayout; 34 35 namespace CodeGen { 36 class ABIArgInfo; 37 class CodeGenModule; 38 class CGFunctionInfo; 39 40 namespace swiftcall { 41 42 class SwiftAggLowering { 43 CodeGenModule &CGM; 44 45 struct StorageEntry { 46 CharUnits Begin; 47 CharUnits End; 48 llvm::Type *Type; 49 50 CharUnits getWidth() const { 51 return End - Begin; 52 } 53 }; 54 SmallVector<StorageEntry, 4> Entries; 55 bool Finished = false; 56 57 public: 58 SwiftAggLowering(CodeGenModule &CGM) : CGM(CGM) {} 59 60 void addOpaqueData(CharUnits begin, CharUnits end) { 61 addEntry(nullptr, begin, end); 62 } 63 64 void addTypedData(QualType type, CharUnits begin); 65 void addTypedData(const RecordDecl *record, CharUnits begin); 66 void addTypedData(const RecordDecl *record, CharUnits begin, 67 const ASTRecordLayout &layout); 68 void addTypedData(llvm::Type *type, CharUnits begin); 69 void addTypedData(llvm::Type *type, CharUnits begin, CharUnits end); 70 71 void finish(); 72 73 /// Does this lowering require passing any data? 74 bool empty() const { 75 assert(Finished && "didn't finish lowering before calling empty()"); 76 return Entries.empty(); 77 } 78 79 /// According to the target Swift ABI, should a value with this lowering 80 /// be passed indirectly? 81 /// 82 /// Note that this decision is based purely on the data layout of the 83 /// value and does not consider whether the type is address-only, 84 /// must be passed indirectly to match a function abstraction pattern, or 85 /// anything else that is expected to be handled by high-level lowering. 86 /// 87 /// \param asReturnValue - if true, answer whether it should be passed 88 /// indirectly as a return value; if false, answer whether it should be 89 /// passed indirectly as an argument 90 bool shouldPassIndirectly(bool asReturnValue) const; 91 92 using EnumerationCallback = 93 llvm::function_ref<void(CharUnits offset, CharUnits end, llvm::Type *type)>; 94 95 /// Enumerate the expanded components of this type. 96 /// 97 /// The component types will always be legal vector, floating-point, 98 /// integer, or pointer types. 99 void enumerateComponents(EnumerationCallback callback) const; 100 101 /// Return the types for a coerce-and-expand operation. 102 /// 103 /// The first type matches the memory layout of the data that's been 104 /// added to this structure, including explicit [N x i8] arrays for any 105 /// internal padding. 106 /// 107 /// The second type removes any internal padding members and, if only 108 /// one element remains, is simply that element type. 109 std::pair<llvm::StructType*, llvm::Type*> getCoerceAndExpandTypes() const; 110 111 private: 112 void addBitFieldData(const FieldDecl *field, CharUnits begin, 113 uint64_t bitOffset); 114 void addLegalTypedData(llvm::Type *type, CharUnits begin, CharUnits end); 115 void addEntry(llvm::Type *type, CharUnits begin, CharUnits end); 116 void splitVectorEntry(unsigned index); 117 static bool shouldMergeEntries(const StorageEntry &first, 118 const StorageEntry &second, 119 CharUnits chunkSize); 120 }; 121 122 /// Should an aggregate which expands to the given type sequence 123 /// be passed/returned indirectly under swiftcall? 124 bool shouldPassIndirectly(CodeGenModule &CGM, 125 ArrayRef<llvm::Type*> types, 126 bool asReturnValue); 127 128 /// Return the maximum voluntary integer size for the current target. 129 CharUnits getMaximumVoluntaryIntegerSize(CodeGenModule &CGM); 130 131 /// Return the Swift CC's notion of the natural alignment of a type. 132 CharUnits getNaturalAlignment(CodeGenModule &CGM, llvm::Type *type); 133 134 /// Is the given integer type "legal" for Swift's perspective on the 135 /// current platform? 136 bool isLegalIntegerType(CodeGenModule &CGM, llvm::IntegerType *type); 137 138 /// Is the given vector type "legal" for Swift's perspective on the 139 /// current platform? 140 bool isLegalVectorType(CodeGenModule &CGM, CharUnits vectorSize, 141 llvm::VectorType *vectorTy); 142 bool isLegalVectorType(CodeGenModule &CGM, CharUnits vectorSize, 143 llvm::Type *eltTy, unsigned numElts); 144 145 /// Minimally split a legal vector type. 146 std::pair<llvm::Type*, unsigned> 147 splitLegalVectorType(CodeGenModule &CGM, CharUnits vectorSize, 148 llvm::VectorType *vectorTy); 149 150 /// Turn a vector type in a sequence of legal component vector types. 151 /// 152 /// The caller may assume that the sum of the data sizes of the resulting 153 /// types will equal the data size of the vector type. 154 void legalizeVectorType(CodeGenModule &CGM, CharUnits vectorSize, 155 llvm::VectorType *vectorTy, 156 llvm::SmallVectorImpl<llvm::Type*> &types); 157 158 /// Is the given record type required to be passed and returned indirectly 159 /// because of language restrictions? 160 /// 161 /// This considers *only* mandatory indirectness due to language restrictions, 162 /// such as C++'s non-trivially-copyable types and Objective-C's __weak 163 /// references. A record for which this returns true may still be passed 164 /// indirectly for other reasons, such as being too large to fit in a 165 /// reasonable number of registers. 166 bool mustPassRecordIndirectly(CodeGenModule &CGM, const RecordDecl *record); 167 168 /// Classify the rules for how to return a particular type. 169 ABIArgInfo classifyReturnType(CodeGenModule &CGM, CanQualType type); 170 171 /// Classify the rules for how to pass a particular type. 172 ABIArgInfo classifyArgumentType(CodeGenModule &CGM, CanQualType type); 173 174 /// Compute the ABI information of a swiftcall function. This is a 175 /// private interface for Clang. 176 void computeABIInfo(CodeGenModule &CGM, CGFunctionInfo &FI); 177 178 /// Is swifterror lowered to a register by the target ABI? 179 bool isSwiftErrorLoweredInRegister(CodeGenModule &CGM); 180 181 } // end namespace swiftcall 182 } // end namespace CodeGen 183 } // end namespace clang 184 185 #endif 186