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