@@ -125,28 +125,76 @@ namespace irgen {
125
125
// / A function pointer value.
126
126
class FunctionPointer {
127
127
public:
128
- struct KindTy {
129
- enum class Value {
130
- Function,
131
- AsyncFunctionPointer,
132
- };
133
- static const Value Function = Value::Function;
134
- static const Value AsyncFunctionPointer = Value::AsyncFunctionPointer;
135
- Value value;
136
- KindTy (Value value) : value(value) {}
137
- KindTy (CanSILFunctionType fnType)
138
- : value(fnType->isAsync () ? Value::AsyncFunctionPointer
139
- : Value::Function) {}
140
- friend bool operator ==(const KindTy &lhs, const KindTy &rhs) {
128
+ enum class BasicKind {
129
+ Function,
130
+ AsyncFunctionPointer
131
+ };
132
+
133
+ enum class SpecialKind {
134
+ TaskFutureWait,
135
+ TaskFutureWaitThrowing,
136
+ TaskGroupWaitNext,
137
+ };
138
+
139
+ class Kind {
140
+ static constexpr unsigned SpecialOffset = 2 ;
141
+ unsigned value;
142
+ public:
143
+ static constexpr BasicKind Function =
144
+ BasicKind::Function;
145
+ static constexpr BasicKind AsyncFunctionPointer =
146
+ BasicKind::AsyncFunctionPointer;
147
+
148
+ Kind (BasicKind kind) : value(unsigned (kind)) {}
149
+ Kind (SpecialKind kind) : value(unsigned (kind) + SpecialOffset) {}
150
+ Kind (CanSILFunctionType fnType)
151
+ : Kind(fnType->isAsync () ? BasicKind::AsyncFunctionPointer
152
+ : BasicKind::Function) {}
153
+
154
+ BasicKind getBasicKind () const {
155
+ return value < SpecialOffset ? BasicKind (value) : BasicKind::Function;
156
+ }
157
+ bool isAsyncFunctionPointer () const {
158
+ return value == unsigned (BasicKind::AsyncFunctionPointer);
159
+ }
160
+
161
+ bool isSpecial () const {
162
+ return value >= SpecialOffset;
163
+ }
164
+ SpecialKind getSpecialKind () const {
165
+ assert (isSpecial ());
166
+ return SpecialKind (value - SpecialOffset);
167
+ }
168
+
169
+ // / Should we suppress the generic signature from the given function?
170
+ // /
171
+ // / This is a micro-optimization we apply to certain special functions
172
+ // / that we know don't need generics.
173
+ bool suppressGenerics () const {
174
+ if (!isSpecial ()) return false ;
175
+
176
+ switch (getSpecialKind ()) {
177
+ case SpecialKind::TaskFutureWait:
178
+ case SpecialKind::TaskFutureWaitThrowing:
179
+ // We suppress generics from these as a code-size optimization
180
+ // because the runtime can recover the success type from the
181
+ // future.
182
+ return true ;
183
+ case SpecialKind::TaskGroupWaitNext:
184
+ return false ;
185
+ }
186
+ }
187
+
188
+ friend bool operator ==(Kind lhs, Kind rhs) {
141
189
return lhs.value == rhs.value ;
142
190
}
143
- friend bool operator !=(const KindTy & lhs, const KindTy & rhs) {
191
+ friend bool operator !=(Kind lhs, Kind rhs) {
144
192
return !(lhs == rhs);
145
193
}
146
194
};
147
195
148
196
private:
149
- KindTy Kind;
197
+ Kind kind ;
150
198
151
199
// / The actual pointer, either to the function or to its descriptor.
152
200
llvm::Value *Value;
@@ -155,34 +203,29 @@ namespace irgen {
155
203
156
204
Signature Sig;
157
205
158
- bool isFunctionPointerWithoutContext = false ;
159
-
160
206
public:
161
207
// / Construct a FunctionPointer for an arbitrary pointer value.
162
208
// / We may add more arguments to this; try to use the other
163
209
// / constructors/factories if possible.
164
- explicit FunctionPointer (KindTy kind, llvm::Value *value,
210
+ explicit FunctionPointer (Kind kind, llvm::Value *value,
165
211
PointerAuthInfo authInfo,
166
- const Signature &signature,
167
- bool isWithoutCtxt = false )
168
- : Kind(kind), Value(value), AuthInfo(authInfo), Sig(signature),
169
- isFunctionPointerWithoutContext(isWithoutCtxt) {
212
+ const Signature &signature)
213
+ : kind(kind), Value(value), AuthInfo(authInfo), Sig(signature) {
170
214
// The function pointer should have function type.
171
215
assert (value->getType ()->getPointerElementType ()->isFunctionTy ());
172
216
// TODO: maybe assert similarity to signature.getType()?
173
217
}
174
218
175
219
// Temporary only!
176
- explicit FunctionPointer (KindTy kind, llvm::Value *value,
177
- const Signature &signature,
178
- bool isWithoutCtxt = false )
179
- : FunctionPointer(kind, value, PointerAuthInfo(), signature, isWithoutCtxt) {}
220
+ explicit FunctionPointer (Kind kind, llvm::Value *value,
221
+ const Signature &signature)
222
+ : FunctionPointer(kind, value, PointerAuthInfo(), signature) {}
180
223
181
224
static FunctionPointer forDirect (IRGenModule &IGM,
182
225
llvm::Constant *value,
183
226
CanSILFunctionType fnType);
184
227
185
- static FunctionPointer forDirect (KindTy kind, llvm::Constant *value,
228
+ static FunctionPointer forDirect (Kind kind, llvm::Constant *value,
186
229
const Signature &signature) {
187
230
return FunctionPointer (kind, value, PointerAuthInfo (), signature);
188
231
}
@@ -197,7 +240,8 @@ namespace irgen {
197
240
return (isa<llvm::Constant>(Value) && AuthInfo.isConstant ());
198
241
}
199
242
200
- KindTy getKind () const { return Kind; }
243
+ Kind getKind () const { return kind; }
244
+ BasicKind getBasicKind () const { return kind.getBasicKind (); }
201
245
202
246
// / Given that this value is known to have been constructed from a direct
203
247
// / function, Return the name of that function.
@@ -250,7 +294,11 @@ namespace irgen {
250
294
FunctionPointer getAsFunction (IRGenFunction &IGF) const ;
251
295
252
296
bool useStaticContextSize () const {
253
- return isFunctionPointerWithoutContext;
297
+ return !kind.isAsyncFunctionPointer ();
298
+ }
299
+
300
+ bool suppressGenerics () const {
301
+ return kind.suppressGenerics ();
254
302
}
255
303
};
256
304
@@ -315,6 +363,10 @@ namespace irgen {
315
363
return Fn.getSignature ();
316
364
}
317
365
366
+ bool suppressGenerics () const {
367
+ return Fn.suppressGenerics ();
368
+ }
369
+
318
370
// / If this callee has a value for the Swift context slot, return
319
371
// / it; otherwise return non-null.
320
372
llvm::Value *getSwiftContext () const ;
0 commit comments