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#include <sstream>
14
15#include "llvm/ADT/STLExtras.h"
16#include "llvm/IR/DerivedTypes.h"
17
20#include "lldb/Core/Value.h"
23#include "lldb/Target/Thread.h"
27
28#define DEFINE_REG_NAME(reg_num) ConstString(#reg_num).GetCString()
29#define DEFINE_REG_NAME_STR(reg_name) ConstString(reg_name).GetCString()
30
31// The ABI is not a source of such information as size, offset, encoding, etc.
32// of a register. Just provides correct dwarf and eh_frame numbers.
33
34#define DEFINE_GENERIC_REGISTER_STUB(dwarf_num, str_name, generic_num) \
35 { \
36 DEFINE_REG_NAME(dwarf_num), DEFINE_REG_NAME_STR(str_name), 0, 0, \
37 eEncodingInvalid, eFormatDefault, \
38 {dwarf_num, dwarf_num, generic_num, LLDB_INVALID_REGNUM, dwarf_num}, \
39 nullptr, nullptr, nullptr, \
40 }
41
42#define DEFINE_REGISTER_STUB(dwarf_num, str_name) \
43 DEFINE_GENERIC_REGISTER_STUB(dwarf_num, str_name, LLDB_INVALID_REGNUM)
44
45using namespace lldb;
46using namespace lldb_private;
47
49
50namespace {
51namespace dwarf {
52enum regnums {
53 zero,
54 ra,
55 sp,
56 gp,
57 tp,
58 t0,
59 t1,
60 t2,
61 fp,
62 s0 = fp,
63 s1,
64 a0,
65 a1,
66 a2,
67 a3,
68 a4,
69 a5,
70 a6,
71 a7,
72 s2,
73 s3,
74 s4,
75 s5,
76 s6,
77 s7,
78 s8,
79 s9,
80 s10,
81 s11,
82 t3,
83 t4,
84 t5,
85 t6,
88 ft1,
89 ft2,
90 ft3,
91 ft4,
92 ft5,
93 ft6,
94 ft7,
95 fs0,
96 fs1,
97 fa0,
98 fa1,
99 fa2,
100 fa3,
101 fa4,
102 fa5,
103 fa6,
104 fa7,
105 fs2,
106 fs3,
107 fs4,
108 fs5,
109 fs6,
110 fs7,
111 fs8,
112 fs9,
113 fs10,
114 fs11,
115 ft8,
116 ft9,
117 ft10,
118 ft11
119};
120
121static const std::array<RegisterInfo, 65> g_register_infos = {
122 {DEFINE_REGISTER_STUB(zero, nullptr),
125 DEFINE_REGISTER_STUB(gp, nullptr),
127 DEFINE_REGISTER_STUB(t0, nullptr),
128 DEFINE_REGISTER_STUB(t1, nullptr),
129 DEFINE_REGISTER_STUB(t2, nullptr),
131 DEFINE_REGISTER_STUB(s1, nullptr),
140 DEFINE_REGISTER_STUB(s2, nullptr),
141 DEFINE_REGISTER_STUB(s3, nullptr),
142 DEFINE_REGISTER_STUB(s4, nullptr),
143 DEFINE_REGISTER_STUB(s5, nullptr),
144 DEFINE_REGISTER_STUB(s6, nullptr),
145 DEFINE_REGISTER_STUB(s7, nullptr),
146 DEFINE_REGISTER_STUB(s8, nullptr),
147 DEFINE_REGISTER_STUB(s9, nullptr),
148 DEFINE_REGISTER_STUB(s10, nullptr),
149 DEFINE_REGISTER_STUB(s11, nullptr),
150 DEFINE_REGISTER_STUB(t3, nullptr),
151 DEFINE_REGISTER_STUB(t4, nullptr),
152 DEFINE_REGISTER_STUB(t5, nullptr),
153 DEFINE_REGISTER_STUB(t6, nullptr),
155 DEFINE_REGISTER_STUB(ft0, nullptr),
156 DEFINE_REGISTER_STUB(ft1, nullptr),
157 DEFINE_REGISTER_STUB(ft2, nullptr),
158 DEFINE_REGISTER_STUB(ft3, nullptr),
159 DEFINE_REGISTER_STUB(ft4, nullptr),
160 DEFINE_REGISTER_STUB(ft5, nullptr),
161 DEFINE_REGISTER_STUB(ft6, nullptr),
162 DEFINE_REGISTER_STUB(ft7, nullptr),
163 DEFINE_REGISTER_STUB(fs0, nullptr),
164 DEFINE_REGISTER_STUB(fs1, nullptr),
165 DEFINE_REGISTER_STUB(fa0, nullptr),
166 DEFINE_REGISTER_STUB(fa1, nullptr),
167 DEFINE_REGISTER_STUB(fa2, nullptr),
168 DEFINE_REGISTER_STUB(fa3, nullptr),
169 DEFINE_REGISTER_STUB(fa4, nullptr),
170 DEFINE_REGISTER_STUB(fa5, nullptr),
171 DEFINE_REGISTER_STUB(fa6, nullptr),
172 DEFINE_REGISTER_STUB(fa7, nullptr),
173 DEFINE_REGISTER_STUB(fs2, nullptr),
174 DEFINE_REGISTER_STUB(fs3, nullptr),
175 DEFINE_REGISTER_STUB(fs4, nullptr),
176 DEFINE_REGISTER_STUB(fs5, nullptr),
177 DEFINE_REGISTER_STUB(fs6, nullptr),
178 DEFINE_REGISTER_STUB(fs7, nullptr),
179 DEFINE_REGISTER_STUB(fs8, nullptr),
180 DEFINE_REGISTER_STUB(fs9, nullptr),
181 DEFINE_REGISTER_STUB(fs10, nullptr),
182 DEFINE_REGISTER_STUB(fs11, nullptr),
183 DEFINE_REGISTER_STUB(ft8, nullptr),
184 DEFINE_REGISTER_STUB(ft9, nullptr),
185 DEFINE_REGISTER_STUB(ft10, nullptr),
186 DEFINE_REGISTER_STUB(ft11, nullptr)}};
187} // namespace dwarf
188} // namespace
189
190// Number of argument registers (the base integer calling convention
191// provides 8 argument registers, a0-a7)
192static constexpr size_t g_regs_for_args_count = 8U;
193
195 count = dwarf::g_register_infos.size();
196 return dwarf::g_register_infos.data();
197}
198
199//------------------------------------------------------------------
200// Static Functions
201//------------------------------------------------------------------
202
203ABISP
205 llvm::Triple::ArchType machine = arch.GetTriple().getArch();
206
207 if (llvm::Triple::riscv32 != machine && llvm::Triple::riscv64 != machine)
208 return ABISP();
209
210 ABISysV_riscv *abi = new ABISysV_riscv(std::move(process_sp),
211 MakeMCRegisterInfo(arch));
212 if (abi)
213 abi->SetIsRV64((llvm::Triple::riscv64 == machine) ? true : false);
214 return ABISP(abi);
215}
216
217static inline size_t AugmentArgSize(bool is_rv64, size_t size_in_bytes) {
218 size_t word_size = is_rv64 ? 8 : 4;
219 return llvm::alignTo(size_in_bytes, word_size);
220}
221
222static size_t
224 const llvm::ArrayRef<ABI::CallArgument> &args) {
225 size_t reg_size = is_rv64 ? 8 : 4;
226 size_t word_size = reg_size;
227 size_t total_size = 0;
228 for (const auto &arg : args)
229 total_size +=
230 (ABI::CallArgument::TargetValue == arg.type ? AugmentArgSize(is_rv64,
231 arg.size)
232 : reg_size) /
233 word_size;
234
235 return total_size;
236}
237
238static bool UpdateRegister(RegisterContext *reg_ctx,
239 const lldb::RegisterKind reg_kind,
240 const uint32_t reg_num, const addr_t value) {
242
243 const RegisterInfo *reg_info = reg_ctx->GetRegisterInfo(reg_kind, reg_num);
244
245 LLDB_LOG(log, "Writing {0}: {1:x}", reg_info->name,
246 static_cast<uint64_t>(value));
247 if (!reg_ctx->WriteRegisterFromUnsigned(reg_info, value)) {
248 LLDB_LOG(log, "Writing {0}: failed", reg_info->name);
249 return false;
250 }
251 return true;
252}
253
254static void LogInitInfo(Log &log, const Thread &thread, addr_t sp,
255 addr_t func_addr, addr_t return_addr,
256 const llvm::ArrayRef<addr_t> args) {
257 std::stringstream ss;
258 ss << "ABISysV_riscv::PrepareTrivialCall"
259 << " (tid = 0x" << std::hex << thread.GetID() << ", sp = 0x" << sp
260 << ", func_addr = 0x" << func_addr << ", return_addr = 0x" << return_addr;
261
262 for (auto [idx, arg] : enumerate(args))
263 ss << ", arg" << std::dec << idx << " = 0x" << std::hex << arg;
264 ss << ")";
265 log.PutString(ss.str());
266}
267
269 addr_t func_addr, addr_t return_addr,
270 llvm::ArrayRef<addr_t> args) const {
271 Log *log = GetLog(LLDBLog::Expressions);
272 if (log)
273 LogInitInfo(*log, thread, sp, func_addr, return_addr, args);
274
275 const auto reg_ctx_sp = thread.GetRegisterContext();
276 if (!reg_ctx_sp) {
277 LLDB_LOG(log, "Failed to get RegisterContext");
278 return false;
279 }
280
281 if (args.size() > g_regs_for_args_count) {
282 LLDB_LOG(log, "Function has {0} arguments, but only {1} are allowed!",
283 args.size(), g_regs_for_args_count);
284 return false;
285 }
286
287 // Write arguments to registers
288 for (auto [idx, arg] : enumerate(args)) {
289 const RegisterInfo *reg_info = reg_ctx_sp->GetRegisterInfo(
291 LLDB_LOG(log, "About to write arg{0} ({1:x}) into {2}", idx, arg,
292 reg_info->name);
293
294 if (!reg_ctx_sp->WriteRegisterFromUnsigned(reg_info, arg)) {
295 LLDB_LOG(log, "Failed to write arg{0} ({1:x}) into {2}", idx, arg,
296 reg_info->name);
297 return false;
298 }
299 }
300
301 if (!UpdateRegister(reg_ctx_sp.get(), eRegisterKindGeneric,
302 LLDB_REGNUM_GENERIC_PC, func_addr))
303 return false;
304 if (!UpdateRegister(reg_ctx_sp.get(), eRegisterKindGeneric,
306 return false;
307 if (!UpdateRegister(reg_ctx_sp.get(), eRegisterKindGeneric,
308 LLDB_REGNUM_GENERIC_RA, return_addr))
309 return false;
310
311 LLDB_LOG(log, "ABISysV_riscv::{0}() success", __FUNCTION__);
312 return true;
313}
314
316 Thread &thread, addr_t sp, addr_t pc, addr_t ra, llvm::Type &prototype,
317 llvm::ArrayRef<ABI::CallArgument> args) const {
318 auto reg_ctx = thread.GetRegisterContext();
319 if (!reg_ctx)
320 return false;
321
322 uint32_t pc_reg = reg_ctx->ConvertRegisterKindToRegisterNumber(
324 if (pc_reg == LLDB_INVALID_REGNUM)
325 return false;
326
327 uint32_t ra_reg = reg_ctx->ConvertRegisterKindToRegisterNumber(
329 if (ra_reg == LLDB_INVALID_REGNUM)
330 return false;
331
332 uint32_t sp_reg = reg_ctx->ConvertRegisterKindToRegisterNumber(
334 if (sp_reg == LLDB_INVALID_REGNUM)
335 return false;
336
338 ProcessSP process = thread.GetProcess();
339 if (!process)
340 return false;
341
342 size_t reg_size = m_is_rv64 ? 8 : 4;
343 size_t word_size = reg_size;
344 // Push host data onto target.
345 for (const auto &arg : args) {
346 // Skip over target values.
347 if (arg.type == ABI::CallArgument::TargetValue)
348 continue;
349
350 // Create space on the host stack for this data 4-byte aligned.
351 sp -= AugmentArgSize(m_is_rv64, arg.size);
352
353 if (process->WriteMemory(sp, arg.data_up.get(), arg.size, error) <
354 arg.size ||
355 error.Fail())
356 return false;
357
358 // Update the argument with the target pointer.
359 *const_cast<addr_t *>(&arg.value) = sp;
360 }
361
362 // Make sure number of parameters matches prototype.
363 assert(prototype.getFunctionNumParams() == args.size());
364
365 const size_t num_args = args.size();
366 const size_t num_args_in_regs =
367 num_args > g_regs_for_args_count ? g_regs_for_args_count : num_args;
368
369 // Number of arguments passed on stack.
370 size_t args_size = TotalArgsSizeInWords(m_is_rv64, args);
371 auto on_stack = args_size <= g_regs_for_args_count
372 ? 0
373 : args_size - g_regs_for_args_count;
374 auto offset = on_stack * word_size;
375
376 uint8_t reg_value[8];
377 size_t reg_index = LLDB_REGNUM_GENERIC_ARG1;
378
379 for (size_t i = 0; i < args_size; ++i) {
380 auto value = reinterpret_cast<const uint8_t *>(&args[i].value);
381 auto size =
382 ABI::CallArgument::TargetValue == args[i].type ? args[i].size : reg_size;
383
384 // Pass arguments via registers.
385 if (i < num_args_in_regs) {
386 // copy value to register, padding if arg is smaller than register
387 auto end = size < reg_size ? size : reg_size;
388 memcpy(reg_value, value, end);
389 if (reg_size > end)
390 memset(reg_value + end, 0, reg_size - end);
391
392 RegisterValue reg_val_obj(llvm::ArrayRef(reg_value, reg_size),
394 if (!reg_ctx->WriteRegister(
395 reg_ctx->GetRegisterInfo(eRegisterKindGeneric, reg_index),
396 reg_val_obj))
397 return false;
398
399 // NOTE: It's unsafe to iterate through LLDB_REGNUM_GENERICs
400 // But the "a" registers are sequential in the RISC-V register space
401 ++reg_index;
402 }
403
404 if (reg_index < g_regs_for_args_count || size == 0)
405 continue;
406
407 // Remaining arguments are passed on the stack.
408 if (process->WriteMemory(sp - offset, value, size, error) < size ||
409 !error.Success())
410 return false;
411
412 offset -= AugmentArgSize(m_is_rv64, size);
413 }
414
415 // Set stack pointer immediately below arguments.
416 sp -= on_stack * word_size;
417
418 // Update registers with current function call state.
419 reg_ctx->WriteRegisterFromUnsigned(pc_reg, pc);
420 reg_ctx->WriteRegisterFromUnsigned(ra_reg, ra);
421 reg_ctx->WriteRegisterFromUnsigned(sp_reg, sp);
422
423 return true;
424}
425
427 // TODO: Implement
428 return false;
429}
430
432 ValueObjectSP &new_value_sp) {
433 Status result;
434 if (!new_value_sp) {
435 result = Status::FromErrorString("Empty value object for return value.");
436 return result;
437 }
438
439 CompilerType compiler_type = new_value_sp->GetCompilerType();
440 if (!compiler_type) {
441 result = Status::FromErrorString("Null clang type for return value.");
442 return result;
443 }
444
445 auto &reg_ctx = *frame_sp->GetThread()->GetRegisterContext();
446
447 bool is_signed = false;
448 if (!compiler_type.IsIntegerOrEnumerationType(is_signed) &&
449 !compiler_type.IsPointerType()) {
451 "We don't support returning other types at present");
452 return result;
453 }
454
455 DataExtractor data;
456 size_t num_bytes = new_value_sp->GetData(data, result);
457
458 if (result.Fail()) {
460 "Couldn't convert return value to raw data: %s", result.AsCString());
461 return result;
462 }
463
464 size_t reg_size = m_is_rv64 ? 8 : 4;
465 if (num_bytes <= 2 * reg_size) {
466 offset_t offset = 0;
467 uint64_t raw_value = data.GetMaxU64(&offset, num_bytes);
468
469 auto reg_info =
470 reg_ctx.GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1);
471 if (!reg_ctx.WriteRegisterFromUnsigned(reg_info, raw_value)) {
473 "Couldn't write value to register %s", reg_info->name);
474 return result;
475 }
476
477 if (num_bytes <= reg_size)
478 return result; // Successfully written.
479
480 // for riscv32, get the upper 32 bits from raw_value and write them
481 // for riscv64, get the next 64 bits from data and write them
482 if (4 == reg_size)
483 raw_value >>= 32;
484 else
485 raw_value = data.GetMaxU64(&offset, num_bytes - reg_size);
486 reg_info =
487 reg_ctx.GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG2);
488 if (!reg_ctx.WriteRegisterFromUnsigned(reg_info, raw_value)) {
490 "Couldn't write value to register %s", reg_info->name);
491 }
492
493 return result;
494 }
495
497 "We don't support returning large integer values at present.");
498 return result;
499}
500
501template <typename T>
502static void SetInteger(Scalar &scalar, uint64_t raw_value, bool is_signed) {
503 raw_value &= std::numeric_limits<T>::max();
504 if (is_signed)
505 scalar = static_cast<typename std::make_signed<T>::type>(raw_value);
506 else
507 scalar = static_cast<T>(raw_value);
508}
509
510static bool SetSizedInteger(Scalar &scalar, uint64_t raw_value,
511 uint8_t size_in_bytes, bool is_signed) {
512 switch (size_in_bytes) {
513 default:
514 return false;
515
516 case sizeof(uint64_t):
517 SetInteger<uint64_t>(scalar, raw_value, is_signed);
518 break;
519
520 case sizeof(uint32_t):
521 SetInteger<uint32_t>(scalar, raw_value, is_signed);
522 break;
523
524 case sizeof(uint16_t):
525 SetInteger<uint16_t>(scalar, raw_value, is_signed);
526 break;
527
528 case sizeof(uint8_t):
529 SetInteger<uint8_t>(scalar, raw_value, is_signed);
530 break;
531 }
532
533 return true;
534}
535
536static bool SetSizedFloat(Scalar &scalar, uint64_t raw_value,
537 uint8_t size_in_bytes) {
538 switch (size_in_bytes) {
539 default:
540 return false;
541
542 case sizeof(uint64_t):
543 scalar = *reinterpret_cast<double *>(&raw_value);
544 break;
545
546 case sizeof(uint32_t):
547 scalar = *reinterpret_cast<float *>(&raw_value);
548 break;
549 }
550
551 return true;
552}
553
555 const RegisterContextSP &reg_ctx,
556 llvm::Triple::ArchType machine,
557 uint32_t type_flags,
558 uint32_t byte_size) {
559 Value value;
560 ValueObjectSP return_valobj_sp;
561 auto reg_info_a0 =
562 reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1);
563 auto reg_info_a1 =
564 reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG2);
565 uint64_t raw_value;
566
567 switch (byte_size) {
568 case sizeof(uint32_t):
569 // Read a0 to get the arg
570 raw_value = reg_ctx->ReadRegisterAsUnsigned(reg_info_a0, 0) & UINT32_MAX;
571 break;
572 case sizeof(uint64_t):
573 // Read a0 to get the arg on riscv64, a0 and a1 on riscv32
574 if (llvm::Triple::riscv32 == machine) {
575 raw_value = reg_ctx->ReadRegisterAsUnsigned(reg_info_a0, 0) & UINT32_MAX;
576 raw_value |=
577 (reg_ctx->ReadRegisterAsUnsigned(reg_info_a1, 0) & UINT32_MAX) << 32U;
578 } else {
579 raw_value = reg_ctx->ReadRegisterAsUnsigned(reg_info_a0, 0);
580 }
581 break;
582 case 16: {
583 // Read a0 and a1 to get the arg on riscv64, not supported on riscv32
584 if (llvm::Triple::riscv32 == machine)
585 return return_valobj_sp;
586
587 // Create the ValueObjectSP here and return
588 std::unique_ptr<DataBufferHeap> heap_data_up(
589 new DataBufferHeap(byte_size, 0));
590 const ByteOrder byte_order = thread.GetProcess()->GetByteOrder();
591 RegisterValue reg_value_a0, reg_value_a1;
592 if (reg_ctx->ReadRegister(reg_info_a0, reg_value_a0) &&
593 reg_ctx->ReadRegister(reg_info_a1, reg_value_a1)) {
595 if (reg_value_a0.GetAsMemoryData(*reg_info_a0,
596 heap_data_up->GetBytes() + 0, 8,
597 byte_order, error) &&
598 reg_value_a1.GetAsMemoryData(*reg_info_a1,
599 heap_data_up->GetBytes() + 8, 8,
600 byte_order, error)) {
601 value.SetBytes(heap_data_up.release(), byte_size);
603 thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));
604 }
605 }
606 break;
607 }
608 default:
609 return return_valobj_sp;
610 }
611
612 if (type_flags & eTypeIsInteger) {
613 const bool is_signed = (type_flags & eTypeIsSigned) != 0;
614 if (!SetSizedInteger(value.GetScalar(), raw_value, byte_size, is_signed))
615 return return_valobj_sp;
616 } else if (type_flags & eTypeIsFloat) {
617 if (!SetSizedFloat(value.GetScalar(), raw_value, byte_size))
618 return return_valobj_sp;
619 } else
620 return return_valobj_sp;
621
623 return_valobj_sp = ValueObjectConstResult::Create(
624 thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));
625 return return_valobj_sp;
626}
627
628static ValueObjectSP
630 llvm::Triple::ArchType machine, uint32_t arch_fp_flags,
631 uint32_t type_flags, uint32_t byte_size) {
632 auto reg_info_fa0 = reg_ctx->GetRegisterInfoByName("fa0");
633 bool use_fp_regs = false;
634 ValueObjectSP return_valobj_sp;
635
636 switch (arch_fp_flags) {
637 // fp return value in integer registers a0 and possibly a1
639 return_valobj_sp =
640 GetValObjFromIntRegs(thread, reg_ctx, machine, type_flags, byte_size);
641 return return_valobj_sp;
642 // fp return value in fp register fa0 (only float)
644 if (byte_size <= 4)
645 use_fp_regs = true;
646 break;
647 // fp return value in fp registers fa0 (float, double)
649 [[fallthrough]];
650 // fp return value in fp registers fa0 (float, double, quad)
651 // not implemented; act like they're doubles
653 if (byte_size <= 8)
654 use_fp_regs = true;
655 break;
656 }
657
658 if (use_fp_regs) {
659 uint64_t raw_value;
660 Value value;
661 raw_value = reg_ctx->ReadRegisterAsUnsigned(reg_info_fa0, 0);
662 if (!SetSizedFloat(value.GetScalar(), raw_value, byte_size))
663 return return_valobj_sp;
665 return ValueObjectConstResult::Create(thread.GetStackFrameAtIndex(0).get(),
666 value, ConstString(""));
667 }
668 // we should never reach this, but if we do, use the integer registers
669 return GetValObjFromIntRegs(thread, reg_ctx, machine, type_flags, byte_size);
670}
671
674 CompilerType &compiler_type) const {
675 ValueObjectSP return_valobj_sp;
676
677 if (!compiler_type)
678 return return_valobj_sp;
679
680 auto reg_ctx = thread.GetRegisterContext();
681 if (!reg_ctx)
682 return return_valobj_sp;
683
684 Value value;
685 value.SetCompilerType(compiler_type);
686
687 const uint32_t type_flags = compiler_type.GetTypeInfo();
688 const size_t byte_size =
689 llvm::expectedToOptional(compiler_type.GetByteSize(&thread)).value_or(0);
690 const ArchSpec arch = thread.GetProcess()->GetTarget().GetArchitecture();
691 const llvm::Triple::ArchType machine = arch.GetMachine();
692
693 // Integer return type.
694 if (type_flags & eTypeIsInteger) {
695 return_valobj_sp =
696 GetValObjFromIntRegs(thread, reg_ctx, machine, type_flags, byte_size);
697 return return_valobj_sp;
698 }
699 // Pointer return type.
700 else if (type_flags & eTypeIsPointer) {
701 auto reg_info_a0 = reg_ctx->GetRegisterInfo(eRegisterKindGeneric,
703 value.GetScalar() = reg_ctx->ReadRegisterAsUnsigned(reg_info_a0, 0);
705 return ValueObjectConstResult::Create(thread.GetStackFrameAtIndex(0).get(),
706 value, ConstString(""));
707 }
708 // Floating point return type.
709 else if (compiler_type.IsRealFloatingPointType()) {
710 const uint32_t arch_fp_flags =
712 return_valobj_sp = GetValObjFromFPRegs(
713 thread, reg_ctx, machine, arch_fp_flags, type_flags, byte_size);
714 return return_valobj_sp;
715 }
716
717 // Unsupported return type.
718 return return_valobj_sp;
719}
720
723 llvm::Type &type) const {
724 Value value;
725 ValueObjectSP return_valobj_sp;
726
727 auto reg_ctx = thread.GetRegisterContext();
728 if (!reg_ctx)
729 return return_valobj_sp;
730
731 uint32_t type_flags = 0;
732 if (type.isIntegerTy())
733 type_flags = eTypeIsInteger;
734 else if (type.isVoidTy())
735 type_flags = eTypeIsPointer;
736 else if (type.isFloatTy())
737 type_flags = eTypeIsFloat;
738
739 const uint32_t byte_size = type.getPrimitiveSizeInBits() / CHAR_BIT;
740 const ArchSpec arch = thread.GetProcess()->GetTarget().GetArchitecture();
741 const llvm::Triple::ArchType machine = arch.GetMachine();
742
743 // Integer return type.
744 if (type_flags & eTypeIsInteger) {
745 return_valobj_sp =
746 GetValObjFromIntRegs(thread, reg_ctx, machine, type_flags, byte_size);
747 return return_valobj_sp;
748 }
749 // Pointer return type.
750 else if (type_flags & eTypeIsPointer) {
751 auto reg_info_a0 = reg_ctx->GetRegisterInfo(eRegisterKindGeneric,
753 value.GetScalar() = reg_ctx->ReadRegisterAsUnsigned(reg_info_a0, 0);
755 return ValueObjectConstResult::Create(thread.GetStackFrameAtIndex(0).get(),
756 value, ConstString(""));
757 }
758 // Floating point return type.
759 else if (type_flags & eTypeIsFloat) {
760 const uint32_t arch_fp_flags =
762 return_valobj_sp = GetValObjFromFPRegs(
763 thread, reg_ctx, machine, arch_fp_flags, type_flags, byte_size);
764 return return_valobj_sp;
765 }
766 // Unsupported return type.
767 return return_valobj_sp;
768}
769
771 Thread &thread, CompilerType &return_compiler_type) const {
772 ValueObjectSP return_valobj_sp;
773
774 if (!return_compiler_type)
775 return return_valobj_sp;
776
777 ExecutionContext exe_ctx(thread.shared_from_this());
778 return GetReturnValueObjectSimple(thread, return_compiler_type);
779}
780
782 uint32_t pc_reg_num = riscv_dwarf::dwarf_gpr_pc;
783 uint32_t sp_reg_num = riscv_dwarf::dwarf_gpr_sp;
784 uint32_t ra_reg_num = riscv_dwarf::dwarf_gpr_ra;
785
786 UnwindPlan::Row row;
787
788 // Define CFA as the stack pointer
789 row.GetCFAValue().SetIsRegisterPlusOffset(sp_reg_num, 0);
790
791 // Previous frame's pc is in ra
792 row.SetRegisterLocationToRegister(pc_reg_num, ra_reg_num, true);
793
794 auto plan_sp = std::make_shared<UnwindPlan>(eRegisterKindDWARF);
795 plan_sp->AppendRow(std::move(row));
796 plan_sp->SetSourceName("riscv function-entry unwind plan");
797 plan_sp->SetSourcedFromCompiler(eLazyBoolNo);
798 plan_sp->SetUnwindPlanForSignalTrap(eLazyBoolNo);
799
800 return plan_sp;
801}
802
804 uint32_t pc_reg_num = LLDB_REGNUM_GENERIC_PC;
805 uint32_t fp_reg_num = LLDB_REGNUM_GENERIC_FP;
806
807 UnwindPlan::Row row;
808
809 // Define the CFA as the current frame pointer value.
810 row.GetCFAValue().SetIsRegisterPlusOffset(fp_reg_num, 0);
811
812 int reg_size = 4;
813 if (m_is_rv64)
814 reg_size = 8;
815
816 // Assume the ra reg (return pc) and caller's frame pointer
817 // have been spilled to stack already.
818 row.SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, reg_size * -2, true);
819 row.SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, reg_size * -1, true);
821
822 auto plan_sp = std::make_shared<UnwindPlan>(eRegisterKindGeneric);
823 plan_sp->AppendRow(std::move(row));
824 plan_sp->SetSourceName("riscv default unwind plan");
825 plan_sp->SetSourcedFromCompiler(eLazyBoolNo);
826 plan_sp->SetUnwindPlanValidAtAllInstructions(eLazyBoolNo);
827 plan_sp->SetUnwindPlanForSignalTrap(eLazyBoolNo);
828
829 return plan_sp;
830}
831
833 return !RegisterIsCalleeSaved(reg_info);
834}
835
837 if (!reg_info)
838 return false;
839
840 const char *name = reg_info->name;
841 ArchSpec arch = GetProcessSP()->GetTarget().GetArchitecture();
842 uint32_t arch_flags = arch.GetFlags();
843 // floating point registers are only callee saved when using
844 // F, D or Q hardware floating point ABIs
845 bool is_hw_fp = (arch_flags & ArchSpec::eRISCV_float_abi_mask) != 0;
846
847 bool is_callee_saved =
848 llvm::StringSwitch<bool>(name)
849 // integer ABI names
850 .Cases({"ra", "sp", "fp"}, true)
851 .Cases({"s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9"},
852 true)
853 .Cases({"s10", "s11"}, true)
854 // integer hardware names
855 .Cases({"x1", "x2", "x8", "x9", "x18", "x19", "x20", "x21", "x22"},
856 true)
857 .Cases({"x23", "x24", "x25", "x26", "x27"}, true)
858 // floating point ABI names
859 .Cases({"fs0", "fs1", "fs2", "fs3", "fs4", "fs5", "fs6", "fs7"},
860 is_hw_fp)
861 .Cases({"fs8", "fs9", "fs10", "fs11"}, is_hw_fp)
862 // floating point hardware names
863 .Cases({"f8", "f9", "f18", "f19", "f20", "f21", "f22", "f23"},
864 is_hw_fp)
865 .Cases({"f24", "f25", "f26", "f27"}, is_hw_fp)
866 // vlenb is constant and needed for vector unwinding.
867 .Case("vlenb", true)
868 .Default(false);
869
870 return is_callee_saved;
871}
872
875 GetPluginNameStatic(), "System V ABI for RISCV targets", CreateInstance);
876}
877
881
882static uint32_t GetGenericNum(llvm::StringRef name) {
883 return llvm::StringSwitch<uint32_t>(name)
884 .Case("pc", LLDB_REGNUM_GENERIC_PC)
885 .Cases({"ra", "x1"}, LLDB_REGNUM_GENERIC_RA)
886 .Cases({"sp", "x2"}, LLDB_REGNUM_GENERIC_SP)
887 .Cases({"fp", "s0", "x8"}, LLDB_REGNUM_GENERIC_FP)
888 .Cases({"tp", "x4"}, LLDB_REGNUM_GENERIC_TP)
889 .Case("a0", LLDB_REGNUM_GENERIC_ARG1)
890 .Case("a1", LLDB_REGNUM_GENERIC_ARG2)
891 .Case("a2", LLDB_REGNUM_GENERIC_ARG3)
892 .Case("a3", LLDB_REGNUM_GENERIC_ARG4)
893 .Case("a4", LLDB_REGNUM_GENERIC_ARG5)
894 .Case("a5", LLDB_REGNUM_GENERIC_ARG6)
895 .Case("a6", LLDB_REGNUM_GENERIC_ARG7)
896 .Case("a7", LLDB_REGNUM_GENERIC_ARG8)
897 .Default(LLDB_INVALID_REGNUM);
898}
899
901 std::vector<lldb_private::DynamicRegisterInfo::Register> &regs) {
903
904 for (auto it : llvm::enumerate(regs)) {
905 // Set alt name for certain registers for convenience
906 if (it.value().name == "zero")
907 it.value().alt_name.SetCString("x0");
908 else if (it.value().name == "ra")
909 it.value().alt_name.SetCString("x1");
910 else if (it.value().name == "sp")
911 it.value().alt_name.SetCString("x2");
912 else if (it.value().name == "gp")
913 it.value().alt_name.SetCString("x3");
914 else if (it.value().name == "fp") {
915 it.value().name.SetCString("s0");
916 it.value().alt_name.SetCString("x8");
917 } else if (it.value().name == "tp")
918 it.value().alt_name.SetCString("x4");
919 else if (it.value().name == "s0")
920 it.value().alt_name.SetCString("x8");
921 else if (it.value().name == "s1")
922 it.value().alt_name.SetCString("x9");
923 else if (it.value().name == "t0")
924 it.value().alt_name.SetCString("x5");
925 else if (it.value().name == "t1")
926 it.value().alt_name.SetCString("x6");
927 else if (it.value().name == "t2")
928 it.value().alt_name.SetCString("x7");
929 else if (it.value().name == "a0")
930 it.value().alt_name.SetCString("x10");
931 else if (it.value().name == "a1")
932 it.value().alt_name.SetCString("x11");
933 else if (it.value().name == "a2")
934 it.value().alt_name.SetCString("x12");
935 else if (it.value().name == "a3")
936 it.value().alt_name.SetCString("x13");
937 else if (it.value().name == "a4")
938 it.value().alt_name.SetCString("x14");
939 else if (it.value().name == "a5")
940 it.value().alt_name.SetCString("x15");
941 else if (it.value().name == "a6")
942 it.value().alt_name.SetCString("x16");
943 else if (it.value().name == "a7")
944 it.value().alt_name.SetCString("x17");
945 else if (it.value().name == "s2")
946 it.value().alt_name.SetCString("x18");
947 else if (it.value().name == "s3")
948 it.value().alt_name.SetCString("x19");
949 else if (it.value().name == "s4")
950 it.value().alt_name.SetCString("x20");
951 else if (it.value().name == "s5")
952 it.value().alt_name.SetCString("x21");
953 else if (it.value().name == "s6")
954 it.value().alt_name.SetCString("x22");
955 else if (it.value().name == "s7")
956 it.value().alt_name.SetCString("x23");
957 else if (it.value().name == "s8")
958 it.value().alt_name.SetCString("x24");
959 else if (it.value().name == "s9")
960 it.value().alt_name.SetCString("x25");
961 else if (it.value().name == "s10")
962 it.value().alt_name.SetCString("x26");
963 else if (it.value().name == "s11")
964 it.value().alt_name.SetCString("x27");
965 else if (it.value().name == "t3")
966 it.value().alt_name.SetCString("x28");
967 else if (it.value().name == "t4")
968 it.value().alt_name.SetCString("x29");
969 else if (it.value().name == "t5")
970 it.value().alt_name.SetCString("x30");
971 else if (it.value().name == "t6")
972 it.value().alt_name.SetCString("x31");
973
974 // Set generic regnum so lldb knows what the PC, etc is
975 it.value().regnum_generic = GetGenericNum(it.value().name.GetStringRef());
976 }
977}
static const RegisterInfo g_register_infos[]
#define DEFINE_REGISTER_STUB(dwarf_num, str_name)
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)
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 bool UpdateRegister(RegisterContext *reg_ctx, const lldb::RegisterKind reg_kind, const uint32_t reg_num, const addr_t value)
static void LogInitInfo(Log &log, const Thread &thread, addr_t sp, addr_t func_addr, addr_t return_addr, const llvm::ArrayRef< addr_t > args)
static ValueObjectSP GetValObjFromFPRegs(Thread &thread, const RegisterContextSP &reg_ctx, llvm::Triple::ArchType machine, uint32_t type_flags, uint32_t byte_size)
static uint32_t GetGenericNum(llvm::StringRef name)
static constexpr size_t g_regs_for_args_count
static ValueObjectSP GetValObjFromIntRegs(Thread &thread, const RegisterContextSP &reg_ctx, llvm::Triple::ArchType machine, uint32_t type_flags, uint32_t byte_size)
static bool UpdateRegister(RegisterContext *reg_ctx, const lldb::RegisterKind reg_kind, const uint32_t reg_num, const addr_t value)
static void LogInitInfo(Log &log, const Thread &thread, addr_t sp, addr_t func_addr, addr_t return_addr, const llvm::ArrayRef< addr_t > args)
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_LOG(log,...)
The LLDB_LOG* macros defined below are the way to emit log messages.
Definition Log.h:375
#define LLDB_PLUGIN_DEFINE_ADV(ClassName, PluginName)
static void Initialize()
static llvm::StringRef GetPluginNameStatic()
bool RegisterIsCalleeSaved(const lldb_private::RegisterInfo *reg_info)
void SetIsRV64(bool is_rv64)
lldb::UnwindPlanSP CreateDefaultUnwindPlan() override
void AugmentRegisterInfo(std::vector< lldb_private::DynamicRegisterInfo::Register > &regs) override
lldb::UnwindPlanSP CreateFunctionEntryUnwindPlan() 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:225
lldb::ProcessSP GetProcessSP() const
Request to get a Process shared pointer.
Definition ABI.h:97
An architecture specification class.
Definition ArchSpec.h:32
llvm::Triple & GetTriple()
Architecture triple accessor.
Definition ArchSpec.h:547
uint32_t GetFlags() const
Definition ArchSpec.h:618
llvm::Triple::ArchType GetMachine() const
Returns a machine family for the current architecture.
Definition ArchSpec.cpp:886
@ eRISCV_float_abi_double
single precision floating point, +f
Definition ArchSpec.h:98
@ eRISCV_float_abi_soft
RVC, +c.
Definition ArchSpec.h:96
@ eRISCV_float_abi_quad
double precision floating point, +d
Definition ArchSpec.h:99
@ eRISCV_float_abi_mask
quad precision floating point, +q
Definition ArchSpec.h:100
@ eRISCV_float_abi_single
soft float
Definition ArchSpec.h:97
Generic representation of a type in a programming language.
llvm::Expected< uint64_t > GetByteSize(ExecutionContextScope *exe_scope) const
Return the size of the type in bytes.
bool IsIntegerOrEnumerationType(bool &is_signed) const
uint32_t GetTypeInfo(CompilerType *pointee_or_element_compiler_type=nullptr) const
bool IsRealFloatingPointType() const
Returns true for non-complex float types.
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.
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.
void PutString(llvm::StringRef str)
Definition Log.cpp:164
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:242
const RegisterInfo * GetRegisterInfo(lldb::RegisterKind reg_kind, uint32_t reg_num)
bool WriteRegisterFromUnsigned(uint32_t reg, uint64_t uval)
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:118
static Status FromErrorStringWithFormat(const char *format,...) __attribute__((format(printf
Definition Status.cpp:106
static Status FromErrorString(const char *str)
Definition Status.h:141
bool Fail() const
Test for error condition.
Definition Status.cpp:293
const char * AsCString(const char *default_error_str="unknown error") const
Get the error string associated with the current error.
Definition Status.cpp:194
virtual lldb::RegisterContextSP GetRegisterContext()=0
lldb::ProcessSP GetProcess() const
Definition Thread.h:162
void SetIsRegisterPlusOffset(uint32_t reg_num, int32_t offset)
Definition UnwindPlan.h:240
bool SetRegisterLocationToAtCFAPlusOffset(uint32_t reg_num, int32_t offset, bool can_replace)
const FAValue & GetCFAValue() const
Definition UnwindPlan.h:365
bool SetRegisterLocationToRegister(uint32_t reg_num, uint32_t other_reg_num, bool can_replace)
void SetUnspecifiedRegistersAreUndefined(bool unspec_is_undef)
Definition UnwindPlan.h:408
static lldb::ValueObjectSP Create(ExecutionContextScope *exe_scope, lldb::ByteOrder byte_order, uint32_t addr_byte_size, lldb::addr_t address=LLDB_INVALID_ADDRESS, ValueObjectManager *manager=nullptr)
These routines create ValueObjectConstResult ValueObjects from various data sources.
const Scalar & GetScalar() const
See comment on m_scalar to understand what GetScalar returns.
Definition Value.h:114
@ Scalar
A raw scalar value.
Definition Value.h:46
void SetCompilerType(const CompilerType &compiler_type)
Definition Value.cpp:276
void SetValueType(ValueType value_type)
Definition Value.h:90
void SetBytes(const void *bytes, int len)
Definition Value.cpp:90
#define LLDB_REGNUM_GENERIC_RA
#define LLDB_REGNUM_GENERIC_ARG8
#define LLDB_REGNUM_GENERIC_ARG6
#define LLDB_REGNUM_GENERIC_SP
#define LLDB_REGNUM_GENERIC_ARG4
#define LLDB_REGNUM_GENERIC_ARG3
#define LLDB_REGNUM_GENERIC_ARG1
#define LLDB_REGNUM_GENERIC_ARG7
#define UINT32_MAX
#define LLDB_INVALID_REGNUM
#define LLDB_REGNUM_GENERIC_TP
#define LLDB_REGNUM_GENERIC_ARG2
#define LLDB_REGNUM_GENERIC_PC
#define LLDB_REGNUM_GENERIC_FP
#define LLDB_REGNUM_GENERIC_ARG5
A class that represents a running process on the host machine.
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
Definition Log.h:338
std::shared_ptr< lldb_private::ABI > ABISP
std::shared_ptr< lldb_private::StackFrame > StackFrameSP
std::shared_ptr< lldb_private::ValueObject > ValueObjectSP
uint64_t offset_t
Definition lldb-types.h:86
std::shared_ptr< lldb_private::Process > ProcessSP
ByteOrder
Byte ordering definitions.
std::shared_ptr< lldb_private::UnwindPlan > UnwindPlanSP
uint64_t addr_t
Definition lldb-types.h:80
std::shared_ptr< lldb_private::RegisterContext > RegisterContextSP
RegisterKind
Register numbering types.
@ 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),...
const char * name
Name of this register, can't be NULL.