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