@@ -533,6 +533,74 @@ bool DWARFExpression::LinkThreadLocalStorage(
533533 return true ;
534534}
535535
536+ // / Returns true if \c opcodes contains the opcode for the register used for the
537+ // / Swift Async Context (x22 for aarch64, r14 for x86-64). It must also not
538+ // / contain any other opcodes.
539+ static bool IsAsyncRegCtxExpr (DataExtractor &opcodes,
540+ llvm::Triple::ArchType triple) {
541+ offset_t offset = 0 ;
542+ const uint8_t op_async_ctx_reg = opcodes.GetU8 (&offset);
543+ if (opcodes.BytesLeft (offset) != 0 )
544+ return false ;
545+
546+ // FIXME: could this be exposed through the ABI/Language plugins?
547+ return (triple == llvm::Triple::x86_64 && op_async_ctx_reg == DW_OP_reg14) ||
548+ (triple == llvm::Triple::aarch64 && op_async_ctx_reg == DW_OP_reg22);
549+ }
550+
551+ // / If \c opcodes contain the location of asynchronous contexts in Swift,
552+ // / evaluates DW_OP_call_frame_cfa, returns its result, and updates
553+ // / \c current_offset. Otherwise, does nothing. This is possible because, for
554+ // / async frames, the language unwinder treats the asynchronous context as the
555+ // / CFA of the frame.
556+ static llvm::Expected<Value> SwiftAsyncEvaluate_DW_OP_entry_value (
557+ ExecutionContext &exe_ctx, StackFrame ¤t_frame,
558+ const DWARFUnit *dwarf_cu, Function &func, const DataExtractor &opcodes,
559+ offset_t ¤t_offset) {
560+ auto func_name = func.GetMangled ().GetMangledName ();
561+ if (!SwiftLanguageRuntime::IsAnySwiftAsyncFunctionSymbol (func_name))
562+ return llvm::createStringError (
563+ " SwiftAsyncEvaluate_DW_OP_entry_value: not an async function" );
564+
565+ offset_t new_offset = current_offset;
566+ const uint32_t subexpr_len = opcodes.GetULEB128 (&new_offset);
567+ const void *subexpr_data = opcodes.GetData (&new_offset, subexpr_len);
568+ if (!subexpr_data)
569+ return llvm::createStringError (
570+ " SwiftAsyncEvaluate_DW_OP_entry_value: failed to extract subexpr" );
571+
572+ DataExtractor subexpr_extractor (
573+ subexpr_data, subexpr_len, opcodes.GetByteOrder (),
574+ opcodes.GetAddressByteSize (), opcodes.getTargetByteSize ());
575+ if (!IsAsyncRegCtxExpr (subexpr_extractor,
576+ exe_ctx.GetTargetRef ().GetArchitecture ().GetMachine ()))
577+ return llvm::createStringError (" SwiftAsyncEvaluate_DW_OP_entry_value: "
578+ " missing async context register opcode" );
579+
580+ // Q funclets require an extra level of indirection.
581+ if (SwiftLanguageRuntime::IsSwiftAsyncAwaitResumePartialFunctionSymbol (
582+ func_name)) {
583+ const uint8_t maybe_op_deref = opcodes.GetU8 (&new_offset);
584+ if (maybe_op_deref != DW_OP_deref)
585+ return llvm::createStringError (" SwiftAsyncEvaluate_DW_OP_entry_value: "
586+ " missing DW_OP_deref in Q funclet" );
587+ }
588+
589+ static const uint8_t cfa_opcode = DW_OP_call_frame_cfa;
590+ DataExtractor cfa_expr_data (&cfa_opcode, 1 , opcodes.GetByteOrder (),
591+ opcodes.GetAddressByteSize (),
592+ opcodes.getTargetByteSize ());
593+ DWARFExpressionList cfa_expr (func.CalculateSymbolContextModule (),
594+ cfa_expr_data, dwarf_cu);
595+ llvm::Expected<Value> maybe_result = cfa_expr.Evaluate (
596+ &exe_ctx, current_frame.GetRegisterContext ().get (), LLDB_INVALID_ADDRESS,
597+ /* initial_value_ptr=*/ nullptr ,
598+ /* object_address_ptr=*/ nullptr );
599+ if (maybe_result)
600+ current_offset = new_offset;
601+ return maybe_result;
602+ }
603+
536604static llvm::Error
537605Evaluate_DW_OP_entry_value (std::vector<Value> &stack, const DWARFUnit *dwarf_cu,
538606 ExecutionContext *exe_ctx, RegisterContext *reg_ctx,
@@ -630,20 +698,19 @@ Evaluate_DW_OP_entry_value(std::vector<Value> &stack, const DWARFUnit *dwarf_cu,
630698 if (!current_func)
631699 return llvm::createStringError (" no current function" );
632700
701+ if (llvm::Expected<Value> result = SwiftAsyncEvaluate_DW_OP_entry_value (
702+ *exe_ctx, *current_frame, dwarf_cu, *current_func, opcodes,
703+ opcode_offset)) {
704+ stack.push_back (*result);
705+ return llvm::Error::success ();
706+ } else
707+ LLDB_LOG_ERROR (log, result.takeError (), " {0}" );
708+
633709 CallEdge *call_edge = nullptr ;
634710 ModuleList &modlist = target.GetImages ();
635711 ExecutionContext parent_exe_ctx = *exe_ctx;
636712 parent_exe_ctx.SetFrameSP (parent_frame);
637713 Function *parent_func = nullptr ;
638- #ifdef LLDB_ENABLE_SWIFT
639- // Swift async function arguments are represented relative to a
640- // DW_OP_entry_value that fetches the async context register. This
641- // register is known to the unwinder and can always be restored
642- // therefore it is not necessary to match up a call site parameter
643- // with it.
644- auto fn_name = current_func->GetMangled ().GetMangledName ().GetStringRef ();
645- if (!SwiftLanguageRuntime::IsAnySwiftAsyncFunctionSymbol (fn_name)) {
646- #endif
647714
648715 parent_func =
649716 parent_frame->GetSymbolContext (eSymbolContextFunction).function ;
@@ -678,25 +745,16 @@ Evaluate_DW_OP_entry_value(std::vector<Value> &stack, const DWARFUnit *dwarf_cu,
678745 if (!call_edge)
679746 return llvm::createStringError (" no unambiguous edge from parent "
680747 " to current function" );
681- #ifdef LLDB_ENABLE_SWIFT
682- }
683- #endif
684748
685749 // 3. Attempt to locate the DW_OP_entry_value expression in the set of
686750 // available call site parameters. If found, evaluate the corresponding
687751 // parameter in the context of the parent frame.
688752 const uint32_t subexpr_len = opcodes.GetULEB128 (&opcode_offset);
689- #ifdef LLDB_ENABLE_SWIFT
690- lldb::offset_t subexpr_offset = opcode_offset;
691- #endif
692753 const void *subexpr_data = opcodes.GetData (&opcode_offset, subexpr_len);
693754 if (!subexpr_data)
694755 return llvm::createStringError (" subexpr could not be read" );
695756
696757 const CallSiteParameter *matched_param = nullptr ;
697- #ifdef LLDB_ENABLE_SWIFT
698- if (call_edge) {
699- #endif
700758 for (const CallSiteParameter ¶m : call_edge->GetCallSiteParameters ()) {
701759 DataExtractor param_subexpr_extractor;
702760 if (!param.LocationInCallee .GetExpressionData (param_subexpr_extractor))
@@ -722,25 +780,10 @@ Evaluate_DW_OP_entry_value(std::vector<Value> &stack, const DWARFUnit *dwarf_cu,
722780 }
723781 if (!matched_param)
724782 return llvm::createStringError (" no matching call site param found" );
725- #ifdef LLDB_ENABLE_SWIFT
726- }
727- std::optional<DWARFExpressionList> subexpr;
728- if (!matched_param) {
729- auto *ctx_func = parent_func ? parent_func : current_func;
730- subexpr.emplace (ctx_func->CalculateSymbolContextModule (),
731- DataExtractor (opcodes, subexpr_offset, subexpr_len),
732- dwarf_cu);
733- }
734- #endif
735783
736784 // TODO: Add support for DW_OP_push_object_address within a DW_OP_entry_value
737785 // subexpresion whenever llvm does.
738- #ifdef LLDB_ENABLE_SWIFT
739- const DWARFExpressionList ¶m_expr =
740- matched_param ? matched_param->LocationInCaller : *subexpr;
741- #else
742786 const DWARFExpressionList ¶m_expr = matched_param->LocationInCaller ;
743- #endif
744787
745788 llvm::Expected<Value> maybe_result = param_expr.Evaluate (
746789 &parent_exe_ctx, parent_frame->GetRegisterContext ().get (),
0 commit comments