15#include "llvm/ADT/StringRef.h"
16#include "llvm/IR/DerivedTypes.h"
17#include "llvm/Support/MathExtras.h"
29#define DEFINE_REG_NAME(reg_num) ConstString(#reg_num).GetCString()
30#define DEFINE_REG_NAME_STR(reg_name) ConstString(reg_name).GetCString()
35#define DEFINE_GENERIC_REGISTER_STUB(dwarf_num, generic_num) \
37 DEFINE_REG_NAME(dwarf_num), \
38 DEFINE_REG_NAME_STR(nullptr), \
43 {dwarf_num, dwarf_num, generic_num, LLDB_INVALID_REGNUM, dwarf_num}, \
49#define DEFINE_REGISTER_STUB(dwarf_num) \
50 DEFINE_GENERIC_REGISTER_STUB(dwarf_num, LLDB_INVALID_REGNUM)
140 count = dwarf::g_register_infos.size();
141 return dwarf::g_register_infos.data();
150 llvm::Triple::ArchType machine = arch.
GetTriple().getArch();
152 if (llvm::Triple::loongarch32 != machine &&
153 llvm::Triple::loongarch64 != machine)
159 abi->
SetIsLA64(llvm::Triple::loongarch64 == machine);
165 const uint32_t reg_num,
const addr_t value) {
171 static_cast<uint64_t
>(value));
181 const llvm::ArrayRef<addr_t> args) {
182 std::stringstream ss;
183 ss <<
"ABISysV_loongarch::PrepareTrivialCall"
184 <<
" (tid = 0x" << std::hex << thread.GetID() <<
", sp = 0x" <<
sp
185 <<
", func_addr = 0x" << func_addr <<
", return_addr = 0x" << return_addr;
187 for (
auto [idx, arg] : enumerate(args))
188 ss <<
", arg" << std::dec << idx <<
" = 0x" << std::hex << arg;
195 llvm::ArrayRef<addr_t> args)
const {
200 const auto reg_ctx_sp = thread.GetRegisterContext();
202 LLDB_LOG(log,
"Failed to get RegisterContext");
207 LLDB_LOG(log,
"Function has {0} arguments, but only {1} are allowed!",
213 for (
auto [idx, arg] : enumerate(args)) {
214 const RegisterInfo *reg_info = reg_ctx_sp->GetRegisterInfo(
216 LLDB_LOG(log,
"About to write arg{0} ({1:x}) into {2}", idx, arg,
219 if (!reg_ctx_sp->WriteRegisterFromUnsigned(reg_info, arg)) {
220 LLDB_LOG(log,
"Failed to write arg{0} ({1:x}) into {2}", idx, arg,
236 LLDB_LOG(log,
"ABISysV_loongarch::{0}() success", __FUNCTION__);
254 CompilerType compiler_type = new_value_sp->GetCompilerType();
255 if (!compiler_type) {
260 auto ®_ctx = *frame_sp->GetThread()->GetRegisterContext();
262 bool is_signed =
false;
266 "We don't support returning other types at present");
271 size_t num_bytes = new_value_sp->
GetData(data, result);
275 "Couldn't convert return value to raw data: %s", result.
AsCString());
287 "We don't support returning large integer values at present.");
292 uint64_t raw_value = data.
GetMaxU64(&offset, num_bytes);
296 raw_value = llvm::SignExtend64<32>(raw_value);
299 if (!reg_ctx.WriteRegisterFromUnsigned(reg_info, raw_value)) {
301 "Couldn't write value to register %s", reg_info->name);
317 if (!reg_ctx.WriteRegisterFromUnsigned(reg_info, raw_value))
319 "Couldn't write value to register %s", reg_info->name);
326 static_assert(std::is_unsigned<T>::value,
"T must be an unsigned type.");
327 raw_value &= std::numeric_limits<T>::max();
329 scalar =
static_cast<typename std::make_signed<T>::type
>(raw_value);
331 scalar =
static_cast<T
>(raw_value);
335 uint8_t size_in_bytes,
bool is_signed) {
336 switch (size_in_bytes) {
340 case sizeof(uint64_t):
344 case sizeof(uint32_t):
348 case sizeof(uint16_t):
352 case sizeof(uint8_t):
361 uint8_t size_in_bytes) {
362 switch (size_in_bytes) {
366 case sizeof(uint64_t):
367 scalar = *
reinterpret_cast<double *
>(&raw_value);
370 case sizeof(uint32_t):
371 scalar = *
reinterpret_cast<float *
>(&raw_value);
380 llvm::Triple::ArchType machine,
382 uint32_t byte_size) {
389 uint64_t raw_value = 0;
392 case sizeof(uint32_t):
394 raw_value = reg_ctx->ReadRegisterAsUnsigned(reg_info_a0, 0) &
UINT32_MAX;
396 case sizeof(uint64_t):
398 if (llvm::Triple::loongarch32 == machine) {
399 raw_value = reg_ctx->ReadRegisterAsUnsigned(reg_info_a0, 0) &
UINT32_MAX;
401 (reg_ctx->ReadRegisterAsUnsigned(reg_info_a1, 0) &
UINT32_MAX) << 32U;
403 raw_value = reg_ctx->ReadRegisterAsUnsigned(reg_info_a0, 0);
409 if (llvm::Triple::loongarch32 == machine)
410 return return_valobj_sp;
413 std::unique_ptr<DataBufferHeap> heap_data_up(
415 const ByteOrder byte_order = thread.GetProcess()->GetByteOrder();
417 if (reg_ctx->ReadRegister(reg_info_a0, reg_value_a0) &&
418 reg_ctx->ReadRegister(reg_info_a1, reg_value_a1)) {
421 heap_data_up->GetBytes() + 0, 8,
422 byte_order,
error) &&
424 heap_data_up->GetBytes() + 8, 8,
425 byte_order,
error)) {
426 value.
SetBytes(heap_data_up.release(), byte_size);
428 thread.GetStackFrameAtIndex(0).get(), value,
ConstString(
""));
434 return return_valobj_sp;
437 if (type_flags & eTypeIsInteger) {
439 type_flags & eTypeIsSigned))
440 return return_valobj_sp;
441 }
else if (type_flags & eTypeIsFloat) {
443 return return_valobj_sp;
445 return return_valobj_sp;
449 thread.GetStackFrameAtIndex(0).get(), value,
ConstString(
""));
450 return return_valobj_sp;
455 llvm::Triple::ArchType machine,
457 uint32_t byte_size) {
458 auto *reg_info_fa0 = reg_ctx->GetRegisterInfoByName(
"f0");
459 bool use_fp_regs =
false;
468 raw_value = reg_ctx->ReadRegisterAsUnsigned(reg_info_fa0, 0);
470 return return_valobj_sp;
484 return return_valobj_sp;
486 auto reg_ctx = thread.GetRegisterContext();
488 return return_valobj_sp;
493 const uint32_t type_flags = compiler_type.
GetTypeInfo();
494 const size_t byte_size =
495 llvm::expectedToOptional(compiler_type.
GetByteSize(&thread)).value_or(0);
496 const ArchSpec arch = thread.GetProcess()->GetTarget().GetArchitecture();
497 const llvm::Triple::ArchType machine = arch.
GetMachine();
499 if (type_flags & eTypeIsInteger) {
502 return return_valobj_sp;
504 if (type_flags & eTypeIsPointer) {
505 const auto *reg_info_a0 = reg_ctx->GetRegisterInfo(
507 value.
GetScalar() = reg_ctx->ReadRegisterAsUnsigned(reg_info_a0, 0);
512 if (type_flags & eTypeIsFloat) {
513 uint32_t float_count = 0;
514 bool is_complex =
false;
517 float_count == 1 && !is_complex) {
520 return return_valobj_sp;
523 return return_valobj_sp;
530 if (!return_compiler_type)
531 return return_valobj_sp;
551 plan_sp->AppendRow(std::move(row));
552 plan_sp->SetSourceName(
"loongarch function-entry unwind plan");
576 plan_sp->AppendRow(std::move(row));
577 plan_sp->SetSourceName(
"loongarch default unwind plan");
579 plan_sp->SetUnwindPlanValidAtAllInstructions(
eLazyBoolNo);
591 const char *name = reg_info->
name;
593 uint32_t arch_flags = arch.
GetFlags();
598 return llvm::StringSwitch<bool>(name)
600 .Cases(
"ra",
"sp",
"fp",
true)
601 .Cases(
"s0",
"s1",
"s2",
"s3",
"s4",
"s5",
"s6",
"s7",
"s8",
"s9",
true)
603 .Cases(
"r1",
"r3",
"r22",
true)
604 .Cases(
"r23",
"r24",
"r25",
"r26",
"r27",
"r28",
"r29",
"r30",
"31",
true)
606 .Cases(
"fs0",
"fs1",
"fs2",
"fs3",
"fs4",
"fs5",
"fs6",
"fs7", is_hw_fp)
608 .Cases(
"f24",
"f25",
"f26",
"f27",
"f28",
"f29",
"f30",
"f31", is_hw_fp)
614 "System V ABI for LoongArch targets",
623 return llvm::StringSwitch<uint32_t>(name)
640 std::vector<lldb_private::DynamicRegisterInfo::Register> ®s) {
643 static const llvm::StringMap<llvm::StringRef> isa_to_abi_alias_map = {
644 {
"r0",
"zero"}, {
"r1",
"ra"}, {
"r2",
"tp"}, {
"r3",
"sp"},
645 {
"r4",
"a0"}, {
"r5",
"a1"}, {
"r6",
"a2"}, {
"r7",
"a3"},
646 {
"r8",
"a4"}, {
"r9",
"a5"}, {
"r10",
"a6"}, {
"r11",
"a7"},
647 {
"r12",
"t0"}, {
"r13",
"t1"}, {
"r14",
"t2"}, {
"r15",
"t3"},
648 {
"r16",
"t4"}, {
"r17",
"t5"}, {
"r18",
"t6"}, {
"r19",
"t7"},
649 {
"r20",
"t8"}, {
"r22",
"fp"}, {
"r23",
"s0"}, {
"r24",
"s1"},
650 {
"r25",
"s2"}, {
"r26",
"s3"}, {
"r27",
"s4"}, {
"r28",
"s5"},
651 {
"r29",
"s6"}, {
"r30",
"s7"}, {
"r31",
"s8"}};
653 for (
auto it : llvm::enumerate(regs)) {
654 llvm::StringRef reg_name = it.value().name.GetStringRef();
657 llvm::StringRef alias_name = isa_to_abi_alias_map.lookup(reg_name);
658 if (!alias_name.empty())
659 it.value().alt_name.SetString(alias_name);
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)
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
lldb::UnwindPlanSP CreateDefaultUnwindPlan() override
static llvm::StringRef GetPluginNameStatic()
lldb::UnwindPlanSP CreateFunctionEntryUnwindPlan() 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.
@ 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.
llvm::Expected< 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.
void SetIsRegisterPlusOffset(uint32_t reg_num, int32_t offset)
bool SetRegisterLocationToAtCFAPlusOffset(uint32_t reg_num, int32_t offset, bool can_replace)
const FAValue & GetCFAValue() const
bool SetRegisterLocationToRegister(uint32_t reg_num, uint32_t other_reg_num, bool can_replace)
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
See comment on m_scalar to understand what GetScalar returns.
@ Scalar
A raw scalar value.
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::UnwindPlan > UnwindPlanSP
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.