Skip to content

Commit 0901b2b

Browse files
committed
Add builtin support for starting a task on a specific executor.
This should be close enough to the creation of this builtin that we don't need a new feature for it specifically.
1 parent d887249 commit 0901b2b

File tree

12 files changed

+151
-36
lines changed

12 files changed

+151
-36
lines changed

include/swift/AST/Builtins.def

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -953,19 +953,19 @@ BUILTIN_MISC_OPERATION(AddressOfBorrowOpaque, "addressOfBorrowOpaque", "", Speci
953953
BUILTIN_MISC_OPERATION(UnprotectedAddressOfBorrowOpaque, "unprotectedAddressOfBorrowOpaque", "", Special)
954954

955955
/// createTask<T>(flags: Int,
956+
/// initialSerialExecutor: (Builtin.Executor)? = nil,
956957
/// taskGroup: Builtin.RawPointer? = nil,
957958
/// initialTaskExecutor: (Builtin.Executor)? = nil,
958-
/// initialExecutor: (Builtin.Executor)? = nil,
959959
/// operation: @escaping () async throws -> T)
960960
/// -> Builtin.NativeObject, Builtin.RawPointer)
961961
///
962962
/// Create a new task.
963963
BUILTIN_SIL_OPERATION(CreateTask, "createTask", Special)
964964

965965
/// createDiscardingTask(flags: Int,
966+
/// initialSerialExecutor: (Builtin.Executor)? = nil,
966967
/// taskGroup: Builtin.RawPointer? = nil,
967968
/// initialTaskExecutor: (Builtin.Executor)? = nil,
968-
/// initialExecutor: (Builtin.Executor)? = nil,
969969
/// operation: @escaping () async throws -> ())
970970
/// -> (Builtin.NativeObject, Builtin.RawPointer)
971971
///

lib/AST/Builtins.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1531,8 +1531,8 @@ static ValueDecl *getCreateTask(ASTContext &ctx, Identifier id) {
15311531
ctx, id, _thin, _generics(_unrestricted, _conformsToDefaults(0)),
15321532
_parameters(
15331533
_label("flags", _swiftInt),
1534+
_label("initialSerialExecutor", _defaulted(_optional(_executor), _nil)),
15341535
_label("taskGroup", _defaulted(_optional(_rawPointer), _nil)),
1535-
//_label("initialExecutor", _defaulted(_optional(_executor), _nil)),
15361536
_label("initialTaskExecutor", _defaulted(_optional(_executor), _nil)),
15371537
_label("operation", _function(_async(_throws(_sendable(_thick))),
15381538
_typeparam(0), _parameters()))),
@@ -1544,8 +1544,8 @@ static ValueDecl *getCreateDiscardingTask(ASTContext &ctx, Identifier id) {
15441544
ctx, id, _thin,
15451545
_parameters(
15461546
_label("flags", _swiftInt),
1547+
_label("initialSerialExecutor", _defaulted(_optional(_executor), _nil)),
15471548
_label("taskGroup", _defaulted(_optional(_rawPointer), _nil)),
1548-
//_label("initialExecutor", _defaulted(_optional(_executor), _nil)),
15491549
_label("initialTaskExecutor", _defaulted(_optional(_executor), _nil)),
15501550
_label("operation", _function(_async(_throws(_sendable(_thick))),
15511551
_void, _parameters()))),

lib/IRGen/GenConcurrency.cpp

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -598,6 +598,31 @@ llvm::Value *irgen::maybeAddEmbeddedSwiftResultTypeInfo(IRGenFunction &IGF,
598598

599599
namespace {
600600

601+
struct InitialSerialExecutorRecordTraits {
602+
static StringRef getLabel() {
603+
return "initial_serial_executor";
604+
}
605+
static llvm::StructType *getRecordType(IRGenModule &IGM) {
606+
return IGM.SwiftInitialSerialExecutorTaskOptionRecordTy;
607+
}
608+
static TaskOptionRecordFlags getRecordFlags() {
609+
return TaskOptionRecordFlags(TaskOptionRecordKind::InitialSerialExecutor);
610+
}
611+
static CanType getValueType(ASTContext &ctx) {
612+
return ctx.TheExecutorType;
613+
}
614+
615+
void initialize(IRGenFunction &IGF, Address recordAddr,
616+
Explosion &serialExecutor) const {
617+
auto executorRecord =
618+
IGF.Builder.CreateStructGEP(recordAddr, 1, 2 * IGF.IGM.getPointerSize());
619+
IGF.Builder.CreateStore(serialExecutor.claimNext(),
620+
IGF.Builder.CreateStructGEP(executorRecord, 0, Size()));
621+
IGF.Builder.CreateStore(serialExecutor.claimNext(),
622+
IGF.Builder.CreateStructGEP(executorRecord, 1, Size()));
623+
}
624+
};
625+
601626
struct TaskGroupRecordTraits {
602627
static StringRef getLabel() {
603628
return "task_group";
@@ -647,6 +672,15 @@ struct InitialTaskExecutorRecordTraits {
647672

648673
} // end anonymous namespace
649674

675+
static llvm::Value *
676+
maybeAddInitialSerialExecutorOptionRecord(IRGenFunction &IGF,
677+
llvm::Value *prevOptions,
678+
OptionalExplosion &serialExecutor) {
679+
return maybeAddOptionRecord(IGF, prevOptions,
680+
InitialSerialExecutorRecordTraits(),
681+
serialExecutor);
682+
}
683+
650684
static llvm::Value *
651685
maybeAddTaskGroupOptionRecord(IRGenFunction &IGF, llvm::Value *prevOptions,
652686
OptionalExplosion &taskGroup) {
@@ -665,6 +699,7 @@ maybeAddInitialTaskExecutorOptionRecord(IRGenFunction &IGF,
665699

666700
std::pair<llvm::Value *, llvm::Value *>
667701
irgen::emitTaskCreate(IRGenFunction &IGF, llvm::Value *flags,
702+
OptionalExplosion &serialExecutor,
668703
OptionalExplosion &taskGroup,
669704
OptionalExplosion &taskExecutor,
670705
Explosion &taskFunction,
@@ -686,6 +721,10 @@ irgen::emitTaskCreate(IRGenFunction &IGF, llvm::Value *flags,
686721
resultTypeMetadata = IGF.emitTypeMetadataRef(resultType);
687722
}
688723

724+
// Add an option record for the initial serial executor, if present.
725+
taskOptions =
726+
maybeAddInitialSerialExecutorOptionRecord(IGF, taskOptions, serialExecutor);
727+
689728
// Add an option record for the task group, if present.
690729
taskOptions = maybeAddTaskGroupOptionRecord(IGF, taskOptions, taskGroup);
691730

lib/IRGen/GenConcurrency.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ llvm::Value *maybeAddEmbeddedSwiftResultTypeInfo(IRGenFunction &IGF,
102102
/// task function.
103103
std::pair<llvm::Value *, llvm::Value *>
104104
emitTaskCreate(IRGenFunction &IGF, llvm::Value *flags,
105+
OptionalExplosion &initialExecutor,
105106
OptionalExplosion &taskGroup,
106107
OptionalExplosion &taskExecutor,
107108
Explosion &taskFunction,

lib/IRGen/IRGenModule.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -702,6 +702,11 @@ IRGenModule::IRGenModule(IRGenerator &irgen,
702702
ExecutorFirstTy, // identity
703703
ExecutorSecondTy, // implementation
704704
});
705+
SwiftInitialSerialExecutorTaskOptionRecordTy =
706+
createStructType(*this, "swift.serial_executor_task_option", {
707+
SwiftTaskOptionRecordTy, // Base option record
708+
SwiftExecutorTy, // Executor
709+
});
705710
SwiftInitialTaskExecutorPreferenceTaskOptionRecordTy =
706711
createStructType(*this, "swift.task_executor_task_option", {
707712
SwiftTaskOptionRecordTy, // Base option record

lib/IRGen/IRGenModule.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -819,6 +819,7 @@ class IRGenModule {
819819
llvm::IntegerType *SwiftTaskOptionRecordPtrTy;
820820
llvm::PointerType *SwiftTaskGroupPtrTy;
821821
llvm::StructType *SwiftTaskOptionRecordTy;
822+
llvm::StructType *SwiftInitialSerialExecutorTaskOptionRecordTy;
822823
llvm::StructType *SwiftTaskGroupTaskOptionRecordTy;
823824
llvm::StructType *SwiftInitialTaskExecutorPreferenceTaskOptionRecordTy;
824825
llvm::StructType *SwiftResultTypeInfoTaskOptionRecordTy;

lib/IRGen/IRGenSIL.cpp

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3568,13 +3568,14 @@ static void emitBuiltinStackDealloc(IRGenSILFunction &IGF,
35683568
static void emitBuiltinCreateAsyncTask(IRGenSILFunction &IGF,
35693569
swift::BuiltinInst *i) {
35703570
auto flags = IGF.getLoweredSingletonExplosion(i->getOperand(0));
3571-
auto taskGroup = IGF.getLoweredOptionalExplosion(i->getOperand(1));
3572-
auto taskExecutor = IGF.getLoweredOptionalExplosion(i->getOperand(2));
3573-
Explosion taskFunction = IGF.getLoweredExplosion(i->getOperand(3));
3571+
auto serialExecutor = IGF.getLoweredOptionalExplosion(i->getOperand(1));
3572+
auto taskGroup = IGF.getLoweredOptionalExplosion(i->getOperand(2));
3573+
auto taskExecutor = IGF.getLoweredOptionalExplosion(i->getOperand(3));
3574+
Explosion taskFunction = IGF.getLoweredExplosion(i->getOperand(4));
35743575

35753576
auto taskAndContext =
3576-
emitTaskCreate(IGF, flags, taskGroup, taskExecutor, taskFunction,
3577-
i->getSubstitutions());
3577+
emitTaskCreate(IGF, flags, serialExecutor, taskGroup, taskExecutor,
3578+
taskFunction, i->getSubstitutions());
35783579
Explosion out;
35793580
out.add(taskAndContext.first);
35803581
out.add(taskAndContext.second);

lib/SIL/Verifier/SILVerifier.cpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2292,15 +2292,17 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
22922292
if (builtinKind == BuiltinValueKind::CreateAsyncTask) {
22932293
requireType(BI->getType(), _object(_tuple(_nativeObject, _rawPointer)),
22942294
"result of createAsyncTask");
2295-
require(arguments.size() == 4,
2296-
"createAsyncTask expects four arguments");
2295+
require(arguments.size() == 5,
2296+
"createAsyncTask expects five arguments");
22972297
requireType(arguments[0]->getType(), _object(_swiftInt),
22982298
"first argument of createAsyncTask");
2299-
requireType(arguments[1]->getType(), _object(_optional(_rawPointer)),
2299+
requireType(arguments[1]->getType(), _object(_optional(_executor)),
23002300
"second argument of createAsyncTask");
2301-
requireType(arguments[2]->getType(), _object(_optional(_executor)),
2301+
requireType(arguments[2]->getType(), _object(_optional(_rawPointer)),
23022302
"third argument of createAsyncTask");
2303-
auto fnType = requireObjectType(SILFunctionType, arguments[3],
2303+
requireType(arguments[3]->getType(), _object(_optional(_executor)),
2304+
"fourth argument of createAsyncTask");
2305+
auto fnType = requireObjectType(SILFunctionType, arguments[4],
23042306
"result of createAsyncTask");
23052307
auto expectedExtInfo =
23062308
SILExtInfoBuilder().withAsync(true).withConcurrent(true).build();

lib/SILGen/SILGenBuiltin.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1576,6 +1576,14 @@ static ManagedValue emitCreateAsyncTask(SILGenFunction &SGF, SILLocation loc,
15761576

15771577
ManagedValue flags = nextArg().getAsSingleValue(SGF);
15781578

1579+
ManagedValue initialExecutor = [&] {
1580+
if (options & CreateTaskOptions::OptionalEverything) {
1581+
return nextArg().getAsSingleValue(SGF);
1582+
} else {
1583+
return emitOptionalNone(ctx.TheExecutorType);
1584+
}
1585+
}();
1586+
15791587
ManagedValue taskGroup = [&] {
15801588
if (options & CreateTaskOptions::OptionalEverything) {
15811589
return nextArg().getAsSingleValue(SGF);
@@ -1638,6 +1646,7 @@ static ManagedValue emitCreateAsyncTask(SILGenFunction &SGF, SILLocation loc,
16381646

16391647
SILValue builtinArgs[] = {
16401648
flags.getUnmanagedValue(),
1649+
initialExecutor.getUnmanagedValue(),
16411650
taskGroup.getUnmanagedValue(),
16421651
taskExecutor.getUnmanagedValue(),
16431652
functionValue.forward(SGF)

test/Concurrency/async_main.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,13 +67,14 @@ func asyncFunc() async {
6767
// CHECK-SIL-NEXT: [[ASYNC_MAIN_FN:%.*]] = function_ref @async_Main : $@convention(thin) @async () -> ()
6868
// CHECK-SIL-NEXT: [[T0:%.*]] = integer_literal $Builtin.Int64, 2048
6969
// CHECK-SIL-NEXT: [[FLAGS:%.*]] = struct $Int ([[T0]] : $Builtin.Int64)
70+
// CHECK-SIL-NEXT: [[OPT_SERIAL_EXECUTOR:%.*]] = enum $Optional<Builtin.Executor>, #Optional.none
7071
// CHECK-SIL-NEXT: [[GROUP:%.*]] = enum $Optional<Builtin.RawPointer>, #Optional.none
7172
// CHECK-SIL-NEXT: [[TASK_EXECUTOR:%.*]] = enum $Optional<Builtin.Executor>, #Optional.none
7273
// CHECK-SIL-NEXT: // function_ref thunk for @escaping @convention(thin) @async () -> ()
7374
// CHECK-SIL-NEXT: [[THUNK_FN:%.*]] = function_ref @$sIetH_yts5Error_pIeghHrzo_TR : $@convention(thin) @Sendable @async (@convention(thin) @async () -> ()) -> (@out (), @error any Error)
7475
// CHECK-SIL-NEXT: [[THUNK:%.*]] = partial_apply [callee_guaranteed] [[THUNK_FN]]([[ASYNC_MAIN_FN]]) : $@convention(thin) @Sendable @async (@convention(thin) @async () -> ()) -> (@out (), @error any Error)
7576
// CHECK-SIL-NEXT: [[CONVERTED_THUNK:%.*]] = convert_function [[THUNK]] : $@Sendable @async @callee_guaranteed () -> (@out (), @error any Error) to $@Sendable @async @callee_guaranteed @substituted <τ_0_0> () -> (@out τ_0_0, @error any Error) for <()>
76-
// CHECK-SIL-NEXT: [[TASK_RESULT:%.*]] = builtin "createAsyncTask"<()>([[FLAGS]] : $Int, [[GROUP]] : $Optional<Builtin.RawPointer>, [[TASK_EXECUTOR]] : $Optional<Builtin.Executor>, [[CONVERTED_THUNK]] : $@Sendable @async @callee_guaranteed @substituted <τ_0_0> () -> (@out τ_0_0, @error any Error) for <()>) : $(Builtin.NativeObject, Builtin.RawPointer)
77+
// CHECK-SIL-NEXT: [[TASK_RESULT:%.*]] = builtin "createAsyncTask"<()>([[FLAGS]] : $Int, [[OPT_SERIAL_EXECUTOR]] : $Optional<Builtin.Executor>, [[GROUP]] : $Optional<Builtin.RawPointer>, [[TASK_EXECUTOR]] : $Optional<Builtin.Executor>, [[CONVERTED_THUNK]] : $@Sendable @async @callee_guaranteed @substituted <τ_0_0> () -> (@out τ_0_0, @error any Error) for <()>) : $(Builtin.NativeObject, Builtin.RawPointer)
7778
// CHECK-SIL-NEXT: [[TASK:%.*]] = tuple_extract [[TASK_RESULT]] : $(Builtin.NativeObject, Builtin.RawPointer), 0
7879
// CHECK-SIL-NEXT: // function_ref swift_job_run
7980
// CHECK-SIL-NEXT: [[RUN_FN:%.*]] = function_ref @swift_job_run : $@convention(thin) (UnownedJob, UnownedSerialExecutor) -> ()

0 commit comments

Comments
 (0)