14#include "llvm/IR/DerivedTypes.h"
24#define DEFINE_REG_NAME(reg_num) ConstString(#reg_num).GetCString()
25#define DEFINE_REG_NAME_STR(reg_name) ConstString(reg_name).GetCString()
30#define DEFINE_GENERIC_REGISTER_STUB(dwarf_num, str_name, generic_num) \
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, \
38#define DEFINE_REGISTER_STUB(dwarf_num, str_name) \
39 DEFINE_GENERIC_REGISTER_STUB(dwarf_num, str_name, LLDB_INVALID_REGNUM)
123 count = dwarf::g_register_infos.size();
124 return dwarf::g_register_infos.
data();
133 llvm::Triple::ArchType machine = arch.
GetTriple().getArch();
135 if (llvm::Triple::riscv32 != machine && llvm::Triple::riscv64 != machine)
141 abi->
SetIsRV64((llvm::Triple::riscv64 == machine) ?
true :
false);
147 return llvm::alignTo(size_in_bytes,
word_size);
152 const llvm::ArrayRef<ABI::CallArgument> &args) {
155 size_t total_size = 0;
156 for (
const auto &arg : args)
168 llvm::ArrayRef<addr_t> args)
const {
175 llvm::ArrayRef<ABI::CallArgument> args)
const {
180 uint32_t pc_reg = reg_ctx->ConvertRegisterKindToRegisterNumber(
185 uint32_t ra_reg = reg_ctx->ConvertRegisterKindToRegisterNumber(
190 uint32_t sp_reg = reg_ctx->ConvertRegisterKindToRegisterNumber(
203 for (
const auto &arg : args) {
211 if (process->WriteMemory(
sp, arg.data_up.get(), arg.size,
error) <
217 *
const_cast<addr_t *
>(&arg.value) =
sp;
221 assert(prototype.getFunctionNumParams() == args.size());
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;
231 args_size <= regs_for_args_count ? 0 : args_size - regs_for_args_count;
234 uint8_t reg_value[8];
237 for (
size_t i = 0; i < args_size; ++i) {
238 auto value =
reinterpret_cast<const uint8_t *
>(&args[i].value);
243 if (i < num_args_in_regs) {
246 memcpy(reg_value, value, end);
248 memset(reg_value + end, 0,
reg_size - end);
252 if (!reg_ctx->WriteRegister(
262 if (reg_index < regs_for_args_count || size == 0)
266 if (process->WriteMemory(
sp - offset, value, size,
error) < size ||
277 reg_ctx->WriteRegisterFromUnsigned(pc_reg,
pc);
278 reg_ctx->WriteRegisterFromUnsigned(ra_reg,
ra);
279 reg_ctx->WriteRegisterFromUnsigned(sp_reg,
sp);
297 CompilerType compiler_type = new_value_sp->GetCompilerType();
298 if (!compiler_type) {
303 auto ®_ctx = *frame_sp->GetThread()->GetRegisterContext();
305 bool is_signed =
false;
308 result.
SetErrorString(
"We don't support returning other types at present");
313 size_t num_bytes = new_value_sp->
GetData(data, result);
317 "Couldn't convert return value to raw data: %s", result.
AsCString());
324 uint64_t raw_value = data.
GetMaxU64(&offset, num_bytes);
328 if (!reg_ctx.WriteRegisterFromUnsigned(reg_info, raw_value)) {
345 if (!reg_ctx.WriteRegisterFromUnsigned(reg_info, raw_value)) {
354 "We don't support returning large integer values at present.");
360 raw_value &= std::numeric_limits<T>::max();
362 scalar =
static_cast<typename std::make_signed<T>::type
>(raw_value);
364 scalar =
static_cast<T
>(raw_value);
368 uint8_t size_in_bytes,
bool is_signed) {
369 switch (size_in_bytes) {
373 case sizeof(uint64_t):
374 SetInteger<uint64_t>(scalar, raw_value, is_signed);
377 case sizeof(uint32_t):
378 SetInteger<uint32_t>(scalar, raw_value, is_signed);
381 case sizeof(uint16_t):
382 SetInteger<uint16_t>(scalar, raw_value, is_signed);
385 case sizeof(uint8_t):
386 SetInteger<uint8_t>(scalar, raw_value, is_signed);
394 uint8_t size_in_bytes) {
395 switch (size_in_bytes) {
399 case sizeof(uint64_t):
400 scalar = *
reinterpret_cast<double *
>(&raw_value);
403 case sizeof(uint32_t):
404 scalar = *
reinterpret_cast<float *
>(&raw_value);
413 llvm::Triple::ArchType machine,
415 uint32_t byte_size) {
425 case sizeof(uint32_t):
427 raw_value = reg_ctx->ReadRegisterAsUnsigned(reg_info_a0, 0) &
UINT32_MAX;
429 case sizeof(uint64_t):
431 if (llvm::Triple::riscv32 == machine) {
432 raw_value = reg_ctx->ReadRegisterAsUnsigned(reg_info_a0, 0) &
UINT32_MAX;
434 (reg_ctx->ReadRegisterAsUnsigned(reg_info_a1, 0) &
UINT32_MAX) << 32U;
436 raw_value = reg_ctx->ReadRegisterAsUnsigned(reg_info_a0, 0);
441 if (llvm::Triple::riscv32 == machine)
442 return return_valobj_sp;
445 std::unique_ptr<DataBufferHeap> heap_data_up(
449 if (reg_ctx->ReadRegister(reg_info_a0, reg_value_a0) &&
450 reg_ctx->ReadRegister(reg_info_a1, reg_value_a1)) {
453 heap_data_up->GetBytes() + 0, 8,
454 byte_order,
error) &&
456 heap_data_up->GetBytes() + 8, 8,
457 byte_order,
error)) {
458 value.
SetBytes(heap_data_up.release(), byte_size);
466 return return_valobj_sp;
469 if (type_flags & eTypeIsInteger) {
470 const bool is_signed = (type_flags & eTypeIsSigned) != 0;
472 return return_valobj_sp;
473 }
else if (type_flags & eTypeIsFloat) {
475 return return_valobj_sp;
477 return return_valobj_sp;
482 return return_valobj_sp;
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;
493 switch (arch_fp_flags) {
498 return return_valobj_sp;
518 raw_value = reg_ctx->ReadRegisterAsUnsigned(reg_info_fa0, 0);
520 return return_valobj_sp;
535 return return_valobj_sp;
539 return return_valobj_sp;
544 const uint32_t type_flags = compiler_type.
GetTypeInfo();
545 const size_t byte_size = compiler_type.
GetByteSize(&thread).value_or(0);
547 const llvm::Triple::ArchType machine = arch.
GetMachine();
550 if (type_flags & eTypeIsInteger) {
553 return return_valobj_sp;
556 else if (type_flags & eTypeIsPointer) {
559 value.
GetScalar() = reg_ctx->ReadRegisterAsUnsigned(reg_info_a0, 0);
565 else if (type_flags & eTypeIsFloat) {
566 uint32_t float_count = 0;
567 bool is_complex =
false;
570 float_count == 1 && !is_complex) {
571 const uint32_t arch_fp_flags =
574 thread, reg_ctx, machine, arch_fp_flags, type_flags, byte_size);
575 return return_valobj_sp;
579 return return_valobj_sp;
584 llvm::Type &type)
const {
590 return return_valobj_sp;
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;
600 const uint32_t byte_size = type.getPrimitiveSizeInBits() / CHAR_BIT;
602 const llvm::Triple::ArchType machine = arch.
GetMachine();
605 if (type_flags & eTypeIsInteger) {
608 return return_valobj_sp;
611 else if (type_flags & eTypeIsPointer) {
614 value.
GetScalar() = reg_ctx->ReadRegisterAsUnsigned(reg_info_a0, 0);
620 else if (type_flags & eTypeIsFloat) {
621 const uint32_t arch_fp_flags =
624 thread, reg_ctx, machine, arch_fp_flags, type_flags, byte_size);
625 return return_valobj_sp;
628 return return_valobj_sp;
635 if (!return_compiler_type)
636 return return_valobj_sp;
653 row->GetCFAValue().SetIsRegisterPlusOffset(sp_reg_num, 0);
657 row->SetRegisterLocationToRegister(pc_reg_num, ra_reg_num,
true);
659 unwind_plan.
SetSourceName(
"riscv function-entry unwind plan");
675 row->GetCFAValue().SetIsRegisterPlusOffset(fp_reg_num, 0);
684 row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num,
reg_size * -2,
true);
685 row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num,
reg_size * -1,
true);
702 const char *name = reg_info->
name;
704 uint32_t arch_flags = arch.
GetFlags();
709 bool is_callee_saved =
710 llvm::StringSwitch<bool>(name)
712 .Cases(
"ra",
"sp",
"fp",
true)
713 .Cases(
"s0",
"s1",
"s2",
"s3",
"s4",
"s5",
"s6",
"s7",
"s8",
"s9",
715 .Cases(
"s10",
"s11",
true)
717 .Cases(
"x1",
"x2",
"x8",
"x9",
"x18",
"x19",
"x20",
"x21",
"x22",
719 .Cases(
"x23",
"x24",
"x25",
"x26",
"x27",
true)
721 .Cases(
"fs0",
"fs1",
"fs2",
"fs3",
"fs4",
"fs5",
"fs6",
"fs7",
723 .Cases(
"fs8",
"fs9",
"fs10",
"fs11", is_hw_fp)
725 .Cases(
"f8",
"f9",
"f18",
"f19",
"f20",
"f21",
"f22",
"f23", is_hw_fp)
726 .Cases(
"f24",
"f25",
"f26",
"f27", is_hw_fp)
729 return is_callee_saved;
742 return llvm::StringSwitch<uint32_t>(name)
759 std::vector<lldb_private::DynamicRegisterInfo::Register> ®s) {
762 for (
auto it : llvm::enumerate(regs)) {
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");
778 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.