@@ -46,15 +46,13 @@ enum class ThunkKind {
4646 ObjCAttribute,
4747 Reabstraction,
4848 ProtocolConformance,
49- AsyncFunction,
5049};
5150
5251enum class ThunkAction {
5352 Unknown = 0 ,
5453 GetThunkTarget,
5554 StepIntoConformance,
5655 StepThrough,
57- AsyncStepIn,
5856};
5957
6058} // namespace
@@ -232,12 +230,8 @@ static ThunkKind GetThunkKind(Symbol *symbol) {
232230 if (nodes->getNumChildren () == 0 )
233231 return ThunkKind::Unknown;
234232
235- if (!demangle_ctx.isThunkSymbol (symbol_name)) {
236- if (IsSwiftAsyncFunctionSymbol (nodes)) {
237- return ThunkKind::AsyncFunction;
238- }
233+ if (!demangle_ctx.isThunkSymbol (symbol_name))
239234 return ThunkKind::Unknown;
240- }
241235
242236 NodePointer main_node = nodes->getFirstChild ();
243237 switch (main_node->getKind ()) {
@@ -276,8 +270,6 @@ static const char *GetThunkKindName(ThunkKind kind) {
276270 return " GetThunkTarget" ;
277271 case ThunkKind::ProtocolConformance:
278272 return " StepIntoConformance" ;
279- case ThunkKind::AsyncFunction:
280- return " AsyncStepIn" ;
281273 }
282274}
283275
@@ -295,220 +287,9 @@ static ThunkAction GetThunkAction(ThunkKind kind) {
295287 return ThunkAction::StepThrough;
296288 case ThunkKind::ProtocolConformance:
297289 return ThunkAction::StepIntoConformance;
298- case ThunkKind::AsyncFunction:
299- return ThunkAction::AsyncStepIn;
300290 }
301291}
302292
303- class ThreadPlanStepInAsync : public ThreadPlan {
304- public:
305- static bool NeedsStep (SymbolContext &sc) {
306- if (sc.line_entry .IsValid () && sc.line_entry .line == 0 )
307- // Compiler generated function, need to step in.
308- return true ;
309-
310- // TEMPORARY HACK WORKAROUND
311- if (!sc.symbol || !sc.comp_unit )
312- return false ;
313- auto fn_start = sc.symbol ->GetFileAddress ();
314- auto fn_end = sc.symbol ->GetFileAddress () + sc.symbol ->GetByteSize ();
315- llvm::SmallSet<uint32_t , 2 > unique_debug_lines;
316- if (auto *line_table = sc.comp_unit ->GetLineTable ()) {
317- for (uint32_t i = 0 ; i < line_table->GetSize (); ++i) {
318- LineEntry line_entry;
319- if (line_table->GetLineEntryAtIndex (i, line_entry)) {
320- if (!line_entry.IsValid () || line_entry.line == 0 )
321- continue ;
322-
323- auto line_start = line_entry.range .GetBaseAddress ().GetFileAddress ();
324- if (fn_start <= line_start && line_start < fn_end) {
325- unique_debug_lines.insert (line_entry.line );
326- // This logic is to distinguish between async functions that only
327- // call `swift_task_switch` (which, from the perspective of the
328- // user, has no meaningful function body), vs async functions that
329- // do have a function body. In the first case, lldb should step
330- // further to find the function body, in the second case lldb has
331- // found a body and should stop.
332- //
333- // Currently, async functions that go through `swift_task_switch`
334- // are generated with a reference to a single line. If this function
335- // has more than one unique debug line, then it is a function that
336- // has a body, and execution can stop here.
337- if (unique_debug_lines.size () >= 2 )
338- // No step into `swift_task_switch` required.
339- return false ;
340- }
341- }
342- }
343- }
344-
345- return true ;
346- }
347-
348- ThreadPlanStepInAsync (Thread &thread, SymbolContext &sc)
349- : ThreadPlan(eKindGeneric, " step-in-async" , thread, eVoteNoOpinion,
350- eVoteNoOpinion) {
351- assert (sc.function );
352- if (!sc.function )
353- return ;
354-
355- m_step_in_plan_sp = std::make_shared<ThreadPlanStepInRange>(
356- thread, sc.function ->GetAddressRange (), sc, " swift_task_switch" ,
357- RunMode::eAllThreads, eLazyBoolNo, eLazyBoolNo);
358- }
359-
360- void DidPush () override {
361- if (m_step_in_plan_sp)
362- PushPlan (m_step_in_plan_sp);
363- }
364-
365- bool ValidatePlan (Stream *error) override { return (bool )m_step_in_plan_sp; }
366-
367- void GetDescription (Stream *s, lldb::DescriptionLevel level) override {
368- // TODO: Implement completely.
369- s->PutCString (" ThreadPlanStepInAsync" );
370- }
371-
372- bool DoPlanExplainsStop (Event *event) override {
373- if (!HasTID ())
374- return false ;
375-
376- if (!m_async_breakpoint_sp)
377- return false ;
378-
379- return GetBreakpointAsyncContext () == m_initial_async_ctx;
380- }
381-
382- bool ShouldStop (Event *event) override {
383- if (!m_async_breakpoint_sp)
384- return false ;
385-
386- if (GetBreakpointAsyncContext () != m_initial_async_ctx)
387- return false ;
388-
389- SetPlanComplete ();
390- return true ;
391- }
392-
393- bool MischiefManaged () override {
394- if (IsPlanComplete ())
395- return true ;
396-
397- if (!m_step_in_plan_sp->IsPlanComplete ())
398- return false ;
399-
400- if (!m_step_in_plan_sp->PlanSucceeded ()) {
401- // If the step in fails, then this plan fails.
402- SetPlanComplete (false );
403- return true ;
404- }
405-
406- if (!m_async_breakpoint_sp) {
407- auto &thread = GetThread ();
408- m_async_breakpoint_sp = CreateAsyncBreakpoint (thread);
409- m_initial_async_ctx = GetAsyncContext (thread.GetStackFrameAtIndex (1 ));
410- ClearTID ();
411- }
412-
413- return false ;
414- }
415-
416- bool WillStop () override { return false ; }
417-
418- lldb::StateType GetPlanRunState () override { return eStateRunning; }
419-
420- bool StopOthers () override { return false ; }
421-
422- void DidPop () override {
423- if (m_async_breakpoint_sp)
424- m_async_breakpoint_sp->GetTarget ().RemoveBreakpointByID (
425- m_async_breakpoint_sp->GetID ());
426- }
427-
428- private:
429- bool IsAtAsyncBreakpoint () {
430- auto stop_info_sp = GetPrivateStopInfo ();
431- if (!stop_info_sp)
432- return false ;
433-
434- if (stop_info_sp->GetStopReason () != eStopReasonBreakpoint)
435- return false ;
436-
437- auto &site_list = m_process.GetBreakpointSiteList ();
438- auto site_sp = site_list.FindByID (stop_info_sp->GetValue ());
439- if (!site_sp)
440- return false ;
441-
442- return site_sp->IsBreakpointAtThisSite (m_async_breakpoint_sp->GetID ());
443- }
444-
445- std::optional<lldb::addr_t > GetBreakpointAsyncContext () {
446- if (m_breakpoint_async_ctx)
447- return m_breakpoint_async_ctx;
448-
449- if (!IsAtAsyncBreakpoint ())
450- return {};
451-
452- auto frame_sp = GetThread ().GetStackFrameAtIndex (0 );
453- auto async_ctx = GetAsyncContext (frame_sp);
454-
455- if (!IsIndirectContext (frame_sp)) {
456- m_breakpoint_async_ctx = async_ctx;
457- return m_breakpoint_async_ctx;
458- }
459-
460- // Dereference the indirect async context.
461- auto process_sp = GetThread ().GetProcess ();
462- Status error;
463- m_breakpoint_async_ctx =
464- process_sp->ReadPointerFromMemory (async_ctx, error);
465- return m_breakpoint_async_ctx;
466- }
467-
468- bool IsIndirectContext (lldb::StackFrameSP frame_sp) {
469- auto sc = frame_sp->GetSymbolContext (eSymbolContextSymbol);
470- auto mangled_name = sc.symbol ->GetMangled ().GetMangledName ().GetStringRef ();
471- return SwiftLanguageRuntime::IsSwiftAsyncAwaitResumePartialFunctionSymbol (
472- mangled_name);
473- }
474-
475- BreakpointSP CreateAsyncBreakpoint (Thread &thread) {
476- // The signature for `swift_task_switch` is as follows:
477- // SWIFT_CC(swiftasync)
478- // void swift_task_switch(
479- // SWIFT_ASYNC_CONTEXT AsyncContext *resumeContext,
480- // TaskContinuationFunction *resumeFunction,
481- // ExecutorRef newExecutor);
482- //
483- // The async context given as the first argument is not passed using the
484- // calling convention's first register, it's passed in the platform's async
485- // context register. This means the `resumeFunction` parameter uses the
486- // first ABI register (ex: x86-64: rdi, arm64: x0).
487- auto reg_ctx = thread.GetStackFrameAtIndex (0 )->GetRegisterContext ();
488- constexpr auto resume_fn_regnum = LLDB_REGNUM_GENERIC_ARG1;
489- auto resume_fn_reg = reg_ctx->ConvertRegisterKindToRegisterNumber (
490- RegisterKind::eRegisterKindGeneric, resume_fn_regnum);
491- auto resume_fn_ptr = reg_ctx->ReadRegisterAsUnsigned (resume_fn_reg, 0 );
492- if (!resume_fn_ptr)
493- return {};
494-
495- auto &target = thread.GetProcess ()->GetTarget ();
496- auto breakpoint_sp = target.CreateBreakpoint (resume_fn_ptr, true , false );
497- breakpoint_sp->SetBreakpointKind (" async-step" );
498- return breakpoint_sp;
499- }
500-
501- static lldb::addr_t GetAsyncContext (lldb::StackFrameSP frame_sp) {
502- auto reg_ctx_sp = frame_sp->GetRegisterContext ();
503- return SwiftLanguageRuntime::GetAsyncContext (reg_ctx_sp.get ());
504- }
505-
506- ThreadPlanSP m_step_in_plan_sp;
507- BreakpointSP m_async_breakpoint_sp;
508- std::optional<lldb::addr_t > m_initial_async_ctx;
509- std::optional<lldb::addr_t > m_breakpoint_async_ctx;
510- };
511-
512293static lldb::ThreadPlanSP GetStepThroughTrampolinePlan (Thread &thread,
513294 bool stop_others) {
514295 // Here are the trampolines we have at present.
@@ -546,10 +327,6 @@ static lldb::ThreadPlanSP GetStepThroughTrampolinePlan(Thread &thread,
546327 switch (thunk_action) {
547328 case ThunkAction::Unknown:
548329 return nullptr ;
549- case ThunkAction::AsyncStepIn:
550- if (ThreadPlanStepInAsync::NeedsStep (sc))
551- return std::make_shared<ThreadPlanStepInAsync>(thread, sc);
552- return nullptr ;
553330 case ThunkAction::GetThunkTarget: {
554331 swift::Demangle::Context demangle_ctx;
555332 std::string thunk_target = demangle_ctx.getThunkTarget (symbol_name);
0 commit comments