Skip to content

Commit 9263f61

Browse files
committed
Runtime: Workaround armv7k code lowering bug
This is to workaround a bug in llvm's codegen when emitting the callee-pop stack adjustment on a regular return from a swiftasync function (vs. a tail call). Without the workaround we fail to emit the callee-pop stack adjustment leading to a mis-aligned stack on return. ``` pop {r7, pc} add sp, swiftlang#16 ``` Workaround for rdar://79726989
1 parent 7ccc1b0 commit 9263f61

File tree

2 files changed

+64
-0
lines changed

2 files changed

+64
-0
lines changed

stdlib/public/Concurrency/Task.cpp

+42
Original file line numberDiff line numberDiff line change
@@ -720,6 +720,22 @@ swift::swift_task_create_group_future(
720720
initialContextSize);
721721
}
722722

723+
#ifdef __ARM_ARCH_7K__
724+
__attribute__((noinline))
725+
SWIFT_CC(swiftasync) static void workaround_function_swift_task_future_waitImpl(
726+
OpaqueValue *result, SWIFT_ASYNC_CONTEXT AsyncContext *callerContext,
727+
AsyncTask *task, TaskContinuationFunction resumeFunction,
728+
AsyncContext *callContext) {
729+
// Make sure we don't eliminate calls to this function.
730+
asm volatile("" // Do nothing.
731+
: // Output list, empty.
732+
: "r"(result), "r"(callerContext), "r"(task) // Input list.
733+
: // Clobber list, empty.
734+
);
735+
return;
736+
}
737+
#endif
738+
723739
SWIFT_CC(swiftasync)
724740
static void swift_task_future_waitImpl(
725741
OpaqueValue *result,
@@ -739,7 +755,12 @@ static void swift_task_future_waitImpl(
739755
result)) {
740756
case FutureFragment::Status::Executing:
741757
// The waiting task has been queued on the future.
758+
#ifdef __ARM_ARCH_7K__
759+
return workaround_function_swift_task_future_waitImpl(
760+
result, callerContext, task, resumeFn, callContext);
761+
#else
742762
return;
763+
#endif
743764

744765
case FutureFragment::Status::Success: {
745766
// Run the task with a successful result.
@@ -754,6 +775,22 @@ static void swift_task_future_waitImpl(
754775
}
755776
}
756777

778+
#ifdef __ARM_ARCH_7K__
779+
__attribute__((noinline))
780+
SWIFT_CC(swiftasync) static void workaround_function_swift_task_future_wait_throwingImpl(
781+
OpaqueValue *result, SWIFT_ASYNC_CONTEXT AsyncContext *callerContext,
782+
AsyncTask *task, ThrowingTaskFutureWaitContinuationFunction resumeFunction,
783+
AsyncContext *callContext) {
784+
// Make sure we don't eliminate calls to this function.
785+
asm volatile("" // Do nothing.
786+
: // Output list, empty.
787+
: "r"(result), "r"(callerContext), "r"(task) // Input list.
788+
: // Clobber list, empty.
789+
);
790+
return;
791+
}
792+
#endif
793+
757794
SWIFT_CC(swiftasync)
758795
void swift_task_future_wait_throwingImpl(
759796
OpaqueValue *result, SWIFT_ASYNC_CONTEXT AsyncContext *callerContext,
@@ -774,7 +811,12 @@ void swift_task_future_wait_throwingImpl(
774811
result)) {
775812
case FutureFragment::Status::Executing:
776813
// The waiting task has been queued on the future.
814+
#ifdef __ARM_ARCH_7K__
815+
return workaround_function_swift_task_future_wait_throwingImpl(
816+
result, callerContext, task, resumeFunction, callContext);
817+
#else
777818
return;
819+
#endif
778820

779821
case FutureFragment::Status::Success: {
780822
auto future = task->futureFragment();

stdlib/public/Concurrency/TaskGroup.cpp

+22
Original file line numberDiff line numberDiff line change
@@ -648,6 +648,23 @@ task_group_wait_resume_adapter(SWIFT_ASYNC_CONTEXT AsyncContext *_context) {
648648
return resumeWithError(context->Parent, context->errorResult);
649649
}
650650

651+
#ifdef __ARM_ARCH_7K__
652+
__attribute__((noinline))
653+
SWIFT_CC(swiftasync) static void workaround_function_swift_taskGroup_wait_next_throwingImpl(
654+
OpaqueValue *result, SWIFT_ASYNC_CONTEXT AsyncContext *callerContext,
655+
TaskGroup *_group,
656+
ThrowingTaskFutureWaitContinuationFunction resumeFunction,
657+
AsyncContext *callContext) {
658+
// Make sure we don't eliminate calls to this function.
659+
asm volatile("" // Do nothing.
660+
: // Output list, empty.
661+
: "r"(result), "r"(callerContext), "r"(_group) // Input list.
662+
: // Clobber list, empty.
663+
);
664+
return;
665+
}
666+
#endif
667+
651668
// =============================================================================
652669
// ==== group.next() implementation (wait_next and groupPoll) ------------------
653670
SWIFT_CC(swiftasync)
@@ -675,7 +692,12 @@ static void swift_taskGroup_wait_next_throwingImpl(
675692
case PollStatus::MustWait:
676693
// The waiting task has been queued on the channel,
677694
// there were pending tasks so it will be woken up eventually.
695+
#ifdef __ARM_ARCH_7K__
696+
return workaround_function_swift_taskGroup_wait_next_throwingImpl(
697+
resultPointer, callerContext, _group, resumeFunction, rawContext);
698+
#else
678699
return;
700+
#endif
679701

680702
case PollStatus::Empty:
681703
case PollStatus::Error:

0 commit comments

Comments
 (0)