[embedded] Introduce a new swift_taskGroup_initializeWithOptions runtime entrypoint

This commit is contained in:
Kuba Mracek
2024-10-01 14:56:38 -07:00
parent f1c2334c9a
commit a2dcb6045c
6 changed files with 78 additions and 44 deletions

View File

@@ -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.

View File

@@ -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.

View File

@@ -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,

View File

@@ -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);

View File

@@ -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),

View File

@@ -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<ResultTypeInfoTaskOptionRecord>(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()) {