@@ -361,23 +361,13 @@ class ThreadPlanRunToAddressOnAsyncCtx : public ThreadPlan {
361361
362362// / Given a thread that is stopped at the start of swift_task_switch, create a
363363// / thread plan that runs to the address of the resume function.
364- static ThreadPlanSP CreateRunThroughTaskSwitchThreadPlan (Thread &thread) {
365- // The signature for `swift_task_switch` is as follows:
366- // SWIFT_CC(swiftasync)
367- // void swift_task_switch(
368- // SWIFT_ASYNC_CONTEXT AsyncContext *resumeContext,
369- // TaskContinuationFunction *resumeFunction,
370- // ExecutorRef newExecutor);
371- //
372- // The async context given as the first argument is not passed using the
373- // calling convention's first register, it's passed in the platform's async
374- // context register. This means the `resumeFunction` parameter uses the
375- // first ABI register (ex: x86-64: rdi, arm64: x0).
364+ static ThreadPlanSP
365+ CreateRunThroughTaskSwitchThreadPlan (Thread &thread,
366+ unsigned resume_fn_generic_regnum) {
376367 RegisterContextSP reg_ctx =
377368 thread.GetStackFrameAtIndex (0 )->GetRegisterContext ();
378- constexpr unsigned resume_fn_regnum = LLDB_REGNUM_GENERIC_ARG1;
379369 unsigned resume_fn_reg = reg_ctx->ConvertRegisterKindToRegisterNumber (
380- RegisterKind::eRegisterKindGeneric, resume_fn_regnum );
370+ RegisterKind::eRegisterKindGeneric, resume_fn_generic_regnum );
381371 uint64_t resume_fn_ptr = reg_ctx->ReadRegisterAsUnsigned (resume_fn_reg, 0 );
382372 if (!resume_fn_ptr)
383373 return {};
@@ -397,6 +387,41 @@ static ThreadPlanSP CreateRunThroughTaskSwitchThreadPlan(Thread &thread) {
397387 thread, resume_fn_ptr, async_ctx);
398388}
399389
390+ // / Creates a thread plan to step over swift runtime functions that can trigger
391+ // / a task switch, like `async_task_switch` or `swift_asyncLet_get`.
392+ static ThreadPlanSP
393+ CreateRunThroughTaskSwitchingTrampolines (Thread &thread,
394+ StringRef trampoline_name) {
395+ // The signature for `swift_task_switch` is as follows:
396+ // SWIFT_CC(swiftasync)
397+ // void swift_task_switch(
398+ // SWIFT_ASYNC_CONTEXT AsyncContext *resumeContext,
399+ // TaskContinuationFunction *resumeFunction,
400+ // ExecutorRef newExecutor);
401+ //
402+ // The async context given as the first argument is not passed using the
403+ // calling convention's first register, it's passed in the platform's async
404+ // context register. This means the `resumeFunction` parameter uses the
405+ // first ABI register (ex: x86-64: rdi, arm64: x0).
406+ if (trampoline_name == " swift_task_switch" )
407+ return CreateRunThroughTaskSwitchThreadPlan (thread,
408+ LLDB_REGNUM_GENERIC_ARG1);
409+ // The signature for `swift_asyncLet_get` and `swift_asyncLet_finish` are the
410+ // same. Like `task_switch`, the async context (first argument) uses the async
411+ // context register, and not the arg1 register; as such, the continuation
412+ // funclet can be found in arg3.
413+ //
414+ // swift_asyncLet_get(SWIFT_ASYNC_CONTEXT AsyncContext *,
415+ // AsyncLet *,
416+ // void *,
417+ // TaskContinuationFunction *,
418+ if (trampoline_name == " swift_asyncLet_get" ||
419+ trampoline_name == " swift_asyncLet_finish" )
420+ return CreateRunThroughTaskSwitchThreadPlan (thread,
421+ LLDB_REGNUM_GENERIC_ARG3);
422+ return nullptr ;
423+ }
424+
400425static lldb::ThreadPlanSP GetStepThroughTrampolinePlan (Thread &thread,
401426 bool stop_others) {
402427 // Here are the trampolines we have at present.
@@ -429,8 +454,9 @@ static lldb::ThreadPlanSP GetStepThroughTrampolinePlan(Thread &thread,
429454 Mangled &mangled_symbol_name = symbol->GetMangled ();
430455 const char *symbol_name = mangled_symbol_name.GetMangledName ().AsCString ();
431456
432- if (mangled_symbol_name.GetDemangledName () == " swift_task_switch" )
433- return CreateRunThroughTaskSwitchThreadPlan (thread);
457+ if (ThreadPlanSP thread_plan = CreateRunThroughTaskSwitchingTrampolines (
458+ thread, mangled_symbol_name.GetDemangledName ()))
459+ return thread_plan;
434460
435461 ThunkKind thunk_kind = GetThunkKind (symbol);
436462 ThunkAction thunk_action = GetThunkAction (thunk_kind);
0 commit comments