xref: /freebsd/contrib/llvm-project/clang/include/clang/CodeGen/SwiftCallingConv.h (revision 04eeddc0aa8e0a417a16eaf9d7d095207f4a8623)
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