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 bool is_complex =
false;
516 !(type_flags & eTypeIsVector) && !is_complex) {
519 return return_valobj_sp;
522 return return_valobj_sp;
529 if (!return_compiler_type)
530 return return_valobj_sp;
550 plan_sp->AppendRow(std::move(row));
551 plan_sp->SetSourceName(
"loongarch function-entry unwind plan");
575 plan_sp->AppendRow(std::move(row));
576 plan_sp->SetSourceName(
"loongarch default unwind plan");
578 plan_sp->SetUnwindPlanValidAtAllInstructions(
eLazyBoolNo);
590 const char *name = reg_info->
name;
592 uint32_t arch_flags = arch.
GetFlags();
597 return llvm::StringSwitch<bool>(name)
599 .Cases({
"ra",
"sp",
"fp"},
true)
600 .Cases({
"s0",
"s1",
"s2",
"s3",
"s4",
"s5",
"s6",
"s7",
"s8",
"s9"},
true)
602 .Cases({
"r1",
"r3",
"r22"},
true)
603 .Cases({
"r23",
"r24",
"r25",
"r26",
"r27",
"r28",
"r29",
"r30",
"31"},
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 IsIntegerOrEnumerationType(bool &is_signed) const
uint32_t GetTypeInfo(CompilerType *pointee_or_element_compiler_type=nullptr) const
bool IsFloatingPointType(bool &is_complex) 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.