1 //===-- ABISysV_mips64.cpp ------------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "ABISysV_mips64.h"
11 #include "llvm/ADT/STLExtras.h"
12 #include "llvm/TargetParser/Triple.h"
14 #include "lldb/Core/Module.h"
15 #include "lldb/Core/PluginManager.h"
16 #include "lldb/Core/Value.h"
17 #include "lldb/Core/ValueObjectConstResult.h"
18 #include "lldb/Core/ValueObjectMemory.h"
19 #include "lldb/Core/ValueObjectRegister.h"
20 #include "lldb/Symbol/UnwindPlan.h"
21 #include "lldb/Target/Process.h"
22 #include "lldb/Target/RegisterContext.h"
23 #include "lldb/Target/StackFrame.h"
24 #include "lldb/Target/Target.h"
25 #include "lldb/Target/Thread.h"
26 #include "lldb/Utility/ConstString.h"
27 #include "lldb/Utility/DataExtractor.h"
28 #include "lldb/Utility/LLDBLog.h"
29 #include "lldb/Utility/Log.h"
30 #include "lldb/Utility/RegisterValue.h"
31 #include "lldb/Utility/Status.h"
35 using namespace lldb_private
;
37 LLDB_PLUGIN_DEFINE(ABISysV_mips64
)
80 static const RegisterInfo g_register_infos_mips64
[] = {
81 // NAME ALT SZ OFF ENCODING FORMAT EH_FRAME
82 // DWARF GENERIC PROCESS PLUGIN
84 // ======== ====== == === ============= ========== =============
85 // ================= ==================== =================
86 // ====================
93 {dwarf_r0
, dwarf_r0
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
105 {dwarf_r1
, dwarf_r1
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
106 LLDB_INVALID_REGNUM
},
118 {dwarf_r2
, dwarf_r2
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
119 LLDB_INVALID_REGNUM
},
130 {dwarf_r3
, dwarf_r3
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
131 LLDB_INVALID_REGNUM
},
142 {dwarf_r4
, dwarf_r4
, LLDB_REGNUM_GENERIC_ARG1
, LLDB_INVALID_REGNUM
,
143 LLDB_INVALID_REGNUM
},
154 {dwarf_r5
, dwarf_r5
, LLDB_REGNUM_GENERIC_ARG2
, LLDB_INVALID_REGNUM
,
155 LLDB_INVALID_REGNUM
},
166 {dwarf_r6
, dwarf_r6
, LLDB_REGNUM_GENERIC_ARG3
, LLDB_INVALID_REGNUM
,
167 LLDB_INVALID_REGNUM
},
178 {dwarf_r7
, dwarf_r7
, LLDB_REGNUM_GENERIC_ARG4
, LLDB_INVALID_REGNUM
,
179 LLDB_INVALID_REGNUM
},
190 {dwarf_r8
, dwarf_r8
, LLDB_REGNUM_GENERIC_ARG5
, LLDB_INVALID_REGNUM
,
191 LLDB_INVALID_REGNUM
},
202 {dwarf_r9
, dwarf_r9
, LLDB_REGNUM_GENERIC_ARG6
, LLDB_INVALID_REGNUM
,
203 LLDB_INVALID_REGNUM
},
214 {dwarf_r10
, dwarf_r10
, LLDB_REGNUM_GENERIC_ARG7
, LLDB_INVALID_REGNUM
,
215 LLDB_INVALID_REGNUM
},
226 {dwarf_r11
, dwarf_r11
, LLDB_REGNUM_GENERIC_ARG8
, LLDB_INVALID_REGNUM
,
227 LLDB_INVALID_REGNUM
},
238 {dwarf_r12
, dwarf_r12
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
239 LLDB_INVALID_REGNUM
},
250 {dwarf_r13
, dwarf_r13
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
251 LLDB_INVALID_REGNUM
},
262 {dwarf_r14
, dwarf_r14
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
263 LLDB_INVALID_REGNUM
},
274 {dwarf_r15
, dwarf_r15
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
275 LLDB_INVALID_REGNUM
},
286 {dwarf_r16
, dwarf_r16
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
287 LLDB_INVALID_REGNUM
},
298 {dwarf_r17
, dwarf_r17
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
299 LLDB_INVALID_REGNUM
},
310 {dwarf_r18
, dwarf_r18
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
311 LLDB_INVALID_REGNUM
},
322 {dwarf_r19
, dwarf_r19
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
323 LLDB_INVALID_REGNUM
},
334 {dwarf_r20
, dwarf_r20
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
335 LLDB_INVALID_REGNUM
},
346 {dwarf_r21
, dwarf_r21
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
347 LLDB_INVALID_REGNUM
},
358 {dwarf_r22
, dwarf_r22
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
359 LLDB_INVALID_REGNUM
},
370 {dwarf_r23
, dwarf_r23
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
371 LLDB_INVALID_REGNUM
},
382 {dwarf_r24
, dwarf_r24
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
383 LLDB_INVALID_REGNUM
},
394 {dwarf_r25
, dwarf_r25
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
395 LLDB_INVALID_REGNUM
},
406 {dwarf_r26
, dwarf_r26
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
407 LLDB_INVALID_REGNUM
},
418 {dwarf_r27
, dwarf_r27
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
419 LLDB_INVALID_REGNUM
},
430 {dwarf_r28
, dwarf_r28
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
431 LLDB_INVALID_REGNUM
},
442 {dwarf_r29
, dwarf_r29
, LLDB_REGNUM_GENERIC_SP
, LLDB_INVALID_REGNUM
,
443 LLDB_INVALID_REGNUM
},
454 {dwarf_r30
, dwarf_r30
, LLDB_REGNUM_GENERIC_FP
, LLDB_INVALID_REGNUM
,
455 LLDB_INVALID_REGNUM
},
466 {dwarf_r31
, dwarf_r31
, LLDB_REGNUM_GENERIC_RA
, LLDB_INVALID_REGNUM
,
467 LLDB_INVALID_REGNUM
},
478 {dwarf_sr
, dwarf_sr
, LLDB_REGNUM_GENERIC_FLAGS
, LLDB_INVALID_REGNUM
,
479 LLDB_INVALID_REGNUM
},
490 {dwarf_lo
, dwarf_lo
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
491 LLDB_INVALID_REGNUM
},
502 {dwarf_hi
, dwarf_hi
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
503 LLDB_INVALID_REGNUM
},
514 {dwarf_bad
, dwarf_bad
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
515 LLDB_INVALID_REGNUM
},
526 {dwarf_cause
, dwarf_cause
, LLDB_INVALID_REGNUM
, LLDB_INVALID_REGNUM
,
527 LLDB_INVALID_REGNUM
},
538 {dwarf_pc
, dwarf_pc
, LLDB_REGNUM_GENERIC_PC
, LLDB_INVALID_REGNUM
,
539 LLDB_INVALID_REGNUM
},
546 static const uint32_t k_num_register_infos
= std::size(g_register_infos_mips64
);
548 const lldb_private::RegisterInfo
*
549 ABISysV_mips64::GetRegisterInfoArray(uint32_t &count
) {
550 count
= k_num_register_infos
;
551 return g_register_infos_mips64
;
554 size_t ABISysV_mips64::GetRedZoneSize() const { return 0; }
559 ABISysV_mips64::CreateInstance(lldb::ProcessSP process_sp
, const ArchSpec
&arch
) {
560 if (arch
.GetTriple().isMIPS64())
562 new ABISysV_mips64(std::move(process_sp
), MakeMCRegisterInfo(arch
)));
566 bool ABISysV_mips64::PrepareTrivialCall(Thread
&thread
, addr_t sp
,
567 addr_t func_addr
, addr_t return_addr
,
568 llvm::ArrayRef
<addr_t
> args
) const {
569 Log
*log
= GetLog(LLDBLog::Expressions
);
573 s
.Printf("ABISysV_mips64::PrepareTrivialCall (tid = 0x%" PRIx64
574 ", sp = 0x%" PRIx64
", func_addr = 0x%" PRIx64
575 ", return_addr = 0x%" PRIx64
,
576 thread
.GetID(), (uint64_t)sp
, (uint64_t)func_addr
,
577 (uint64_t)return_addr
);
579 for (size_t i
= 0; i
< args
.size(); ++i
)
580 s
.Printf(", arg%zd = 0x%" PRIx64
, i
+ 1, args
[i
]);
582 log
->PutString(s
.GetString());
585 RegisterContext
*reg_ctx
= thread
.GetRegisterContext().get();
589 const RegisterInfo
*reg_info
= nullptr;
591 if (args
.size() > 8) // TODO handle more than 8 arguments
594 for (size_t i
= 0; i
< args
.size(); ++i
) {
595 reg_info
= reg_ctx
->GetRegisterInfo(eRegisterKindGeneric
,
596 LLDB_REGNUM_GENERIC_ARG1
+ i
);
597 LLDB_LOGF(log
, "About to write arg%zd (0x%" PRIx64
") into %s", i
+ 1,
598 args
[i
], reg_info
->name
);
599 if (!reg_ctx
->WriteRegisterFromUnsigned(reg_info
, args
[i
]))
603 // First, align the SP
605 LLDB_LOGF(log
, "16-byte aligning SP: 0x%" PRIx64
" to 0x%" PRIx64
,
606 (uint64_t)sp
, (uint64_t)(sp
& ~0xfull
));
608 sp
&= ~(0xfull
); // 16-byte alignment
611 const RegisterInfo
*pc_reg_info
=
612 reg_ctx
->GetRegisterInfo(eRegisterKindGeneric
, LLDB_REGNUM_GENERIC_PC
);
613 const RegisterInfo
*sp_reg_info
=
614 reg_ctx
->GetRegisterInfo(eRegisterKindGeneric
, LLDB_REGNUM_GENERIC_SP
);
615 const RegisterInfo
*ra_reg_info
=
616 reg_ctx
->GetRegisterInfo(eRegisterKindGeneric
, LLDB_REGNUM_GENERIC_RA
);
617 const RegisterInfo
*r25_info
= reg_ctx
->GetRegisterInfoByName("r25", 0);
618 const RegisterInfo
*r0_info
= reg_ctx
->GetRegisterInfoByName("zero", 0);
620 LLDB_LOGF(log
, "Writing R0: 0x%" PRIx64
, (uint64_t)0);
622 /* Write r0 with 0, in case we are stopped in syscall,
623 * such setting prevents automatic decrement of the PC.
624 * This clears the bug 23659 for MIPS.
626 if (!reg_ctx
->WriteRegisterFromUnsigned(r0_info
, (uint64_t)0))
629 LLDB_LOGF(log
, "Writing SP: 0x%" PRIx64
, (uint64_t)sp
);
631 // Set "sp" to the requested value
632 if (!reg_ctx
->WriteRegisterFromUnsigned(sp_reg_info
, sp
))
635 LLDB_LOGF(log
, "Writing RA: 0x%" PRIx64
, (uint64_t)return_addr
);
637 // Set "ra" to the return address
638 if (!reg_ctx
->WriteRegisterFromUnsigned(ra_reg_info
, return_addr
))
641 LLDB_LOGF(log
, "Writing PC: 0x%" PRIx64
, (uint64_t)func_addr
);
643 // Set pc to the address of the called function.
644 if (!reg_ctx
->WriteRegisterFromUnsigned(pc_reg_info
, func_addr
))
647 LLDB_LOGF(log
, "Writing r25: 0x%" PRIx64
, (uint64_t)func_addr
);
649 // All callers of position independent functions must place the address of
650 // the called function in t9 (r25)
651 if (!reg_ctx
->WriteRegisterFromUnsigned(r25_info
, func_addr
))
657 bool ABISysV_mips64::GetArgumentValues(Thread
&thread
,
658 ValueList
&values
) const {
662 Status
ABISysV_mips64::SetReturnValueObject(lldb::StackFrameSP
&frame_sp
,
663 lldb::ValueObjectSP
&new_value_sp
) {
666 error
.SetErrorString("Empty value object for return value.");
670 CompilerType compiler_type
= new_value_sp
->GetCompilerType();
671 if (!compiler_type
) {
672 error
.SetErrorString("Null clang type for return value.");
676 Thread
*thread
= frame_sp
->GetThread().get();
678 RegisterContext
*reg_ctx
= thread
->GetRegisterContext().get();
681 error
.SetErrorString("no registers are available");
685 size_t num_bytes
= new_value_sp
->GetData(data
, data_error
);
686 if (data_error
.Fail()) {
687 error
.SetErrorStringWithFormat(
688 "Couldn't convert return value to raw data: %s",
689 data_error
.AsCString());
693 const uint32_t type_flags
= compiler_type
.GetTypeInfo(nullptr);
695 if (type_flags
& eTypeIsScalar
|| type_flags
& eTypeIsPointer
) {
696 if (type_flags
& eTypeIsInteger
|| type_flags
& eTypeIsPointer
) {
697 lldb::offset_t offset
= 0;
699 if (num_bytes
<= 16) {
700 const RegisterInfo
*r2_info
= reg_ctx
->GetRegisterInfoByName("r2", 0);
701 if (num_bytes
<= 8) {
702 uint64_t raw_value
= data
.GetMaxU64(&offset
, num_bytes
);
704 if (!reg_ctx
->WriteRegisterFromUnsigned(r2_info
, raw_value
))
705 error
.SetErrorString("failed to write register r2");
707 uint64_t raw_value
= data
.GetMaxU64(&offset
, 8);
708 if (reg_ctx
->WriteRegisterFromUnsigned(r2_info
, raw_value
)) {
709 const RegisterInfo
*r3_info
=
710 reg_ctx
->GetRegisterInfoByName("r3", 0);
711 raw_value
= data
.GetMaxU64(&offset
, num_bytes
- offset
);
713 if (!reg_ctx
->WriteRegisterFromUnsigned(r3_info
, raw_value
))
714 error
.SetErrorString("failed to write register r3");
716 error
.SetErrorString("failed to write register r2");
719 error
.SetErrorString("We don't support returning longer than 128 bit "
720 "integer values at present.");
722 } else if (type_flags
& eTypeIsFloat
) {
723 error
.SetErrorString("TODO: Handle Float Types.");
725 } else if (type_flags
& eTypeIsVector
) {
726 error
.SetErrorString("returning vector values are not supported");
732 ValueObjectSP
ABISysV_mips64::GetReturnValueObjectSimple(
733 Thread
&thread
, CompilerType
&return_compiler_type
) const {
734 ValueObjectSP return_valobj_sp
;
735 return return_valobj_sp
;
738 ValueObjectSP
ABISysV_mips64::GetReturnValueObjectImpl(
739 Thread
&thread
, CompilerType
&return_compiler_type
) const {
740 ValueObjectSP return_valobj_sp
;
744 ExecutionContext
exe_ctx(thread
.shared_from_this());
745 if (exe_ctx
.GetTargetPtr() == nullptr || exe_ctx
.GetProcessPtr() == nullptr)
746 return return_valobj_sp
;
748 value
.SetCompilerType(return_compiler_type
);
750 RegisterContext
*reg_ctx
= thread
.GetRegisterContext().get();
752 return return_valobj_sp
;
754 Target
*target
= exe_ctx
.GetTargetPtr();
755 const ArchSpec target_arch
= target
->GetArchitecture();
756 ByteOrder target_byte_order
= target_arch
.GetByteOrder();
757 std::optional
<uint64_t> byte_size
= return_compiler_type
.GetByteSize(&thread
);
759 return return_valobj_sp
;
760 const uint32_t type_flags
= return_compiler_type
.GetTypeInfo(nullptr);
762 target_arch
.GetFlags() & lldb_private::ArchSpec::eMIPS_ABI_FP_mask
;
764 const RegisterInfo
*r2_info
= reg_ctx
->GetRegisterInfoByName("r2", 0);
765 const RegisterInfo
*r3_info
= reg_ctx
->GetRegisterInfoByName("r3", 0);
766 assert(r2_info
&& r3_info
&& "Basic registers should always be present.");
768 if (type_flags
& eTypeIsScalar
|| type_flags
& eTypeIsPointer
) {
769 value
.SetValueType(Value::ValueType::Scalar
);
771 bool success
= false;
772 if (type_flags
& eTypeIsInteger
|| type_flags
& eTypeIsPointer
) {
773 // Extract the register context so we can read arguments from registers
774 // In MIPS register "r2" (v0) holds the integer function return values
776 uint64_t raw_value
= reg_ctx
->ReadRegisterAsUnsigned(r2_info
, 0);
778 const bool is_signed
= (type_flags
& eTypeIsSigned
) != 0;
779 switch (*byte_size
) {
783 case sizeof(uint64_t):
785 value
.GetScalar() = (int64_t)(raw_value
);
787 value
.GetScalar() = (uint64_t)(raw_value
);
791 case sizeof(uint32_t):
793 value
.GetScalar() = (int32_t)(raw_value
& UINT32_MAX
);
795 value
.GetScalar() = (uint32_t)(raw_value
& UINT32_MAX
);
799 case sizeof(uint16_t):
801 value
.GetScalar() = (int16_t)(raw_value
& UINT16_MAX
);
803 value
.GetScalar() = (uint16_t)(raw_value
& UINT16_MAX
);
807 case sizeof(uint8_t):
809 value
.GetScalar() = (int8_t)(raw_value
& UINT8_MAX
);
811 value
.GetScalar() = (uint8_t)(raw_value
& UINT8_MAX
);
815 } else if (type_flags
& eTypeIsFloat
) {
816 if (type_flags
& eTypeIsComplex
) {
817 // Don't handle complex yet.
818 } else if (IsSoftFloat(fp_flag
)) {
819 uint64_t raw_value
= reg_ctx
->ReadRegisterAsUnsigned(r2_info
, 0);
820 switch (*byte_size
) {
822 value
.GetScalar() = *((float *)(&raw_value
));
826 value
.GetScalar() = *((double *)(&raw_value
));
831 if (target_byte_order
== eByteOrderLittle
) {
832 result
[0] = raw_value
;
833 result
[1] = reg_ctx
->ReadRegisterAsUnsigned(r3_info
, 0);
834 value
.GetScalar() = *((long double *)(result
));
836 result
[0] = reg_ctx
->ReadRegisterAsUnsigned(r3_info
, 0);
837 result
[1] = raw_value
;
838 value
.GetScalar() = *((long double *)(result
));
845 if (*byte_size
<= sizeof(long double)) {
846 const RegisterInfo
*f0_info
= reg_ctx
->GetRegisterInfoByName("f0", 0);
848 RegisterValue f0_value
;
849 DataExtractor f0_data
;
851 reg_ctx
->ReadRegister(f0_info
, f0_value
);
853 f0_value
.GetData(f0_data
);
855 lldb::offset_t offset
= 0;
856 if (*byte_size
== sizeof(float)) {
857 value
.GetScalar() = (float)f0_data
.GetFloat(&offset
);
859 } else if (*byte_size
== sizeof(double)) {
860 value
.GetScalar() = (double)f0_data
.GetDouble(&offset
);
862 } else if (*byte_size
== sizeof(long double)) {
863 const RegisterInfo
*f2_info
=
864 reg_ctx
->GetRegisterInfoByName("f2", 0);
865 RegisterValue f2_value
;
866 DataExtractor f2_data
;
867 reg_ctx
->ReadRegister(f2_info
, f2_value
);
868 DataExtractor
*copy_from_extractor
= nullptr;
869 WritableDataBufferSP
data_sp(new DataBufferHeap(16, 0));
870 DataExtractor
return_ext(
871 data_sp
, target_byte_order
,
872 target
->GetArchitecture().GetAddressByteSize());
874 if (target_byte_order
== eByteOrderLittle
) {
875 copy_from_extractor
= &f0_data
;
876 copy_from_extractor
->CopyByteOrderedData(
877 0, 8, data_sp
->GetBytes(), *byte_size
- 8, target_byte_order
);
878 f2_value
.GetData(f2_data
);
879 copy_from_extractor
= &f2_data
;
880 copy_from_extractor
->CopyByteOrderedData(
881 0, 8, data_sp
->GetBytes() + 8, *byte_size
- 8,
884 copy_from_extractor
= &f0_data
;
885 copy_from_extractor
->CopyByteOrderedData(
886 0, 8, data_sp
->GetBytes() + 8, *byte_size
- 8,
888 f2_value
.GetData(f2_data
);
889 copy_from_extractor
= &f2_data
;
890 copy_from_extractor
->CopyByteOrderedData(
891 0, 8, data_sp
->GetBytes(), *byte_size
- 8, target_byte_order
);
894 return_valobj_sp
= ValueObjectConstResult::Create(
895 &thread
, return_compiler_type
, ConstString(""), return_ext
);
896 return return_valobj_sp
;
903 return_valobj_sp
= ValueObjectConstResult::Create(
904 thread
.GetStackFrameAtIndex(0).get(), value
, ConstString(""));
905 } else if (type_flags
& eTypeIsStructUnion
|| type_flags
& eTypeIsClass
||
906 type_flags
& eTypeIsVector
) {
907 // Any structure of up to 16 bytes in size is returned in the registers.
908 if (*byte_size
<= 16) {
909 WritableDataBufferSP
data_sp(new DataBufferHeap(16, 0));
910 DataExtractor
return_ext(data_sp
, target_byte_order
,
911 target
->GetArchitecture().GetAddressByteSize());
913 RegisterValue r2_value
, r3_value
, f0_value
, f1_value
, f2_value
;
914 // Tracks how much bytes of r2 and r3 registers we've consumed so far
915 uint32_t integer_bytes
= 0;
917 // True if return values are in FP return registers.
918 bool use_fp_regs
= false;
919 // True if we found any non floating point field in structure.
920 bool found_non_fp_field
= false;
921 // True if return values are in r2 register.
923 // True if return values are in r3 register.
925 // True if the result is copied into our data buffer
930 const uint32_t num_children
= return_compiler_type
.GetNumFields();
932 // A structure consisting of one or two FP values (and nothing else) will
933 // be returned in the two FP return-value registers i.e fp0 and fp2.
934 if (num_children
<= 2) {
935 uint64_t field_bit_offset
= 0;
937 // Check if this structure contains only floating point fields
938 for (uint32_t idx
= 0; idx
< num_children
; idx
++) {
939 CompilerType field_compiler_type
=
940 return_compiler_type
.GetFieldAtIndex(idx
, name
, &field_bit_offset
,
943 if (field_compiler_type
.IsFloatingPointType(count
, is_complex
))
946 found_non_fp_field
= true;
949 if (use_fp_regs
&& !found_non_fp_field
) {
950 // We have one or two FP-only values in this structure. Get it from
952 DataExtractor f0_data
, f1_data
, f2_data
;
953 const RegisterInfo
*f0_info
= reg_ctx
->GetRegisterInfoByName("f0", 0);
954 const RegisterInfo
*f1_info
= reg_ctx
->GetRegisterInfoByName("f1", 0);
955 const RegisterInfo
*f2_info
= reg_ctx
->GetRegisterInfoByName("f2", 0);
957 reg_ctx
->ReadRegister(f0_info
, f0_value
);
958 reg_ctx
->ReadRegister(f2_info
, f2_value
);
960 f0_value
.GetData(f0_data
);
962 for (uint32_t idx
= 0; idx
< num_children
; idx
++) {
963 CompilerType field_compiler_type
=
964 return_compiler_type
.GetFieldAtIndex(
965 idx
, name
, &field_bit_offset
, nullptr, nullptr);
966 std::optional
<uint64_t> field_byte_width
=
967 field_compiler_type
.GetByteSize(&thread
);
968 if (!field_byte_width
)
969 return return_valobj_sp
;
971 DataExtractor
*copy_from_extractor
= nullptr;
972 uint64_t return_value
[2];
976 // This case is for long double type.
977 if (*field_byte_width
== 16) {
979 // If structure contains long double type, then it is returned
980 // in fp0/fp1 registers.
981 if (target_byte_order
== eByteOrderLittle
) {
982 return_value
[0] = f0_data
.GetU64(&offset
);
983 reg_ctx
->ReadRegister(f1_info
, f1_value
);
984 f1_value
.GetData(f1_data
);
986 return_value
[1] = f1_data
.GetU64(&offset
);
988 return_value
[1] = f0_data
.GetU64(&offset
);
989 reg_ctx
->ReadRegister(f1_info
, f1_value
);
990 f1_value
.GetData(f1_data
);
992 return_value
[0] = f1_data
.GetU64(&offset
);
995 f0_data
.SetData(return_value
, *field_byte_width
,
998 copy_from_extractor
= &f0_data
; // This is in f0, copy from
999 // register to our result
1002 f2_value
.GetData(f2_data
);
1003 // This is in f2, copy from register to our result structure
1004 copy_from_extractor
= &f2_data
;
1007 // Sanity check to avoid crash
1008 if (!copy_from_extractor
||
1009 *field_byte_width
> copy_from_extractor
->GetByteSize())
1010 return return_valobj_sp
;
1012 // copy the register contents into our data buffer
1013 copy_from_extractor
->CopyByteOrderedData(
1014 0, *field_byte_width
,
1015 data_sp
->GetBytes() + (field_bit_offset
/ 8), *field_byte_width
,
1019 // The result is in our data buffer. Create a variable object out of
1021 return_valobj_sp
= ValueObjectConstResult::Create(
1022 &thread
, return_compiler_type
, ConstString(""), return_ext
);
1024 return return_valobj_sp
;
1028 // If we reach here, it means this structure either contains more than
1029 // two fields or it contains at least one non floating point type. In
1030 // that case, all fields are returned in GP return registers.
1031 for (uint32_t idx
= 0; idx
< num_children
; idx
++) {
1032 uint64_t field_bit_offset
= 0;
1036 CompilerType field_compiler_type
= return_compiler_type
.GetFieldAtIndex(
1037 idx
, name
, &field_bit_offset
, nullptr, nullptr);
1038 std::optional
<uint64_t> field_byte_width
=
1039 field_compiler_type
.GetByteSize(&thread
);
1041 // if we don't know the size of the field (e.g. invalid type), just
1043 if (!field_byte_width
|| *field_byte_width
== 0)
1046 uint32_t field_byte_offset
= field_bit_offset
/ 8;
1048 if (field_compiler_type
.IsIntegerOrEnumerationType(is_signed
) ||
1049 field_compiler_type
.IsPointerType() ||
1050 field_compiler_type
.IsFloatingPointType(count
, is_complex
)) {
1051 padding
= field_byte_offset
- integer_bytes
;
1053 if (integer_bytes
< 8) {
1054 // We have not yet consumed r2 completely.
1055 if (integer_bytes
+ *field_byte_width
+ padding
<= 8) {
1056 // This field fits in r2, copy its value from r2 to our result
1058 integer_bytes
= integer_bytes
+ *field_byte_width
+
1059 padding
; // Increase the consumed bytes.
1062 // There isn't enough space left in r2 for this field, so this
1064 integer_bytes
= integer_bytes
+ *field_byte_width
+
1065 padding
; // Increase the consumed bytes.
1069 // We already have consumed at-least 8 bytes that means r2 is done,
1070 // and this field will be in r3. Check if this field can fit in r3.
1071 else if (integer_bytes
+ *field_byte_width
+ padding
<= 16) {
1072 integer_bytes
= integer_bytes
+ *field_byte_width
+ padding
;
1075 // There isn't any space left for this field, this should not
1076 // happen as we have already checked the overall size is not
1077 // greater than 16 bytes. For now, return a nullptr return value
1079 return return_valobj_sp
;
1083 // Vector types up to 16 bytes are returned in GP return registers
1084 if (type_flags
& eTypeIsVector
) {
1085 if (*byte_size
<= 8)
1094 reg_ctx
->ReadRegister(r2_info
, r2_value
);
1096 const size_t bytes_copied
= r2_value
.GetAsMemoryData(
1097 *r2_info
, data_sp
->GetBytes(), r2_info
->byte_size
,
1098 target_byte_order
, error
);
1099 if (bytes_copied
!= r2_info
->byte_size
)
1100 return return_valobj_sp
;
1104 reg_ctx
->ReadRegister(r3_info
, r3_value
);
1105 const size_t bytes_copied
= r3_value
.GetAsMemoryData(
1106 *r3_info
, data_sp
->GetBytes() + r2_info
->byte_size
,
1107 r3_info
->byte_size
, target_byte_order
, error
);
1109 if (bytes_copied
!= r3_info
->byte_size
)
1110 return return_valobj_sp
;
1114 // The result is in our data buffer. Create a variable object out of
1116 return_valobj_sp
= ValueObjectConstResult::Create(
1117 &thread
, return_compiler_type
, ConstString(""), return_ext
);
1119 return return_valobj_sp
;
1122 // Any structure/vector greater than 16 bytes in size is returned in
1123 // memory. The pointer to that memory is returned in r2.
1124 uint64_t mem_address
= reg_ctx
->ReadRegisterAsUnsigned(
1125 reg_ctx
->GetRegisterInfoByName("r2", 0), 0);
1127 // We have got the address. Create a memory object out of it
1128 return_valobj_sp
= ValueObjectMemory::Create(
1129 &thread
, "", Address(mem_address
, nullptr), return_compiler_type
);
1131 return return_valobj_sp
;
1134 bool ABISysV_mips64::CreateFunctionEntryUnwindPlan(UnwindPlan
&unwind_plan
) {
1135 unwind_plan
.Clear();
1136 unwind_plan
.SetRegisterKind(eRegisterKindDWARF
);
1138 UnwindPlan::RowSP
row(new UnwindPlan::Row
);
1140 // Our Call Frame Address is the stack pointer value
1141 row
->GetCFAValue().SetIsRegisterPlusOffset(dwarf_r29
, 0);
1143 // The previous PC is in the RA
1144 row
->SetRegisterLocationToRegister(dwarf_pc
, dwarf_r31
, true);
1145 unwind_plan
.AppendRow(row
);
1147 // All other registers are the same.
1149 unwind_plan
.SetSourceName("mips64 at-func-entry default");
1150 unwind_plan
.SetSourcedFromCompiler(eLazyBoolNo
);
1151 unwind_plan
.SetReturnAddressRegister(dwarf_r31
);
1155 bool ABISysV_mips64::CreateDefaultUnwindPlan(UnwindPlan
&unwind_plan
) {
1156 unwind_plan
.Clear();
1157 unwind_plan
.SetRegisterKind(eRegisterKindDWARF
);
1159 UnwindPlan::RowSP
row(new UnwindPlan::Row
);
1161 row
->SetUnspecifiedRegistersAreUndefined(true);
1162 row
->GetCFAValue().SetIsRegisterPlusOffset(dwarf_r29
, 0);
1164 row
->SetRegisterLocationToRegister(dwarf_pc
, dwarf_r31
, true);
1166 unwind_plan
.AppendRow(row
);
1167 unwind_plan
.SetSourceName("mips64 default unwind plan");
1168 unwind_plan
.SetSourcedFromCompiler(eLazyBoolNo
);
1169 unwind_plan
.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo
);
1170 unwind_plan
.SetUnwindPlanForSignalTrap(eLazyBoolNo
);
1174 bool ABISysV_mips64::RegisterIsVolatile(const RegisterInfo
*reg_info
) {
1175 return !RegisterIsCalleeSaved(reg_info
);
1178 bool ABISysV_mips64::IsSoftFloat(uint32_t fp_flag
) const {
1179 return (fp_flag
== lldb_private::ArchSpec::eMIPS_ABI_FP_SOFT
);
1182 bool ABISysV_mips64::RegisterIsCalleeSaved(const RegisterInfo
*reg_info
) {
1184 // Preserved registers are :
1185 // r16-r23, r28, r29, r30, r31
1187 int reg
= ((reg_info
->byte_offset
) / 8);
1189 bool save
= (reg
>= 16) && (reg
<= 23);
1190 save
|= (reg
>= 28) && (reg
<= 31);
1197 void ABISysV_mips64::Initialize() {
1198 PluginManager::RegisterPlugin(
1199 GetPluginNameStatic(), "System V ABI for mips64 targets", CreateInstance
);
1202 void ABISysV_mips64::Terminate() {
1203 PluginManager::UnregisterPlugin(CreateInstance
);