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