14#include "llvm/IR/DerivedTypes.h"
25#define DEFINE_REG_NAME(reg_num) ConstString(#reg_num).GetCString()
26#define DEFINE_REG_NAME_STR(reg_name) ConstString(reg_name).GetCString()
31#define DEFINE_GENERIC_REGISTER_STUB(dwarf_num, str_name, generic_num) \
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, \
39#define DEFINE_REGISTER_STUB(dwarf_num, str_name) \
40 DEFINE_GENERIC_REGISTER_STUB(dwarf_num, str_name, LLDB_INVALID_REGNUM)
124 count = dwarf::g_register_infos.size();
125 return dwarf::g_register_infos.
data();
134 llvm::Triple::ArchType machine = arch.
GetTriple().getArch();
136 if (llvm::Triple::riscv32 != machine && llvm::Triple::riscv64 != machine)
142 abi->
SetIsRV64((llvm::Triple::riscv64 == machine) ?
true :
false);
148 return llvm::alignTo(size_in_bytes,
word_size);
153 const llvm::ArrayRef<ABI::CallArgument> &args) {
156 size_t total_size = 0;
157 for (
const auto &arg : args)
169 llvm::ArrayRef<addr_t> args)
const {
176 llvm::ArrayRef<ABI::CallArgument> args)
const {
181 uint32_t pc_reg = reg_ctx->ConvertRegisterKindToRegisterNumber(
186 uint32_t ra_reg = reg_ctx->ConvertRegisterKindToRegisterNumber(
191 uint32_t sp_reg = reg_ctx->ConvertRegisterKindToRegisterNumber(
204 for (
const auto &arg : args) {
212 if (process->WriteMemory(
sp, arg.data_up.get(), arg.size,
error) <
218 *
const_cast<addr_t *
>(&arg.value) =
sp;
222 assert(prototype.getFunctionNumParams() == args.size());
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;
232 args_size <= regs_for_args_count ? 0 : args_size - regs_for_args_count;
235 uint8_t reg_value[8];
238 for (
size_t i = 0; i < args_size; ++i) {
239 auto value =
reinterpret_cast<const uint8_t *
>(&args[i].value);
244 if (i < num_args_in_regs) {
247 memcpy(reg_value, value, end);
249 memset(reg_value + end, 0,
reg_size - end);
253 if (!reg_ctx->WriteRegister(
263 if (reg_index < regs_for_args_count || size == 0)
267 if (process->WriteMemory(
sp - offset, value, size,
error) < size ||
278 reg_ctx->WriteRegisterFromUnsigned(pc_reg,
pc);
279 reg_ctx->WriteRegisterFromUnsigned(ra_reg,
ra);
280 reg_ctx->WriteRegisterFromUnsigned(sp_reg,
sp);
298 CompilerType compiler_type = new_value_sp->GetCompilerType();
299 if (!compiler_type) {
304 auto ®_ctx = *frame_sp->GetThread()->GetRegisterContext();
306 bool is_signed =
false;
309 result.
SetErrorString(
"We don't support returning other types at present");
314 size_t num_bytes = new_value_sp->
GetData(data, result);
318 "Couldn't convert return value to raw data: %s", result.
AsCString());
325 uint64_t raw_value = data.
GetMaxU64(&offset, num_bytes);
329 if (!reg_ctx.WriteRegisterFromUnsigned(reg_info, raw_value)) {
346 if (!reg_ctx.WriteRegisterFromUnsigned(reg_info, raw_value)) {
355 "We don't support returning large integer values at present.");
361 raw_value &= std::numeric_limits<T>::max();
363 scalar =
static_cast<typename std::make_signed<T>::type
>(raw_value);
365 scalar =
static_cast<T
>(raw_value);
369 uint8_t size_in_bytes,
bool is_signed) {
370 switch (size_in_bytes) {
374 case sizeof(uint64_t):
375 SetInteger<uint64_t>(scalar, raw_value, is_signed);
378 case sizeof(uint32_t):
379 SetInteger<uint32_t>(scalar, raw_value, is_signed);
382 case sizeof(uint16_t):
383 SetInteger<uint16_t>(scalar, raw_value, is_signed);
386 case sizeof(uint8_t):
387 SetInteger<uint8_t>(scalar, raw_value, is_signed);
395 uint8_t size_in_bytes) {
396 switch (size_in_bytes) {
400 case sizeof(uint64_t):
401 scalar = *
reinterpret_cast<double *
>(&raw_value);
404 case sizeof(uint32_t):
405 scalar = *
reinterpret_cast<float *
>(&raw_value);
414 llvm::Triple::ArchType machine,
416 uint32_t byte_size) {
426 case sizeof(uint32_t):
428 raw_value = reg_ctx->ReadRegisterAsUnsigned(reg_info_a0, 0) &
UINT32_MAX;
430 case sizeof(uint64_t):
432 if (llvm::Triple::riscv32 == machine) {
433 raw_value = reg_ctx->ReadRegisterAsUnsigned(reg_info_a0, 0) &
UINT32_MAX;
435 (reg_ctx->ReadRegisterAsUnsigned(reg_info_a1, 0) &
UINT32_MAX) << 32U;
437 raw_value = reg_ctx->ReadRegisterAsUnsigned(reg_info_a0, 0);
442 if (llvm::Triple::riscv32 == machine)
443 return return_valobj_sp;
446 std::unique_ptr<DataBufferHeap> heap_data_up(
450 if (reg_ctx->ReadRegister(reg_info_a0, reg_value_a0) &&
451 reg_ctx->ReadRegister(reg_info_a1, reg_value_a1)) {
454 heap_data_up->GetBytes() + 0, 8,
455 byte_order,
error) &&
457 heap_data_up->GetBytes() + 8, 8,
458 byte_order,
error)) {
459 value.
SetBytes(heap_data_up.release(), byte_size);
467 return return_valobj_sp;
470 if (type_flags & eTypeIsInteger) {
471 const bool is_signed = (type_flags & eTypeIsSigned) != 0;
473 return return_valobj_sp;
474 }
else if (type_flags & eTypeIsFloat) {
476 return return_valobj_sp;
478 return return_valobj_sp;
483 return return_valobj_sp;
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;
494 switch (arch_fp_flags) {
499 return return_valobj_sp;
519 raw_value = reg_ctx->ReadRegisterAsUnsigned(reg_info_fa0, 0);
521 return return_valobj_sp;
536 return return_valobj_sp;
540 return return_valobj_sp;
545 const uint32_t type_flags = compiler_type.
GetTypeInfo();
546 const size_t byte_size = compiler_type.
GetByteSize(&thread).value_or(0);
548 const llvm::Triple::ArchType machine = arch.
GetMachine();
551 if (type_flags & eTypeIsInteger) {
554 return return_valobj_sp;
557 else if (type_flags & eTypeIsPointer) {
560 value.
GetScalar() = reg_ctx->ReadRegisterAsUnsigned(reg_info_a0, 0);
566 else if (type_flags & eTypeIsFloat) {
567 uint32_t float_count = 0;
568 bool is_complex =
false;
571 float_count == 1 && !is_complex) {
572 const uint32_t arch_fp_flags =
575 thread, reg_ctx, machine, arch_fp_flags, type_flags, byte_size);
576 return return_valobj_sp;
580 return return_valobj_sp;
585 llvm::Type &type)
const {
591 return return_valobj_sp;
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;
601 const uint32_t byte_size = type.getPrimitiveSizeInBits() / CHAR_BIT;
603 const llvm::Triple::ArchType machine = arch.
GetMachine();
606 if (type_flags & eTypeIsInteger) {
609 return return_valobj_sp;
612 else if (type_flags & eTypeIsPointer) {
615 value.
GetScalar() = reg_ctx->ReadRegisterAsUnsigned(reg_info_a0, 0);
621 else if (type_flags & eTypeIsFloat) {
622 const uint32_t arch_fp_flags =
625 thread, reg_ctx, machine, arch_fp_flags, type_flags, byte_size);
626 return return_valobj_sp;
629 return return_valobj_sp;
636 if (!return_compiler_type)
637 return return_valobj_sp;
654 row->GetCFAValue().SetIsRegisterPlusOffset(sp_reg_num, 0);
658 row->SetRegisterLocationToRegister(pc_reg_num, ra_reg_num,
true);
660 unwind_plan.
SetSourceName(
"riscv function-entry unwind plan");
676 row->GetCFAValue().SetIsRegisterPlusOffset(fp_reg_num, 0);
685 row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num,
reg_size * -2,
true);
686 row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num,
reg_size * -1,
true);
703 const char *name = reg_info->
name;
705 uint32_t arch_flags = arch.
GetFlags();
710 bool is_callee_saved =
711 llvm::StringSwitch<bool>(name)
713 .Cases(
"ra",
"sp",
"fp",
true)
714 .Cases(
"s0",
"s1",
"s2",
"s3",
"s4",
"s5",
"s6",
"s7",
"s8",
"s9",
716 .Cases(
"s10",
"s11",
true)
718 .Cases(
"x1",
"x2",
"x8",
"x9",
"x18",
"x19",
"x20",
"x21",
"x22",
720 .Cases(
"x23",
"x24",
"x25",
"x26",
"x27",
true)
722 .Cases(
"fs0",
"fs1",
"fs2",
"fs3",
"fs4",
"fs5",
"fs6",
"fs7",
724 .Cases(
"fs8",
"fs9",
"fs10",
"fs11", is_hw_fp)
726 .Cases(
"f8",
"f9",
"f18",
"f19",
"f20",
"f21",
"f22",
"f23", is_hw_fp)
727 .Cases(
"f24",
"f25",
"f26",
"f27", is_hw_fp)
730 return is_callee_saved;
743 return llvm::StringSwitch<uint32_t>(name)
760 std::vector<lldb_private::DynamicRegisterInfo::Register> ®s) {
763 for (
auto it : llvm::enumerate(regs)) {
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");
779 it.value().regnum_generic =
GetGenericNum(it.value().name.GetStringRef());
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 ®_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 ®_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)
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)
bool CreateDefaultUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override
void AugmentRegisterInfo(std::vector< lldb_private::DynamicRegisterInfo::Register > ®s) 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 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.
lldb::ProcessSP GetProcessSP() const
Request to get a Process shared pointer.
An architecture specification class.
llvm::Triple & GetTriple()
Architecture triple accessor.
uint32_t GetFlags() const
llvm::Triple::ArchType GetMachine() const
Returns a machine family for the current architecture.
@ eRISCV_float_abi_double
single precision floating point, +f
@ eRISCV_float_abi_soft
RVC, +c.
@ eRISCV_float_abi_quad
double precision floating point, +d
@ eRISCV_float_abi_mask
quad precision floating point, +q
@ eRISCV_float_abi_single
soft float
Generic representation of a type in a programming language.
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.
A subclass of DataBuffer that stores a data buffer on the heap.
"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 > ®s) override
uint32_t GetAsMemoryData(const RegisterInfo ®_info, void *dst, uint32_t dst_len, lldb::ByteOrder dst_byte_order, Status &error) const
int SetErrorStringWithFormat(const char *format,...) __attribute__((format(printf
Set the current error string to a formatted error string.
bool Fail() const
Test for error condition.
const char * AsCString(const char *default_error_str="unknown error") const
Get the error string associated with the current error.
void SetErrorString(llvm::StringRef err_str)
Set the current error string to err_str.
virtual lldb::StackFrameSP GetStackFrameAtIndex(uint32_t idx)
virtual lldb::RegisterContextSP GetRegisterContext()=0
lldb::ProcessSP GetProcess() const
void SetRegisterKind(lldb::RegisterKind kind)
void AppendRow(const RowSP &row_sp)
std::shared_ptr< Row > RowSP
void SetSourcedFromCompiler(lldb_private::LazyBool from_compiler)
void SetSourceName(const char *)
void SetUnwindPlanValidAtAllInstructions(lldb_private::LazyBool valid_at_all_insn)
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
RegisterInfo * GetRegisterInfo() const
void SetCompilerType(const CompilerType &compiler_type)
void SetValueType(ValueType value_type)
void SetBytes(const void *bytes, int len)
#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 LLDB_INVALID_REGNUM
#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.
std::shared_ptr< lldb_private::ABI > ABISP
std::shared_ptr< lldb_private::StackFrame > StackFrameSP
std::shared_ptr< lldb_private::ValueObject > ValueObjectSP
std::shared_ptr< lldb_private::Process > ProcessSP
ByteOrder
Byte ordering definitions.
std::shared_ptr< lldb_private::RegisterContext > RegisterContextSP
@ 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.