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