@@ -533,6 +533,74 @@ bool DWARFExpression::LinkThreadLocalStorage(
533
533
return true ;
534
534
}
535
535
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
+
536
604
static llvm::Error
537
605
Evaluate_DW_OP_entry_value (std::vector<Value> &stack, const DWARFUnit *dwarf_cu,
538
606
ExecutionContext *exe_ctx, RegisterContext *reg_ctx,
@@ -630,20 +698,19 @@ Evaluate_DW_OP_entry_value(std::vector<Value> &stack, const DWARFUnit *dwarf_cu,
630
698
if (!current_func)
631
699
return llvm::createStringError (" no current function" );
632
700
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
+
633
709
CallEdge *call_edge = nullptr ;
634
710
ModuleList &modlist = target.GetImages ();
635
711
ExecutionContext parent_exe_ctx = *exe_ctx;
636
712
parent_exe_ctx.SetFrameSP (parent_frame);
637
713
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
647
714
648
715
parent_func =
649
716
parent_frame->GetSymbolContext (eSymbolContextFunction).function ;
@@ -678,25 +745,16 @@ Evaluate_DW_OP_entry_value(std::vector<Value> &stack, const DWARFUnit *dwarf_cu,
678
745
if (!call_edge)
679
746
return llvm::createStringError (" no unambiguous edge from parent "
680
747
" to current function" );
681
- #ifdef LLDB_ENABLE_SWIFT
682
- }
683
- #endif
684
748
685
749
// 3. Attempt to locate the DW_OP_entry_value expression in the set of
686
750
// available call site parameters. If found, evaluate the corresponding
687
751
// parameter in the context of the parent frame.
688
752
const uint32_t subexpr_len = opcodes.GetULEB128 (&opcode_offset);
689
- #ifdef LLDB_ENABLE_SWIFT
690
- lldb::offset_t subexpr_offset = opcode_offset;
691
- #endif
692
753
const void *subexpr_data = opcodes.GetData (&opcode_offset, subexpr_len);
693
754
if (!subexpr_data)
694
755
return llvm::createStringError (" subexpr could not be read" );
695
756
696
757
const CallSiteParameter *matched_param = nullptr ;
697
- #ifdef LLDB_ENABLE_SWIFT
698
- if (call_edge) {
699
- #endif
700
758
for (const CallSiteParameter ¶m : call_edge->GetCallSiteParameters ()) {
701
759
DataExtractor param_subexpr_extractor;
702
760
if (!param.LocationInCallee .GetExpressionData (param_subexpr_extractor))
@@ -722,25 +780,10 @@ Evaluate_DW_OP_entry_value(std::vector<Value> &stack, const DWARFUnit *dwarf_cu,
722
780
}
723
781
if (!matched_param)
724
782
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
735
783
736
784
// TODO: Add support for DW_OP_push_object_address within a DW_OP_entry_value
737
785
// subexpresion whenever llvm does.
738
- #ifdef LLDB_ENABLE_SWIFT
739
- const DWARFExpressionList ¶m_expr =
740
- matched_param ? matched_param->LocationInCaller : *subexpr;
741
- #else
742
786
const DWARFExpressionList ¶m_expr = matched_param->LocationInCaller ;
743
- #endif
744
787
745
788
llvm::Expected<Value> maybe_result = param_expr.Evaluate (
746
789
&parent_exe_ctx, parent_frame->GetRegisterContext ().get (),
0 commit comments