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