15#include "llvm/IR/DerivedTypes.h"
16#include "llvm/Support/MathExtras.h"
28#define DEFINE_REG_NAME(reg_num) ConstString(#reg_num).GetCString()
29#define DEFINE_REG_NAME_STR(reg_name) ConstString(reg_name).GetCString()
34#define DEFINE_GENERIC_REGISTER_STUB(dwarf_num, generic_num) \
36 DEFINE_REG_NAME(dwarf_num), \
37 DEFINE_REG_NAME_STR(nullptr), \
42 {dwarf_num, dwarf_num, generic_num, LLDB_INVALID_REGNUM, dwarf_num}, \
48#define DEFINE_REGISTER_STUB(dwarf_num) \
49 DEFINE_GENERIC_REGISTER_STUB(dwarf_num, LLDB_INVALID_REGNUM)
139 count = dwarf::g_register_infos.size();
140 return dwarf::g_register_infos.
data();
149 llvm::Triple::ArchType machine = arch.
GetTriple().getArch();
151 if (llvm::Triple::loongarch32 != machine &&
152 llvm::Triple::loongarch64 != machine)
158 abi->
SetIsLA64(llvm::Triple::loongarch64 == machine);
164 const uint32_t reg_num,
const addr_t value) {
170 static_cast<uint64_t
>(value));
180 const llvm::ArrayRef<addr_t> args) {
181 std::stringstream ss;
182 ss <<
"ABISysV_loongarch::PrepareTrivialCall"
183 <<
" (tid = 0x" << std::hex << thread.
GetID() <<
", sp = 0x" <<
sp
184 <<
", func_addr = 0x" << func_addr <<
", return_addr = 0x" << return_addr;
186 for (
auto [idx, arg] : enumerate(args))
187 ss <<
", arg" << std::dec << idx <<
" = 0x" << std::hex << arg;
194 llvm::ArrayRef<addr_t> args)
const {
201 LLDB_LOG(log,
"Failed to get RegisterContext");
206 LLDB_LOG(log,
"Function has {0} arguments, but only {1} are allowed!",
212 for (
auto [idx, arg] : enumerate(args)) {
213 const RegisterInfo *reg_info = reg_ctx_sp->GetRegisterInfo(
215 LLDB_LOG(log,
"About to write arg{0} ({1:x}) into {2}", idx, arg,
218 if (!reg_ctx_sp->WriteRegisterFromUnsigned(reg_info, arg)) {
219 LLDB_LOG(log,
"Failed to write arg{0} ({1:x}) into {2}", idx, arg,
235 LLDB_LOG(log,
"ABISysV_loongarch::{0}() success", __FUNCTION__);
253 CompilerType compiler_type = new_value_sp->GetCompilerType();
254 if (!compiler_type) {
259 auto ®_ctx = *frame_sp->GetThread()->GetRegisterContext();
261 bool is_signed =
false;
265 "We don't support returning other types at present");
270 size_t num_bytes = new_value_sp->
GetData(data, result);
274 "Couldn't convert return value to raw data: %s", result.
AsCString());
286 "We don't support returning large integer values at present.");
291 uint64_t raw_value = data.
GetMaxU64(&offset, num_bytes);
295 raw_value = llvm::SignExtend64<32>(raw_value);
298 if (!reg_ctx.WriteRegisterFromUnsigned(reg_info, raw_value)) {
300 "Couldn't write value to register %s", reg_info->name);
316 if (!reg_ctx.WriteRegisterFromUnsigned(reg_info, raw_value))
318 "Couldn't write value to register %s", reg_info->name);
325 static_assert(std::is_unsigned<T>::value,
"T must be an unsigned type.");
326 raw_value &= std::numeric_limits<T>::max();
328 scalar =
static_cast<typename std::make_signed<T>::type
>(raw_value);
330 scalar =
static_cast<T
>(raw_value);
334 uint8_t size_in_bytes,
bool is_signed) {
335 switch (size_in_bytes) {
339 case sizeof(uint64_t):
340 SetInteger<uint64_t>(scalar, raw_value, is_signed);
343 case sizeof(uint32_t):
344 SetInteger<uint32_t>(scalar, raw_value, is_signed);
347 case sizeof(uint16_t):
348 SetInteger<uint16_t>(scalar, raw_value, is_signed);
351 case sizeof(uint8_t):
352 SetInteger<uint8_t>(scalar, raw_value, is_signed);
360 uint8_t size_in_bytes) {
361 switch (size_in_bytes) {
365 case sizeof(uint64_t):
366 scalar = *
reinterpret_cast<double *
>(&raw_value);
369 case sizeof(uint32_t):
370 scalar = *
reinterpret_cast<float *
>(&raw_value);
379 llvm::Triple::ArchType machine,
381 uint32_t byte_size) {
388 uint64_t raw_value = 0;
391 case sizeof(uint32_t):
393 raw_value = reg_ctx->ReadRegisterAsUnsigned(reg_info_a0, 0) &
UINT32_MAX;
395 case sizeof(uint64_t):
397 if (llvm::Triple::loongarch32 == machine) {
398 raw_value = reg_ctx->ReadRegisterAsUnsigned(reg_info_a0, 0) &
UINT32_MAX;
400 (reg_ctx->ReadRegisterAsUnsigned(reg_info_a1, 0) &
UINT32_MAX) << 32U;
402 raw_value = reg_ctx->ReadRegisterAsUnsigned(reg_info_a0, 0);
408 if (llvm::Triple::loongarch32 == machine)
409 return return_valobj_sp;
412 std::unique_ptr<DataBufferHeap> heap_data_up(
416 if (reg_ctx->ReadRegister(reg_info_a0, reg_value_a0) &&
417 reg_ctx->ReadRegister(reg_info_a1, reg_value_a1)) {
420 heap_data_up->GetBytes() + 0, 8,
421 byte_order,
error) &&
423 heap_data_up->GetBytes() + 8, 8,
424 byte_order,
error)) {
425 value.
SetBytes(heap_data_up.release(), byte_size);
433 return return_valobj_sp;
436 if (type_flags & eTypeIsInteger) {
438 type_flags & eTypeIsSigned))
439 return return_valobj_sp;
440 }
else if (type_flags & eTypeIsFloat) {
442 return return_valobj_sp;
444 return return_valobj_sp;
449 return return_valobj_sp;
454 llvm::Triple::ArchType machine,
456 uint32_t byte_size) {
457 auto *reg_info_fa0 = reg_ctx->GetRegisterInfoByName(
"f0");
458 bool use_fp_regs =
false;
467 raw_value = reg_ctx->ReadRegisterAsUnsigned(reg_info_fa0, 0);
469 return return_valobj_sp;
483 return return_valobj_sp;
487 return return_valobj_sp;
492 const uint32_t type_flags = compiler_type.
GetTypeInfo();
493 const size_t byte_size = compiler_type.
GetByteSize(&thread).value_or(0);
495 const llvm::Triple::ArchType machine = arch.
GetMachine();
497 if (type_flags & eTypeIsInteger) {
500 return return_valobj_sp;
502 if (type_flags & eTypeIsPointer) {
503 const auto *reg_info_a0 = reg_ctx->GetRegisterInfo(
505 value.
GetScalar() = reg_ctx->ReadRegisterAsUnsigned(reg_info_a0, 0);
510 if (type_flags & eTypeIsFloat) {
511 uint32_t float_count = 0;
512 bool is_complex =
false;
515 float_count == 1 && !is_complex) {
518 return return_valobj_sp;
521 return return_valobj_sp;
528 if (!return_compiler_type)
529 return return_valobj_sp;
546 row->GetCFAValue().SetIsRegisterPlusOffset(sp_reg_num, 0);
550 row->SetRegisterLocationToRegister(pc_reg_num, ra_reg_num,
true);
552 unwind_plan.
SetSourceName(
"loongarch function-entry unwind plan");
568 row->GetCFAValue().SetIsRegisterPlusOffset(fp_reg_num, 0);
577 row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num,
reg_size * -2,
true);
578 row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num,
reg_size * -1,
true);
595 const char *name = reg_info->
name;
597 uint32_t arch_flags = arch.
GetFlags();
602 return llvm::StringSwitch<bool>(name)
604 .Cases(
"ra",
"sp",
"fp",
true)
605 .Cases(
"s0",
"s1",
"s2",
"s3",
"s4",
"s5",
"s6",
"s7",
"s8",
"s9",
true)
607 .Cases(
"r1",
"r3",
"r22",
true)
608 .Cases(
"r23",
"r24",
"r25",
"r26",
"r27",
"r28",
"r29",
"r30",
"31",
true)
610 .Cases(
"fs0",
"fs1",
"fs2",
"fs3",
"fs4",
"fs5",
"fs6",
"fs7", is_hw_fp)
612 .Cases(
"f24",
"f25",
"f26",
"f27",
"f28",
"f29",
"f30",
"f31", is_hw_fp)
618 "System V ABI for LoongArch targets",
627 return llvm::StringSwitch<uint32_t>(name)
644 std::vector<lldb_private::DynamicRegisterInfo::Register> ®s) {
647 for (
auto it : llvm::enumerate(regs)) {
649 if (it.value().name ==
"r0")
650 it.value().alt_name.SetCString(
"zero");
651 else if (it.value().name ==
"r1")
652 it.value().alt_name.SetCString(
"ra");
653 else if (it.value().name ==
"r3")
654 it.value().alt_name.SetCString(
"sp");
655 else if (it.value().name ==
"r22")
656 it.value().alt_name.SetCString(
"fp");
657 else if (it.value().name ==
"r4")
658 it.value().alt_name.SetCString(
"a0");
659 else if (it.value().name ==
"r5")
660 it.value().alt_name.SetCString(
"a1");
661 else if (it.value().name ==
"r6")
662 it.value().alt_name.SetCString(
"a2");
663 else if (it.value().name ==
"r7")
664 it.value().alt_name.SetCString(
"a3");
665 else if (it.value().name ==
"r8")
666 it.value().alt_name.SetCString(
"a4");
667 else if (it.value().name ==
"r9")
668 it.value().alt_name.SetCString(
"a5");
669 else if (it.value().name ==
"r10")
670 it.value().alt_name.SetCString(
"a6");
671 else if (it.value().name ==
"r11")
672 it.value().alt_name.SetCString(
"a7");
675 it.value().regnum_generic =
GetGenericNum(it.value().name.GetStringRef());
static const RegisterInfo g_register_infos[]
#define DEFINE_REGISTER_STUB(dwarf_num, str_name)
#define DEFINE_GENERIC_REGISTER_STUB(dwarf_num, str_name, generic_num)
static const size_t reg_size
static ValueObjectSP GetValObjFromIntRegs(Thread &thread, const RegisterContextSP ®_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 void SetInteger(Scalar &scalar, uint64_t raw_value, bool is_signed)
static ValueObjectSP GetValObjFromFPRegs(Thread &thread, const RegisterContextSP ®_ctx, llvm::Triple::ArchType machine, uint32_t type_flags, uint32_t byte_size)
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 constexpr size_t g_regs_for_args_count
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.
#define LLDB_PLUGIN_DEFINE_ADV(ClassName, PluginName)
bool RegisterIsCalleeSaved(const lldb_private::RegisterInfo *reg_info)
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
const lldb_private::RegisterInfo * GetRegisterInfoArray(uint32_t &count) override
lldb::ValueObjectSP GetReturnValueObjectSimple(lldb_private::Thread &thread, lldb_private::CompilerType &ast_type) const
void AugmentRegisterInfo(std::vector< lldb_private::DynamicRegisterInfo::Register > ®s) override
void SetIsLA64(bool is_la64)
bool CreateDefaultUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override
static lldb::ABISP CreateInstance(lldb::ProcessSP process_sp, const lldb_private::ArchSpec &arch)
bool RegisterIsVolatile(const lldb_private::RegisterInfo *reg_info) override
lldb_private::Status SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value) override
bool GetArgumentValues(lldb_private::Thread &thread, lldb_private::ValueList &values) const override
lldb::ValueObjectSP GetReturnValueObjectImpl(lldb_private::Thread &thread, lldb_private::CompilerType &type) const override
bool CreateFunctionEntryUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override
static llvm::StringRef GetPluginNameStatic()
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.
@ eLoongArch_abi_mask
double precision floating point, +d
uint32_t GetFlags() const
llvm::Triple::ArchType GetMachine() const
Returns a machine family for the current architecture.
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.
void PutString(llvm::StringRef str)
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
const RegisterInfo * GetRegisterInfo(lldb::RegisterKind reg_kind, uint32_t reg_num)
bool WriteRegisterFromUnsigned(uint32_t reg, uint64_t uval)
uint32_t GetAsMemoryData(const RegisterInfo ®_info, void *dst, uint32_t dst_len, lldb::ByteOrder dst_byte_order, Status &error) const
static Status FromErrorStringWithFormat(const char *format,...) __attribute__((format(printf
static Status FromErrorString(const char *str)
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.
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.
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
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
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),...
llvm::ArrayRef< uint8_t > data(const uint8_t *context_base) const
const char * name
Name of this register, can't be NULL.
lldb::user_id_t GetID() const
Get accessor for the user ID.