xref: /freebsd/contrib/llvm-project/lldb/source/Plugins/ABI/RISCV/ABISysV_riscv.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1 //===-- ABISysV_riscv.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_riscv.h"
10 
11 #include <array>
12 #include <limits>
13 
14 #include "llvm/IR/DerivedTypes.h"
15 
16 #include "Utility/RISCV_DWARF_Registers.h"
17 #include "lldb/Core/PluginManager.h"
18 #include "lldb/Core/Value.h"
19 #include "lldb/Core/ValueObjectConstResult.h"
20 #include "lldb/Target/RegisterContext.h"
21 #include "lldb/Target/StackFrame.h"
22 #include "lldb/Target/Thread.h"
23 #include "lldb/Utility/RegisterValue.h"
24 
25 #define DEFINE_REG_NAME(reg_num) ConstString(#reg_num).GetCString()
26 #define DEFINE_REG_NAME_STR(reg_name) ConstString(reg_name).GetCString()
27 
28 // The ABI is not a source of such information as size, offset, encoding, etc.
29 // of a register. Just provides correct dwarf and eh_frame numbers.
30 
31 #define DEFINE_GENERIC_REGISTER_STUB(dwarf_num, str_name, generic_num)         \
32   {                                                                            \
33     DEFINE_REG_NAME(dwarf_num), DEFINE_REG_NAME_STR(str_name), 0, 0,           \
34         eEncodingInvalid, eFormatDefault,                                      \
35         {dwarf_num, dwarf_num, generic_num, LLDB_INVALID_REGNUM, dwarf_num},   \
36         nullptr, nullptr, nullptr,                                             \
37   }
38 
39 #define DEFINE_REGISTER_STUB(dwarf_num, str_name)                              \
40   DEFINE_GENERIC_REGISTER_STUB(dwarf_num, str_name, LLDB_INVALID_REGNUM)
41 
42 using namespace lldb;
43 using namespace lldb_private;
44 
45 LLDB_PLUGIN_DEFINE_ADV(ABISysV_riscv, ABIRISCV)
46 
47 namespace {
48 namespace dwarf {
49 enum regnums {
50   zero,
51   ra,
52   sp,
53   gp,
54   tp,
55   t0,
56   t1,
57   t2,
58   fp,
59   s0 = fp,
60   s1,
61   a0,
62   a1,
63   a2,
64   a3,
65   a4,
66   a5,
67   a6,
68   a7,
69   s2,
70   s3,
71   s4,
72   s5,
73   s6,
74   s7,
75   s8,
76   s9,
77   s10,
78   s11,
79   t3,
80   t4,
81   t5,
82   t6,
83   pc
84 };
85 
86 static const std::array<RegisterInfo, 33> g_register_infos = {
87     {DEFINE_REGISTER_STUB(zero, nullptr),
88      DEFINE_GENERIC_REGISTER_STUB(ra, nullptr, LLDB_REGNUM_GENERIC_RA),
89      DEFINE_GENERIC_REGISTER_STUB(sp, nullptr, LLDB_REGNUM_GENERIC_SP),
90      DEFINE_REGISTER_STUB(gp, nullptr),
91      DEFINE_REGISTER_STUB(tp, nullptr),
92      DEFINE_REGISTER_STUB(t0, nullptr),
93      DEFINE_REGISTER_STUB(t1, nullptr),
94      DEFINE_REGISTER_STUB(t2, nullptr),
95      DEFINE_GENERIC_REGISTER_STUB(fp, nullptr, LLDB_REGNUM_GENERIC_FP),
96      DEFINE_REGISTER_STUB(s1, nullptr),
97      DEFINE_GENERIC_REGISTER_STUB(a0, nullptr, LLDB_REGNUM_GENERIC_ARG1),
98      DEFINE_GENERIC_REGISTER_STUB(a1, nullptr, LLDB_REGNUM_GENERIC_ARG2),
99      DEFINE_GENERIC_REGISTER_STUB(a2, nullptr, LLDB_REGNUM_GENERIC_ARG3),
100      DEFINE_GENERIC_REGISTER_STUB(a3, nullptr, LLDB_REGNUM_GENERIC_ARG4),
101      DEFINE_GENERIC_REGISTER_STUB(a4, nullptr, LLDB_REGNUM_GENERIC_ARG5),
102      DEFINE_GENERIC_REGISTER_STUB(a5, nullptr, LLDB_REGNUM_GENERIC_ARG6),
103      DEFINE_GENERIC_REGISTER_STUB(a6, nullptr, LLDB_REGNUM_GENERIC_ARG7),
104      DEFINE_GENERIC_REGISTER_STUB(a7, nullptr, LLDB_REGNUM_GENERIC_ARG8),
105      DEFINE_REGISTER_STUB(s2, nullptr),
106      DEFINE_REGISTER_STUB(s3, nullptr),
107      DEFINE_REGISTER_STUB(s4, nullptr),
108      DEFINE_REGISTER_STUB(s5, nullptr),
109      DEFINE_REGISTER_STUB(s6, nullptr),
110      DEFINE_REGISTER_STUB(s7, nullptr),
111      DEFINE_REGISTER_STUB(s8, nullptr),
112      DEFINE_REGISTER_STUB(s9, nullptr),
113      DEFINE_REGISTER_STUB(s10, nullptr),
114      DEFINE_REGISTER_STUB(s11, nullptr),
115      DEFINE_REGISTER_STUB(t3, nullptr),
116      DEFINE_REGISTER_STUB(t4, nullptr),
117      DEFINE_REGISTER_STUB(t5, nullptr),
118      DEFINE_REGISTER_STUB(t6, nullptr),
119      DEFINE_GENERIC_REGISTER_STUB(pc, nullptr, LLDB_REGNUM_GENERIC_PC)}};
120 } // namespace dwarf
121 } // namespace
122 
GetRegisterInfoArray(uint32_t & count)123 const RegisterInfo *ABISysV_riscv::GetRegisterInfoArray(uint32_t &count) {
124   count = dwarf::g_register_infos.size();
125   return dwarf::g_register_infos.data();
126 }
127 
128 //------------------------------------------------------------------
129 // Static Functions
130 //------------------------------------------------------------------
131 
132 ABISP
CreateInstance(ProcessSP process_sp,const ArchSpec & arch)133 ABISysV_riscv::CreateInstance(ProcessSP process_sp, const ArchSpec &arch) {
134   llvm::Triple::ArchType machine = arch.GetTriple().getArch();
135 
136   if (llvm::Triple::riscv32 != machine && llvm::Triple::riscv64 != machine)
137     return ABISP();
138 
139   ABISysV_riscv *abi = new ABISysV_riscv(std::move(process_sp),
140                                          MakeMCRegisterInfo(arch));
141   if (abi)
142     abi->SetIsRV64((llvm::Triple::riscv64 == machine) ? true : false);
143   return ABISP(abi);
144 }
145 
AugmentArgSize(bool is_rv64,size_t size_in_bytes)146 static inline size_t AugmentArgSize(bool is_rv64, size_t size_in_bytes) {
147   size_t word_size = is_rv64 ? 8 : 4;
148   return llvm::alignTo(size_in_bytes, word_size);
149 }
150 
151 static size_t
TotalArgsSizeInWords(bool is_rv64,const llvm::ArrayRef<ABI::CallArgument> & args)152 TotalArgsSizeInWords(bool is_rv64,
153                      const llvm::ArrayRef<ABI::CallArgument> &args) {
154   size_t reg_size = is_rv64 ? 8 : 4;
155   size_t word_size = reg_size;
156   size_t total_size = 0;
157   for (const auto &arg : args)
158     total_size +=
159         (ABI::CallArgument::TargetValue == arg.type ? AugmentArgSize(is_rv64,
160                                                                      arg.size)
161                                                     : reg_size) /
162         word_size;
163 
164   return total_size;
165 }
166 
PrepareTrivialCall(Thread & thread,addr_t sp,addr_t func_addr,addr_t return_addr,llvm::ArrayRef<addr_t> args) const167 bool ABISysV_riscv::PrepareTrivialCall(Thread &thread, addr_t sp,
168                                        addr_t func_addr, addr_t return_addr,
169                                        llvm::ArrayRef<addr_t> args) const {
170   // TODO: Implement
171   return false;
172 }
173 
PrepareTrivialCall(Thread & thread,addr_t sp,addr_t pc,addr_t ra,llvm::Type & prototype,llvm::ArrayRef<ABI::CallArgument> args) const174 bool ABISysV_riscv::PrepareTrivialCall(
175     Thread &thread, addr_t sp, addr_t pc, addr_t ra, llvm::Type &prototype,
176     llvm::ArrayRef<ABI::CallArgument> args) const {
177   auto reg_ctx = thread.GetRegisterContext();
178   if (!reg_ctx)
179     return false;
180 
181   uint32_t pc_reg = reg_ctx->ConvertRegisterKindToRegisterNumber(
182       eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
183   if (pc_reg == LLDB_INVALID_REGNUM)
184     return false;
185 
186   uint32_t ra_reg = reg_ctx->ConvertRegisterKindToRegisterNumber(
187       eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA);
188   if (ra_reg == LLDB_INVALID_REGNUM)
189     return false;
190 
191   uint32_t sp_reg = reg_ctx->ConvertRegisterKindToRegisterNumber(
192       eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
193   if (sp_reg == LLDB_INVALID_REGNUM)
194     return false;
195 
196   Status error;
197   ProcessSP process = thread.GetProcess();
198   if (!process)
199     return false;
200 
201   size_t reg_size = m_is_rv64 ? 8 : 4;
202   size_t word_size = reg_size;
203   // Push host data onto target.
204   for (const auto &arg : args) {
205     // Skip over target values.
206     if (arg.type == ABI::CallArgument::TargetValue)
207       continue;
208 
209     // Create space on the host stack for this data 4-byte aligned.
210     sp -= AugmentArgSize(m_is_rv64, arg.size);
211 
212     if (process->WriteMemory(sp, arg.data_up.get(), arg.size, error) <
213             arg.size ||
214         error.Fail())
215       return false;
216 
217     // Update the argument with the target pointer.
218     *const_cast<addr_t *>(&arg.value) = sp;
219   }
220 
221   // Make sure number of parameters matches prototype.
222   assert(prototype.getFunctionNumParams() == args.size());
223 
224   const size_t num_args = args.size();
225   const size_t regs_for_args_count = 8U;
226   const size_t num_args_in_regs =
227       num_args > regs_for_args_count ?  regs_for_args_count : num_args;
228 
229   // Number of arguments passed on stack.
230   size_t args_size = TotalArgsSizeInWords(m_is_rv64, args);
231   auto on_stack =
232       args_size <= regs_for_args_count ? 0 : args_size - regs_for_args_count;
233   auto offset = on_stack * word_size;
234 
235   uint8_t reg_value[8];
236   size_t reg_index = LLDB_REGNUM_GENERIC_ARG1;
237 
238   for (size_t i = 0; i < args_size; ++i) {
239     auto value = reinterpret_cast<const uint8_t *>(&args[i].value);
240     auto size =
241         ABI::CallArgument::TargetValue == args[i].type ? args[i].size : reg_size;
242 
243     // Pass arguments via registers.
244     if (i < num_args_in_regs) {
245       // copy value to register, padding if arg is smaller than register
246       auto end = size < reg_size ? size : reg_size;
247       memcpy(reg_value, value, end);
248       if (reg_size > end)
249         memset(reg_value + end, 0, reg_size - end);
250 
251       RegisterValue reg_val_obj(llvm::ArrayRef(reg_value, reg_size),
252                                 eByteOrderLittle);
253       if (!reg_ctx->WriteRegister(
254               reg_ctx->GetRegisterInfo(eRegisterKindGeneric, reg_index),
255               reg_val_obj))
256         return false;
257 
258       // NOTE: It's unsafe to iterate through LLDB_REGNUM_GENERICs
259       // But the "a" registers are sequential in the RISC-V register space
260       ++reg_index;
261     }
262 
263     if (reg_index < regs_for_args_count || size == 0)
264       continue;
265 
266     // Remaining arguments are passed on the stack.
267     if (process->WriteMemory(sp - offset, value, size, error) < size ||
268         !error.Success())
269       return false;
270 
271     offset -= AugmentArgSize(m_is_rv64, size);
272   }
273 
274   // Set stack pointer immediately below arguments.
275   sp -= on_stack * word_size;
276 
277   // Update registers with current function call state.
278   reg_ctx->WriteRegisterFromUnsigned(pc_reg, pc);
279   reg_ctx->WriteRegisterFromUnsigned(ra_reg, ra);
280   reg_ctx->WriteRegisterFromUnsigned(sp_reg, sp);
281 
282   return true;
283 }
284 
GetArgumentValues(Thread & thread,ValueList & values) const285 bool ABISysV_riscv::GetArgumentValues(Thread &thread, ValueList &values) const {
286   // TODO: Implement
287   return false;
288 }
289 
SetReturnValueObject(StackFrameSP & frame_sp,ValueObjectSP & new_value_sp)290 Status ABISysV_riscv::SetReturnValueObject(StackFrameSP &frame_sp,
291                                            ValueObjectSP &new_value_sp) {
292   Status result;
293   if (!new_value_sp) {
294     result.SetErrorString("Empty value object for return value.");
295     return result;
296   }
297 
298   CompilerType compiler_type = new_value_sp->GetCompilerType();
299   if (!compiler_type) {
300     result.SetErrorString("Null clang type for return value.");
301     return result;
302   }
303 
304   auto &reg_ctx = *frame_sp->GetThread()->GetRegisterContext();
305 
306   bool is_signed = false;
307   if (!compiler_type.IsIntegerOrEnumerationType(is_signed) &&
308       !compiler_type.IsPointerType()) {
309     result.SetErrorString("We don't support returning other types at present");
310     return result;
311   }
312 
313   DataExtractor data;
314   size_t num_bytes = new_value_sp->GetData(data, result);
315 
316   if (result.Fail()) {
317     result.SetErrorStringWithFormat(
318         "Couldn't convert return value to raw data: %s", result.AsCString());
319     return result;
320   }
321 
322   size_t reg_size = m_is_rv64 ? 8 : 4;
323   if (num_bytes <= 2 * reg_size) {
324     offset_t offset = 0;
325     uint64_t raw_value = data.GetMaxU64(&offset, num_bytes);
326 
327     auto reg_info =
328         reg_ctx.GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1);
329     if (!reg_ctx.WriteRegisterFromUnsigned(reg_info, raw_value)) {
330       result.SetErrorStringWithFormat("Couldn't write value to register %s",
331                                       reg_info->name);
332       return result;
333     }
334 
335     if (num_bytes <= reg_size)
336       return result; // Successfully written.
337 
338     // for riscv32, get the upper 32 bits from raw_value and write them
339     // for riscv64, get the next 64 bits from data and write them
340     if (4 == reg_size)
341       raw_value >>= 32;
342     else
343       raw_value = data.GetMaxU64(&offset, num_bytes - reg_size);
344     reg_info =
345         reg_ctx.GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG2);
346     if (!reg_ctx.WriteRegisterFromUnsigned(reg_info, raw_value)) {
347       result.SetErrorStringWithFormat("Couldn't write value to register %s",
348                                       reg_info->name);
349     }
350 
351     return result;
352   }
353 
354   result.SetErrorString(
355       "We don't support returning large integer values at present.");
356   return result;
357 }
358 
359 template <typename T>
SetInteger(Scalar & scalar,uint64_t raw_value,bool is_signed)360 static void SetInteger(Scalar &scalar, uint64_t raw_value, bool is_signed) {
361   raw_value &= std::numeric_limits<T>::max();
362   if (is_signed)
363     scalar = static_cast<typename std::make_signed<T>::type>(raw_value);
364   else
365     scalar = static_cast<T>(raw_value);
366 }
367 
SetSizedInteger(Scalar & scalar,uint64_t raw_value,uint8_t size_in_bytes,bool is_signed)368 static bool SetSizedInteger(Scalar &scalar, uint64_t raw_value,
369                             uint8_t size_in_bytes, bool is_signed) {
370   switch (size_in_bytes) {
371   default:
372     return false;
373 
374   case sizeof(uint64_t):
375     SetInteger<uint64_t>(scalar, raw_value, is_signed);
376     break;
377 
378   case sizeof(uint32_t):
379     SetInteger<uint32_t>(scalar, raw_value, is_signed);
380     break;
381 
382   case sizeof(uint16_t):
383     SetInteger<uint16_t>(scalar, raw_value, is_signed);
384     break;
385 
386   case sizeof(uint8_t):
387     SetInteger<uint8_t>(scalar, raw_value, is_signed);
388     break;
389   }
390 
391   return true;
392 }
393 
SetSizedFloat(Scalar & scalar,uint64_t raw_value,uint8_t size_in_bytes)394 static bool SetSizedFloat(Scalar &scalar, uint64_t raw_value,
395                           uint8_t size_in_bytes) {
396   switch (size_in_bytes) {
397   default:
398     return false;
399 
400   case sizeof(uint64_t):
401     scalar = *reinterpret_cast<double *>(&raw_value);
402     break;
403 
404   case sizeof(uint32_t):
405     scalar = *reinterpret_cast<float *>(&raw_value);
406     break;
407   }
408 
409   return true;
410 }
411 
GetValObjFromIntRegs(Thread & thread,const RegisterContextSP & reg_ctx,llvm::Triple::ArchType machine,uint32_t type_flags,uint32_t byte_size)412 static ValueObjectSP GetValObjFromIntRegs(Thread &thread,
413                                           const RegisterContextSP &reg_ctx,
414                                           llvm::Triple::ArchType machine,
415                                           uint32_t type_flags,
416                                           uint32_t byte_size) {
417   Value value;
418   ValueObjectSP return_valobj_sp;
419   auto reg_info_a0 =
420       reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1);
421   auto reg_info_a1 =
422       reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG2);
423   uint64_t raw_value;
424 
425   switch (byte_size) {
426   case sizeof(uint32_t):
427     // Read a0 to get the arg
428     raw_value = reg_ctx->ReadRegisterAsUnsigned(reg_info_a0, 0) & UINT32_MAX;
429     break;
430   case sizeof(uint64_t):
431     // Read a0 to get the arg on riscv64, a0 and a1 on riscv32
432     if (llvm::Triple::riscv32 == machine) {
433       raw_value = reg_ctx->ReadRegisterAsUnsigned(reg_info_a0, 0) & UINT32_MAX;
434       raw_value |=
435           (reg_ctx->ReadRegisterAsUnsigned(reg_info_a1, 0) & UINT32_MAX) << 32U;
436     } else {
437       raw_value = reg_ctx->ReadRegisterAsUnsigned(reg_info_a0, 0);
438     }
439     break;
440   case 16: {
441     // Read a0 and a1 to get the arg on riscv64, not supported on riscv32
442     if (llvm::Triple::riscv32 == machine)
443       return return_valobj_sp;
444 
445     // Create the ValueObjectSP here and return
446     std::unique_ptr<DataBufferHeap> heap_data_up(
447         new DataBufferHeap(byte_size, 0));
448     const ByteOrder byte_order = thread.GetProcess()->GetByteOrder();
449     RegisterValue reg_value_a0, reg_value_a1;
450     if (reg_ctx->ReadRegister(reg_info_a0, reg_value_a0) &&
451         reg_ctx->ReadRegister(reg_info_a1, reg_value_a1)) {
452       Status error;
453       if (reg_value_a0.GetAsMemoryData(*reg_info_a0,
454                                        heap_data_up->GetBytes() + 0, 8,
455                                        byte_order, error) &&
456           reg_value_a1.GetAsMemoryData(*reg_info_a1,
457                                        heap_data_up->GetBytes() + 8, 8,
458                                        byte_order, error)) {
459         value.SetBytes(heap_data_up.release(), byte_size);
460         return ValueObjectConstResult::Create(
461             thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));
462       }
463     }
464     break;
465   }
466   default:
467     return return_valobj_sp;
468   }
469 
470   if (type_flags & eTypeIsInteger) {
471     const bool is_signed = (type_flags & eTypeIsSigned) != 0;
472     if (!SetSizedInteger(value.GetScalar(), raw_value, byte_size, is_signed))
473       return return_valobj_sp;
474   } else if (type_flags & eTypeIsFloat) {
475     if (!SetSizedFloat(value.GetScalar(), raw_value, byte_size))
476       return return_valobj_sp;
477   } else
478     return return_valobj_sp;
479 
480   value.SetValueType(Value::ValueType::Scalar);
481   return_valobj_sp = ValueObjectConstResult::Create(
482       thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));
483   return return_valobj_sp;
484 }
485 
486 static ValueObjectSP
GetValObjFromFPRegs(Thread & thread,const RegisterContextSP & reg_ctx,llvm::Triple::ArchType machine,uint32_t arch_fp_flags,uint32_t type_flags,uint32_t byte_size)487 GetValObjFromFPRegs(Thread &thread, const RegisterContextSP &reg_ctx,
488                     llvm::Triple::ArchType machine, uint32_t arch_fp_flags,
489                     uint32_t type_flags, uint32_t byte_size) {
490   auto reg_info_fa0 = reg_ctx->GetRegisterInfoByName("fa0");
491   bool use_fp_regs = false;
492   ValueObjectSP return_valobj_sp;
493 
494   switch (arch_fp_flags) {
495   // fp return value in integer registers a0 and possibly a1
496   case ArchSpec::eRISCV_float_abi_soft:
497     return_valobj_sp =
498         GetValObjFromIntRegs(thread, reg_ctx, machine, type_flags, byte_size);
499     return return_valobj_sp;
500   // fp return value in fp register fa0 (only float)
501   case ArchSpec::eRISCV_float_abi_single:
502     if (byte_size <= 4)
503       use_fp_regs = true;
504     break;
505   // fp return value in fp registers fa0 (float, double)
506   case ArchSpec::eRISCV_float_abi_double:
507     [[fallthrough]];
508   // fp return value in fp registers fa0 (float, double, quad)
509   // not implemented; act like they're doubles
510   case ArchSpec::eRISCV_float_abi_quad:
511     if (byte_size <= 8)
512       use_fp_regs = true;
513     break;
514   }
515 
516   if (use_fp_regs) {
517     uint64_t raw_value;
518     Value value;
519     raw_value = reg_ctx->ReadRegisterAsUnsigned(reg_info_fa0, 0);
520     if (!SetSizedFloat(value.GetScalar(), raw_value, byte_size))
521       return return_valobj_sp;
522     value.SetValueType(Value::ValueType::Scalar);
523     return ValueObjectConstResult::Create(thread.GetStackFrameAtIndex(0).get(),
524                                           value, ConstString(""));
525   }
526   // we should never reach this, but if we do, use the integer registers
527   return GetValObjFromIntRegs(thread, reg_ctx, machine, type_flags, byte_size);
528 }
529 
530 ValueObjectSP
GetReturnValueObjectSimple(Thread & thread,CompilerType & compiler_type) const531 ABISysV_riscv::GetReturnValueObjectSimple(Thread &thread,
532                                           CompilerType &compiler_type) const {
533   ValueObjectSP return_valobj_sp;
534 
535   if (!compiler_type)
536     return return_valobj_sp;
537 
538   auto reg_ctx = thread.GetRegisterContext();
539   if (!reg_ctx)
540     return return_valobj_sp;
541 
542   Value value;
543   value.SetCompilerType(compiler_type);
544 
545   const uint32_t type_flags = compiler_type.GetTypeInfo();
546   const size_t byte_size = compiler_type.GetByteSize(&thread).value_or(0);
547   const ArchSpec arch = thread.GetProcess()->GetTarget().GetArchitecture();
548   const llvm::Triple::ArchType machine = arch.GetMachine();
549 
550   // Integer return type.
551   if (type_flags & eTypeIsInteger) {
552     return_valobj_sp =
553         GetValObjFromIntRegs(thread, reg_ctx, machine, type_flags, byte_size);
554     return return_valobj_sp;
555   }
556   // Pointer return type.
557   else if (type_flags & eTypeIsPointer) {
558     auto reg_info_a0 = reg_ctx->GetRegisterInfo(eRegisterKindGeneric,
559                                                 LLDB_REGNUM_GENERIC_ARG1);
560     value.GetScalar() = reg_ctx->ReadRegisterAsUnsigned(reg_info_a0, 0);
561     value.SetValueType(Value::ValueType::Scalar);
562     return ValueObjectConstResult::Create(thread.GetStackFrameAtIndex(0).get(),
563                                           value, ConstString(""));
564   }
565   // Floating point return type.
566   else if (type_flags & eTypeIsFloat) {
567     uint32_t float_count = 0;
568     bool is_complex = false;
569 
570     if (compiler_type.IsFloatingPointType(float_count, is_complex) &&
571         float_count == 1 && !is_complex) {
572       const uint32_t arch_fp_flags =
573           arch.GetFlags() & ArchSpec::eRISCV_float_abi_mask;
574       return_valobj_sp = GetValObjFromFPRegs(
575           thread, reg_ctx, machine, arch_fp_flags, type_flags, byte_size);
576       return return_valobj_sp;
577     }
578   }
579   // Unsupported return type.
580   return return_valobj_sp;
581 }
582 
583 ValueObjectSP
GetReturnValueObjectImpl(lldb_private::Thread & thread,llvm::Type & type) const584 ABISysV_riscv::GetReturnValueObjectImpl(lldb_private::Thread &thread,
585                                         llvm::Type &type) const {
586   Value value;
587   ValueObjectSP return_valobj_sp;
588 
589   auto reg_ctx = thread.GetRegisterContext();
590   if (!reg_ctx)
591     return return_valobj_sp;
592 
593   uint32_t type_flags = 0;
594   if (type.isIntegerTy())
595     type_flags = eTypeIsInteger;
596   else if (type.isVoidTy())
597     type_flags = eTypeIsPointer;
598   else if (type.isFloatTy())
599     type_flags = eTypeIsFloat;
600 
601   const uint32_t byte_size = type.getPrimitiveSizeInBits() / CHAR_BIT;
602   const ArchSpec arch = thread.GetProcess()->GetTarget().GetArchitecture();
603   const llvm::Triple::ArchType machine = arch.GetMachine();
604 
605   // Integer return type.
606   if (type_flags & eTypeIsInteger) {
607     return_valobj_sp =
608         GetValObjFromIntRegs(thread, reg_ctx, machine, type_flags, byte_size);
609     return return_valobj_sp;
610   }
611   // Pointer return type.
612   else if (type_flags & eTypeIsPointer) {
613     auto reg_info_a0 = reg_ctx->GetRegisterInfo(eRegisterKindGeneric,
614                                                 LLDB_REGNUM_GENERIC_ARG1);
615     value.GetScalar() = reg_ctx->ReadRegisterAsUnsigned(reg_info_a0, 0);
616     value.SetValueType(Value::ValueType::Scalar);
617     return ValueObjectConstResult::Create(thread.GetStackFrameAtIndex(0).get(),
618                                           value, ConstString(""));
619   }
620   // Floating point return type.
621   else if (type_flags & eTypeIsFloat) {
622     const uint32_t arch_fp_flags =
623         arch.GetFlags() & ArchSpec::eRISCV_float_abi_mask;
624     return_valobj_sp = GetValObjFromFPRegs(
625         thread, reg_ctx, machine, arch_fp_flags, type_flags, byte_size);
626     return return_valobj_sp;
627   }
628   // Unsupported return type.
629   return return_valobj_sp;
630 }
631 
GetReturnValueObjectImpl(Thread & thread,CompilerType & return_compiler_type) const632 ValueObjectSP ABISysV_riscv::GetReturnValueObjectImpl(
633     Thread &thread, CompilerType &return_compiler_type) const {
634   ValueObjectSP return_valobj_sp;
635 
636   if (!return_compiler_type)
637     return return_valobj_sp;
638 
639   ExecutionContext exe_ctx(thread.shared_from_this());
640   return GetReturnValueObjectSimple(thread, return_compiler_type);
641 }
642 
CreateFunctionEntryUnwindPlan(UnwindPlan & unwind_plan)643 bool ABISysV_riscv::CreateFunctionEntryUnwindPlan(UnwindPlan &unwind_plan) {
644   unwind_plan.Clear();
645   unwind_plan.SetRegisterKind(eRegisterKindDWARF);
646 
647   uint32_t pc_reg_num = riscv_dwarf::dwarf_gpr_pc;
648   uint32_t sp_reg_num = riscv_dwarf::dwarf_gpr_sp;
649   uint32_t ra_reg_num = riscv_dwarf::dwarf_gpr_ra;
650 
651   UnwindPlan::RowSP row(new UnwindPlan::Row);
652 
653   // Define CFA as the stack pointer
654   row->GetCFAValue().SetIsRegisterPlusOffset(sp_reg_num, 0);
655 
656   // Previous frame's pc is in ra
657 
658   row->SetRegisterLocationToRegister(pc_reg_num, ra_reg_num, true);
659   unwind_plan.AppendRow(row);
660   unwind_plan.SetSourceName("riscv function-entry unwind plan");
661   unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
662 
663   return true;
664 }
665 
CreateDefaultUnwindPlan(UnwindPlan & unwind_plan)666 bool ABISysV_riscv::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) {
667   unwind_plan.Clear();
668   unwind_plan.SetRegisterKind(eRegisterKindGeneric);
669 
670   uint32_t pc_reg_num = LLDB_REGNUM_GENERIC_PC;
671   uint32_t fp_reg_num = LLDB_REGNUM_GENERIC_FP;
672 
673   UnwindPlan::RowSP row(new UnwindPlan::Row);
674 
675   // Define the CFA as the current frame pointer value.
676   row->GetCFAValue().SetIsRegisterPlusOffset(fp_reg_num, 0);
677   row->SetOffset(0);
678 
679   int reg_size = 4;
680   if (m_is_rv64)
681     reg_size = 8;
682 
683   // Assume the ra reg (return pc) and caller's frame pointer
684   // have been spilled to stack already.
685   row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, reg_size * -2, true);
686   row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, reg_size * -1, true);
687 
688   unwind_plan.AppendRow(row);
689   unwind_plan.SetSourceName("riscv default unwind plan");
690   unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
691   unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo);
692   return true;
693 }
694 
RegisterIsVolatile(const RegisterInfo * reg_info)695 bool ABISysV_riscv::RegisterIsVolatile(const RegisterInfo *reg_info) {
696   return !RegisterIsCalleeSaved(reg_info);
697 }
698 
RegisterIsCalleeSaved(const RegisterInfo * reg_info)699 bool ABISysV_riscv::RegisterIsCalleeSaved(const RegisterInfo *reg_info) {
700   if (!reg_info)
701     return false;
702 
703   const char *name = reg_info->name;
704   ArchSpec arch = GetProcessSP()->GetTarget().GetArchitecture();
705   uint32_t arch_flags = arch.GetFlags();
706   // floating point registers are only callee saved when using
707   // F, D or Q hardware floating point ABIs
708   bool is_hw_fp = (arch_flags & ArchSpec::eRISCV_float_abi_mask) != 0;
709 
710   bool is_callee_saved =
711       llvm::StringSwitch<bool>(name)
712           // integer ABI names
713           .Cases("ra", "sp", "fp", true)
714           .Cases("s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9",
715                  true)
716           .Cases("s10", "s11", true)
717           // integer hardware names
718           .Cases("x1", "x2", "x8", "x9", "x18", "x19", "x20", "x21", "x22",
719                  true)
720           .Cases("x23", "x24", "x25", "x26", "x27", true)
721           // floating point ABI names
722           .Cases("fs0", "fs1", "fs2", "fs3", "fs4", "fs5", "fs6", "fs7",
723                  is_hw_fp)
724           .Cases("fs8", "fs9", "fs10", "fs11", is_hw_fp)
725           // floating point hardware names
726           .Cases("f8", "f9", "f18", "f19", "f20", "f21", "f22", "f23", is_hw_fp)
727           .Cases("f24", "f25", "f26", "f27", is_hw_fp)
728           .Default(false);
729 
730   return is_callee_saved;
731 }
732 
Initialize()733 void ABISysV_riscv::Initialize() {
734   PluginManager::RegisterPlugin(
735       GetPluginNameStatic(), "System V ABI for RISCV targets", CreateInstance);
736 }
737 
Terminate()738 void ABISysV_riscv::Terminate() {
739   PluginManager::UnregisterPlugin(CreateInstance);
740 }
741 
GetGenericNum(llvm::StringRef name)742 static uint32_t GetGenericNum(llvm::StringRef name) {
743   return llvm::StringSwitch<uint32_t>(name)
744       .Case("pc", LLDB_REGNUM_GENERIC_PC)
745       .Cases("ra", "x1", LLDB_REGNUM_GENERIC_RA)
746       .Cases("sp", "x2", LLDB_REGNUM_GENERIC_SP)
747       .Cases("fp", "s0", LLDB_REGNUM_GENERIC_FP)
748       .Case("a0", LLDB_REGNUM_GENERIC_ARG1)
749       .Case("a1", LLDB_REGNUM_GENERIC_ARG2)
750       .Case("a2", LLDB_REGNUM_GENERIC_ARG3)
751       .Case("a3", LLDB_REGNUM_GENERIC_ARG4)
752       .Case("a4", LLDB_REGNUM_GENERIC_ARG5)
753       .Case("a5", LLDB_REGNUM_GENERIC_ARG6)
754       .Case("a6", LLDB_REGNUM_GENERIC_ARG7)
755       .Case("a7", LLDB_REGNUM_GENERIC_ARG8)
756       .Default(LLDB_INVALID_REGNUM);
757 }
758 
AugmentRegisterInfo(std::vector<lldb_private::DynamicRegisterInfo::Register> & regs)759 void ABISysV_riscv::AugmentRegisterInfo(
760     std::vector<lldb_private::DynamicRegisterInfo::Register> &regs) {
761   lldb_private::RegInfoBasedABI::AugmentRegisterInfo(regs);
762 
763   for (auto it : llvm::enumerate(regs)) {
764     // Set alt name for certain registers for convenience
765     if (it.value().name == "zero")
766       it.value().alt_name.SetCString("x0");
767     else if (it.value().name == "ra")
768       it.value().alt_name.SetCString("x1");
769     else if (it.value().name == "sp")
770       it.value().alt_name.SetCString("x2");
771     else if (it.value().name == "gp")
772       it.value().alt_name.SetCString("x3");
773     else if (it.value().name == "fp")
774       it.value().alt_name.SetCString("s0");
775     else if (it.value().name == "s0")
776       it.value().alt_name.SetCString("x8");
777 
778     // Set generic regnum so lldb knows what the PC, etc is
779     it.value().regnum_generic = GetGenericNum(it.value().name.GetStringRef());
780   }
781 }
782