diff --git a/include/swift/ABI/MetadataValues.h b/include/swift/ABI/MetadataValues.h index 8bf82ebfae1..07fc0304dde 100644 --- a/include/swift/ABI/MetadataValues.h +++ b/include/swift/ABI/MetadataValues.h @@ -2792,10 +2792,6 @@ public: /// Request the TaskGroup to immediately release completed tasks, /// and not store their results. This also effectively disables `next()`. TaskGroup_DiscardResults = 8, - /// The `Metadata *T` in swift_taskGroup_initialize and in - /// swift_taskGroup_initializeWithFlags pointer is actually a - /// TaskOptionRecord pointer. Used only in Embedded Swift. - TaskGroup_MetadataAsOptionRecord = 9, }; explicit TaskGroupFlags(uint32_t bits) : FlagSet(bits) {} @@ -2804,10 +2800,6 @@ public: FLAGSET_DEFINE_FLAG_ACCESSORS(TaskGroup_DiscardResults, isDiscardResults, setIsDiscardResults) - - FLAGSET_DEFINE_FLAG_ACCESSORS(TaskGroup_MetadataAsOptionRecord, - isMetadataAsOptionRecord, - setIsMetadataAsOptionRecord) }; /// Flags for cancellation records. diff --git a/include/swift/Runtime/Concurrency.h b/include/swift/Runtime/Concurrency.h index 4d9a64c9db9..7a969bebd37 100644 --- a/include/swift/Runtime/Concurrency.h +++ b/include/swift/Runtime/Concurrency.h @@ -215,6 +215,17 @@ void swift_taskGroup_initialize(TaskGroup *group, const Metadata *T); SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift) void swift_taskGroup_initializeWithFlags(size_t flags, TaskGroup *group, const Metadata *T); +/// Initialize a `TaskGroup` in the passed `group` memory location. +/// The caller is responsible for retaining and managing the group's lifecycle. +/// +/// Its Swift signature is +/// +/// \code +/// func swift_taskGroup_initialize(flags: Int, group: Builtin.RawPointer) +/// \endcode +SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift) +void swift_taskGroup_initializeWithOptions(size_t flags, TaskGroup *group, const Metadata *T, TaskOptionRecord *options); + /// Attach a child task to the parent task's task group record. /// /// This function MUST be called from the AsyncTask running the task group. diff --git a/include/swift/Runtime/RuntimeFunctions.def b/include/swift/Runtime/RuntimeFunctions.def index 84ac37cfef5..93db683cc01 100644 --- a/include/swift/Runtime/RuntimeFunctions.def +++ b/include/swift/Runtime/RuntimeFunctions.def @@ -2555,7 +2555,7 @@ FUNCTION(TaskRunInline, EFFECT(NoEffect), UNKNOWN_MEMEFFECTS) -// void swift_taskGroup_initialize(TaskGroup *group); +// void swift_taskGroup_initialize(TaskGroup *group, const Metadata *T); FUNCTION(TaskGroupInitialize, swift_taskGroup_initialize, SwiftCC, ConcurrencyAvailability, @@ -2565,7 +2565,7 @@ FUNCTION(TaskGroupInitialize, EFFECT(Concurrency), UNKNOWN_MEMEFFECTS) -// void swift_taskGroup_initializeWithFlags(size_t flags, TaskGroup *group); +// void swift_taskGroup_initializeWithFlags(size_t flags, TaskGroup *group, const Metadata *T); FUNCTION(TaskGroupInitializeWithFlags, swift_taskGroup_initializeWithFlags, SwiftCC, ConcurrencyDiscardingTaskGroupAvailability, @@ -2578,6 +2578,20 @@ FUNCTION(TaskGroupInitializeWithFlags, EFFECT(Concurrency), UNKNOWN_MEMEFFECTS) +// void swift_taskGroup_initializeWithTaskOptions(size_t flags, TaskGroup *group, const Metadata *T, TaskOptionRecord *options); +FUNCTION(TaskGroupInitializeWithOptions, + swift_taskGroup_initializeWithOptions, SwiftCC, + ConcurrencyDiscardingTaskGroupAvailability, + RETURNS(VoidTy), + ARGS(SizeTy, // flags + Int8PtrTy, // group + TypeMetadataPtrTy, // T.Type + SwiftTaskOptionRecordPtrTy // options + ), + ATTRS(NoUnwind), + EFFECT(Concurrency), + UNKNOWN_MEMEFFECTS) + // void swift_taskGroup_destroy(TaskGroup *group); FUNCTION(TaskGroupDestroy, swift_taskGroup_destroy, SwiftCC, diff --git a/lib/IRGen/GenConcurrency.cpp b/lib/IRGen/GenConcurrency.cpp index d4703dc06a6..1e4d78ebaa4 100644 --- a/lib/IRGen/GenConcurrency.cpp +++ b/lib/IRGen/GenConcurrency.cpp @@ -336,38 +336,30 @@ llvm::Value *irgen::emitCreateTaskGroup(IRGenFunction &IGF, "createTaskGroup should have a type substitution"); auto resultType = subs.getReplacementTypes()[0]->getCanonicalType(); - // In desktop Swift, we pass a Metadata pointer as the last argument. In - // Embedded Swift, we pass a TaskOptionRecord list, and mark a bit in - // groupFlags. - llvm::Value *metadataOrTypeOptionRecord; if (IGF.IGM.Context.LangOpts.hasFeature(Feature::Embedded)) { - metadataOrTypeOptionRecord = - llvm::ConstantPointerNull::get(IGF.IGM.Int8PtrTy); - metadataOrTypeOptionRecord = maybeAddEmbeddedSwiftResultTypeInfo( - IGF, metadataOrTypeOptionRecord, resultType); - llvm::IntegerType *IntPtrTy = IGF.IGM.IntPtrTy; - TaskGroupFlags taskgroupFlags(0); - taskgroupFlags.setIsMetadataAsOptionRecord(true); - auto flagValue = llvm::ConstantInt::get(IGF.IGM.IntPtrTy, - taskgroupFlags.getOpaqueValue()); - if (!groupFlags) { - groupFlags = flagValue; - } else { - groupFlags = IGF.Builder.CreateOr(groupFlags, flagValue); - } - } else { - metadataOrTypeOptionRecord = IGF.emitAbstractTypeMetadataRef(resultType); + // In Embedded Swift, call swift_taskGroup_initializeWithOptions instead, to + // avoid needing a Metadata argument. + llvm::Value *options = llvm::ConstantPointerNull::get(IGF.IGM.Int8PtrTy); + llvm::Value *resultTypeMetadata = llvm::ConstantPointerNull::get(IGF.IGM.Int8PtrTy); + options = maybeAddEmbeddedSwiftResultTypeInfo(IGF, options, resultType); + if (!groupFlags) groupFlags = llvm::ConstantInt::get(IGF.IGM.SizeTy, 0); + llvm::CallInst *call = IGF.Builder.CreateCall(IGF.IGM.getTaskGroupInitializeWithOptionsFunctionPointer(), + {groupFlags, group, resultTypeMetadata, options}); + call->setDoesNotThrow(); + call->setCallingConv(IGF.IGM.SwiftCC); + return group; } + auto resultTypeMetadata = IGF.emitAbstractTypeMetadataRef(resultType); + llvm::CallInst *call; if (groupFlags) { - call = IGF.Builder.CreateCall( - IGF.IGM.getTaskGroupInitializeWithFlagsFunctionPointer(), - {groupFlags, group, metadataOrTypeOptionRecord}); + call = IGF.Builder.CreateCall(IGF.IGM.getTaskGroupInitializeWithFlagsFunctionPointer(), + {groupFlags, group, resultTypeMetadata}); } else { call = IGF.Builder.CreateCall(IGF.IGM.getTaskGroupInitializeFunctionPointer(), - {group, metadataOrTypeOptionRecord}); + {group, resultTypeMetadata}); } call->setDoesNotThrow(); call->setCallingConv(IGF.IGM.SwiftCC); diff --git a/stdlib/public/CompatibilityOverride/CompatibilityOverrideConcurrency.def b/stdlib/public/CompatibilityOverride/CompatibilityOverrideConcurrency.def index e8d4c68eecb..49fe4a37bd7 100644 --- a/stdlib/public/CompatibilityOverride/CompatibilityOverrideConcurrency.def +++ b/stdlib/public/CompatibilityOverride/CompatibilityOverrideConcurrency.def @@ -300,6 +300,10 @@ OVERRIDE_TASK_GROUP(taskGroup_initializeWithFlags, void, SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swift), swift::, (size_t flags, TaskGroup *group, const Metadata *T), (flags, group, T)) +OVERRIDE_TASK_GROUP(taskGroup_initializeWithOptions, void, + SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swift), + swift::, (size_t flags, TaskGroup *group, const Metadata *T, TaskOptionRecord *options), (flags, group, T, options)) + OVERRIDE_TASK_STATUS(taskGroup_attachChild, void, SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swift), swift::, (TaskGroup *group, AsyncTask *child), diff --git a/stdlib/public/Concurrency/TaskGroup.cpp b/stdlib/public/Concurrency/TaskGroup.cpp index ff001bceb4c..0c5c9e6deaa 100644 --- a/stdlib/public/Concurrency/TaskGroup.cpp +++ b/stdlib/public/Concurrency/TaskGroup.cpp @@ -955,6 +955,8 @@ TaskGroup* TaskGroupTaskStatusRecord::getGroup() { // ============================================================================= // ==== initialize ------------------------------------------------------------- +static void _swift_taskGroup_initialize(ResultTypeInfo resultType, size_t rawGroupFlags, TaskGroup *group); + // Initializes into the preallocated _group an actual TaskGroupBase. SWIFT_CC(swift) static void swift_taskGroup_initializeImpl(TaskGroup *group, const Metadata *T) { @@ -965,21 +967,27 @@ static void swift_taskGroup_initializeImpl(TaskGroup *group, const Metadata *T) SWIFT_CC(swift) static void swift_taskGroup_initializeWithFlagsImpl(size_t rawGroupFlags, TaskGroup *group, const Metadata *T) { - TaskGroupFlags groupFlags(rawGroupFlags); - SWIFT_TASK_GROUP_DEBUG_LOG_0(group, "create group, from task:%p; flags: isDiscardingResults=%d", - swift_task_getCurrent(), - groupFlags.isDiscardResults()); - ResultTypeInfo resultType; #if !SWIFT_CONCURRENCY_EMBEDDED resultType.metadata = T; - assert(!groupFlags.isMetadataAsOptionRecord()); #else - assert(groupFlags.isMetadataAsOptionRecord()); - TaskOptionRecord *options = (TaskOptionRecord *)T; + swift_unreachable("swift_taskGroup_initializeWithFlags in embedded"); +#endif + _swift_taskGroup_initialize(resultType, rawGroupFlags, group); +} + +// Initializes into the preallocated _group an actual instance. +SWIFT_CC(swift) +static void swift_taskGroup_initializeWithOptionsImpl(size_t rawGroupFlags, TaskGroup *group, const Metadata *T, TaskOptionRecord *options) { + ResultTypeInfo resultType; +#if !SWIFT_CONCURRENCY_EMBEDDED + resultType.metadata = T; +#endif + for (auto option = options; option; option = option->getParent()) { switch (option->getKind()) { case TaskOptionRecordKind::ResultTypeInfo: { +#if SWIFT_CONCURRENCY_EMBEDDED auto *typeInfo = cast(option); resultType = { .size = typeInfo->size, @@ -988,13 +996,26 @@ static void swift_taskGroup_initializeWithFlagsImpl(size_t rawGroupFlags, .storeEnumTagSinglePayload = typeInfo->storeEnumTagSinglePayload, .destroy = typeInfo->destroy, }; +#else + swift_unreachable("ResultTypeInfo in non embedded"); +#endif break; } default: - swift_unreachable("only ResultTypeInfo expected"); + break; // ignore unknown records } } -#endif + + assert(!resultType.isNull()); + + _swift_taskGroup_initialize(resultType, rawGroupFlags, group); +} + +static void _swift_taskGroup_initialize(ResultTypeInfo resultType, size_t rawGroupFlags, TaskGroup *group) { + TaskGroupFlags groupFlags(rawGroupFlags); + SWIFT_TASK_GROUP_DEBUG_LOG_0(group, "create group, from task:%p; flags: isDiscardingResults=%d", + swift_task_getCurrent(), + groupFlags.isDiscardResults()); TaskGroupBase *impl; if (groupFlags.isDiscardResults()) {