[C++20][modules] Fix std::initializer_list recognition if it's exported out of a...
[llvm-project.git] / lldb / source / Plugins / ABI / Mips / ABISysV_mips.cpp
blob9c7312b975c4b65ef0d9f0d76309f0ef31c3e10c
1 //===-- ABISysV_mips.cpp --------------------------------------------------===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
9 #include "ABISysV_mips.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/Symbol/UnwindPlan.h"
18 #include "lldb/Target/Process.h"
19 #include "lldb/Target/RegisterContext.h"
20 #include "lldb/Target/StackFrame.h"
21 #include "lldb/Target/Target.h"
22 #include "lldb/Target/Thread.h"
23 #include "lldb/Utility/ConstString.h"
24 #include "lldb/Utility/DataExtractor.h"
25 #include "lldb/Utility/LLDBLog.h"
26 #include "lldb/Utility/Log.h"
27 #include "lldb/Utility/RegisterValue.h"
28 #include "lldb/Utility/Status.h"
29 #include "lldb/ValueObject/ValueObjectConstResult.h"
30 #include "lldb/ValueObject/ValueObjectMemory.h"
31 #include "lldb/ValueObject/ValueObjectRegister.h"
32 #include <optional>
34 using namespace lldb;
35 using namespace lldb_private;
37 LLDB_PLUGIN_DEFINE(ABISysV_mips)
39 enum dwarf_regnums {
40 dwarf_r0 = 0,
41 dwarf_r1,
42 dwarf_r2,
43 dwarf_r3,
44 dwarf_r4,
45 dwarf_r5,
46 dwarf_r6,
47 dwarf_r7,
48 dwarf_r8,
49 dwarf_r9,
50 dwarf_r10,
51 dwarf_r11,
52 dwarf_r12,
53 dwarf_r13,
54 dwarf_r14,
55 dwarf_r15,
56 dwarf_r16,
57 dwarf_r17,
58 dwarf_r18,
59 dwarf_r19,
60 dwarf_r20,
61 dwarf_r21,
62 dwarf_r22,
63 dwarf_r23,
64 dwarf_r24,
65 dwarf_r25,
66 dwarf_r26,
67 dwarf_r27,
68 dwarf_r28,
69 dwarf_r29,
70 dwarf_r30,
71 dwarf_r31,
72 dwarf_sr,
73 dwarf_lo,
74 dwarf_hi,
75 dwarf_bad,
76 dwarf_cause,
77 dwarf_pc
80 static const RegisterInfo g_register_infos[] = {
81 {"r0",
82 "zero",
85 eEncodingUint,
86 eFormatHex,
87 {dwarf_r0, dwarf_r0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
88 LLDB_INVALID_REGNUM},
89 nullptr,
90 nullptr,
91 nullptr,
93 {"r1",
94 "AT",
97 eEncodingUint,
98 eFormatHex,
99 {dwarf_r1, dwarf_r1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
100 LLDB_INVALID_REGNUM},
101 nullptr,
102 nullptr,
103 nullptr,
105 {"r2",
106 "v0",
109 eEncodingUint,
110 eFormatHex,
111 {dwarf_r2, dwarf_r2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
112 LLDB_INVALID_REGNUM},
113 nullptr,
114 nullptr,
115 nullptr,
117 {"r3",
118 "v1",
121 eEncodingUint,
122 eFormatHex,
123 {dwarf_r3, dwarf_r3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
124 LLDB_INVALID_REGNUM},
125 nullptr,
126 nullptr,
127 nullptr,
129 {"r4",
130 nullptr,
133 eEncodingUint,
134 eFormatHex,
135 {dwarf_r4, dwarf_r4, LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM,
136 LLDB_INVALID_REGNUM},
137 nullptr,
138 nullptr,
139 nullptr,
141 {"r5",
142 nullptr,
145 eEncodingUint,
146 eFormatHex,
147 {dwarf_r5, dwarf_r5, LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM,
148 LLDB_INVALID_REGNUM},
149 nullptr,
150 nullptr,
151 nullptr,
153 {"r6",
154 nullptr,
157 eEncodingUint,
158 eFormatHex,
159 {dwarf_r6, dwarf_r6, LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM,
160 LLDB_INVALID_REGNUM},
161 nullptr,
162 nullptr,
163 nullptr,
165 {"r7",
166 nullptr,
169 eEncodingUint,
170 eFormatHex,
171 {dwarf_r7, dwarf_r7, LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM,
172 LLDB_INVALID_REGNUM},
173 nullptr,
174 nullptr,
175 nullptr,
177 {"r8",
178 "arg5",
181 eEncodingUint,
182 eFormatHex,
183 {dwarf_r8, dwarf_r8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
184 LLDB_INVALID_REGNUM},
185 nullptr,
186 nullptr,
187 nullptr,
189 {"r9",
190 "arg6",
193 eEncodingUint,
194 eFormatHex,
195 {dwarf_r9, dwarf_r9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
196 LLDB_INVALID_REGNUM},
197 nullptr,
198 nullptr,
199 nullptr,
201 {"r10",
202 "arg7",
205 eEncodingUint,
206 eFormatHex,
207 {dwarf_r10, dwarf_r10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
208 LLDB_INVALID_REGNUM},
209 nullptr,
210 nullptr,
211 nullptr,
213 {"r11",
214 "arg8",
217 eEncodingUint,
218 eFormatHex,
219 {dwarf_r11, dwarf_r11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
220 LLDB_INVALID_REGNUM},
221 nullptr,
222 nullptr,
223 nullptr,
225 {"r12",
226 nullptr,
229 eEncodingUint,
230 eFormatHex,
231 {dwarf_r12, dwarf_r12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
232 LLDB_INVALID_REGNUM},
233 nullptr,
234 nullptr,
235 nullptr,
237 {"r13",
238 nullptr,
241 eEncodingUint,
242 eFormatHex,
243 {dwarf_r13, dwarf_r13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
244 LLDB_INVALID_REGNUM},
245 nullptr,
246 nullptr,
247 nullptr,
249 {"r14",
250 nullptr,
253 eEncodingUint,
254 eFormatHex,
255 {dwarf_r14, dwarf_r14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
256 LLDB_INVALID_REGNUM},
257 nullptr,
258 nullptr,
259 nullptr,
261 {"r15",
262 nullptr,
265 eEncodingUint,
266 eFormatHex,
267 {dwarf_r15, dwarf_r15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
268 LLDB_INVALID_REGNUM},
269 nullptr,
270 nullptr,
271 nullptr,
273 {"r16",
274 nullptr,
277 eEncodingUint,
278 eFormatHex,
279 {dwarf_r16, dwarf_r16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
280 LLDB_INVALID_REGNUM},
281 nullptr,
282 nullptr,
283 nullptr,
285 {"r17",
286 nullptr,
289 eEncodingUint,
290 eFormatHex,
291 {dwarf_r17, dwarf_r17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
292 LLDB_INVALID_REGNUM},
293 nullptr,
294 nullptr,
295 nullptr,
297 {"r18",
298 nullptr,
301 eEncodingUint,
302 eFormatHex,
303 {dwarf_r18, dwarf_r18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
304 LLDB_INVALID_REGNUM},
305 nullptr,
306 nullptr,
307 nullptr,
309 {"r19",
310 nullptr,
313 eEncodingUint,
314 eFormatHex,
315 {dwarf_r19, dwarf_r19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
316 LLDB_INVALID_REGNUM},
317 nullptr,
318 nullptr,
319 nullptr,
321 {"r20",
322 nullptr,
325 eEncodingUint,
326 eFormatHex,
327 {dwarf_r20, dwarf_r20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
328 LLDB_INVALID_REGNUM},
329 nullptr,
330 nullptr,
331 nullptr,
333 {"r21",
334 nullptr,
337 eEncodingUint,
338 eFormatHex,
339 {dwarf_r21, dwarf_r21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
340 LLDB_INVALID_REGNUM},
341 nullptr,
342 nullptr,
343 nullptr,
345 {"r22",
346 nullptr,
349 eEncodingUint,
350 eFormatHex,
351 {dwarf_r22, dwarf_r22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
352 LLDB_INVALID_REGNUM},
353 nullptr,
354 nullptr,
355 nullptr,
357 {"r23",
358 nullptr,
361 eEncodingUint,
362 eFormatHex,
363 {dwarf_r23, dwarf_r23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
364 LLDB_INVALID_REGNUM},
365 nullptr,
366 nullptr,
367 nullptr,
369 {"r24",
370 nullptr,
373 eEncodingUint,
374 eFormatHex,
375 {dwarf_r24, dwarf_r24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
376 LLDB_INVALID_REGNUM},
377 nullptr,
378 nullptr,
379 nullptr,
381 {"r25",
382 nullptr,
385 eEncodingUint,
386 eFormatHex,
387 {dwarf_r25, dwarf_r25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
388 LLDB_INVALID_REGNUM},
389 nullptr,
390 nullptr,
391 nullptr,
393 {"r26",
394 nullptr,
397 eEncodingUint,
398 eFormatHex,
399 {dwarf_r26, dwarf_r26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
400 LLDB_INVALID_REGNUM},
401 nullptr,
402 nullptr,
403 nullptr,
405 {"r27",
406 nullptr,
409 eEncodingUint,
410 eFormatHex,
411 {dwarf_r27, dwarf_r27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
412 LLDB_INVALID_REGNUM},
413 nullptr,
414 nullptr,
415 nullptr,
417 {"r28",
418 "gp",
421 eEncodingUint,
422 eFormatHex,
423 {dwarf_r28, dwarf_r28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
424 LLDB_INVALID_REGNUM},
425 nullptr,
426 nullptr,
427 nullptr,
429 {"r29",
430 nullptr,
433 eEncodingUint,
434 eFormatHex,
435 {dwarf_r29, dwarf_r29, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM,
436 LLDB_INVALID_REGNUM},
437 nullptr,
438 nullptr,
439 nullptr,
441 {"r30",
442 nullptr,
445 eEncodingUint,
446 eFormatHex,
447 {dwarf_r30, dwarf_r30, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM,
448 LLDB_INVALID_REGNUM},
449 nullptr,
450 nullptr,
451 nullptr,
453 {"r31",
454 nullptr,
457 eEncodingUint,
458 eFormatHex,
459 {dwarf_r31, dwarf_r31, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM,
460 LLDB_INVALID_REGNUM},
461 nullptr,
462 nullptr,
463 nullptr,
465 {"sr",
466 nullptr,
469 eEncodingUint,
470 eFormatHex,
471 {dwarf_sr, dwarf_sr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM,
472 LLDB_INVALID_REGNUM},
473 nullptr,
474 nullptr,
475 nullptr,
477 {"lo",
478 nullptr,
481 eEncodingUint,
482 eFormatHex,
483 {dwarf_lo, dwarf_lo, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
484 LLDB_INVALID_REGNUM},
485 nullptr,
486 nullptr,
487 nullptr,
489 {"hi",
490 nullptr,
493 eEncodingUint,
494 eFormatHex,
495 {dwarf_hi, dwarf_hi, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
496 LLDB_INVALID_REGNUM},
497 nullptr,
498 nullptr,
499 nullptr,
501 {"bad",
502 nullptr,
505 eEncodingUint,
506 eFormatHex,
507 {dwarf_bad, dwarf_bad, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
508 LLDB_INVALID_REGNUM},
509 nullptr,
510 nullptr,
511 nullptr,
513 {"cause",
514 nullptr,
517 eEncodingUint,
518 eFormatHex,
519 {dwarf_cause, dwarf_cause, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
520 LLDB_INVALID_REGNUM},
521 nullptr,
522 nullptr,
523 nullptr,
525 {"pc",
526 nullptr,
529 eEncodingUint,
530 eFormatHex,
531 {dwarf_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM,
532 LLDB_INVALID_REGNUM},
533 nullptr,
534 nullptr,
535 nullptr,
539 static const uint32_t k_num_register_infos = std::size(g_register_infos);
541 const lldb_private::RegisterInfo *
542 ABISysV_mips::GetRegisterInfoArray(uint32_t &count) {
543 count = k_num_register_infos;
544 return g_register_infos;
547 size_t ABISysV_mips::GetRedZoneSize() const { return 0; }
549 // Static Functions
551 ABISP
552 ABISysV_mips::CreateInstance(lldb::ProcessSP process_sp, const ArchSpec &arch) {
553 const llvm::Triple::ArchType arch_type = arch.GetTriple().getArch();
554 if ((arch_type == llvm::Triple::mips) ||
555 (arch_type == llvm::Triple::mipsel)) {
556 return ABISP(
557 new ABISysV_mips(std::move(process_sp), MakeMCRegisterInfo(arch)));
559 return ABISP();
562 bool ABISysV_mips::PrepareTrivialCall(Thread &thread, addr_t sp,
563 addr_t func_addr, addr_t return_addr,
564 llvm::ArrayRef<addr_t> args) const {
565 Log *log = GetLog(LLDBLog::Expressions);
567 if (log) {
568 StreamString s;
569 s.Printf("ABISysV_mips::PrepareTrivialCall (tid = 0x%" PRIx64
570 ", sp = 0x%" PRIx64 ", func_addr = 0x%" PRIx64
571 ", return_addr = 0x%" PRIx64,
572 thread.GetID(), (uint64_t)sp, (uint64_t)func_addr,
573 (uint64_t)return_addr);
575 for (size_t i = 0; i < args.size(); ++i)
576 s.Printf(", arg%zd = 0x%" PRIx64, i + 1, args[i]);
577 s.PutCString(")");
578 log->PutString(s.GetString());
581 RegisterContext *reg_ctx = thread.GetRegisterContext().get();
582 if (!reg_ctx)
583 return false;
585 const RegisterInfo *reg_info = nullptr;
587 RegisterValue reg_value;
589 // Argument registers
590 const char *reg_names[] = {"r4", "r5", "r6", "r7"};
592 llvm::ArrayRef<addr_t>::iterator ai = args.begin(), ae = args.end();
594 // Write arguments to registers
595 for (size_t i = 0; i < std::size(reg_names); ++i) {
596 if (ai == ae)
597 break;
599 reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric,
600 LLDB_REGNUM_GENERIC_ARG1 + i);
601 LLDB_LOGF(log, "About to write arg%zd (0x%" PRIx64 ") into %s", i + 1,
602 args[i], reg_info->name);
604 if (!reg_ctx->WriteRegisterFromUnsigned(reg_info, args[i]))
605 return false;
607 ++ai;
610 // If we have more than 4 arguments --Spill onto the stack
611 if (ai != ae) {
612 // No of arguments to go on stack
613 size_t num_stack_regs = args.size();
615 // Allocate needed space for args on the stack
616 sp -= (num_stack_regs * 4);
618 // Keep the stack 8 byte aligned
619 sp &= ~(8ull - 1ull);
621 // just using arg1 to get the right size
622 const RegisterInfo *reg_info = reg_ctx->GetRegisterInfo(
623 eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1);
625 addr_t arg_pos = sp + 16;
627 size_t i = 4;
628 for (; ai != ae; ++ai) {
629 reg_value.SetUInt32(*ai);
630 LLDB_LOGF(log, "About to write arg%zd (0x%" PRIx64 ") at 0x%" PRIx64 "",
631 i + 1, args[i], arg_pos);
633 if (reg_ctx
634 ->WriteRegisterValueToMemory(reg_info, arg_pos,
635 reg_info->byte_size, reg_value)
636 .Fail())
637 return false;
638 arg_pos += reg_info->byte_size;
639 i++;
643 Status error;
644 const RegisterInfo *pc_reg_info =
645 reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
646 const RegisterInfo *sp_reg_info =
647 reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
648 const RegisterInfo *ra_reg_info =
649 reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA);
650 const RegisterInfo *r25_info = reg_ctx->GetRegisterInfoByName("r25", 0);
651 const RegisterInfo *r0_info = reg_ctx->GetRegisterInfoByName("zero", 0);
653 LLDB_LOGF(log, "Writing R0: 0x%" PRIx64, (uint64_t)0);
655 /* Write r0 with 0, in case we are stopped in syscall,
656 * such setting prevents automatic decrement of the PC.
657 * This clears the bug 23659 for MIPS.
659 if (!reg_ctx->WriteRegisterFromUnsigned(r0_info, (uint64_t)0))
660 return false;
662 LLDB_LOGF(log, "Writing SP: 0x%" PRIx64, (uint64_t)sp);
664 // Set "sp" to the requested value
665 if (!reg_ctx->WriteRegisterFromUnsigned(sp_reg_info, sp))
666 return false;
668 LLDB_LOGF(log, "Writing RA: 0x%" PRIx64, (uint64_t)return_addr);
670 // Set "ra" to the return address
671 if (!reg_ctx->WriteRegisterFromUnsigned(ra_reg_info, return_addr))
672 return false;
674 LLDB_LOGF(log, "Writing PC: 0x%" PRIx64, (uint64_t)func_addr);
676 // Set pc to the address of the called function.
677 if (!reg_ctx->WriteRegisterFromUnsigned(pc_reg_info, func_addr))
678 return false;
680 LLDB_LOGF(log, "Writing r25: 0x%" PRIx64, (uint64_t)func_addr);
682 // All callers of position independent functions must place the address of
683 // the called function in t9 (r25)
684 if (!reg_ctx->WriteRegisterFromUnsigned(r25_info, func_addr))
685 return false;
687 return true;
690 bool ABISysV_mips::GetArgumentValues(Thread &thread, ValueList &values) const {
691 return false;
694 Status ABISysV_mips::SetReturnValueObject(lldb::StackFrameSP &frame_sp,
695 lldb::ValueObjectSP &new_value_sp) {
696 Status error;
697 if (!new_value_sp) {
698 error = Status::FromErrorString("Empty value object for return value.");
699 return error;
702 CompilerType compiler_type = new_value_sp->GetCompilerType();
703 if (!compiler_type) {
704 error = Status::FromErrorString("Null clang type for return value.");
705 return error;
708 Thread *thread = frame_sp->GetThread().get();
710 bool is_signed;
711 uint32_t count;
712 bool is_complex;
714 RegisterContext *reg_ctx = thread->GetRegisterContext().get();
716 bool set_it_simple = false;
717 if (compiler_type.IsIntegerOrEnumerationType(is_signed) ||
718 compiler_type.IsPointerType()) {
719 DataExtractor data;
720 Status data_error;
721 size_t num_bytes = new_value_sp->GetData(data, data_error);
722 if (data_error.Fail()) {
723 error = Status::FromErrorStringWithFormat(
724 "Couldn't convert return value to raw data: %s",
725 data_error.AsCString());
726 return error;
729 lldb::offset_t offset = 0;
730 if (num_bytes <= 8) {
731 const RegisterInfo *r2_info = reg_ctx->GetRegisterInfoByName("r2", 0);
732 if (num_bytes <= 4) {
733 uint32_t raw_value = data.GetMaxU32(&offset, num_bytes);
735 if (reg_ctx->WriteRegisterFromUnsigned(r2_info, raw_value))
736 set_it_simple = true;
737 } else {
738 uint32_t raw_value = data.GetMaxU32(&offset, 4);
740 if (reg_ctx->WriteRegisterFromUnsigned(r2_info, raw_value)) {
741 const RegisterInfo *r3_info = reg_ctx->GetRegisterInfoByName("r3", 0);
742 uint32_t raw_value = data.GetMaxU32(&offset, num_bytes - offset);
744 if (reg_ctx->WriteRegisterFromUnsigned(r3_info, raw_value))
745 set_it_simple = true;
748 } else {
749 error = Status::FromErrorString(
750 "We don't support returning longer than 64 bit "
751 "integer values at present.");
753 } else if (compiler_type.IsFloatingPointType(count, is_complex)) {
754 if (is_complex)
755 error = Status::FromErrorString(
756 "We don't support returning complex values at present");
757 else
758 error = Status::FromErrorString(
759 "We don't support returning float values at present");
762 if (!set_it_simple)
763 error = Status::FromErrorString(
764 "We only support setting simple integer return types at present.");
766 return error;
769 ValueObjectSP ABISysV_mips::GetReturnValueObjectSimple(
770 Thread &thread, CompilerType &return_compiler_type) const {
771 ValueObjectSP return_valobj_sp;
772 return return_valobj_sp;
775 ValueObjectSP ABISysV_mips::GetReturnValueObjectImpl(
776 Thread &thread, CompilerType &return_compiler_type) const {
777 ValueObjectSP return_valobj_sp;
778 Value value;
780 if (!return_compiler_type)
781 return return_valobj_sp;
783 ExecutionContext exe_ctx(thread.shared_from_this());
784 if (exe_ctx.GetTargetPtr() == nullptr || exe_ctx.GetProcessPtr() == nullptr)
785 return return_valobj_sp;
787 Target *target = exe_ctx.GetTargetPtr();
788 const ArchSpec target_arch = target->GetArchitecture();
789 ByteOrder target_byte_order = target_arch.GetByteOrder();
790 value.SetCompilerType(return_compiler_type);
791 uint32_t fp_flag =
792 target_arch.GetFlags() & lldb_private::ArchSpec::eMIPS_ABI_FP_mask;
794 RegisterContext *reg_ctx = thread.GetRegisterContext().get();
795 if (!reg_ctx)
796 return return_valobj_sp;
798 bool is_signed = false;
799 bool is_complex = false;
800 uint32_t count = 0;
802 // In MIPS register "r2" (v0) holds the integer function return values
803 const RegisterInfo *r2_reg_info = reg_ctx->GetRegisterInfoByName("r2", 0);
804 std::optional<uint64_t> bit_width = return_compiler_type.GetBitSize(&thread);
805 if (!bit_width)
806 return return_valobj_sp;
807 if (return_compiler_type.IsIntegerOrEnumerationType(is_signed)) {
808 switch (*bit_width) {
809 default:
810 return return_valobj_sp;
811 case 64: {
812 const RegisterInfo *r3_reg_info = reg_ctx->GetRegisterInfoByName("r3", 0);
813 uint64_t raw_value;
814 raw_value = reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT32_MAX;
815 raw_value |= ((uint64_t)(reg_ctx->ReadRegisterAsUnsigned(r3_reg_info, 0) &
816 UINT32_MAX))
817 << 32;
818 if (is_signed)
819 value.GetScalar() = (int64_t)raw_value;
820 else
821 value.GetScalar() = (uint64_t)raw_value;
822 } break;
823 case 32:
824 if (is_signed)
825 value.GetScalar() = (int32_t)(
826 reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT32_MAX);
827 else
828 value.GetScalar() = (uint32_t)(
829 reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT32_MAX);
830 break;
831 case 16:
832 if (is_signed)
833 value.GetScalar() = (int16_t)(
834 reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT16_MAX);
835 else
836 value.GetScalar() = (uint16_t)(
837 reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT16_MAX);
838 break;
839 case 8:
840 if (is_signed)
841 value.GetScalar() = (int8_t)(
842 reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT8_MAX);
843 else
844 value.GetScalar() = (uint8_t)(
845 reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT8_MAX);
846 break;
848 } else if (return_compiler_type.IsPointerType()) {
849 uint32_t ptr =
850 thread.GetRegisterContext()->ReadRegisterAsUnsigned(r2_reg_info, 0) &
851 UINT32_MAX;
852 value.GetScalar() = ptr;
853 } else if (return_compiler_type.IsAggregateType()) {
854 // Structure/Vector is always passed in memory and pointer to that memory
855 // is passed in r2.
856 uint64_t mem_address = reg_ctx->ReadRegisterAsUnsigned(
857 reg_ctx->GetRegisterInfoByName("r2", 0), 0);
858 // We have got the address. Create a memory object out of it
859 return_valobj_sp = ValueObjectMemory::Create(
860 &thread, "", Address(mem_address, nullptr), return_compiler_type);
861 return return_valobj_sp;
862 } else if (return_compiler_type.IsFloatingPointType(count, is_complex)) {
863 if (IsSoftFloat(fp_flag)) {
864 uint64_t raw_value = reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0);
865 if (count != 1 && is_complex)
866 return return_valobj_sp;
867 switch (*bit_width) {
868 default:
869 return return_valobj_sp;
870 case 32:
871 static_assert(sizeof(float) == sizeof(uint32_t));
872 value.GetScalar() = *((float *)(&raw_value));
873 break;
874 case 64:
875 static_assert(sizeof(double) == sizeof(uint64_t));
876 const RegisterInfo *r3_reg_info =
877 reg_ctx->GetRegisterInfoByName("r3", 0);
878 if (target_byte_order == eByteOrderLittle)
879 raw_value =
880 ((reg_ctx->ReadRegisterAsUnsigned(r3_reg_info, 0)) << 32) |
881 raw_value;
882 else
883 raw_value = (raw_value << 32) |
884 reg_ctx->ReadRegisterAsUnsigned(r3_reg_info, 0);
885 value.GetScalar() = *((double *)(&raw_value));
886 break;
890 else {
891 const RegisterInfo *f0_info = reg_ctx->GetRegisterInfoByName("f0", 0);
892 RegisterValue f0_value;
893 DataExtractor f0_data;
894 reg_ctx->ReadRegister(f0_info, f0_value);
895 f0_value.GetData(f0_data);
896 lldb::offset_t offset = 0;
898 if (count == 1 && !is_complex) {
899 switch (*bit_width) {
900 default:
901 return return_valobj_sp;
902 case 64: {
903 static_assert(sizeof(double) == sizeof(uint64_t));
904 const RegisterInfo *f1_info = reg_ctx->GetRegisterInfoByName("f1", 0);
905 RegisterValue f1_value;
906 DataExtractor f1_data;
907 reg_ctx->ReadRegister(f1_info, f1_value);
908 DataExtractor *copy_from_extractor = nullptr;
909 WritableDataBufferSP data_sp(new DataBufferHeap(8, 0));
910 DataExtractor return_ext(
911 data_sp, target_byte_order,
912 target->GetArchitecture().GetAddressByteSize());
914 if (target_byte_order == eByteOrderLittle) {
915 copy_from_extractor = &f0_data;
916 copy_from_extractor->CopyByteOrderedData(
917 offset, 4, data_sp->GetBytes(), 4, target_byte_order);
918 f1_value.GetData(f1_data);
919 copy_from_extractor = &f1_data;
920 copy_from_extractor->CopyByteOrderedData(
921 offset, 4, data_sp->GetBytes() + 4, 4, target_byte_order);
922 } else {
923 copy_from_extractor = &f0_data;
924 copy_from_extractor->CopyByteOrderedData(
925 offset, 4, data_sp->GetBytes() + 4, 4, target_byte_order);
926 f1_value.GetData(f1_data);
927 copy_from_extractor = &f1_data;
928 copy_from_extractor->CopyByteOrderedData(
929 offset, 4, data_sp->GetBytes(), 4, target_byte_order);
931 value.GetScalar() = (double)return_ext.GetDouble(&offset);
932 break;
934 case 32: {
935 static_assert(sizeof(float) == sizeof(uint32_t));
936 value.GetScalar() = (float)f0_data.GetFloat(&offset);
937 break;
940 } else {
941 // not handled yet
942 return return_valobj_sp;
945 } else {
946 // not handled yet
947 return return_valobj_sp;
950 // If we get here, we have a valid Value, so make our ValueObject out of it:
952 return_valobj_sp = ValueObjectConstResult::Create(
953 thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));
954 return return_valobj_sp;
957 bool ABISysV_mips::CreateFunctionEntryUnwindPlan(UnwindPlan &unwind_plan) {
958 unwind_plan.Clear();
959 unwind_plan.SetRegisterKind(eRegisterKindDWARF);
961 UnwindPlan::RowSP row(new UnwindPlan::Row);
963 // Our Call Frame Address is the stack pointer value
964 row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_r29, 0);
966 // The previous PC is in the RA
967 row->SetRegisterLocationToRegister(dwarf_pc, dwarf_r31, true);
968 unwind_plan.AppendRow(row);
970 // All other registers are the same.
972 unwind_plan.SetSourceName("mips at-func-entry default");
973 unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
974 unwind_plan.SetReturnAddressRegister(dwarf_r31);
975 return true;
978 bool ABISysV_mips::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) {
979 unwind_plan.Clear();
980 unwind_plan.SetRegisterKind(eRegisterKindDWARF);
982 UnwindPlan::RowSP row(new UnwindPlan::Row);
984 row->SetUnspecifiedRegistersAreUndefined(true);
985 row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_r29, 0);
987 row->SetRegisterLocationToRegister(dwarf_pc, dwarf_r31, true);
989 unwind_plan.AppendRow(row);
990 unwind_plan.SetSourceName("mips default unwind plan");
991 unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
992 unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo);
993 unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo);
994 return true;
997 bool ABISysV_mips::RegisterIsVolatile(const RegisterInfo *reg_info) {
998 return !RegisterIsCalleeSaved(reg_info);
1001 bool ABISysV_mips::IsSoftFloat(uint32_t fp_flags) const {
1002 return (fp_flags == lldb_private::ArchSpec::eMIPS_ABI_FP_SOFT);
1005 bool ABISysV_mips::RegisterIsCalleeSaved(const RegisterInfo *reg_info) {
1006 if (reg_info) {
1007 // Preserved registers are :
1008 // r16-r23, r28, r29, r30, r31
1009 const char *name = reg_info->name;
1011 if (name[0] == 'r') {
1012 switch (name[1]) {
1013 case '1':
1014 if (name[2] == '6' || name[2] == '7' || name[2] == '8' ||
1015 name[2] == '9') // r16-r19
1016 return name[3] == '\0';
1017 break;
1018 case '2':
1019 if (name[2] == '0' || name[2] == '1' || name[2] == '2' ||
1020 name[2] == '3' // r20-r23
1021 || name[2] == '8' || name[2] == '9') // r28 and r29
1022 return name[3] == '\0';
1023 break;
1024 case '3':
1025 if (name[2] == '0' || name[2] == '1') // r30 and r31
1026 return name[3] == '\0';
1027 break;
1030 if (name[0] == 'g' && name[1] == 'p' && name[2] == '\0') // gp (r28)
1031 return true;
1032 if (name[0] == 's' && name[1] == 'p' && name[2] == '\0') // sp (r29)
1033 return true;
1034 if (name[0] == 'f' && name[1] == 'p' && name[2] == '\0') // fp (r30)
1035 return true;
1036 if (name[0] == 'r' && name[1] == 'a' && name[2] == '\0') // ra (r31)
1037 return true;
1040 return false;
1043 void ABISysV_mips::Initialize() {
1044 PluginManager::RegisterPlugin(
1045 GetPluginNameStatic(), "System V ABI for mips targets", CreateInstance);
1048 void ABISysV_mips::Terminate() {
1049 PluginManager::UnregisterPlugin(CreateInstance);