xref: /freebsd-src/contrib/llvm-project/lldb/source/Plugins/ABI/Mips/ABISysV_mips.cpp (revision b97ee269eae3cbaf35c18f51a459aea581c2a7dc)
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 //===----------------------------------------------------------------------===//
8 
9 #include "ABISysV_mips.h"
10 
11 #include "llvm/ADT/STLExtras.h"
12 #include "llvm/ADT/Triple.h"
13 
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/Log.h"
29 #include "lldb/Utility/RegisterValue.h"
30 #include "lldb/Utility/Status.h"
31 
32 using namespace lldb;
33 using namespace lldb_private;
34 
35 LLDB_PLUGIN_DEFINE(ABISysV_mips)
36 
37 enum dwarf_regnums {
38   dwarf_r0 = 0,
39   dwarf_r1,
40   dwarf_r2,
41   dwarf_r3,
42   dwarf_r4,
43   dwarf_r5,
44   dwarf_r6,
45   dwarf_r7,
46   dwarf_r8,
47   dwarf_r9,
48   dwarf_r10,
49   dwarf_r11,
50   dwarf_r12,
51   dwarf_r13,
52   dwarf_r14,
53   dwarf_r15,
54   dwarf_r16,
55   dwarf_r17,
56   dwarf_r18,
57   dwarf_r19,
58   dwarf_r20,
59   dwarf_r21,
60   dwarf_r22,
61   dwarf_r23,
62   dwarf_r24,
63   dwarf_r25,
64   dwarf_r26,
65   dwarf_r27,
66   dwarf_r28,
67   dwarf_r29,
68   dwarf_r30,
69   dwarf_r31,
70   dwarf_sr,
71   dwarf_lo,
72   dwarf_hi,
73   dwarf_bad,
74   dwarf_cause,
75   dwarf_pc
76 };
77 
78 static const RegisterInfo g_register_infos[] = {
79     //  NAME      ALT    SZ OFF ENCODING        FORMAT         EH_FRAME
80     //  DWARF                   GENERIC                     PROCESS PLUGINS
81     //  LLDB NATIVE            VALUE REGS  INVALIDATE REGS
82     //  ========  ======  == === =============  ===========    ============
83     //  ==============          ============                =================
84     //  ===================     ========== =================
85     {"r0",
86      "zero",
87      4,
88      0,
89      eEncodingUint,
90      eFormatHex,
91      {dwarf_r0, dwarf_r0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
92       LLDB_INVALID_REGNUM},
93      nullptr,
94      nullptr,
95     },
96     {"r1",
97      "AT",
98      4,
99      0,
100      eEncodingUint,
101      eFormatHex,
102      {dwarf_r1, dwarf_r1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
103       LLDB_INVALID_REGNUM},
104      nullptr,
105      nullptr,
106     },
107     {"r2",
108      "v0",
109      4,
110      0,
111      eEncodingUint,
112      eFormatHex,
113      {dwarf_r2, dwarf_r2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
114       LLDB_INVALID_REGNUM},
115      nullptr,
116      nullptr,
117     },
118     {"r3",
119      "v1",
120      4,
121      0,
122      eEncodingUint,
123      eFormatHex,
124      {dwarf_r3, dwarf_r3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
125       LLDB_INVALID_REGNUM},
126      nullptr,
127      nullptr,
128     },
129     {"r4",
130      nullptr,
131      4,
132      0,
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     },
140     {"r5",
141      nullptr,
142      4,
143      0,
144      eEncodingUint,
145      eFormatHex,
146      {dwarf_r5, dwarf_r5, LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM,
147       LLDB_INVALID_REGNUM},
148      nullptr,
149      nullptr,
150     },
151     {"r6",
152      nullptr,
153      4,
154      0,
155      eEncodingUint,
156      eFormatHex,
157      {dwarf_r6, dwarf_r6, LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM,
158       LLDB_INVALID_REGNUM},
159      nullptr,
160      nullptr,
161     },
162     {"r7",
163      nullptr,
164      4,
165      0,
166      eEncodingUint,
167      eFormatHex,
168      {dwarf_r7, dwarf_r7, LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM,
169       LLDB_INVALID_REGNUM},
170      nullptr,
171      nullptr,
172     },
173     {"r8",
174      "arg5",
175      4,
176      0,
177      eEncodingUint,
178      eFormatHex,
179      {dwarf_r8, dwarf_r8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
180       LLDB_INVALID_REGNUM},
181      nullptr,
182      nullptr,
183     },
184     {"r9",
185      "arg6",
186      4,
187      0,
188      eEncodingUint,
189      eFormatHex,
190      {dwarf_r9, dwarf_r9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
191       LLDB_INVALID_REGNUM},
192      nullptr,
193      nullptr,
194     },
195     {"r10",
196      "arg7",
197      4,
198      0,
199      eEncodingUint,
200      eFormatHex,
201      {dwarf_r10, dwarf_r10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
202       LLDB_INVALID_REGNUM},
203      nullptr,
204      nullptr,
205     },
206     {"r11",
207      "arg8",
208      4,
209      0,
210      eEncodingUint,
211      eFormatHex,
212      {dwarf_r11, dwarf_r11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
213       LLDB_INVALID_REGNUM},
214      nullptr,
215      nullptr,
216     },
217     {"r12",
218      nullptr,
219      4,
220      0,
221      eEncodingUint,
222      eFormatHex,
223      {dwarf_r12, dwarf_r12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
224       LLDB_INVALID_REGNUM},
225      nullptr,
226      nullptr,
227     },
228     {"r13",
229      nullptr,
230      4,
231      0,
232      eEncodingUint,
233      eFormatHex,
234      {dwarf_r13, dwarf_r13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
235       LLDB_INVALID_REGNUM},
236      nullptr,
237      nullptr,
238     },
239     {"r14",
240      nullptr,
241      4,
242      0,
243      eEncodingUint,
244      eFormatHex,
245      {dwarf_r14, dwarf_r14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
246       LLDB_INVALID_REGNUM},
247      nullptr,
248      nullptr,
249     },
250     {"r15",
251      nullptr,
252      4,
253      0,
254      eEncodingUint,
255      eFormatHex,
256      {dwarf_r15, dwarf_r15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
257       LLDB_INVALID_REGNUM},
258      nullptr,
259      nullptr,
260     },
261     {"r16",
262      nullptr,
263      4,
264      0,
265      eEncodingUint,
266      eFormatHex,
267      {dwarf_r16, dwarf_r16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
268       LLDB_INVALID_REGNUM},
269      nullptr,
270      nullptr,
271     },
272     {"r17",
273      nullptr,
274      4,
275      0,
276      eEncodingUint,
277      eFormatHex,
278      {dwarf_r17, dwarf_r17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
279       LLDB_INVALID_REGNUM},
280      nullptr,
281      nullptr,
282     },
283     {"r18",
284      nullptr,
285      4,
286      0,
287      eEncodingUint,
288      eFormatHex,
289      {dwarf_r18, dwarf_r18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
290       LLDB_INVALID_REGNUM},
291      nullptr,
292      nullptr,
293     },
294     {"r19",
295      nullptr,
296      4,
297      0,
298      eEncodingUint,
299      eFormatHex,
300      {dwarf_r19, dwarf_r19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
301       LLDB_INVALID_REGNUM},
302      nullptr,
303      nullptr,
304     },
305     {"r20",
306      nullptr,
307      4,
308      0,
309      eEncodingUint,
310      eFormatHex,
311      {dwarf_r20, dwarf_r20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
312       LLDB_INVALID_REGNUM},
313      nullptr,
314      nullptr,
315     },
316     {"r21",
317      nullptr,
318      4,
319      0,
320      eEncodingUint,
321      eFormatHex,
322      {dwarf_r21, dwarf_r21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
323       LLDB_INVALID_REGNUM},
324      nullptr,
325      nullptr,
326     },
327     {"r22",
328      nullptr,
329      4,
330      0,
331      eEncodingUint,
332      eFormatHex,
333      {dwarf_r22, dwarf_r22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
334       LLDB_INVALID_REGNUM},
335      nullptr,
336      nullptr,
337     },
338     {"r23",
339      nullptr,
340      4,
341      0,
342      eEncodingUint,
343      eFormatHex,
344      {dwarf_r23, dwarf_r23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
345       LLDB_INVALID_REGNUM},
346      nullptr,
347      nullptr,
348     },
349     {"r24",
350      nullptr,
351      4,
352      0,
353      eEncodingUint,
354      eFormatHex,
355      {dwarf_r24, dwarf_r24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
356       LLDB_INVALID_REGNUM},
357      nullptr,
358      nullptr,
359     },
360     {"r25",
361      nullptr,
362      4,
363      0,
364      eEncodingUint,
365      eFormatHex,
366      {dwarf_r25, dwarf_r25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
367       LLDB_INVALID_REGNUM},
368      nullptr,
369      nullptr,
370     },
371     {"r26",
372      nullptr,
373      4,
374      0,
375      eEncodingUint,
376      eFormatHex,
377      {dwarf_r26, dwarf_r26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
378       LLDB_INVALID_REGNUM},
379      nullptr,
380      nullptr,
381     },
382     {"r27",
383      nullptr,
384      4,
385      0,
386      eEncodingUint,
387      eFormatHex,
388      {dwarf_r27, dwarf_r27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
389       LLDB_INVALID_REGNUM},
390      nullptr,
391      nullptr,
392     },
393     {"r28",
394      "gp",
395      4,
396      0,
397      eEncodingUint,
398      eFormatHex,
399      {dwarf_r28, dwarf_r28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
400       LLDB_INVALID_REGNUM},
401      nullptr,
402      nullptr,
403     },
404     {"r29",
405      nullptr,
406      4,
407      0,
408      eEncodingUint,
409      eFormatHex,
410      {dwarf_r29, dwarf_r29, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM,
411       LLDB_INVALID_REGNUM},
412      nullptr,
413      nullptr,
414     },
415     {"r30",
416      nullptr,
417      4,
418      0,
419      eEncodingUint,
420      eFormatHex,
421      {dwarf_r30, dwarf_r30, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM,
422       LLDB_INVALID_REGNUM},
423      nullptr,
424      nullptr,
425     },
426     {"r31",
427      nullptr,
428      4,
429      0,
430      eEncodingUint,
431      eFormatHex,
432      {dwarf_r31, dwarf_r31, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM,
433       LLDB_INVALID_REGNUM},
434      nullptr,
435      nullptr,
436     },
437     {"sr",
438      nullptr,
439      4,
440      0,
441      eEncodingUint,
442      eFormatHex,
443      {dwarf_sr, dwarf_sr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM,
444       LLDB_INVALID_REGNUM},
445      nullptr,
446      nullptr,
447     },
448     {"lo",
449      nullptr,
450      4,
451      0,
452      eEncodingUint,
453      eFormatHex,
454      {dwarf_lo, dwarf_lo, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
455       LLDB_INVALID_REGNUM},
456      nullptr,
457      nullptr,
458     },
459     {"hi",
460      nullptr,
461      4,
462      0,
463      eEncodingUint,
464      eFormatHex,
465      {dwarf_hi, dwarf_hi, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
466       LLDB_INVALID_REGNUM},
467      nullptr,
468      nullptr,
469     },
470     {"bad",
471      nullptr,
472      4,
473      0,
474      eEncodingUint,
475      eFormatHex,
476      {dwarf_bad, dwarf_bad, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
477       LLDB_INVALID_REGNUM},
478      nullptr,
479      nullptr,
480     },
481     {"cause",
482      nullptr,
483      4,
484      0,
485      eEncodingUint,
486      eFormatHex,
487      {dwarf_cause, dwarf_cause, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
488       LLDB_INVALID_REGNUM},
489      nullptr,
490      nullptr,
491     },
492     {"pc",
493      nullptr,
494      4,
495      0,
496      eEncodingUint,
497      eFormatHex,
498      {dwarf_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM,
499       LLDB_INVALID_REGNUM},
500      nullptr,
501      nullptr,
502     },
503 };
504 
505 static const uint32_t k_num_register_infos =
506     llvm::array_lengthof(g_register_infos);
507 
508 const lldb_private::RegisterInfo *
509 ABISysV_mips::GetRegisterInfoArray(uint32_t &count) {
510   count = k_num_register_infos;
511   return g_register_infos;
512 }
513 
514 size_t ABISysV_mips::GetRedZoneSize() const { return 0; }
515 
516 // Static Functions
517 
518 ABISP
519 ABISysV_mips::CreateInstance(lldb::ProcessSP process_sp, const ArchSpec &arch) {
520   const llvm::Triple::ArchType arch_type = arch.GetTriple().getArch();
521   if ((arch_type == llvm::Triple::mips) ||
522       (arch_type == llvm::Triple::mipsel)) {
523     return ABISP(
524         new ABISysV_mips(std::move(process_sp), MakeMCRegisterInfo(arch)));
525   }
526   return ABISP();
527 }
528 
529 bool ABISysV_mips::PrepareTrivialCall(Thread &thread, addr_t sp,
530                                       addr_t func_addr, addr_t return_addr,
531                                       llvm::ArrayRef<addr_t> args) const {
532   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
533 
534   if (log) {
535     StreamString s;
536     s.Printf("ABISysV_mips::PrepareTrivialCall (tid = 0x%" PRIx64
537              ", sp = 0x%" PRIx64 ", func_addr = 0x%" PRIx64
538              ", return_addr = 0x%" PRIx64,
539              thread.GetID(), (uint64_t)sp, (uint64_t)func_addr,
540              (uint64_t)return_addr);
541 
542     for (size_t i = 0; i < args.size(); ++i)
543       s.Printf(", arg%zd = 0x%" PRIx64, i + 1, args[i]);
544     s.PutCString(")");
545     log->PutString(s.GetString());
546   }
547 
548   RegisterContext *reg_ctx = thread.GetRegisterContext().get();
549   if (!reg_ctx)
550     return false;
551 
552   const RegisterInfo *reg_info = nullptr;
553 
554   RegisterValue reg_value;
555 
556   // Argument registers
557   const char *reg_names[] = {"r4", "r5", "r6", "r7"};
558 
559   llvm::ArrayRef<addr_t>::iterator ai = args.begin(), ae = args.end();
560 
561   // Write arguments to registers
562   for (size_t i = 0; i < llvm::array_lengthof(reg_names); ++i) {
563     if (ai == ae)
564       break;
565 
566     reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric,
567                                         LLDB_REGNUM_GENERIC_ARG1 + i);
568     LLDB_LOGF(log, "About to write arg%zd (0x%" PRIx64 ") into %s", i + 1,
569               args[i], reg_info->name);
570 
571     if (!reg_ctx->WriteRegisterFromUnsigned(reg_info, args[i]))
572       return false;
573 
574     ++ai;
575   }
576 
577   // If we have more than 4 arguments --Spill onto the stack
578   if (ai != ae) {
579     // No of arguments to go on stack
580     size_t num_stack_regs = args.size();
581 
582     // Allocate needed space for args on the stack
583     sp -= (num_stack_regs * 4);
584 
585     // Keep the stack 8 byte aligned
586     sp &= ~(8ull - 1ull);
587 
588     // just using arg1 to get the right size
589     const RegisterInfo *reg_info = reg_ctx->GetRegisterInfo(
590         eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1);
591 
592     addr_t arg_pos = sp + 16;
593 
594     size_t i = 4;
595     for (; ai != ae; ++ai) {
596       reg_value.SetUInt32(*ai);
597       LLDB_LOGF(log, "About to write arg%zd (0x%" PRIx64 ") at  0x%" PRIx64 "",
598                 i + 1, args[i], arg_pos);
599 
600       if (reg_ctx
601               ->WriteRegisterValueToMemory(reg_info, arg_pos,
602                                            reg_info->byte_size, reg_value)
603               .Fail())
604         return false;
605       arg_pos += reg_info->byte_size;
606       i++;
607     }
608   }
609 
610   Status error;
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);
619 
620   LLDB_LOGF(log, "Writing R0: 0x%" PRIx64, (uint64_t)0);
621 
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.
625   */
626   if (!reg_ctx->WriteRegisterFromUnsigned(r0_info, (uint64_t)0))
627     return false;
628 
629   LLDB_LOGF(log, "Writing SP: 0x%" PRIx64, (uint64_t)sp);
630 
631   // Set "sp" to the requested value
632   if (!reg_ctx->WriteRegisterFromUnsigned(sp_reg_info, sp))
633     return false;
634 
635   LLDB_LOGF(log, "Writing RA: 0x%" PRIx64, (uint64_t)return_addr);
636 
637   // Set "ra" to the return address
638   if (!reg_ctx->WriteRegisterFromUnsigned(ra_reg_info, return_addr))
639     return false;
640 
641   LLDB_LOGF(log, "Writing PC: 0x%" PRIx64, (uint64_t)func_addr);
642 
643   // Set pc to the address of the called function.
644   if (!reg_ctx->WriteRegisterFromUnsigned(pc_reg_info, func_addr))
645     return false;
646 
647   LLDB_LOGF(log, "Writing r25: 0x%" PRIx64, (uint64_t)func_addr);
648 
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))
652     return false;
653 
654   return true;
655 }
656 
657 bool ABISysV_mips::GetArgumentValues(Thread &thread, ValueList &values) const {
658   return false;
659 }
660 
661 Status ABISysV_mips::SetReturnValueObject(lldb::StackFrameSP &frame_sp,
662                                           lldb::ValueObjectSP &new_value_sp) {
663   Status error;
664   if (!new_value_sp) {
665     error.SetErrorString("Empty value object for return value.");
666     return error;
667   }
668 
669   CompilerType compiler_type = new_value_sp->GetCompilerType();
670   if (!compiler_type) {
671     error.SetErrorString("Null clang type for return value.");
672     return error;
673   }
674 
675   Thread *thread = frame_sp->GetThread().get();
676 
677   bool is_signed;
678   uint32_t count;
679   bool is_complex;
680 
681   RegisterContext *reg_ctx = thread->GetRegisterContext().get();
682 
683   bool set_it_simple = false;
684   if (compiler_type.IsIntegerOrEnumerationType(is_signed) ||
685       compiler_type.IsPointerType()) {
686     DataExtractor data;
687     Status data_error;
688     size_t num_bytes = new_value_sp->GetData(data, data_error);
689     if (data_error.Fail()) {
690       error.SetErrorStringWithFormat(
691           "Couldn't convert return value to raw data: %s",
692           data_error.AsCString());
693       return error;
694     }
695 
696     lldb::offset_t offset = 0;
697     if (num_bytes <= 8) {
698       const RegisterInfo *r2_info = reg_ctx->GetRegisterInfoByName("r2", 0);
699       if (num_bytes <= 4) {
700         uint32_t raw_value = data.GetMaxU32(&offset, num_bytes);
701 
702         if (reg_ctx->WriteRegisterFromUnsigned(r2_info, raw_value))
703           set_it_simple = true;
704       } else {
705         uint32_t raw_value = data.GetMaxU32(&offset, 4);
706 
707         if (reg_ctx->WriteRegisterFromUnsigned(r2_info, raw_value)) {
708           const RegisterInfo *r3_info = reg_ctx->GetRegisterInfoByName("r3", 0);
709           uint32_t raw_value = data.GetMaxU32(&offset, num_bytes - offset);
710 
711           if (reg_ctx->WriteRegisterFromUnsigned(r3_info, raw_value))
712             set_it_simple = true;
713         }
714       }
715     } else {
716       error.SetErrorString("We don't support returning longer than 64 bit "
717                            "integer values at present.");
718     }
719   } else if (compiler_type.IsFloatingPointType(count, is_complex)) {
720     if (is_complex)
721       error.SetErrorString(
722           "We don't support returning complex values at present");
723     else
724       error.SetErrorString(
725           "We don't support returning float values at present");
726   }
727 
728   if (!set_it_simple)
729     error.SetErrorString(
730         "We only support setting simple integer return types at present.");
731 
732   return error;
733 }
734 
735 ValueObjectSP ABISysV_mips::GetReturnValueObjectSimple(
736     Thread &thread, CompilerType &return_compiler_type) const {
737   ValueObjectSP return_valobj_sp;
738   return return_valobj_sp;
739 }
740 
741 ValueObjectSP ABISysV_mips::GetReturnValueObjectImpl(
742     Thread &thread, CompilerType &return_compiler_type) const {
743   ValueObjectSP return_valobj_sp;
744   Value value;
745 
746   if (!return_compiler_type)
747     return return_valobj_sp;
748 
749   ExecutionContext exe_ctx(thread.shared_from_this());
750   if (exe_ctx.GetTargetPtr() == nullptr || exe_ctx.GetProcessPtr() == nullptr)
751     return return_valobj_sp;
752 
753   Target *target = exe_ctx.GetTargetPtr();
754   const ArchSpec target_arch = target->GetArchitecture();
755   ByteOrder target_byte_order = target_arch.GetByteOrder();
756   value.SetCompilerType(return_compiler_type);
757   uint32_t fp_flag =
758       target_arch.GetFlags() & lldb_private::ArchSpec::eMIPS_ABI_FP_mask;
759 
760   RegisterContext *reg_ctx = thread.GetRegisterContext().get();
761   if (!reg_ctx)
762     return return_valobj_sp;
763 
764   bool is_signed = false;
765   bool is_complex = false;
766   uint32_t count = 0;
767 
768   // In MIPS register "r2" (v0) holds the integer function return values
769   const RegisterInfo *r2_reg_info = reg_ctx->GetRegisterInfoByName("r2", 0);
770   llvm::Optional<uint64_t> bit_width = return_compiler_type.GetBitSize(&thread);
771   if (!bit_width)
772     return return_valobj_sp;
773   if (return_compiler_type.IsIntegerOrEnumerationType(is_signed)) {
774     switch (*bit_width) {
775     default:
776       return return_valobj_sp;
777     case 64: {
778       const RegisterInfo *r3_reg_info = reg_ctx->GetRegisterInfoByName("r3", 0);
779       uint64_t raw_value;
780       raw_value = reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT32_MAX;
781       raw_value |= ((uint64_t)(reg_ctx->ReadRegisterAsUnsigned(r3_reg_info, 0) &
782                                UINT32_MAX))
783                    << 32;
784       if (is_signed)
785         value.GetScalar() = (int64_t)raw_value;
786       else
787         value.GetScalar() = (uint64_t)raw_value;
788     } break;
789     case 32:
790       if (is_signed)
791         value.GetScalar() = (int32_t)(
792             reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT32_MAX);
793       else
794         value.GetScalar() = (uint32_t)(
795             reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT32_MAX);
796       break;
797     case 16:
798       if (is_signed)
799         value.GetScalar() = (int16_t)(
800             reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT16_MAX);
801       else
802         value.GetScalar() = (uint16_t)(
803             reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT16_MAX);
804       break;
805     case 8:
806       if (is_signed)
807         value.GetScalar() = (int8_t)(
808             reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT8_MAX);
809       else
810         value.GetScalar() = (uint8_t)(
811             reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT8_MAX);
812       break;
813     }
814   } else if (return_compiler_type.IsPointerType()) {
815     uint32_t ptr =
816         thread.GetRegisterContext()->ReadRegisterAsUnsigned(r2_reg_info, 0) &
817         UINT32_MAX;
818     value.GetScalar() = ptr;
819   } else if (return_compiler_type.IsAggregateType()) {
820     // Structure/Vector is always passed in memory and pointer to that memory
821     // is passed in r2.
822     uint64_t mem_address = reg_ctx->ReadRegisterAsUnsigned(
823         reg_ctx->GetRegisterInfoByName("r2", 0), 0);
824     // We have got the address. Create a memory object out of it
825     return_valobj_sp = ValueObjectMemory::Create(
826         &thread, "", Address(mem_address, nullptr), return_compiler_type);
827     return return_valobj_sp;
828   } else if (return_compiler_type.IsFloatingPointType(count, is_complex)) {
829     if (IsSoftFloat(fp_flag)) {
830       uint64_t raw_value = reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0);
831       if (count != 1 && is_complex)
832         return return_valobj_sp;
833       switch (*bit_width) {
834       default:
835         return return_valobj_sp;
836       case 32:
837         static_assert(sizeof(float) == sizeof(uint32_t), "");
838         value.GetScalar() = *((float *)(&raw_value));
839         break;
840       case 64:
841         static_assert(sizeof(double) == sizeof(uint64_t), "");
842         const RegisterInfo *r3_reg_info =
843             reg_ctx->GetRegisterInfoByName("r3", 0);
844         if (target_byte_order == eByteOrderLittle)
845           raw_value =
846               ((reg_ctx->ReadRegisterAsUnsigned(r3_reg_info, 0)) << 32) |
847               raw_value;
848         else
849           raw_value = (raw_value << 32) |
850                       reg_ctx->ReadRegisterAsUnsigned(r3_reg_info, 0);
851         value.GetScalar() = *((double *)(&raw_value));
852         break;
853       }
854     }
855 
856     else {
857       const RegisterInfo *f0_info = reg_ctx->GetRegisterInfoByName("f0", 0);
858       RegisterValue f0_value;
859       DataExtractor f0_data;
860       reg_ctx->ReadRegister(f0_info, f0_value);
861       f0_value.GetData(f0_data);
862       lldb::offset_t offset = 0;
863 
864       if (count == 1 && !is_complex) {
865         switch (*bit_width) {
866         default:
867           return return_valobj_sp;
868         case 64: {
869           static_assert(sizeof(double) == sizeof(uint64_t), "");
870           const RegisterInfo *f1_info = reg_ctx->GetRegisterInfoByName("f1", 0);
871           RegisterValue f1_value;
872           DataExtractor f1_data;
873           reg_ctx->ReadRegister(f1_info, f1_value);
874           DataExtractor *copy_from_extractor = nullptr;
875           DataBufferSP data_sp(new DataBufferHeap(8, 0));
876           DataExtractor return_ext(
877               data_sp, target_byte_order,
878               target->GetArchitecture().GetAddressByteSize());
879 
880           if (target_byte_order == eByteOrderLittle) {
881             copy_from_extractor = &f0_data;
882             copy_from_extractor->CopyByteOrderedData(
883                 offset, 4, data_sp->GetBytes(), 4, target_byte_order);
884             f1_value.GetData(f1_data);
885             copy_from_extractor = &f1_data;
886             copy_from_extractor->CopyByteOrderedData(
887                 offset, 4, data_sp->GetBytes() + 4, 4, target_byte_order);
888           } else {
889             copy_from_extractor = &f0_data;
890             copy_from_extractor->CopyByteOrderedData(
891                 offset, 4, data_sp->GetBytes() + 4, 4, target_byte_order);
892             f1_value.GetData(f1_data);
893             copy_from_extractor = &f1_data;
894             copy_from_extractor->CopyByteOrderedData(
895                 offset, 4, data_sp->GetBytes(), 4, target_byte_order);
896           }
897           value.GetScalar() = (double)return_ext.GetDouble(&offset);
898           break;
899         }
900         case 32: {
901           static_assert(sizeof(float) == sizeof(uint32_t), "");
902           value.GetScalar() = (float)f0_data.GetFloat(&offset);
903           break;
904         }
905         }
906       } else {
907         // not handled yet
908         return return_valobj_sp;
909       }
910     }
911   } else {
912     // not handled yet
913     return return_valobj_sp;
914   }
915 
916   // If we get here, we have a valid Value, so make our ValueObject out of it:
917 
918   return_valobj_sp = ValueObjectConstResult::Create(
919       thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));
920   return return_valobj_sp;
921 }
922 
923 bool ABISysV_mips::CreateFunctionEntryUnwindPlan(UnwindPlan &unwind_plan) {
924   unwind_plan.Clear();
925   unwind_plan.SetRegisterKind(eRegisterKindDWARF);
926 
927   UnwindPlan::RowSP row(new UnwindPlan::Row);
928 
929   // Our Call Frame Address is the stack pointer value
930   row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_r29, 0);
931 
932   // The previous PC is in the RA
933   row->SetRegisterLocationToRegister(dwarf_pc, dwarf_r31, true);
934   unwind_plan.AppendRow(row);
935 
936   // All other registers are the same.
937 
938   unwind_plan.SetSourceName("mips at-func-entry default");
939   unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
940   unwind_plan.SetReturnAddressRegister(dwarf_r31);
941   return true;
942 }
943 
944 bool ABISysV_mips::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) {
945   unwind_plan.Clear();
946   unwind_plan.SetRegisterKind(eRegisterKindDWARF);
947 
948   UnwindPlan::RowSP row(new UnwindPlan::Row);
949 
950   row->SetUnspecifiedRegistersAreUndefined(true);
951   row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_r29, 0);
952 
953   row->SetRegisterLocationToRegister(dwarf_pc, dwarf_r31, true);
954 
955   unwind_plan.AppendRow(row);
956   unwind_plan.SetSourceName("mips default unwind plan");
957   unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
958   unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo);
959   unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo);
960   return true;
961 }
962 
963 bool ABISysV_mips::RegisterIsVolatile(const RegisterInfo *reg_info) {
964   return !RegisterIsCalleeSaved(reg_info);
965 }
966 
967 bool ABISysV_mips::IsSoftFloat(uint32_t fp_flags) const {
968   return (fp_flags == lldb_private::ArchSpec::eMIPS_ABI_FP_SOFT);
969 }
970 
971 bool ABISysV_mips::RegisterIsCalleeSaved(const RegisterInfo *reg_info) {
972   if (reg_info) {
973     // Preserved registers are :
974     // r16-r23, r28, r29, r30, r31
975     const char *name = reg_info->name;
976 
977     if (name[0] == 'r') {
978       switch (name[1]) {
979       case '1':
980         if (name[2] == '6' || name[2] == '7' || name[2] == '8' ||
981             name[2] == '9') // r16-r19
982           return name[3] == '\0';
983         break;
984       case '2':
985         if (name[2] == '0' || name[2] == '1' || name[2] == '2' ||
986             name[2] == '3'                       // r20-r23
987             || name[2] == '8' || name[2] == '9') // r28 and r29
988           return name[3] == '\0';
989         break;
990       case '3':
991         if (name[2] == '0' || name[2] == '1') // r30 and r31
992           return name[3] == '\0';
993         break;
994       }
995 
996       if (name[0] == 'g' && name[1] == 'p' && name[2] == '\0') // gp (r28)
997         return true;
998       if (name[0] == 's' && name[1] == 'p' && name[2] == '\0') // sp (r29)
999         return true;
1000       if (name[0] == 'f' && name[1] == 'p' && name[2] == '\0') // fp (r30)
1001         return true;
1002       if (name[0] == 'r' && name[1] == 'a' && name[2] == '\0') // ra (r31)
1003         return true;
1004     }
1005   }
1006   return false;
1007 }
1008 
1009 void ABISysV_mips::Initialize() {
1010   PluginManager::RegisterPlugin(
1011       GetPluginNameStatic(), "System V ABI for mips targets", CreateInstance);
1012 }
1013 
1014 void ABISysV_mips::Terminate() {
1015   PluginManager::UnregisterPlugin(CreateInstance);
1016 }
1017