Skip to content

[DiscardingTG] Remove reabstraction thunk for () -> Void to () -> T #70537

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions include/swift/AST/Builtins.def
Original file line number Diff line number Diff line change
Expand Up @@ -986,6 +986,17 @@ BUILTIN_MISC_OPERATION_WITH_SILGEN(CreateAsyncTask,
BUILTIN_MISC_OPERATION_WITH_SILGEN(CreateAsyncTaskInGroup,
"createAsyncTaskInGroup", "", Special)

/// createAsyncDiscardingTaskInGroup(): (
/// Int, // flags
/// Builtin.RawPointer, // group
/// @escaping () async throws -> Void // function
/// ) -> Builtin.NativeObject
///
/// Create a new asynchronous discarding task, given flags, a parent task,
/// task group and a function to execute.
BUILTIN_MISC_OPERATION_WITH_SILGEN(CreateAsyncDiscardingTaskInGroup,
"createAsyncDiscardingTaskInGroup", "", Special)

/// createAsyncTaskWithExecutor(): (
/// Int, // flags
/// Builtin.Executor, // executor
Expand All @@ -1009,6 +1020,18 @@ BUILTIN_MISC_OPERATION_WITH_SILGEN(CreateAsyncTaskWithExecutor,
BUILTIN_MISC_OPERATION_WITH_SILGEN(CreateAsyncTaskInGroupWithExecutor,
"createAsyncTaskInGroupWithExecutor", "", Special)

/// createAsyncDiscardingTaskInGroupWithExecutor(): (
/// Int, // flags
/// Builtin.RawPointer, // group
/// Builtin.Executor, // executor
/// @escaping () async throws -> Void // function
/// ) -> Builtin.NativeObject
///
/// Create a new asynchronous discarding task, given flags, a parent task,
/// task group and a function to execute.
BUILTIN_MISC_OPERATION_WITH_SILGEN(CreateAsyncDiscardingTaskInGroupWithExecutor,
"createAsyncDiscardingTaskInGroupWithExecutor", "", Special)

/// Build a Builtin.Executor value from an "ordinary" task executor
/// reference.
BUILTIN_MISC_OPERATION_WITH_SILGEN(BuildOrdinaryTaskExecutorRef,
Expand Down
31 changes: 22 additions & 9 deletions lib/AST/Builtins.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1466,9 +1466,10 @@ Type swift::getAsyncTaskAndContextType(ASTContext &ctx) {
}

static ValueDecl *getCreateAsyncTask(ASTContext &ctx, Identifier id,
bool inGroup, bool withTaskExecutor) {
BuiltinFunctionBuilder builder(ctx);
auto genericParam = makeGenericParam().build(builder); // <T>
bool inGroup, bool withTaskExecutor,
bool isDiscarding) {
unsigned numGenericParams = isDiscarding ? 0 : 1;
BuiltinFunctionBuilder builder(ctx, numGenericParams);
builder.addParameter(makeConcrete(ctx.getIntType())); // 0 flags
if (inGroup) {
builder.addParameter(makeConcrete(ctx.TheRawPointerType)); // group
Expand All @@ -1477,8 +1478,14 @@ static ValueDecl *getCreateAsyncTask(ASTContext &ctx, Identifier id,
builder.addParameter(makeConcrete(ctx.TheExecutorType)); // executor
}
auto extInfo = ASTExtInfoBuilder().withAsync().withThrows().build();
builder.addParameter(
makeConcrete(FunctionType::get({}, genericParam, extInfo))); // operation
Type operationResultType;
if (isDiscarding) {
operationResultType = TupleType::getEmpty(ctx); // ()
} else {
operationResultType = makeGenericParam().build(builder); // <T>
}
builder.addParameter(makeConcrete(
FunctionType::get({}, operationResultType, extInfo))); // operation
builder.setResult(makeConcrete(getAsyncTaskAndContextType(ctx)));
return builder.build(id);
}
Expand Down Expand Up @@ -2928,16 +2935,22 @@ ValueDecl *swift::getBuiltinValueDecl(ASTContext &Context, Identifier Id) {

case BuiltinValueKind::CreateAsyncTask:
return getCreateAsyncTask(Context, Id, /*inGroup=*/false,
/*withExecutor=*/false);
/*withExecutor=*/false, /*isDiscarding=*/false);
case BuiltinValueKind::CreateAsyncTaskInGroup:
return getCreateAsyncTask(Context, Id, /*inGroup=*/true,
/*withExecutor=*/false);
/*withExecutor=*/false, /*isDiscarding=*/false);
case BuiltinValueKind::CreateAsyncDiscardingTaskInGroup:
return getCreateAsyncTask(Context, Id, /*inGroup=*/true,
/*withExecutor=*/false, /*isDiscarding=*/true);
case BuiltinValueKind::CreateAsyncTaskWithExecutor:
return getCreateAsyncTask(Context, Id, /*inGroup=*/false,
/*withExecutor=*/true);
/*withExecutor=*/true, /*isDiscarding=*/false);
case BuiltinValueKind::CreateAsyncTaskInGroupWithExecutor:
return getCreateAsyncTask(Context, Id, /*inGroup=*/true,
/*withExecutor=*/true);
/*withExecutor=*/true, /*isDiscarding=*/false);
case BuiltinValueKind::CreateAsyncDiscardingTaskInGroupWithExecutor:
return getCreateAsyncTask(Context, Id, /*inGroup=*/true,
/*withExecutor=*/true, /*isDiscarding=*/true);

case BuiltinValueKind::TaskRunInline:
return getTaskRunInline(Context, Id);
Expand Down
13 changes: 10 additions & 3 deletions lib/IRGen/GenBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -322,27 +322,34 @@ void irgen::emitBuiltinCall(IRGenFunction &IGF, const BuiltinInfo &Builtin,

if (Builtin.ID == BuiltinValueKind::CreateAsyncTask ||
Builtin.ID == BuiltinValueKind::CreateAsyncTaskInGroup ||
Builtin.ID == BuiltinValueKind::CreateAsyncDiscardingTaskInGroup ||
Builtin.ID == BuiltinValueKind::CreateAsyncTaskWithExecutor ||
Builtin.ID == BuiltinValueKind::CreateAsyncTaskInGroupWithExecutor) {
Builtin.ID == BuiltinValueKind::CreateAsyncTaskInGroupWithExecutor ||
Builtin.ID == BuiltinValueKind::CreateAsyncDiscardingTaskInGroupWithExecutor) {

auto flags = args.claimNext();
auto taskGroup =
(Builtin.ID == BuiltinValueKind::CreateAsyncTaskInGroup ||
Builtin.ID == BuiltinValueKind::CreateAsyncTaskInGroupWithExecutor)
Builtin.ID == BuiltinValueKind::CreateAsyncDiscardingTaskInGroup ||
Builtin.ID == BuiltinValueKind::CreateAsyncTaskInGroupWithExecutor ||
Builtin.ID == BuiltinValueKind::CreateAsyncDiscardingTaskInGroupWithExecutor)
? args.claimNext()
: nullptr;

// ExecutorRef is two pointers: {Identity, Implementation}
std::pair<llvm::Value *, llvm::Value *> executorRef =
(Builtin.ID == BuiltinValueKind::CreateAsyncTaskWithExecutor ||
Builtin.ID == BuiltinValueKind::CreateAsyncTaskInGroupWithExecutor)
Builtin.ID == BuiltinValueKind::CreateAsyncTaskInGroupWithExecutor ||
Builtin.ID == BuiltinValueKind::CreateAsyncDiscardingTaskInGroupWithExecutor)
? std::pair(args.claimNext(), args.claimNext())
: std::pair(nullptr, nullptr);

// In embedded Swift, futureResultType is a thin metatype, not backed by any
// actual value.
llvm::Value *futureResultType =
llvm::ConstantPointerNull::get(IGF.IGM.Int8PtrTy);
// FIXME: We pass a metatype of result type even if it's statically known to
// be discarded (`Void`) just to keep the existing behavior.
if (!IGF.IGM.Context.LangOpts.hasFeature(Feature::Embedded)) {
futureResultType = args.claimNext();
}
Expand Down
17 changes: 17 additions & 0 deletions lib/SIL/IR/OperandOwnership.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -912,8 +912,10 @@ ::visitStartAsyncLetWithLocalBuffer(BuiltinInst *bi, StringRef attr) {

const int PARAMETER_INDEX_CREATE_ASYNC_TASK_FUTURE_FUNCTION = 2;
const int PARAMETER_INDEX_CREATE_ASYNC_TASK_GROUP_FUTURE_FUNCTION = 3;
const int PARAMETER_INDEX_CREATE_ASYNC_DISCARDING_TASK_GROUP_FUTURE_FUNCTION = 3;
const int PARAMETER_INDEX_CREATE_ASYNC_TASK_WITH_EXECUTOR_FUNCTION = 3;
const int PARAMETER_INDEX_CREATE_ASYNC_TASK_GROUP_WITH_EXECUTOR_FUNCTION = 4;
const int PARAMETER_INDEX_CREATE_ASYNC_DISCARDING_TASK_GROUP_WITH_EXECUTOR_FUNCTION = 4;

OperandOwnership OperandOwnershipBuiltinClassifier::visitCreateAsyncTask(
BuiltinInst *bi, StringRef attr, int paramIndex) {
Expand All @@ -938,6 +940,14 @@ OperandOwnershipBuiltinClassifier::visitCreateAsyncTaskInGroup(BuiltinInst *bi,
bi, attr, PARAMETER_INDEX_CREATE_ASYNC_TASK_GROUP_FUTURE_FUNCTION);
}

OperandOwnership
OperandOwnershipBuiltinClassifier::visitCreateAsyncDiscardingTaskInGroup(
BuiltinInst *bi, StringRef attr) {
return visitCreateAsyncTask(
bi, attr,
PARAMETER_INDEX_CREATE_ASYNC_DISCARDING_TASK_GROUP_FUTURE_FUNCTION);
}

OperandOwnership
OperandOwnershipBuiltinClassifier::visitCreateAsyncTaskWithExecutor(
BuiltinInst *bi, StringRef attr) {
Expand All @@ -952,6 +962,13 @@ OperandOwnershipBuiltinClassifier::visitCreateAsyncTaskInGroupWithExecutor(
bi, attr, PARAMETER_INDEX_CREATE_ASYNC_TASK_GROUP_WITH_EXECUTOR_FUNCTION);
}

OperandOwnership
OperandOwnershipBuiltinClassifier::visitCreateAsyncDiscardingTaskInGroupWithExecutor(
BuiltinInst *bi, StringRef attr) {
return visitCreateAsyncTask(
bi, attr, PARAMETER_INDEX_CREATE_ASYNC_DISCARDING_TASK_GROUP_WITH_EXECUTOR_FUNCTION);
}

OperandOwnership OperandOwnershipBuiltinClassifier::
visitResumeNonThrowingContinuationReturning(BuiltinInst *bi, StringRef attr) {
// The value operand is consumed.
Expand Down
2 changes: 2 additions & 0 deletions lib/SIL/IR/ValueOwnership.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -590,8 +590,10 @@ CONSTANT_OWNERSHIP_BUILTIN(None, GetCurrentAsyncTask)
CONSTANT_OWNERSHIP_BUILTIN(None, CancelAsyncTask)
CONSTANT_OWNERSHIP_BUILTIN(Owned, CreateAsyncTask)
CONSTANT_OWNERSHIP_BUILTIN(Owned, CreateAsyncTaskInGroup)
CONSTANT_OWNERSHIP_BUILTIN(Owned, CreateAsyncDiscardingTaskInGroup)
CONSTANT_OWNERSHIP_BUILTIN(Owned, CreateAsyncTaskWithExecutor)
CONSTANT_OWNERSHIP_BUILTIN(Owned, CreateAsyncTaskInGroupWithExecutor)
CONSTANT_OWNERSHIP_BUILTIN(Owned, CreateAsyncDiscardingTaskInGroupWithExecutor)
CONSTANT_OWNERSHIP_BUILTIN(None, ConvertTaskToJob)
CONSTANT_OWNERSHIP_BUILTIN(None, InitializeDefaultActor)
CONSTANT_OWNERSHIP_BUILTIN(None, DestroyDefaultActor)
Expand Down
2 changes: 2 additions & 0 deletions lib/SIL/Utils/MemAccessUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2612,8 +2612,10 @@ static void visitBuiltinAddress(BuiltinInst *builtin,
case BuiltinValueKind::CancelAsyncTask:
case BuiltinValueKind::CreateAsyncTask:
case BuiltinValueKind::CreateAsyncTaskInGroup:
case BuiltinValueKind::CreateAsyncDiscardingTaskInGroup:
case BuiltinValueKind::CreateAsyncTaskWithExecutor:
case BuiltinValueKind::CreateAsyncTaskInGroupWithExecutor:
case BuiltinValueKind::CreateAsyncDiscardingTaskInGroupWithExecutor:
case BuiltinValueKind::AutoDiffCreateLinearMapContextWithType:
case BuiltinValueKind::AutoDiffAllocateSubcontextWithType:
case BuiltinValueKind::InitializeDefaultActor:
Expand Down
93 changes: 64 additions & 29 deletions lib/SILGen/SILGenBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1523,7 +1523,8 @@ ManagedValue emitBuiltinCreateAsyncTask(SILGenFunction &SGF, SILLocation loc,
SubstitutionMap subs,
ArrayRef<ManagedValue> args,
SGFContext C, BuiltinValueKind kind,
bool inGroup, bool withExecutor) {
bool inGroup, bool withExecutor,
bool isDiscarding) {
ASTContext &ctx = SGF.getASTContext();

SmallVector<SILValue, 4> builtinArgs;
Expand All @@ -1537,14 +1538,22 @@ ManagedValue emitBuiltinCreateAsyncTask(SILGenFunction &SGF, SILLocation loc,
builtinArgs.push_back(args[nextArgIdx++].forward(SGF)); // executor
}

CanType futureResultType;
// Form the metatype of the result type.
CanType futureResultType =
Type(MetatypeType::get(GenericTypeParamType::get(
/*isParameterPack*/ false,
/*depth*/ 0, /*index*/ 0, SGF.getASTContext()),
MetatypeRepresentation::Thick))
.subst(subs)
->getCanonicalType();
if (isDiscarding) {
futureResultType =
Type(MetatypeType::get(TupleType::getEmpty(ctx)->getCanonicalType(),
MetatypeRepresentation::Thick))
->getCanonicalType();
} else {
futureResultType = Type(MetatypeType::get(GenericTypeParamType::get(
/*isParameterPack*/ false,
/*depth*/ 0, /*index*/ 0,
SGF.getASTContext()),
MetatypeRepresentation::Thick))
.subst(subs)
->getCanonicalType();
}
CanType anyTypeType =
ExistentialMetatypeType::get(ctx.TheAnyType)->getCanonicalType();
auto &anyTypeTL = SGF.getTypeLowering(anyTypeType);
Expand All @@ -1568,21 +1577,27 @@ ManagedValue emitBuiltinCreateAsyncTask(SILGenFunction &SGF, SILLocation loc,
.withThrows()
.withRepresentation(GenericFunctionType::Representation::Swift)
.build();
auto genericSig = subs.getGenericSignature().getCanonicalSignature();
auto genericResult =
GenericTypeParamType::get(/*isParameterPack*/ false,
/*depth*/ 0, /*index*/ 0, SGF.getASTContext());
// <T> () async throws -> T
CanType functionTy =
GenericFunctionType::get(genericSig, {}, genericResult, extInfo)
->getCanonicalType();
AbstractionPattern origParam(genericSig, functionTy);
CanType substParamType = functionTy.subst(subs)->getCanonicalType();
auto reabstractedFun = SGF.emitSubstToOrigValue(loc, args[nextArgIdx],
origParam, substParamType);

ManagedValue entryPointFun;
if (isDiscarding) {
entryPointFun = args[nextArgIdx];
} else {
auto genericSig = subs.getGenericSignature().getCanonicalSignature();
auto genericResult = GenericTypeParamType::get(/*isParameterPack*/ false,
/*depth*/ 0, /*index*/ 0,
SGF.getASTContext());
// <T> () async throws -> T
CanType functionTy =
GenericFunctionType::get(genericSig, {}, genericResult, extInfo)
->getCanonicalType();
AbstractionPattern origParam(genericSig, functionTy);
CanType substParamType = functionTy.subst(subs)->getCanonicalType();
entryPointFun = SGF.emitSubstToOrigValue(loc, args[nextArgIdx], origParam,
substParamType);
}

auto function = emitFunctionArgumentForAsyncTaskEntryPoint(
SGF, loc, reabstractedFun, futureResultType);
SGF, loc, entryPointFun, futureResultType);
builtinArgs.push_back(function.forward(SGF));

auto apply = SGF.B.createBuiltin(
Expand All @@ -1595,9 +1610,19 @@ ManagedValue emitBuiltinCreateAsyncTask(SILGenFunction &SGF, SILLocation loc,
static ManagedValue emitBuiltinCreateAsyncTaskInGroup(
SILGenFunction &SGF, SILLocation loc, SubstitutionMap subs,
ArrayRef<ManagedValue> args, SGFContext C) {
return emitBuiltinCreateAsyncTask(SGF, loc, subs, args, C,
BuiltinValueKind::CreateAsyncTaskInGroup,
/*inGroup=*/true, /*withExecutor=*/false);
return emitBuiltinCreateAsyncTask(
SGF, loc, subs, args, C, BuiltinValueKind::CreateAsyncTaskInGroup,
/*inGroup=*/true, /*withExecutor=*/false, /*isDiscarding=*/false);
}

// Emit SIL for the named builtin: createAsyncDiscardingTaskInGroup.
static ManagedValue emitBuiltinCreateAsyncDiscardingTaskInGroup(
SILGenFunction &SGF, SILLocation loc, SubstitutionMap subs,
ArrayRef<ManagedValue> args, SGFContext C) {
return emitBuiltinCreateAsyncTask(
SGF, loc, subs, args, C,
BuiltinValueKind::CreateAsyncDiscardingTaskInGroup,
/*inGroup=*/true, /*withExecutor=*/false, /*isDiscarding=*/true);
}

// Emit SIL for the named builtin: createAsyncTaskWithExecutor.
Expand All @@ -1606,7 +1631,7 @@ static ManagedValue emitBuiltinCreateAsyncTaskWithExecutor(
ArrayRef<ManagedValue> args, SGFContext C) {
return emitBuiltinCreateAsyncTask(
SGF, loc, subs, args, C, BuiltinValueKind::CreateAsyncTaskWithExecutor,
/*inGroup=*/false, /*withExecutor=*/true);
/*inGroup=*/false, /*withExecutor=*/true, /*isDiscarding=*/false);
}
// Emit SIL for the named builtin: createAsyncTaskInGroupWithExecutor.
static ManagedValue emitBuiltinCreateAsyncTaskInGroupWithExecutor(
Expand All @@ -1615,17 +1640,27 @@ static ManagedValue emitBuiltinCreateAsyncTaskInGroupWithExecutor(
return emitBuiltinCreateAsyncTask(
SGF, loc, subs, args, C,
BuiltinValueKind::CreateAsyncTaskInGroupWithExecutor,
/*inGroup=*/true, /*withExecutor=*/true);
/*inGroup=*/true, /*withExecutor=*/true, /*isDiscarding=*/false);
}

// Emit SIL for the named builtin: createAsyncTaskInGroupWithExecutor.
static ManagedValue emitBuiltinCreateAsyncDiscardingTaskInGroupWithExecutor(
SILGenFunction &SGF, SILLocation loc, SubstitutionMap subs,
ArrayRef<ManagedValue> args, SGFContext C) {
return emitBuiltinCreateAsyncTask(
SGF, loc, subs, args, C,
BuiltinValueKind::CreateAsyncTaskInGroupWithExecutor,
/*inGroup=*/true, /*withExecutor=*/true, /*isDiscarding=*/true);
}

// Emit SIL for the named builtin: createAsyncTask.
ManagedValue emitBuiltinCreateAsyncTask(SILGenFunction &SGF, SILLocation loc,
SubstitutionMap subs,
ArrayRef<ManagedValue> args,
SGFContext C) {
return emitBuiltinCreateAsyncTask(SGF, loc, subs, args, C,
BuiltinValueKind::CreateAsyncTask,
/*inGroup=*/false, /*withExecutor=*/false);
return emitBuiltinCreateAsyncTask(
SGF, loc, subs, args, C, BuiltinValueKind::CreateAsyncTask,
/*inGroup=*/false, /*withExecutor=*/false, /*isDiscarding=*/false);
}

// Shared implementation of withUnsafeContinuation and
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -187,8 +187,10 @@ static bool isBarrier(SILInstruction *inst) {
case BuiltinValueKind::StartAsyncLet:
case BuiltinValueKind::CreateAsyncTask:
case BuiltinValueKind::CreateAsyncTaskInGroup:
case BuiltinValueKind::CreateAsyncDiscardingTaskInGroup:
case BuiltinValueKind::CreateAsyncTaskWithExecutor:
case BuiltinValueKind::CreateAsyncTaskInGroupWithExecutor:
case BuiltinValueKind::CreateAsyncDiscardingTaskInGroupWithExecutor:
case BuiltinValueKind::TaskRunInline:
case BuiltinValueKind::StartAsyncLetWithLocalBuffer:
case BuiltinValueKind::ConvertTaskToJob:
Expand Down
Loading