Skip to content

Commit dea25d5

Browse files
committed
[AsyncLet] reimplemented with new ABI and builtins
1 parent 35a42ef commit dea25d5

27 files changed

+188
-295
lines changed

include/swift/ABI/AsyncLet.h

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//===--- TaskGroup.h - ABI structures for task groups -00--------*- C++ -*-===//
1+
//===--- AsyncLet.h - ABI structures for async let -00-----------*- C++ -*-===//
22
//
33
// This source file is part of the Swift.org open source project
44
//
@@ -32,15 +32,14 @@ class alignas(Alignment_AsyncLet) AsyncLet {
3232
public:
3333
// These constructors do not initialize the AsyncLet instance, and the
3434
// destructor does not destroy the AsyncLet instance; you must call
35-
// swift_asyncLet_{initialize,destroy} yourself.
35+
// swift_asyncLet_{start,end} yourself.
3636
constexpr AsyncLet()
3737
: PrivateData{} {}
3838

39-
// TODO: not sure how many words we should reserve
39+
// FIXME: not sure how many words we should reserve
4040
void *PrivateData[NumWords_AsyncLet];
4141

42-
/// Returns true if the `async let` was already awaited on at-least once.
43-
bool wasAwaitedOn() const;
42+
// TODO: we could offer a "was awaited on" check here
4443

4544
/// Returns the child task that is associated with this async let.
4645
/// The tasks completion is used to fulfil the value represented by this async let.

include/swift/AST/Builtins.def

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -782,12 +782,17 @@ BUILTIN_MISC_OPERATION_WITH_SILGEN(GetCurrentAsyncTask, "getCurrentAsyncTask", "
782782
/// Cancel the given asynchronous task.
783783
BUILTIN_MISC_OPERATION_WITH_SILGEN(CancelAsyncTask, "cancelAsyncTask", "", Special)
784784

785-
/// createAsyncLet(): (
786-
/// Int, @escaping () async throws -> T
785+
/// startAsyncLet()<T>: (
786+
/// __owned @Sendable @escaping () async throws -> T
787787
/// ) -> Builtin.RawPointer
788-
BUILTIN_MISC_OPERATION_WITH_SILGEN(CreateAsyncLet, "createAsyncLet", "", Special)
788+
///
789+
/// Create, initialize and start a new async-let and associated task.
790+
/// Returns an AsyncLet* that must be passed to endAsyncLet for destruction.
791+
BUILTIN_MISC_OPERATION(StartAsyncLet, "startAsyncLet", "", Special)
789792

790793
/// asyncLetEnd(): (Builtin.RawPointer) -> Void
794+
///
795+
/// Ends and destroys an async-let.
791796
BUILTIN_MISC_OPERATION_WITH_SILGEN(EndAsyncLet, "endAsyncLet", "", Special)
792797

793798
/// createAsyncTaskFuture(): (

include/swift/AST/Builtins.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,8 +140,6 @@ bool canBuiltinBeOverloadedForType(BuiltinValueKind ID, Type Ty);
140140
/// createAsyncTask* builtins.
141141
Type getAsyncTaskAndContextType(ASTContext &ctx);
142142

143-
Type getAsyncLetAndTaskType(ASTContext &ctx); // TODO: decide if we use it or not
144-
145143
}
146144

147145
#endif

include/swift/Runtime/Concurrency.h

Lines changed: 6 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ AsyncTaskAndContext swift_task_create_group_future(
7878
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
7979
AsyncTaskAndContext swift_task_create_group_future_f(
8080
JobFlags flags,
81-
TaskGroup *group,
81+
TaskGroup *group,
8282
const Metadata *futureResultType,
8383
FutureAsyncSignature::FunctionType *function,
8484
size_t initialContextSize);
@@ -276,34 +276,21 @@ bool swift_taskGroup_isCancelled(TaskGroup *group);
276276
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
277277
bool swift_taskGroup_isEmpty(TaskGroup *group);
278278

279-
/// Initialize an `AsyncLet` in the passed `asyncLet` memory location.
280-
/// The caller is responsible for retaining and managing the asyncLet's lifecycle.
281-
///
282279
/// Its Swift signature is
283280
///
284281
/// \code
285-
/// func swift_asyncLet_initialize(
286-
/// .... // TODO: fill in
282+
/// func swift_asyncLet_start<T>(
283+
/// _ alet: Builtin.RawPointer,
284+
/// operation: __owned @Sendable @escaping () async throws -> T
287285
/// )
288286
/// \endcode
289-
//SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
290-
//void swift_asyncLet_initialize(AsyncLet *alet, AsyncTask *task);
291287
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
292-
void swift_asyncLet_initialize(
288+
void swift_asyncLet_start(
293289
AsyncLet *alet,
294-
JobFlags flags,
295290
const Metadata *futureResultType,
296291
void *closureEntryPoint,
297292
HeapObject * /* +1 */ closureContext);
298293

299-
/// Its Swift signature is
300-
///
301-
/// \code
302-
/// func swift_asyncLet_start(_ alet: Builtin.RawPointer)
303-
/// \endcode
304-
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
305-
void swift_asyncLet_start(AsyncLet *alet, void* operation);
306-
307294
/// This matches the ABI of a closure `<T>(Builtin.RawPointer) async -> T`
308295
using AsyncLetWaitSignature =
309296
SWIFT_CC(swiftasync)
@@ -336,7 +323,7 @@ void swift_asyncLet_wait(OpaqueValue *,
336323
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swiftasync)
337324
void swift_asyncLet_wait_throwing(OpaqueValue *,
338325
SWIFT_ASYNC_CONTEXT AsyncContext *,
339-
AsyncLet *, Metadata *);
326+
AsyncLet *, Metadata *);
340327

341328
/// Its Swift signature is
342329
///

include/swift/Runtime/RuntimeFunctions.def

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1678,23 +1678,15 @@ FUNCTION(DefaultActorDeallocateResilient,
16781678
ARGS(RefCountedPtrTy),
16791679
ATTRS(NoUnwind))
16801680

1681-
// void swift_asyncLet_initialize(
1682-
// AsyncLet *alet,
1683-
// size_t flags,
1684-
// // FIXME: or is it TaskContinuationFunction* function ?????? like in TaskCreateFunc
1685-
// const Metadata *futureResultType,
1686-
// void *closureEntry,
1687-
// // TODO: do we need the context after all???? HeapObject *closureContext
1688-
// );
1689-
FUNCTION(AsyncLetInitialize,
1690-
swift_asyncLet_initialize, SwiftCC,
1681+
// THE RUNTIME FUNCTION
1682+
FUNCTION(AsyncLetStart,
1683+
swift_asyncLet_start, SwiftCC,
16911684
ConcurrencyAvailability,
16921685
RETURNS(VoidTy),
16931686
ARGS(SwiftAsyncLetPtrTy, // AsyncLet*, alias for Int8PtrTy
1694-
SizeTy, // flags
1695-
TypeMetadataPtrTy, // futureResultType
1696-
Int8PtrTy, // closureEntry
1697-
RefCountedPtrTy, // closureContext
1687+
TypeMetadataPtrTy, // futureResultType
1688+
Int8PtrTy, // closureEntry
1689+
RefCountedPtrTy, // closureContext
16981690
),
16991691
ATTRS(NoUnwind, ArgMemOnly))
17001692

lib/AST/Builtins.cpp

Lines changed: 12 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1424,16 +1424,6 @@ Type swift::getAsyncTaskAndContextType(ASTContext &ctx) {
14241424
return TupleType::get(resultTupleElements, ctx);
14251425
}
14261426

1427-
Type swift::getAsyncLetAndTaskType(ASTContext &ctx) {
1428-
TupleTypeElt resultTupleElements[2] = {
1429-
ctx.TheRawPointerType, // AsyncLet *,
1430-
ctx.TheRawPointerType, // AsyncLet *,
1431-
// ctx.TheNativeObjectType // task
1432-
};
1433-
1434-
return TupleType::get(resultTupleElements, ctx);
1435-
}
1436-
14371427
static ValueDecl *getCreateAsyncTaskFuture(ASTContext &ctx, Identifier id) {
14381428
BuiltinFunctionBuilder builder(ctx);
14391429
auto genericParam = makeGenericParam().build(builder);
@@ -1491,32 +1481,30 @@ static ValueDecl *getResumeContinuationThrowing(ASTContext &ctx,
14911481
_void);
14921482
}
14931483

1494-
static ValueDecl *getCreateAsyncLet(ASTContext &ctx, Identifier id) {
1484+
static ValueDecl *getStartAsyncLet(ASTContext &ctx, Identifier id) {
1485+
// return getBuiltinFunction(ctx, id, _thin,
1486+
// _generics(_unrestricted),
1487+
// _parameters(_rawPointer, <function>), TODO: seems we can't express function here?
1488+
// _rawPointer)
1489+
14951490
ModuleDecl *M = ctx.TheBuiltinModule;
14961491
DeclContext *DC = &M->getMainFile(FileUnitKind::Builtin);
14971492
SynthesisContext SC(ctx, DC);
14981493

14991494
BuiltinFunctionBuilder builder(ctx);
15001495
auto genericParam = makeGenericParam().build(builder); // <T>
15011496

1502-
// flags
1503-
builder.addParameter(
1504-
makeConcrete(ctx.getIntDecl()->getDeclaredInterfaceType()));
1497+
// AsyncLet*
1498+
builder.addParameter(makeConcrete(OptionalType::get(ctx.TheRawPointerType)));
15051499

15061500
// operation async function pointer: () async throws -> T
15071501
auto extInfo = ASTExtInfoBuilder().withAsync().withThrows().build();
15081502
builder.addParameter(
15091503
makeConcrete(FunctionType::get({ }, genericParam, extInfo)));
15101504

1511-
// -> AsyncLet*
1512-
// auto resultType = synthesizeType(SC, _rawPointer);
1513-
// builder.setResult(makeConcrete(resultType));
1514-
builder.setResult(makeConcrete(getAsyncLetAndTaskType(ctx))); // TODO: this can work I think
1505+
// -> Builtin.RawPointer
1506+
builder.setResult(makeConcrete(synthesizeType(SC, _rawPointer)));
15151507
return builder.build(id);
1516-
1517-
// return getBuiltinFunction(ctx, id, _thin,
1518-
// _parameters(_nativeObject),
1519-
// _rawPointer);
15201508
}
15211509

15221510
static ValueDecl *getEndAsyncLet(ASTContext &ctx, Identifier id) {
@@ -2784,8 +2772,8 @@ ValueDecl *swift::getBuiltinValueDecl(ASTContext &Context, Identifier Id) {
27842772
case BuiltinValueKind::DestroyDefaultActor:
27852773
return getDefaultActorInitDestroy(Context, Id);
27862774

2787-
case BuiltinValueKind::CreateAsyncLet:
2788-
return getCreateAsyncLet(Context, Id);
2775+
case BuiltinValueKind::StartAsyncLet:
2776+
return getStartAsyncLet(Context, Id);
27892777

27902778
case BuiltinValueKind::EndAsyncLet:
27912779
return getEndAsyncLet(Context, Id);

lib/IRGen/GenBuiltin.cpp

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -227,25 +227,12 @@ void irgen::emitBuiltinCall(IRGenFunction &IGF, const BuiltinInfo &Builtin,
227227
return;
228228
}
229229

230-
// emitCreateAsyncLet takes the child task it is associated with.
231-
if (Builtin.ID == BuiltinValueKind::CreateAsyncLet) {
232-
// out.add(emitCreateAsyncLet(IGF, args.claimNext()));
233-
234-
fprintf(stderr, "[%s:%d] (%s) args count:%d\n", __FILE__, __LINE__, __FUNCTION__, args.size());
235-
auto flags = args.claimNext();
236-
fprintf(stderr, "[%s:%d] (%s) flags:%d\n", __FILE__, __LINE__, __FUNCTION__, flags);
237-
auto futureResultType = args.claimNext();
238-
fprintf(stderr, "[%s:%d] (%s) futureResultType:%d\n", __FILE__, __LINE__, __FUNCTION__, futureResultType);
230+
if (Builtin.ID == BuiltinValueKind::StartAsyncLet) {
239231
auto taskFunction = args.claimNext();
240-
fprintf(stderr, "[%s:%d] (%s) taskFunction:%d\n", __FILE__, __LINE__, __FUNCTION__, taskFunction);
241232
auto taskContext = args.claimNext();
242-
fprintf(stderr, "[%s:%d] (%s) taskContext:%d\n", __FILE__, __LINE__, __FUNCTION__, taskContext);
243233

244-
fprintf(stderr, "[%s:%d] (%s) emitCreateAsyncLet...\n", __FILE__, __LINE__, __FUNCTION__);
245-
auto asyncLet = emitCreateAsyncLet(
234+
auto asyncLet = emitBuiltinStartAsyncLet(
246235
IGF,
247-
flags,
248-
futureResultType,
249236
taskFunction,
250237
taskContext,
251238
substitutions

lib/IRGen/GenCall.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ irgen::getAsyncContextLayout(IRGenModule &IGM, CanSILFunctionType originalType,
137137
}
138138

139139
// Add storage for data used by runtime entry points.
140-
// See TaskFutureWaitAsyncContext.
140+
// See TaskFutureWaitAsyncContext and TaskGroupNextAsyncContext.
141141
if (kind.isSpecial()) {
142142
switch (kind.getSpecialKind()) {
143143
case FunctionPointer::SpecialKind::TaskFutureWait:

lib/IRGen/GenConcurrency.cpp

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -171,33 +171,32 @@ void irgen::emitGetCurrentExecutor(IRGenFunction &IGF, Explosion &out) {
171171
IGF.emitAllExtractValues(call, IGF.IGM.SwiftExecutorTy, out);
172172
}
173173

174-
llvm::Value *irgen::emitCreateAsyncLet(IRGenFunction &IGF,
175-
llvm::Value *flags,
176-
llvm::Value *futureResultType,
177-
llvm::Value *taskFunction,
178-
llvm::Value *localContextInfo,
179-
SubstitutionMap subs) {
180-
fprintf(stderr, "[%s:%d] (%s) irgen emitCreateAsyncLet...\n", __FILE__, __LINE__, __FUNCTION__);
181-
174+
llvm::Value *irgen::emitBuiltinStartAsyncLet(IRGenFunction &IGF,
175+
llvm::Value *taskFunction,
176+
llvm::Value *localContextInfo,
177+
SubstitutionMap subs) {
182178
// stack allocate AsyncLet, and begin lifetime for it (until EndAsyncLet)
183179
auto ty = llvm::ArrayType::get(IGF.IGM.Int8PtrTy, NumWords_AsyncLet);
184180
auto address = IGF.createAlloca(ty, Alignment(Alignment_AsyncLet));
185181
auto alet = IGF.Builder.CreateBitCast(address.getAddress(),
186-
IGF.IGM.Int8PtrTy);
182+
IGF.IGM.Int8PtrTy);
187183
IGF.Builder.CreateLifetimeStart(alet);
188184

189-
auto *call = IGF.Builder.CreateCall(IGF.IGM.getAsyncLetInitializeFn(),
185+
assert(subs.getReplacementTypes().size() == 1 &&
186+
"startAsyncLet should have a type substitution");
187+
auto futureResultType = subs.getReplacementTypes()[0]->getCanonicalType();
188+
auto futureResultTypeMetadata = IGF.emitAbstractTypeMetadataRef(futureResultType);
189+
190+
// This is @_silgen_name("swift_asyncLet_start")
191+
auto *call = IGF.Builder.CreateCall(IGF.IGM.getAsyncLetStartFn(),
190192
{alet,
191-
flags,
192-
futureResultType,
193+
futureResultTypeMetadata,
193194
taskFunction,
194195
localContextInfo
195196
});
196197
call->setDoesNotThrow();
197198
call->setCallingConv(IGF.IGM.SwiftCC);
198199

199-
fprintf(stderr, "[%s:%d] (%s) irgen emitCreateAsyncLet done...\n", __FILE__, __LINE__, __FUNCTION__);
200-
201200
return alet;
202201
}
203202

lib/IRGen/GenConcurrency.h

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,10 @@ void emitBuildSerialExecutorRef(IRGenFunction &IGF, llvm::Value *actor,
4646
void emitGetCurrentExecutor(IRGenFunction &IGF, Explosion &out);
4747

4848
/// Emit the createAsyncLet builtin.
49-
llvm::Value *emitCreateAsyncLet(IRGenFunction &IGF,
50-
llvm::Value *flags,
51-
llvm::Value *futureResultType,
52-
llvm::Value *taskFunction,
53-
llvm::Value *localContextInfo,
54-
SubstitutionMap subs);
49+
llvm::Value *emitBuiltinStartAsyncLet(IRGenFunction &IGF,
50+
llvm::Value *taskFunction,
51+
llvm::Value *localContextInfo,
52+
SubstitutionMap subs);
5553

5654
/// Emit the endAsyncLet builtin.
5755
void emitEndAsyncLet(IRGenFunction &IGF, llvm::Value *alet);

lib/SIL/IR/OperandOwnership.cpp

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -745,7 +745,7 @@ BUILTIN_OPERAND_OWNERSHIP(InstantaneousUse, PoundAssert)
745745
BUILTIN_OPERAND_OWNERSHIP(InstantaneousUse, GlobalStringTablePointer)
746746
BUILTIN_OPERAND_OWNERSHIP(InstantaneousUse, TypePtrAuthDiscriminator)
747747
BUILTIN_OPERAND_OWNERSHIP(InstantaneousUse, IntInstrprofIncrement)
748-
//BUILTIN_OPERAND_OWNERSHIP(DestroyingConsume, CreateAsyncLet)
748+
BUILTIN_OPERAND_OWNERSHIP(DestroyingConsume, StartAsyncLet)
749749
BUILTIN_OPERAND_OWNERSHIP(DestroyingConsume, EndAsyncLet)
750750
BUILTIN_OPERAND_OWNERSHIP(InstantaneousUse, CreateTaskGroup)
751751
BUILTIN_OPERAND_OWNERSHIP(InstantaneousUse, DestroyTaskGroup)
@@ -767,20 +767,6 @@ OperandOwnershipBuiltinClassifier::visitCreateAsyncTaskFuture(BuiltinInst *bi,
767767
return OperandOwnership::InteriorPointer;
768768
}
769769

770-
OperandOwnership
771-
OperandOwnershipBuiltinClassifier::visitCreateAsyncLet(BuiltinInst *bi,
772-
StringRef attr) {
773-
// The function operand is consumed by the new task.
774-
if (&op == &bi->getOperandRef(2))
775-
return OperandOwnership::DestroyingConsume;
776-
777-
// FIXME: These are considered InteriorPointer because they may propagate a
778-
// pointer into a borrowed values. If they do not propagate an interior pointer,
779-
// then they should be InstantaneousUse instead and should not require a
780-
// guaranteed value.
781-
return OperandOwnership::InteriorPointer;
782-
}
783-
784770
OperandOwnership
785771
OperandOwnershipBuiltinClassifier::visitCreateAsyncTaskGroupFuture(BuiltinInst *bi,
786772
StringRef attr) {

lib/SIL/IR/ValueOwnership.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -545,7 +545,7 @@ CONSTANT_OWNERSHIP_BUILTIN(None, ResumeNonThrowingContinuationReturning)
545545
CONSTANT_OWNERSHIP_BUILTIN(None, ResumeThrowingContinuationReturning)
546546
CONSTANT_OWNERSHIP_BUILTIN(None, ResumeThrowingContinuationThrowing)
547547
CONSTANT_OWNERSHIP_BUILTIN(None, BuildSerialExecutorRef)
548-
CONSTANT_OWNERSHIP_BUILTIN(None, CreateAsyncLet)
548+
CONSTANT_OWNERSHIP_BUILTIN(None, StartAsyncLet)
549549
CONSTANT_OWNERSHIP_BUILTIN(None, EndAsyncLet)
550550
CONSTANT_OWNERSHIP_BUILTIN(None, CreateTaskGroup)
551551
CONSTANT_OWNERSHIP_BUILTIN(None, DestroyTaskGroup)

lib/SIL/Utils/MemAccessUtils.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1859,7 +1859,7 @@ static void visitBuiltinAddress(BuiltinInst *builtin,
18591859
case BuiltinValueKind::InitializeDefaultActor:
18601860
case BuiltinValueKind::DestroyDefaultActor:
18611861
case BuiltinValueKind::GetCurrentExecutor:
1862-
case BuiltinValueKind::CreateAsyncLet:
1862+
case BuiltinValueKind::StartAsyncLet:
18631863
case BuiltinValueKind::EndAsyncLet:
18641864
case BuiltinValueKind::CreateTaskGroup:
18651865
case BuiltinValueKind::DestroyTaskGroup:

0 commit comments

Comments
 (0)