1//===-- ABISysV_mips64.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_mips64.h"
10
11#include "llvm/ADT/STLExtras.h"
12#include "llvm/TargetParser/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/LLDBLog.h"
29#include "lldb/Utility/Log.h"
30#include "lldb/Utility/RegisterValue.h"
31#include "lldb/Utility/Status.h"
32#include <optional>
33
34using namespace lldb;
35using namespace lldb_private;
36
37LLDB_PLUGIN_DEFINE(ABISysV_mips64)
38
39enum 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
78};
79
80static const RegisterInfo g_register_infos_mips64[] = {
81    //  NAME      ALT    SZ OFF ENCODING        FORMAT         EH_FRAME
82    //  DWARF                   GENERIC                     PROCESS PLUGIN
83    //  LLDB NATIVE
84    //  ========  ======  == === =============  ==========     =============
85    //  =================       ====================        =================
86    //  ====================
87    {"r0",
88     "zero",
89     8,
90     0,
91     eEncodingUint,
92     eFormatHex,
93     {dwarf_r0, dwarf_r0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
94      LLDB_INVALID_REGNUM},
95     nullptr,
96     nullptr,
97     nullptr,
98    },
99    {"r1",
100     "AT",
101     8,
102     0,
103     eEncodingUint,
104     eFormatHex,
105     {dwarf_r1, dwarf_r1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
106      LLDB_INVALID_REGNUM},
107     nullptr,
108     nullptr,
109     nullptr,
110
111    },
112    {"r2",
113     "v0",
114     8,
115     0,
116     eEncodingUint,
117     eFormatHex,
118     {dwarf_r2, dwarf_r2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
119      LLDB_INVALID_REGNUM},
120     nullptr,
121     nullptr,
122     nullptr,
123    },
124    {"r3",
125     "v1",
126     8,
127     0,
128     eEncodingUint,
129     eFormatHex,
130     {dwarf_r3, dwarf_r3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
131      LLDB_INVALID_REGNUM},
132     nullptr,
133     nullptr,
134     nullptr,
135    },
136    {"r4",
137     nullptr,
138     8,
139     0,
140     eEncodingUint,
141     eFormatHex,
142     {dwarf_r4, dwarf_r4, LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM,
143      LLDB_INVALID_REGNUM},
144     nullptr,
145     nullptr,
146     nullptr,
147    },
148    {"r5",
149     nullptr,
150     8,
151     0,
152     eEncodingUint,
153     eFormatHex,
154     {dwarf_r5, dwarf_r5, LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM,
155      LLDB_INVALID_REGNUM},
156     nullptr,
157     nullptr,
158     nullptr,
159    },
160    {"r6",
161     nullptr,
162     8,
163     0,
164     eEncodingUint,
165     eFormatHex,
166     {dwarf_r6, dwarf_r6, LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM,
167      LLDB_INVALID_REGNUM},
168     nullptr,
169     nullptr,
170     nullptr,
171    },
172    {"r7",
173     nullptr,
174     8,
175     0,
176     eEncodingUint,
177     eFormatHex,
178     {dwarf_r7, dwarf_r7, LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM,
179      LLDB_INVALID_REGNUM},
180     nullptr,
181     nullptr,
182     nullptr,
183    },
184    {"r8",
185     nullptr,
186     8,
187     0,
188     eEncodingUint,
189     eFormatHex,
190     {dwarf_r8, dwarf_r8, LLDB_REGNUM_GENERIC_ARG5, LLDB_INVALID_REGNUM,
191      LLDB_INVALID_REGNUM},
192     nullptr,
193     nullptr,
194     nullptr,
195    },
196    {"r9",
197     nullptr,
198     8,
199     0,
200     eEncodingUint,
201     eFormatHex,
202     {dwarf_r9, dwarf_r9, LLDB_REGNUM_GENERIC_ARG6, LLDB_INVALID_REGNUM,
203      LLDB_INVALID_REGNUM},
204     nullptr,
205     nullptr,
206     nullptr,
207    },
208    {"r10",
209     nullptr,
210     8,
211     0,
212     eEncodingUint,
213     eFormatHex,
214     {dwarf_r10, dwarf_r10, LLDB_REGNUM_GENERIC_ARG7, LLDB_INVALID_REGNUM,
215      LLDB_INVALID_REGNUM},
216     nullptr,
217     nullptr,
218     nullptr,
219    },
220    {"r11",
221     nullptr,
222     8,
223     0,
224     eEncodingUint,
225     eFormatHex,
226     {dwarf_r11, dwarf_r11, LLDB_REGNUM_GENERIC_ARG8, LLDB_INVALID_REGNUM,
227      LLDB_INVALID_REGNUM},
228     nullptr,
229     nullptr,
230     nullptr,
231    },
232    {"r12",
233     nullptr,
234     8,
235     0,
236     eEncodingUint,
237     eFormatHex,
238     {dwarf_r12, dwarf_r12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
239      LLDB_INVALID_REGNUM},
240     nullptr,
241     nullptr,
242     nullptr,
243    },
244    {"r13",
245     nullptr,
246     8,
247     0,
248     eEncodingUint,
249     eFormatHex,
250     {dwarf_r13, dwarf_r13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
251      LLDB_INVALID_REGNUM},
252     nullptr,
253     nullptr,
254     nullptr,
255    },
256    {"r14",
257     nullptr,
258     8,
259     0,
260     eEncodingUint,
261     eFormatHex,
262     {dwarf_r14, dwarf_r14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
263      LLDB_INVALID_REGNUM},
264     nullptr,
265     nullptr,
266     nullptr,
267    },
268    {"r15",
269     nullptr,
270     8,
271     0,
272     eEncodingUint,
273     eFormatHex,
274     {dwarf_r15, dwarf_r15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
275      LLDB_INVALID_REGNUM},
276     nullptr,
277     nullptr,
278     nullptr,
279    },
280    {"r16",
281     nullptr,
282     8,
283     0,
284     eEncodingUint,
285     eFormatHex,
286     {dwarf_r16, dwarf_r16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
287      LLDB_INVALID_REGNUM},
288     nullptr,
289     nullptr,
290     nullptr,
291    },
292    {"r17",
293     nullptr,
294     8,
295     0,
296     eEncodingUint,
297     eFormatHex,
298     {dwarf_r17, dwarf_r17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
299      LLDB_INVALID_REGNUM},
300     nullptr,
301     nullptr,
302     nullptr,
303    },
304    {"r18",
305     nullptr,
306     8,
307     0,
308     eEncodingUint,
309     eFormatHex,
310     {dwarf_r18, dwarf_r18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
311      LLDB_INVALID_REGNUM},
312     nullptr,
313     nullptr,
314     nullptr,
315    },
316    {"r19",
317     nullptr,
318     8,
319     0,
320     eEncodingUint,
321     eFormatHex,
322     {dwarf_r19, dwarf_r19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
323      LLDB_INVALID_REGNUM},
324     nullptr,
325     nullptr,
326     nullptr,
327    },
328    {"r20",
329     nullptr,
330     8,
331     0,
332     eEncodingUint,
333     eFormatHex,
334     {dwarf_r20, dwarf_r20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
335      LLDB_INVALID_REGNUM},
336     nullptr,
337     nullptr,
338     nullptr,
339    },
340    {"r21",
341     nullptr,
342     8,
343     0,
344     eEncodingUint,
345     eFormatHex,
346     {dwarf_r21, dwarf_r21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
347      LLDB_INVALID_REGNUM},
348     nullptr,
349     nullptr,
350     nullptr,
351    },
352    {"r22",
353     nullptr,
354     8,
355     0,
356     eEncodingUint,
357     eFormatHex,
358     {dwarf_r22, dwarf_r22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
359      LLDB_INVALID_REGNUM},
360     nullptr,
361     nullptr,
362     nullptr,
363    },
364    {"r23",
365     nullptr,
366     8,
367     0,
368     eEncodingUint,
369     eFormatHex,
370     {dwarf_r23, dwarf_r23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
371      LLDB_INVALID_REGNUM},
372     nullptr,
373     nullptr,
374     nullptr,
375    },
376    {"r24",
377     nullptr,
378     8,
379     0,
380     eEncodingUint,
381     eFormatHex,
382     {dwarf_r24, dwarf_r24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
383      LLDB_INVALID_REGNUM},
384     nullptr,
385     nullptr,
386     nullptr,
387    },
388    {"r25",
389     nullptr,
390     8,
391     0,
392     eEncodingUint,
393     eFormatHex,
394     {dwarf_r25, dwarf_r25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
395      LLDB_INVALID_REGNUM},
396     nullptr,
397     nullptr,
398     nullptr,
399    },
400    {"r26",
401     nullptr,
402     8,
403     0,
404     eEncodingUint,
405     eFormatHex,
406     {dwarf_r26, dwarf_r26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
407      LLDB_INVALID_REGNUM},
408     nullptr,
409     nullptr,
410     nullptr,
411    },
412    {"r27",
413     nullptr,
414     8,
415     0,
416     eEncodingUint,
417     eFormatHex,
418     {dwarf_r27, dwarf_r27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
419      LLDB_INVALID_REGNUM},
420     nullptr,
421     nullptr,
422     nullptr,
423    },
424    {"r28",
425     "gp",
426     8,
427     0,
428     eEncodingUint,
429     eFormatHex,
430     {dwarf_r28, dwarf_r28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
431      LLDB_INVALID_REGNUM},
432     nullptr,
433     nullptr,
434     nullptr,
435    },
436    {"r29",
437     nullptr,
438     8,
439     0,
440     eEncodingUint,
441     eFormatHex,
442     {dwarf_r29, dwarf_r29, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM,
443      LLDB_INVALID_REGNUM},
444     nullptr,
445     nullptr,
446     nullptr,
447    },
448    {"r30",
449     nullptr,
450     8,
451     0,
452     eEncodingUint,
453     eFormatHex,
454     {dwarf_r30, dwarf_r30, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM,
455      LLDB_INVALID_REGNUM},
456     nullptr,
457     nullptr,
458     nullptr,
459    },
460    {"r31",
461     nullptr,
462     8,
463     0,
464     eEncodingUint,
465     eFormatHex,
466     {dwarf_r31, dwarf_r31, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM,
467      LLDB_INVALID_REGNUM},
468     nullptr,
469     nullptr,
470     nullptr,
471    },
472    {"sr",
473     nullptr,
474     4,
475     0,
476     eEncodingUint,
477     eFormatHex,
478     {dwarf_sr, dwarf_sr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM,
479      LLDB_INVALID_REGNUM},
480     nullptr,
481     nullptr,
482     nullptr,
483    },
484    {"lo",
485     nullptr,
486     8,
487     0,
488     eEncodingUint,
489     eFormatHex,
490     {dwarf_lo, dwarf_lo, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
491      LLDB_INVALID_REGNUM},
492     nullptr,
493     nullptr,
494     nullptr,
495    },
496    {"hi",
497     nullptr,
498     8,
499     0,
500     eEncodingUint,
501     eFormatHex,
502     {dwarf_hi, dwarf_hi, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
503      LLDB_INVALID_REGNUM},
504     nullptr,
505     nullptr,
506     nullptr,
507    },
508    {"bad",
509     nullptr,
510     8,
511     0,
512     eEncodingUint,
513     eFormatHex,
514     {dwarf_bad, dwarf_bad, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
515      LLDB_INVALID_REGNUM},
516     nullptr,
517     nullptr,
518     nullptr,
519    },
520    {"cause",
521     nullptr,
522     8,
523     0,
524     eEncodingUint,
525     eFormatHex,
526     {dwarf_cause, dwarf_cause, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
527      LLDB_INVALID_REGNUM},
528     nullptr,
529     nullptr,
530     nullptr,
531    },
532    {"pc",
533     nullptr,
534     8,
535     0,
536     eEncodingUint,
537     eFormatHex,
538     {dwarf_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM,
539      LLDB_INVALID_REGNUM},
540     nullptr,
541     nullptr,
542     nullptr,
543    },
544};
545
546static const uint32_t k_num_register_infos = std::size(g_register_infos_mips64);
547
548const lldb_private::RegisterInfo *
549ABISysV_mips64::GetRegisterInfoArray(uint32_t &count) {
550  count = k_num_register_infos;
551  return g_register_infos_mips64;
552}
553
554size_t ABISysV_mips64::GetRedZoneSize() const { return 0; }
555
556// Static Functions
557
558ABISP
559ABISysV_mips64::CreateInstance(lldb::ProcessSP process_sp, const ArchSpec &arch) {
560  if (arch.GetTriple().isMIPS64())
561    return ABISP(
562        new ABISysV_mips64(std::move(process_sp), MakeMCRegisterInfo(arch)));
563  return ABISP();
564}
565
566bool 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);
570
571  if (log) {
572    StreamString s;
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);
578
579    for (size_t i = 0; i < args.size(); ++i)
580      s.Printf(", arg%zd = 0x%" PRIx64, i + 1, args[i]);
581    s.PutCString(")");
582    log->PutString(s.GetString());
583  }
584
585  RegisterContext *reg_ctx = thread.GetRegisterContext().get();
586  if (!reg_ctx)
587    return false;
588
589  const RegisterInfo *reg_info = nullptr;
590
591  if (args.size() > 8) // TODO handle more than 8 arguments
592    return false;
593
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]))
600      return false;
601  }
602
603  // First, align the SP
604
605  LLDB_LOGF(log, "16-byte aligning SP: 0x%" PRIx64 " to 0x%" PRIx64,
606            (uint64_t)sp, (uint64_t)(sp & ~0xfull));
607
608  sp &= ~(0xfull); // 16-byte alignment
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
657bool ABISysV_mips64::GetArgumentValues(Thread &thread,
658                                       ValueList &values) const {
659  return false;
660}
661
662Status ABISysV_mips64::SetReturnValueObject(lldb::StackFrameSP &frame_sp,
663                                            lldb::ValueObjectSP &new_value_sp) {
664  Status error;
665  if (!new_value_sp) {
666    error.SetErrorString("Empty value object for return value.");
667    return error;
668  }
669
670  CompilerType compiler_type = new_value_sp->GetCompilerType();
671  if (!compiler_type) {
672    error.SetErrorString("Null clang type for return value.");
673    return error;
674  }
675
676  Thread *thread = frame_sp->GetThread().get();
677
678  RegisterContext *reg_ctx = thread->GetRegisterContext().get();
679
680  if (!reg_ctx)
681    error.SetErrorString("no registers are available");
682
683  DataExtractor data;
684  Status data_error;
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());
690    return error;
691  }
692
693  const uint32_t type_flags = compiler_type.GetTypeInfo(nullptr);
694
695  if (type_flags & eTypeIsScalar || type_flags & eTypeIsPointer) {
696    if (type_flags & eTypeIsInteger || type_flags & eTypeIsPointer) {
697      lldb::offset_t offset = 0;
698
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);
703
704          if (!reg_ctx->WriteRegisterFromUnsigned(r2_info, raw_value))
705            error.SetErrorString("failed to write register r2");
706        } else {
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);
712
713            if (!reg_ctx->WriteRegisterFromUnsigned(r3_info, raw_value))
714              error.SetErrorString("failed to write register r3");
715          } else
716            error.SetErrorString("failed to write register r2");
717        }
718      } else {
719        error.SetErrorString("We don't support returning longer than 128 bit "
720                             "integer values at present.");
721      }
722    } else if (type_flags & eTypeIsFloat) {
723      error.SetErrorString("TODO: Handle Float Types.");
724    }
725  } else if (type_flags & eTypeIsVector) {
726    error.SetErrorString("returning vector values are not supported");
727  }
728
729  return error;
730}
731
732ValueObjectSP ABISysV_mips64::GetReturnValueObjectSimple(
733    Thread &thread, CompilerType &return_compiler_type) const {
734  ValueObjectSP return_valobj_sp;
735  return return_valobj_sp;
736}
737
738ValueObjectSP ABISysV_mips64::GetReturnValueObjectImpl(
739    Thread &thread, CompilerType &return_compiler_type) const {
740  ValueObjectSP return_valobj_sp;
741  Value value;
742  Status error;
743
744  ExecutionContext exe_ctx(thread.shared_from_this());
745  if (exe_ctx.GetTargetPtr() == nullptr || exe_ctx.GetProcessPtr() == nullptr)
746    return return_valobj_sp;
747
748  value.SetCompilerType(return_compiler_type);
749
750  RegisterContext *reg_ctx = thread.GetRegisterContext().get();
751  if (!reg_ctx)
752    return return_valobj_sp;
753
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);
758  if (!byte_size)
759    return return_valobj_sp;
760  const uint32_t type_flags = return_compiler_type.GetTypeInfo(nullptr);
761  uint32_t fp_flag =
762      target_arch.GetFlags() & lldb_private::ArchSpec::eMIPS_ABI_FP_mask;
763
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.");
767
768  if (type_flags & eTypeIsScalar || type_flags & eTypeIsPointer) {
769    value.SetValueType(Value::ValueType::Scalar);
770
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
775
776      uint64_t raw_value = reg_ctx->ReadRegisterAsUnsigned(r2_info, 0);
777
778      const bool is_signed = (type_flags & eTypeIsSigned) != 0;
779      switch (*byte_size) {
780      default:
781        break;
782
783      case sizeof(uint64_t):
784        if (is_signed)
785          value.GetScalar() = (int64_t)(raw_value);
786        else
787          value.GetScalar() = (uint64_t)(raw_value);
788        success = true;
789        break;
790
791      case sizeof(uint32_t):
792        if (is_signed)
793          value.GetScalar() = (int32_t)(raw_value & UINT32_MAX);
794        else
795          value.GetScalar() = (uint32_t)(raw_value & UINT32_MAX);
796        success = true;
797        break;
798
799      case sizeof(uint16_t):
800        if (is_signed)
801          value.GetScalar() = (int16_t)(raw_value & UINT16_MAX);
802        else
803          value.GetScalar() = (uint16_t)(raw_value & UINT16_MAX);
804        success = true;
805        break;
806
807      case sizeof(uint8_t):
808        if (is_signed)
809          value.GetScalar() = (int8_t)(raw_value & UINT8_MAX);
810        else
811          value.GetScalar() = (uint8_t)(raw_value & UINT8_MAX);
812        success = true;
813        break;
814      }
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) {
821        case 4:
822          value.GetScalar() = *((float *)(&raw_value));
823          success = true;
824          break;
825        case 8:
826          value.GetScalar() = *((double *)(&raw_value));
827          success = true;
828          break;
829        case 16:
830          uint64_t result[2];
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));
835          } else {
836            result[0] = reg_ctx->ReadRegisterAsUnsigned(r3_info, 0);
837            result[1] = raw_value;
838            value.GetScalar() = *((long double *)(result));
839          }
840          success = true;
841          break;
842        }
843
844      } else {
845        if (*byte_size <= sizeof(long double)) {
846          const RegisterInfo *f0_info = reg_ctx->GetRegisterInfoByName("f0", 0);
847
848          RegisterValue f0_value;
849          DataExtractor f0_data;
850
851          reg_ctx->ReadRegister(f0_info, f0_value);
852
853          f0_value.GetData(f0_data);
854
855          lldb::offset_t offset = 0;
856          if (*byte_size == sizeof(float)) {
857            value.GetScalar() = (float)f0_data.GetFloat(&offset);
858            success = true;
859          } else if (*byte_size == sizeof(double)) {
860            value.GetScalar() = (double)f0_data.GetDouble(&offset);
861            success = true;
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());
873
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,
882                  target_byte_order);
883            } else {
884              copy_from_extractor = &f0_data;
885              copy_from_extractor->CopyByteOrderedData(
886                  0, 8, data_sp->GetBytes() + 8, *byte_size - 8,
887                  target_byte_order);
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);
892            }
893
894            return_valobj_sp = ValueObjectConstResult::Create(
895                &thread, return_compiler_type, ConstString(""), return_ext);
896            return return_valobj_sp;
897          }
898        }
899      }
900    }
901
902    if (success)
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());
912
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;
916
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.
922      bool use_r2 = false;
923      // True if return values are in r3 register.
924      bool use_r3 = false;
925      // True if the result is copied into our data buffer
926      bool sucess = false;
927      std::string name;
928      bool is_complex;
929      uint32_t count;
930      const uint32_t num_children = return_compiler_type.GetNumFields();
931
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;
936
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,
941                                                   nullptr, nullptr);
942
943          if (field_compiler_type.IsFloatingPointType(count, is_complex))
944            use_fp_regs = true;
945          else
946            found_non_fp_field = true;
947        }
948
949        if (use_fp_regs && !found_non_fp_field) {
950          // We have one or two FP-only values in this structure. Get it from
951          // f0/f2 registers.
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);
956
957          reg_ctx->ReadRegister(f0_info, f0_value);
958          reg_ctx->ReadRegister(f2_info, f2_value);
959
960          f0_value.GetData(f0_data);
961
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;
970
971            DataExtractor *copy_from_extractor = nullptr;
972            uint64_t return_value[2];
973            offset_t offset = 0;
974
975            if (idx == 0) {
976              // This case is for long double type.
977              if (*field_byte_width == 16) {
978
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);
985                  offset = 0;
986                  return_value[1] = f1_data.GetU64(&offset);
987                } else {
988                  return_value[1] = f0_data.GetU64(&offset);
989                  reg_ctx->ReadRegister(f1_info, f1_value);
990                  f1_value.GetData(f1_data);
991                  offset = 0;
992                  return_value[0] = f1_data.GetU64(&offset);
993                }
994
995                f0_data.SetData(return_value, *field_byte_width,
996                                target_byte_order);
997              }
998              copy_from_extractor = &f0_data; // This is in f0, copy from
999                                              // register to our result
1000                                              // structure
1001            } else {
1002              f2_value.GetData(f2_data);
1003              // This is in f2, copy from register to our result structure
1004              copy_from_extractor = &f2_data;
1005            }
1006
1007            // Sanity check to avoid crash
1008            if (!copy_from_extractor ||
1009                *field_byte_width > copy_from_extractor->GetByteSize())
1010              return return_valobj_sp;
1011
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,
1016                target_byte_order);
1017          }
1018
1019          // The result is in our data buffer.  Create a variable object out of
1020          // it
1021          return_valobj_sp = ValueObjectConstResult::Create(
1022              &thread, return_compiler_type, ConstString(""), return_ext);
1023
1024          return return_valobj_sp;
1025        }
1026      }
1027
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;
1033        bool is_signed;
1034        uint32_t padding;
1035
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);
1040
1041        // if we don't know the size of the field (e.g. invalid type), just
1042        // bail out
1043        if (!field_byte_width || *field_byte_width == 0)
1044          break;
1045
1046        uint32_t field_byte_offset = field_bit_offset / 8;
1047
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;
1052
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
1057              // structure
1058              integer_bytes = integer_bytes + *field_byte_width +
1059                              padding; // Increase the consumed bytes.
1060              use_r2 = true;
1061            } else {
1062              // There isn't enough space left in r2 for this field, so this
1063              // will be in r3.
1064              integer_bytes = integer_bytes + *field_byte_width +
1065                              padding; // Increase the consumed bytes.
1066              use_r3 = true;
1067            }
1068          }
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;
1073            use_r3 = true;
1074          } else {
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
1078            // object.
1079            return return_valobj_sp;
1080          }
1081        }
1082      }
1083      // Vector types up to 16 bytes are returned in GP return registers
1084      if (type_flags & eTypeIsVector) {
1085        if (*byte_size <= 8)
1086          use_r2 = true;
1087        else {
1088          use_r2 = true;
1089          use_r3 = true;
1090        }
1091      }
1092
1093      if (use_r2) {
1094        reg_ctx->ReadRegister(r2_info, r2_value);
1095
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;
1101        sucess = true;
1102      }
1103      if (use_r3) {
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);
1108
1109        if (bytes_copied != r3_info->byte_size)
1110          return return_valobj_sp;
1111        sucess = true;
1112      }
1113      if (sucess) {
1114        // The result is in our data buffer.  Create a variable object out of
1115        // it
1116        return_valobj_sp = ValueObjectConstResult::Create(
1117            &thread, return_compiler_type, ConstString(""), return_ext);
1118      }
1119      return return_valobj_sp;
1120    }
1121
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);
1126
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);
1130  }
1131  return return_valobj_sp;
1132}
1133
1134bool ABISysV_mips64::CreateFunctionEntryUnwindPlan(UnwindPlan &unwind_plan) {
1135  unwind_plan.Clear();
1136  unwind_plan.SetRegisterKind(eRegisterKindDWARF);
1137
1138  UnwindPlan::RowSP row(new UnwindPlan::Row);
1139
1140  // Our Call Frame Address is the stack pointer value
1141  row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_r29, 0);
1142
1143  // The previous PC is in the RA
1144  row->SetRegisterLocationToRegister(dwarf_pc, dwarf_r31, true);
1145  unwind_plan.AppendRow(row);
1146
1147  // All other registers are the same.
1148
1149  unwind_plan.SetSourceName("mips64 at-func-entry default");
1150  unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
1151  unwind_plan.SetReturnAddressRegister(dwarf_r31);
1152  return true;
1153}
1154
1155bool ABISysV_mips64::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) {
1156  unwind_plan.Clear();
1157  unwind_plan.SetRegisterKind(eRegisterKindDWARF);
1158
1159  UnwindPlan::RowSP row(new UnwindPlan::Row);
1160
1161  row->SetUnspecifiedRegistersAreUndefined(true);
1162  row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_r29, 0);
1163
1164  row->SetRegisterLocationToRegister(dwarf_pc, dwarf_r31, true);
1165
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);
1171  return true;
1172}
1173
1174bool ABISysV_mips64::RegisterIsVolatile(const RegisterInfo *reg_info) {
1175  return !RegisterIsCalleeSaved(reg_info);
1176}
1177
1178bool ABISysV_mips64::IsSoftFloat(uint32_t fp_flag) const {
1179  return (fp_flag == lldb_private::ArchSpec::eMIPS_ABI_FP_SOFT);
1180}
1181
1182bool ABISysV_mips64::RegisterIsCalleeSaved(const RegisterInfo *reg_info) {
1183  if (reg_info) {
1184    // Preserved registers are :
1185    // r16-r23, r28, r29, r30, r31
1186
1187    int reg = ((reg_info->byte_offset) / 8);
1188
1189    bool save = (reg >= 16) && (reg <= 23);
1190    save |= (reg >= 28) && (reg <= 31);
1191
1192    return save;
1193  }
1194  return false;
1195}
1196
1197void ABISysV_mips64::Initialize() {
1198  PluginManager::RegisterPlugin(
1199      GetPluginNameStatic(), "System V ABI for mips64 targets", CreateInstance);
1200}
1201
1202void ABISysV_mips64::Terminate() {
1203  PluginManager::UnregisterPlugin(CreateInstance);
1204}
1205