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