Skip to content

Commit a7d7970

Browse files
committed
Turn finishAsyncLet into a builtin.
This is necessary because we need to model its stack-allocation behavior, although I'm not yet doing that in this patch because StackNesting first needs to be taught to not try to move the deallocation. I'm not convinced that `async let` *should* be doing a stack allocation, but it undoubtedly *is* doing a stack allocation, and until we have an alternative to that, we will need to model it properly.
1 parent ec81d7f commit a7d7970

26 files changed

+211
-41
lines changed

include/swift/AST/Builtins.def

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -926,6 +926,12 @@ BUILTIN_MISC_OPERATION(FlowSensitiveSelfIsolation, "flowSensitiveSelfIsolation",
926926
BUILTIN_MISC_OPERATION(FlowSensitiveDistributedSelfIsolation,
927927
"flowSensitiveDistributedSelfIsolation", "", Special)
928928

929+
/// finishAsyncLet(Builtin.RawPointer, Builtin.RawPointer) -> Void
930+
///
931+
/// End the scope of an async let. An async operation. Deallocates stack
932+
/// memory that was allocated by startAsyncLetWithLocalBuffer.
933+
BUILTIN_MISC_OPERATION(FinishAsyncLet, "finishAsyncLet", "", Special)
934+
929935
/// endAsyncLetLifetime(): (Builtin.RawPointer) -> Void
930936
///
931937
/// Marks the end of an async-let's lifetime.

include/swift/AST/Builtins.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ enum class OverloadedBuiltinKind : uint8_t {
7777
};
7878

7979
/// BuiltinValueKind - The set of (possibly overloaded) builtin functions.
80-
enum class BuiltinValueKind {
80+
enum class BuiltinValueKind : unsigned {
8181
None = 0,
8282
#define BUILTIN(Id, Name, Attrs) Id,
8383
#include "swift/AST/Builtins.def"

include/swift/Runtime/RuntimeFunctions.def

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2578,6 +2578,28 @@ FUNCTION(AsyncLetBegin,
25782578
EFFECT(RuntimeEffect::Concurrency),
25792579
MEMEFFECTS(ArgMemOnly))
25802580

2581+
/// void swift_asyncLet_finish(
2582+
/// AsyncLet *alet,
2583+
/// TaskOptionRecord *options,
2584+
/// const Metadata *futureResultType,
2585+
/// void *closureEntryPoint,
2586+
/// HeapObject *closureContext,
2587+
/// void *resultBuffer
2588+
/// );
2589+
FUNCTION(AsyncLetFinish,
2590+
_Concurrency, swift_asyncLet_finish, SwiftAsyncCC,
2591+
ConcurrencyAvailability,
2592+
RETURNS(VoidTy),
2593+
ARGS(SwiftContextPtrTy, // current context
2594+
SwiftAsyncLetPtrTy, // AsyncLet*
2595+
Int8PtrTy, // resultBuffer
2596+
TaskContinuationFunctionPtrTy, // continuation
2597+
SwiftContextPtrTy // temp context
2598+
),
2599+
ATTRS(NoUnwind),
2600+
EFFECT(RuntimeEffect::Concurrency),
2601+
MEMEFFECTS(ArgMemOnly))
2602+
25812603
/// void swift_task_run_inline(
25822604
/// OpaqueValue *result,
25832605
/// void *closureAFP,

lib/AST/Builtins.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1763,6 +1763,12 @@ static ValueDecl *getStartAsyncLet(ASTContext &ctx, Identifier id) {
17631763
return builder.build(id);
17641764
}
17651765

1766+
static ValueDecl *getFinishAsyncLet(ASTContext &ctx, Identifier id) {
1767+
return getBuiltinFunction(ctx, id, _async(_thin),
1768+
_parameters(_rawPointer, _rawPointer),
1769+
_void);
1770+
}
1771+
17661772
static ValueDecl *getEndAsyncLet(ASTContext &ctx, Identifier id) {
17671773
return getBuiltinFunction(ctx, id, _thin,
17681774
_parameters(_rawPointer),
@@ -3382,6 +3388,9 @@ ValueDecl *swift::getBuiltinValueDecl(ASTContext &Context, Identifier Id) {
33823388
case BuiltinValueKind::StartAsyncLetWithLocalBuffer:
33833389
return getStartAsyncLet(Context, Id);
33843390

3391+
case BuiltinValueKind::FinishAsyncLet:
3392+
return getFinishAsyncLet(Context, Id);
3393+
33853394
case BuiltinValueKind::EndAsyncLetLifetime:
33863395
return getEndAsyncLet(Context, Id);
33873396

lib/IRGen/Callee.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ namespace llvm {
3030
}
3131

3232
namespace swift {
33+
enum class BuiltinValueKind : unsigned;
3334

3435
namespace irgen {
3536
class Callee;
@@ -571,6 +572,13 @@ namespace irgen {
571572
llvm::Value *firstData = nullptr,
572573
llvm::Value *secondData = nullptr);
573574

575+
static Callee forBuiltinRuntimeFunction(IRGenModule &IGM,
576+
llvm::Constant *fnPtr,
577+
BuiltinValueKind builtin,
578+
SubstitutionMap subs,
579+
FunctionPointerKind fpKind =
580+
FunctionPointerKind::Function);
581+
574582
SILFunctionTypeRepresentation getRepresentation() const {
575583
return Info.OrigFnType->getRepresentation();
576584
}

lib/IRGen/GenBuiltin.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,13 @@ void irgen::emitBuiltinCall(IRGenFunction &IGF, const BuiltinInfo &Builtin,
300300
return;
301301
}
302302

303+
case BuiltinValueKind::FinishAsyncLet: {
304+
auto asyncLet = args.claimNext();
305+
auto resultBuffer = args.claimNext();
306+
emitFinishAsyncLet(IGF, asyncLet, resultBuffer);
307+
return;
308+
}
309+
303310
case BuiltinValueKind::EndAsyncLetLifetime: {
304311
IGF.Builder.CreateLifetimeEnd(args.claimNext());
305312
// Ignore a second operand which is inserted by ClosureLifetimeFixup and

lib/IRGen/GenCall.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6430,6 +6430,32 @@ Callee irgen::getCFunctionPointerCallee(IRGenFunction &IGF,
64306430
return Callee(std::move(calleeInfo), fn);
64316431
}
64326432

6433+
Callee Callee::forBuiltinRuntimeFunction(IRGenModule &IGM,
6434+
llvm::Constant *fnPtr,
6435+
BuiltinValueKind builtin,
6436+
SubstitutionMap subs,
6437+
FunctionPointerKind fpKind) {
6438+
auto &ctx = IGM.Context;
6439+
auto builtinDecl =
6440+
getBuiltinValueDecl(ctx, ctx.getIdentifier(getBuiltinName(builtin)));
6441+
6442+
auto loweredFnType = IGM.getSILTypes().getConstantFunctionType(
6443+
TypeExpansionContext::minimal(),
6444+
SILDeclRef(builtinDecl, SILDeclRef::Kind::Func));
6445+
auto signature = IGM.getSignature(loweredFnType, fpKind);
6446+
6447+
auto fp = FunctionPointer::forDirect(fpKind, fnPtr, nullptr, signature);
6448+
6449+
auto substFnType = loweredFnType;
6450+
if (subs) {
6451+
substFnType = loweredFnType->substGenericArgs(IGM.getSILModule(), subs,
6452+
TypeExpansionContext::minimal());
6453+
}
6454+
CalleeInfo calleeInfo(loweredFnType, substFnType, subs);
6455+
6456+
return Callee(std::move(calleeInfo), fp);
6457+
}
6458+
64336459
FunctionPointer FunctionPointer::forDirect(IRGenModule &IGM,
64346460
llvm::Constant *fnPtr,
64356461
llvm::Constant *secondaryValue,

lib/IRGen/GenConcurrency.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "GenConcurrency.h"
1919

2020
#include "BitPatternBuilder.h"
21+
#include "CallEmission.h"
2122
#include "ExtraInhabitants.h"
2223
#include "GenCall.h"
2324
#include "GenPointerAuth.h"
@@ -312,6 +313,28 @@ llvm::Value *irgen::emitBuiltinStartAsyncLet(IRGenFunction &IGF,
312313
return alet;
313314
}
314315

316+
void irgen::emitFinishAsyncLet(IRGenFunction &IGF,
317+
llvm::Value *asyncLet,
318+
llvm::Value *resultBuffer) {
319+
llvm::Constant *function = IGF.IGM.getAsyncLetFinishFn();
320+
auto callee = Callee::forBuiltinRuntimeFunction(IGF.IGM, function,
321+
BuiltinValueKind::FinishAsyncLet, SubstitutionMap(),
322+
FunctionPointerKind::SpecialKind::AsyncLetFinish);
323+
auto emission = getCallEmission(IGF, nullptr, std::move(callee));
324+
325+
emission->begin();
326+
327+
Explosion args;
328+
args.add(asyncLet);
329+
args.add(resultBuffer);
330+
emission->setArgs(args, /*outlined*/ false, /*witness metadata*/ nullptr);
331+
332+
Explosion result;
333+
emission->emitToExplosion(result, false);
334+
335+
emission->end();
336+
}
337+
315338
llvm::Value *irgen::emitCreateTaskGroup(IRGenFunction &IGF,
316339
SubstitutionMap subs,
317340
llvm::Value *groupFlags) {

lib/IRGen/GenConcurrency.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,11 @@ llvm::Value *emitBuiltinStartAsyncLet(IRGenFunction &IGF,
7878
llvm::Value *resultBuffer,
7979
SubstitutionMap subs);
8080

81+
/// Emit the finishAsyncLet builtin.
82+
void emitFinishAsyncLet(IRGenFunction &IGF,
83+
llvm::Value *asyncLet,
84+
llvm::Value *resultBuffer);
85+
8186
/// Emit the createTaskGroup builtin.
8287
llvm::Value *emitCreateTaskGroup(IRGenFunction &IGF, SubstitutionMap subs,
8388
llvm::Value *groupFlags);

lib/SIL/IR/OperandOwnership.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -941,6 +941,7 @@ BUILTIN_OPERAND_OWNERSHIP(InstantaneousUse, GetEnumTag)
941941
BUILTIN_OPERAND_OWNERSHIP(InstantaneousUse, InjectEnumTag)
942942
BUILTIN_OPERAND_OWNERSHIP(InstantaneousUse, DistributedActorAsAnyActor)
943943
BUILTIN_OPERAND_OWNERSHIP(InstantaneousUse, AddressOfRawLayout)
944+
BUILTIN_OPERAND_OWNERSHIP(InstantaneousUse, FinishAsyncLet)
944945
BUILTIN_OPERAND_OWNERSHIP(InstantaneousUse, EndAsyncLetLifetime)
945946
BUILTIN_OPERAND_OWNERSHIP(InstantaneousUse, CreateTaskGroup)
946947
BUILTIN_OPERAND_OWNERSHIP(InstantaneousUse, CreateTaskGroupWithFlags)

0 commit comments

Comments
 (0)