@@ -490,9 +490,11 @@ static bool SetSizedFloat(Scalar &scalar, uint64_t raw_value,
490490static ValueObjectSP GetValObjFromIntRegs (Thread &thread,
491491 const RegisterContextSP ®_ctx,
492492 llvm::Triple::ArchType machine,
493- uint32_t type_flags ,
493+ const CompilerType &compiler_type ,
494494 uint32_t byte_size) {
495495 Value value;
496+ value.SetCompilerType (compiler_type);
497+
496498 ValueObjectSP return_valobj_sp;
497499 auto reg_info_a0 =
498500 reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1);
@@ -545,11 +547,11 @@ static ValueObjectSP GetValObjFromIntRegs(Thread &thread,
545547 return return_valobj_sp;
546548 }
547549
548- if (type_flags & eTypeIsInteger ) {
549- const bool is_signed = (type_flags & eTypeIsSigned) != 0 ;
550+ if (compiler_type. IsInteger () ) {
551+ const bool is_signed = compiler_type. IsSigned () ;
550552 if (!SetSizedInteger (value.GetScalar (), raw_value, byte_size, is_signed))
551553 return return_valobj_sp;
552- } else if (type_flags & eTypeIsFloat ) {
554+ } else if (compiler_type. IsFloat () ) {
553555 if (!SetSizedFloat (value.GetScalar (), raw_value, byte_size))
554556 return return_valobj_sp;
555557 } else
@@ -564,16 +566,16 @@ static ValueObjectSP GetValObjFromIntRegs(Thread &thread,
564566static ValueObjectSP
565567GetValObjFromFPRegs (Thread &thread, const RegisterContextSP ®_ctx,
566568 llvm::Triple::ArchType machine, uint32_t arch_fp_flags,
567- uint32_t type_flags , uint32_t byte_size) {
569+ CompilerType &compiler_type , uint32_t byte_size) {
568570 auto reg_info_fa0 = reg_ctx->GetRegisterInfoByName (" fa0" );
569571 bool use_fp_regs = false ;
570572 ValueObjectSP return_valobj_sp;
571573
572574 switch (arch_fp_flags) {
573575 // fp return value in integer registers a0 and possibly a1
574576 case ArchSpec::eRISCV_float_abi_soft:
575- return_valobj_sp =
576- GetValObjFromIntRegs (thread, reg_ctx, machine, type_flags , byte_size);
577+ return_valobj_sp = GetValObjFromIntRegs (thread, reg_ctx, machine,
578+ compiler_type , byte_size);
577579 return return_valobj_sp;
578580 // fp return value in fp register fa0 (only float)
579581 case ArchSpec::eRISCV_float_abi_single:
@@ -602,7 +604,102 @@ GetValObjFromFPRegs(Thread &thread, const RegisterContextSP ®_ctx,
602604 value, ConstString (" " ));
603605 }
604606 // we should never reach this, but if we do, use the integer registers
605- return GetValObjFromIntRegs (thread, reg_ctx, machine, type_flags, byte_size);
607+ return GetValObjFromIntRegs (thread, reg_ctx, machine, compiler_type,
608+ byte_size);
609+ }
610+
611+ static DataExtractor CopyReturnValueToBuffer (ExecutionContext &exe_ctx,
612+ RegisterValue &a0_reg_value,
613+ RegisterValue &a1_reg_value,
614+ const size_t xlen_byte_size,
615+ const uint32_t byte_size) {
616+
617+ DataExtractor a0_extractor;
618+ DataExtractor a1_extractor;
619+
620+ // RISC-V ABI states:
621+ // "Aggregates whose total size is no more than XLEN bits
622+ // are passed in a register, with the fields laid out as though
623+ // they were passed in memory."
624+ if (byte_size <= xlen_byte_size) {
625+ // value is stored only in a0
626+ a0_reg_value.GetData (a0_extractor);
627+ // shrink data to the size of the return value
628+ return DataExtractor{a0_extractor, /* offset=*/ 0 , byte_size};
629+ }
630+
631+ // "Aggregates whose total size is no more than 2×XLEN bits
632+ // are passed in a pair of registers;"
633+ if (byte_size <= 2 * xlen_byte_size) {
634+ // value is stored in a0 and a1 consecutively
635+ a0_reg_value.GetData (a0_extractor);
636+ a1_reg_value.GetData (a1_extractor);
637+ a0_extractor.Append (a1_extractor);
638+ // shrink data to the size of the return value
639+ return DataExtractor{a0_extractor, /* offset=*/ 0 , byte_size};
640+ }
641+
642+ // "Aggregates larger than 2×XLEN bits are passed by reference
643+ // and are replaced in the argument list with the address"
644+ const lldb::addr_t value_addr =
645+ a1_reg_value.GetAsUInt64 (LLDB_INVALID_ADDRESS, nullptr );
646+
647+ if (value_addr == LLDB_INVALID_ADDRESS)
648+ return DataExtractor{};
649+
650+ Status error;
651+ WritableDataBufferSP data_sp (new DataBufferHeap (byte_size, 0 ));
652+ if (exe_ctx.GetProcessRef ().ReadMemory (value_addr, data_sp->GetBytes (),
653+ byte_size, error) != byte_size ||
654+ error.Fail ())
655+ return DataExtractor{};
656+
657+ DataExtractor data;
658+ data.SetData (data_sp);
659+ return data;
660+ }
661+
662+ static ValueObjectSP GetAggregateObj (Thread &thread, RegisterContextSP reg_ctx,
663+ const CompilerType &compiler_type,
664+ const size_t xlen_byte_size,
665+ const uint32_t byte_size) {
666+ const RegisterInfo *a0_reg_info =
667+ reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1);
668+
669+ const RegisterInfo *a1_reg_info =
670+ reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG2);
671+
672+ if (!a0_reg_info || !a1_reg_info)
673+ return ValueObjectSP{};
674+
675+ RegisterValue a0_reg_value;
676+ RegisterValue a1_reg_value;
677+
678+ if (!reg_ctx->ReadRegister (a0_reg_info, a0_reg_value) ||
679+ !reg_ctx->ReadRegister (a1_reg_info, a1_reg_value))
680+ return ValueObjectSP{};
681+
682+ if (a0_reg_value.GetType () == RegisterValue::Type::eTypeInvalid ||
683+ a1_reg_value.GetType () == RegisterValue::Type::eTypeInvalid)
684+ return ValueObjectSP{};
685+
686+ ExecutionContext exe_ctx (thread.shared_from_this ());
687+ DataExtractor data = CopyReturnValueToBuffer (
688+ exe_ctx, a0_reg_value, a1_reg_value, xlen_byte_size, byte_size);
689+
690+ if (data.GetByteSize () != byte_size)
691+ return ValueObjectSP{};
692+
693+ const ByteOrder byte_order = exe_ctx.GetProcessRef ().GetByteOrder ();
694+ const uint32_t address_byte_size =
695+ exe_ctx.GetProcessRef ().GetAddressByteSize ();
696+ data.SetByteOrder (byte_order);
697+ data.SetAddressByteSize (address_byte_size);
698+
699+ ValueObjectSP return_valobj_sp =
700+ ValueObjectConstResult::Create (thread.GetStackFrameAtIndex (0 ).get (),
701+ compiler_type, ConstString (" " ), data);
702+ return return_valobj_sp;
606703}
607704
608705ValueObjectSP
@@ -617,23 +714,21 @@ ABISysV_riscv::GetReturnValueObjectSimple(Thread &thread,
617714 if (!reg_ctx)
618715 return return_valobj_sp;
619716
620- Value value;
621- value.SetCompilerType (compiler_type);
622-
623- const uint32_t type_flags = compiler_type.GetTypeInfo ();
624717 const size_t byte_size =
625718 llvm::expectedToOptional (compiler_type.GetByteSize (&thread)).value_or (0 );
626719 const ArchSpec arch = thread.GetProcess ()->GetTarget ().GetArchitecture ();
627720 const llvm::Triple::ArchType machine = arch.GetMachine ();
628721
629722 // Integer return type.
630- if (type_flags & eTypeIsInteger ) {
631- return_valobj_sp =
632- GetValObjFromIntRegs (thread, reg_ctx, machine, type_flags , byte_size);
723+ if (compiler_type. IsInteger () ) {
724+ return_valobj_sp = GetValObjFromIntRegs (thread, reg_ctx, machine,
725+ compiler_type , byte_size);
633726 return return_valobj_sp;
634727 }
635728 // Pointer return type.
636- else if (type_flags & eTypeIsPointer) {
729+ if (compiler_type.IsPointerType ()) {
730+ Value value;
731+ value.SetCompilerType (compiler_type);
637732 auto reg_info_a0 = reg_ctx->GetRegisterInfo (eRegisterKindGeneric,
638733 LLDB_REGNUM_GENERIC_ARG1);
639734 value.GetScalar () = reg_ctx->ReadRegisterAsUnsigned (reg_info_a0, 0 );
@@ -642,7 +737,7 @@ ABISysV_riscv::GetReturnValueObjectSimple(Thread &thread,
642737 value, ConstString (" " ));
643738 }
644739 // Floating point return type.
645- else if (type_flags & eTypeIsFloat ) {
740+ if (compiler_type. IsFloat () ) {
646741 uint32_t float_count = 0 ;
647742 bool is_complex = false ;
648743
@@ -651,58 +746,16 @@ ABISysV_riscv::GetReturnValueObjectSimple(Thread &thread,
651746 const uint32_t arch_fp_flags =
652747 arch.GetFlags () & ArchSpec::eRISCV_float_abi_mask;
653748 return_valobj_sp = GetValObjFromFPRegs (
654- thread, reg_ctx, machine, arch_fp_flags, type_flags , byte_size);
749+ thread, reg_ctx, machine, arch_fp_flags, compiler_type , byte_size);
655750 return return_valobj_sp;
656751 }
657752 }
658- // Unsupported return type.
659- return return_valobj_sp;
660- }
661-
662- ValueObjectSP
663- ABISysV_riscv::GetReturnValueObjectImpl (lldb_private::Thread &thread,
664- llvm::Type &type) const {
665- Value value;
666- ValueObjectSP return_valobj_sp;
667-
668- auto reg_ctx = thread.GetRegisterContext ();
669- if (!reg_ctx)
670- return return_valobj_sp;
671-
672- uint32_t type_flags = 0 ;
673- if (type.isIntegerTy ())
674- type_flags = eTypeIsInteger;
675- else if (type.isVoidTy ())
676- type_flags = eTypeIsPointer;
677- else if (type.isFloatTy ())
678- type_flags = eTypeIsFloat;
679-
680- const uint32_t byte_size = type.getPrimitiveSizeInBits () / CHAR_BIT;
681- const ArchSpec arch = thread.GetProcess ()->GetTarget ().GetArchitecture ();
682- const llvm::Triple::ArchType machine = arch.GetMachine ();
753+ // Aggregate return type
754+ if (compiler_type.IsAggregateType ()) {
755+ size_t xlen_byte_size = m_is_rv64 ? 8 : 4 ;
683756
684- // Integer return type.
685- if (type_flags & eTypeIsInteger) {
686- return_valobj_sp =
687- GetValObjFromIntRegs (thread, reg_ctx, machine, type_flags, byte_size);
688- return return_valobj_sp;
689- }
690- // Pointer return type.
691- else if (type_flags & eTypeIsPointer) {
692- auto reg_info_a0 = reg_ctx->GetRegisterInfo (eRegisterKindGeneric,
693- LLDB_REGNUM_GENERIC_ARG1);
694- value.GetScalar () = reg_ctx->ReadRegisterAsUnsigned (reg_info_a0, 0 );
695- value.SetValueType (Value::ValueType::Scalar);
696- return ValueObjectConstResult::Create (thread.GetStackFrameAtIndex (0 ).get (),
697- value, ConstString (" " ));
698- }
699- // Floating point return type.
700- else if (type_flags & eTypeIsFloat) {
701- const uint32_t arch_fp_flags =
702- arch.GetFlags () & ArchSpec::eRISCV_float_abi_mask;
703- return_valobj_sp = GetValObjFromFPRegs (
704- thread, reg_ctx, machine, arch_fp_flags, type_flags, byte_size);
705- return return_valobj_sp;
757+ return GetAggregateObj (thread, reg_ctx, compiler_type, xlen_byte_size,
758+ byte_size);
706759 }
707760 // Unsupported return type.
708761 return return_valobj_sp;
0 commit comments