@@ -159,8 +159,7 @@ namespace irgen {
159
159
}
160
160
};
161
161
162
- // / A function pointer value.
163
- class FunctionPointer {
162
+ class FunctionPointerKind {
164
163
public:
165
164
enum class BasicKind {
166
165
Function,
@@ -179,85 +178,124 @@ namespace irgen {
179
178
DistributedExecuteTarget,
180
179
};
181
180
182
- class Kind {
183
- static constexpr unsigned SpecialOffset = 2 ;
184
- unsigned value;
185
- public:
186
- static constexpr BasicKind Function =
187
- BasicKind::Function;
188
- static constexpr BasicKind AsyncFunctionPointer =
189
- BasicKind::AsyncFunctionPointer;
190
-
191
- Kind (BasicKind kind) : value(unsigned (kind)) {}
192
- Kind (SpecialKind kind) : value(unsigned (kind) + SpecialOffset) {}
193
- Kind (CanSILFunctionType fnType)
194
- : Kind(fnType->isAsync () ? BasicKind::AsyncFunctionPointer
195
- : BasicKind::Function) {}
196
-
197
- BasicKind getBasicKind () const {
198
- return value < SpecialOffset ? BasicKind (value) : BasicKind::Function;
199
- }
200
- bool isAsyncFunctionPointer () const {
201
- return value == unsigned (BasicKind::AsyncFunctionPointer);
202
- }
203
-
204
- bool isSpecial () const {
205
- return value >= SpecialOffset;
181
+ private:
182
+ static constexpr unsigned SpecialOffset = 2 ;
183
+ unsigned value;
184
+ public:
185
+ static constexpr BasicKind Function =
186
+ BasicKind::Function;
187
+ static constexpr BasicKind AsyncFunctionPointer =
188
+ BasicKind::AsyncFunctionPointer;
189
+
190
+ FunctionPointerKind (BasicKind kind)
191
+ : value(unsigned (kind)) {}
192
+ FunctionPointerKind (SpecialKind kind)
193
+ : value(unsigned (kind) + SpecialOffset) {}
194
+ FunctionPointerKind (CanSILFunctionType fnType)
195
+ : FunctionPointerKind(fnType->isAsync ()
196
+ ? BasicKind::AsyncFunctionPointer
197
+ : BasicKind::Function) {}
198
+
199
+ static FunctionPointerKind defaultSync () {
200
+ return BasicKind::Function;
201
+ }
202
+ static FunctionPointerKind defaultAsync () {
203
+ return BasicKind::AsyncFunctionPointer;
204
+ }
205
+
206
+ BasicKind getBasicKind () const {
207
+ return value < SpecialOffset ? BasicKind (value) : BasicKind::Function;
208
+ }
209
+ bool isAsyncFunctionPointer () const {
210
+ return value == unsigned (BasicKind::AsyncFunctionPointer);
211
+ }
212
+
213
+ bool isSpecial () const {
214
+ return value >= SpecialOffset;
215
+ }
216
+ SpecialKind getSpecialKind () const {
217
+ assert (isSpecial ());
218
+ return SpecialKind (value - SpecialOffset);
219
+ }
220
+
221
+
222
+ // / Given that this is an async function, does it have a
223
+ // / statically-specified size for its async context?
224
+ // /
225
+ // / Returning a non-None value is necessary for special functions
226
+ // / defined in the runtime. Without this, we'll attempt to load
227
+ // / the context size from an async FP symbol which the runtime
228
+ // / doesn't actually emit.
229
+ Optional<Size> getStaticAsyncContextSize (IRGenModule &IGM) const ;
230
+
231
+ // / Given that this is an async function, should we pass the
232
+ // / continuation function pointer and context directly to it
233
+ // / rather than building a frame?
234
+ // /
235
+ // / This is a micro-optimization that is reasonable for functions
236
+ // / that are expected to return immediately in a common fast path.
237
+ // / Other functions should not do this.
238
+ bool shouldPassContinuationDirectly () const {
239
+ if (!isSpecial ()) return false ;
240
+
241
+ switch (getSpecialKind ()) {
242
+ case SpecialKind::TaskFutureWaitThrowing:
243
+ case SpecialKind::TaskFutureWait:
244
+ case SpecialKind::AsyncLetWait:
245
+ case SpecialKind::AsyncLetWaitThrowing:
246
+ case SpecialKind::AsyncLetGet:
247
+ case SpecialKind::AsyncLetGetThrowing:
248
+ case SpecialKind::AsyncLetFinish:
249
+ case SpecialKind::TaskGroupWaitNext:
250
+ case SpecialKind::DistributedExecuteTarget:
251
+ return true ;
206
252
}
207
- SpecialKind getSpecialKind () const {
208
- assert (isSpecial ());
209
- return SpecialKind (value - SpecialOffset);
210
- }
211
-
212
- bool isSpecialAsyncLet () const {
213
- if (!isSpecial ()) return false ;
214
- switch (getSpecialKind ()) {
215
- case SpecialKind::AsyncLetGet:
216
- case SpecialKind::AsyncLetGetThrowing:
217
- case SpecialKind::AsyncLetFinish:
218
- return true ;
219
-
220
- case SpecialKind::TaskFutureWaitThrowing:
221
- case SpecialKind::TaskFutureWait:
222
- case SpecialKind::AsyncLetWait:
223
- case SpecialKind::AsyncLetWaitThrowing:
224
- case SpecialKind::TaskGroupWaitNext:
225
- case SpecialKind::DistributedExecuteTarget:
226
- return false ;
227
- }
228
-
229
- return false ;
253
+ llvm_unreachable (" covered switch" );
254
+ }
255
+
256
+ // / Should we suppress passing arguments associated with the generic
257
+ // / signature from the given function?
258
+ // /
259
+ // / This is a micro-optimization for certain runtime functions that
260
+ // / are known to not need the generic arguments, probably because
261
+ // / they've already been stored elsewhere.
262
+ // /
263
+ // / This may only work for async function types right now. If so,
264
+ // / that's a totally unnecessary restriction which should be easy
265
+ // / to lift, if you have a sync runtime function that would benefit
266
+ // / from this.
267
+ bool shouldSuppressPolymorphicArguments () const {
268
+ if (!isSpecial ()) return false ;
269
+
270
+ switch (getSpecialKind ()) {
271
+ case SpecialKind::TaskFutureWaitThrowing:
272
+ case SpecialKind::TaskFutureWait:
273
+ case SpecialKind::AsyncLetWait:
274
+ case SpecialKind::AsyncLetWaitThrowing:
275
+ case SpecialKind::AsyncLetGet:
276
+ case SpecialKind::AsyncLetGetThrowing:
277
+ case SpecialKind::AsyncLetFinish:
278
+ case SpecialKind::TaskGroupWaitNext:
279
+ case SpecialKind::DistributedExecuteTarget:
280
+ return true ;
230
281
}
282
+ llvm_unreachable (" covered switch" );
283
+ }
231
284
232
- // / Should we suppress the generic signature from the given function?
233
- // /
234
- // / This is a micro-optimization we apply to certain special functions
235
- // / that we know don't need generics.
236
- bool useSpecialConvention () const {
237
- if (!isSpecial ()) return false ;
238
-
239
- switch (getSpecialKind ()) {
240
- case SpecialKind::TaskFutureWaitThrowing:
241
- case SpecialKind::TaskFutureWait:
242
- case SpecialKind::AsyncLetWait:
243
- case SpecialKind::AsyncLetWaitThrowing:
244
- case SpecialKind::AsyncLetGet:
245
- case SpecialKind::AsyncLetGetThrowing:
246
- case SpecialKind::AsyncLetFinish:
247
- case SpecialKind::TaskGroupWaitNext:
248
- case SpecialKind::DistributedExecuteTarget:
249
- return true ;
250
- }
251
- llvm_unreachable (" covered switch" );
252
- }
285
+ friend bool operator ==(FunctionPointerKind lhs, FunctionPointerKind rhs) {
286
+ return lhs.value == rhs.value ;
287
+ }
288
+ friend bool operator !=(FunctionPointerKind lhs, FunctionPointerKind rhs) {
289
+ return !(lhs == rhs);
290
+ }
291
+ };
253
292
254
- friend bool operator ==(Kind lhs, Kind rhs) {
255
- return lhs.value == rhs.value ;
256
- }
257
- friend bool operator !=(Kind lhs, Kind rhs) {
258
- return !(lhs == rhs);
259
- }
260
- };
293
+ // / A function pointer value.
294
+ class FunctionPointer {
295
+ public:
296
+ using Kind = FunctionPointerKind;
297
+ using BasicKind = Kind::BasicKind;
298
+ using SpecialKind = Kind::SpecialKind;
261
299
262
300
private:
263
301
Kind kind;
@@ -388,11 +426,15 @@ namespace irgen {
388
426
// / Form a FunctionPointer whose Kind is ::Function.
389
427
FunctionPointer getAsFunction (IRGenFunction &IGF) const ;
390
428
391
- bool useStaticContextSize () const {
392
- return !kind.isAsyncFunctionPointer ();
429
+ Optional<Size> getStaticAsyncContextSize (IRGenModule &IGM) const {
430
+ return kind.getStaticAsyncContextSize (IGM);
431
+ }
432
+ bool shouldPassContinuationDirectly () const {
433
+ return kind.shouldPassContinuationDirectly ();
434
+ }
435
+ bool shouldSuppressPolymorphicArguments () const {
436
+ return kind.shouldSuppressPolymorphicArguments ();
393
437
}
394
-
395
- bool useSpecialConvention () const { return kind.useSpecialConvention (); }
396
438
};
397
439
398
440
class Callee {
@@ -456,7 +498,15 @@ namespace irgen {
456
498
return Fn.getSignature ();
457
499
}
458
500
459
- bool useSpecialConvention () const { return Fn.useSpecialConvention (); }
501
+ Optional<Size> getStaticAsyncContextSize (IRGenModule &IGM) const {
502
+ return Fn.getStaticAsyncContextSize (IGM);
503
+ }
504
+ bool shouldPassContinuationDirectly () const {
505
+ return Fn.shouldPassContinuationDirectly ();
506
+ }
507
+ bool shouldSuppressPolymorphicArguments () const {
508
+ return Fn.shouldSuppressPolymorphicArguments ();
509
+ }
460
510
461
511
// / If this callee has a value for the Swift context slot, return
462
512
// / it; otherwise return non-null.
0 commit comments