-
Notifications
You must be signed in to change notification settings - Fork 12.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[lldb][LoongArch] Function calls support in lldb expressions #114742
[lldb][LoongArch] Function calls support in lldb expressions #114742
Conversation
Created using spr 1.3.5-bogner
Created using spr 1.3.5-bogner [skip ci]
@llvm/pr-subscribers-lldb Author: wanglei (wangleiat) ChangesThis patch adds desired feature flags in JIT compiler to enable Fited tests: Similar as #99336 Patch is 31.85 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/114742.diff 7 Files Affected:
diff --git a/lldb/include/lldb/Utility/ArchSpec.h b/lldb/include/lldb/Utility/ArchSpec.h
index 5990f984b09e2d..2a74058673bae5 100644
--- a/lldb/include/lldb/Utility/ArchSpec.h
+++ b/lldb/include/lldb/Utility/ArchSpec.h
@@ -107,6 +107,15 @@ class ArchSpec {
eRISCVSubType_riscv64,
};
+ enum LoongArcheflags {
+ eLoongArch_abi_soft_float = 0x00000000, /// soft float
+ eLoongArch_abi_single_float =
+ 0x00000001, /// single precision floating point, +f
+ eLoongArch_abi_double_float =
+ 0x00000002, /// double precision floating point, +d
+ eLoongArch_abi_mask = 0x00000003,
+ };
+
enum LoongArchSubType {
eLoongArchSubType_unknown,
eLoongArchSubType_loongarch32,
diff --git a/lldb/source/Plugins/ABI/CMakeLists.txt b/lldb/source/Plugins/ABI/CMakeLists.txt
index 9241a2487d522f..e33ac87354860e 100644
--- a/lldb/source/Plugins/ABI/CMakeLists.txt
+++ b/lldb/source/Plugins/ABI/CMakeLists.txt
@@ -1,4 +1,4 @@
-foreach(target AArch64 ARM ARC Hexagon Mips MSP430 PowerPC RISCV SystemZ X86)
+foreach(target AArch64 ARM ARC Hexagon LoongArch Mips MSP430 PowerPC RISCV SystemZ X86)
if (${target} IN_LIST LLVM_TARGETS_TO_BUILD)
add_subdirectory(${target})
endif()
diff --git a/lldb/source/Plugins/ABI/LoongArch/ABISysV_loongarch.cpp b/lldb/source/Plugins/ABI/LoongArch/ABISysV_loongarch.cpp
new file mode 100644
index 00000000000000..cd8270c01113f7
--- /dev/null
+++ b/lldb/source/Plugins/ABI/LoongArch/ABISysV_loongarch.cpp
@@ -0,0 +1,664 @@
+//===-- ABISysV_loongarch.cpp----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "ABISysV_loongarch.h"
+
+#include <array>
+#include <limits>
+#include <sstream>
+
+#include "llvm/IR/DerivedTypes.h"
+
+#include "Utility/LoongArch_DWARF_Registers.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/Value.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/StackFrame.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Utility/LLDBLog.h"
+#include "lldb/Utility/RegisterValue.h"
+#include "lldb/ValueObject/ValueObjectConstResult.h"
+
+#define DEFINE_REG_NAME(reg_num) ConstString(#reg_num).GetCString()
+#define DEFINE_REG_NAME_STR(reg_name) ConstString(reg_name).GetCString()
+
+// The ABI is not a source of such information as size, offset, encoding, etc.
+// of a register. Just provides correct dwarf and eh_frame numbers.
+
+#define DEFINE_GENERIC_REGISTER_STUB(dwarf_num, str_name, generic_num) \
+ { \
+ DEFINE_REG_NAME(dwarf_num), \
+ DEFINE_REG_NAME_STR(str_name), \
+ 0, \
+ 0, \
+ eEncodingInvalid, \
+ eFormatDefault, \
+ {dwarf_num, dwarf_num, generic_num, LLDB_INVALID_REGNUM, dwarf_num}, \
+ nullptr, \
+ nullptr, \
+ nullptr, \
+ }
+
+#define DEFINE_REGISTER_STUB(dwarf_num, str_name) \
+ DEFINE_GENERIC_REGISTER_STUB(dwarf_num, str_name, LLDB_INVALID_REGNUM)
+
+using namespace lldb;
+using namespace lldb_private;
+
+LLDB_PLUGIN_DEFINE_ADV(ABISysV_loongarch, ABILoongArch)
+
+namespace {
+namespace dwarf {
+enum regnums {
+ r0,
+ ra,
+ r1 = ra,
+ r2,
+ sp,
+ r3 = sp,
+ r4,
+ r5,
+ r6,
+ r7,
+ r8,
+ r9,
+ r10,
+ r11,
+ r12,
+ r13,
+ r14,
+ r15,
+ r16,
+ r17,
+ r18,
+ r19,
+ r20,
+ r21,
+ fp,
+ r22 = fp,
+ r23,
+ r24,
+ r25,
+ r26,
+ r27,
+ r28,
+ r29,
+ r30,
+ r31,
+ pc
+};
+
+static const std::array<RegisterInfo, 33> g_register_infos = {
+ {DEFINE_REGISTER_STUB(r0, nullptr),
+ DEFINE_GENERIC_REGISTER_STUB(r1, nullptr, LLDB_REGNUM_GENERIC_RA),
+ DEFINE_REGISTER_STUB(r2, nullptr),
+ DEFINE_GENERIC_REGISTER_STUB(r3, nullptr, LLDB_REGNUM_GENERIC_SP),
+ DEFINE_GENERIC_REGISTER_STUB(r4, nullptr, LLDB_REGNUM_GENERIC_ARG1),
+ DEFINE_GENERIC_REGISTER_STUB(r5, nullptr, LLDB_REGNUM_GENERIC_ARG2),
+ DEFINE_GENERIC_REGISTER_STUB(r6, nullptr, LLDB_REGNUM_GENERIC_ARG3),
+ DEFINE_GENERIC_REGISTER_STUB(r7, nullptr, LLDB_REGNUM_GENERIC_ARG4),
+ DEFINE_GENERIC_REGISTER_STUB(r8, nullptr, LLDB_REGNUM_GENERIC_ARG5),
+ DEFINE_GENERIC_REGISTER_STUB(r9, nullptr, LLDB_REGNUM_GENERIC_ARG6),
+ DEFINE_GENERIC_REGISTER_STUB(r10, nullptr, LLDB_REGNUM_GENERIC_ARG7),
+ DEFINE_GENERIC_REGISTER_STUB(r11, nullptr, LLDB_REGNUM_GENERIC_ARG8),
+ DEFINE_REGISTER_STUB(r12, nullptr),
+ DEFINE_REGISTER_STUB(r13, nullptr),
+ DEFINE_REGISTER_STUB(r14, nullptr),
+ DEFINE_REGISTER_STUB(r15, nullptr),
+ DEFINE_REGISTER_STUB(r16, nullptr),
+ DEFINE_REGISTER_STUB(r17, nullptr),
+ DEFINE_REGISTER_STUB(r18, nullptr),
+ DEFINE_REGISTER_STUB(r19, nullptr),
+ DEFINE_REGISTER_STUB(r20, nullptr),
+ DEFINE_REGISTER_STUB(r21, nullptr),
+ DEFINE_GENERIC_REGISTER_STUB(r22, nullptr, LLDB_REGNUM_GENERIC_FP),
+ DEFINE_REGISTER_STUB(r23, nullptr),
+ DEFINE_REGISTER_STUB(r24, nullptr),
+ DEFINE_REGISTER_STUB(r25, nullptr),
+ DEFINE_REGISTER_STUB(r26, nullptr),
+ DEFINE_REGISTER_STUB(r27, nullptr),
+ DEFINE_REGISTER_STUB(r28, nullptr),
+ DEFINE_REGISTER_STUB(r29, nullptr),
+ DEFINE_REGISTER_STUB(r30, nullptr),
+ DEFINE_REGISTER_STUB(r31, nullptr),
+ DEFINE_GENERIC_REGISTER_STUB(pc, nullptr, LLDB_REGNUM_GENERIC_PC)}};
+} // namespace dwarf
+} // namespace
+
+// Number of argument registers (the base integer calling convention
+// provides 8 argument registers, a0-a7)
+static constexpr size_t g_regs_for_args_count = 8U;
+
+const RegisterInfo *ABISysV_loongarch::GetRegisterInfoArray(uint32_t &count) {
+ count = dwarf::g_register_infos.size();
+ return dwarf::g_register_infos.data();
+}
+
+//------------------------------------------------------------------
+// Static Functions
+//------------------------------------------------------------------
+
+ABISP
+ABISysV_loongarch::CreateInstance(ProcessSP process_sp, const ArchSpec &arch) {
+ llvm::Triple::ArchType machine = arch.GetTriple().getArch();
+
+ if (llvm::Triple::loongarch32 != machine &&
+ llvm::Triple::loongarch64 != machine)
+ return ABISP();
+
+ ABISysV_loongarch *abi =
+ new ABISysV_loongarch(std::move(process_sp), MakeMCRegisterInfo(arch));
+ if (abi)
+ abi->SetIsLA64((llvm::Triple::loongarch64 == machine) ? true : false);
+ return ABISP(abi);
+}
+
+static bool UpdateRegister(RegisterContext *reg_ctx,
+ const lldb::RegisterKind reg_kind,
+ const uint32_t reg_num, const addr_t value) {
+ Log *log = GetLog(LLDBLog::Expressions);
+
+ const RegisterInfo *reg_info = reg_ctx->GetRegisterInfo(reg_kind, reg_num);
+
+ LLDB_LOG(log, "Writing {0}: 0x{1:x}", reg_info->name,
+ static_cast<uint64_t>(value));
+ if (!reg_ctx->WriteRegisterFromUnsigned(reg_info, value)) {
+ LLDB_LOG(log, "Writing {0}: failed", reg_info->name);
+ return false;
+ }
+ return true;
+}
+
+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) {
+ std::stringstream ss;
+ ss << "ABISysV_loongarch::PrepareTrivialCall"
+ << " (tid = 0x" << std::hex << thread.GetID() << ", sp = 0x" << sp
+ << ", func_addr = 0x" << func_addr << ", return_addr = 0x" << return_addr;
+
+ for (auto [idx, arg] : enumerate(args))
+ ss << ", arg" << std::dec << idx << " = 0x" << std::hex << arg;
+ ss << ")";
+ log.PutString(ss.str());
+}
+
+bool ABISysV_loongarch::PrepareTrivialCall(Thread &thread, addr_t sp,
+ addr_t func_addr, addr_t return_addr,
+ llvm::ArrayRef<addr_t> args) const {
+ Log *log = GetLog(LLDBLog::Expressions);
+ if (log)
+ LogInitInfo(*log, thread, sp, func_addr, return_addr, args);
+
+ const auto reg_ctx_sp = thread.GetRegisterContext();
+ if (!reg_ctx_sp) {
+ LLDB_LOG(log, "Failed to get RegisterContext");
+ return false;
+ }
+
+ if (args.size() > g_regs_for_args_count) {
+ LLDB_LOG(log, "Function has {0} arguments, but only {1} are allowed!",
+ args.size(), g_regs_for_args_count);
+ return false;
+ }
+
+ // Write arguments to registers
+ for (auto [idx, arg] : enumerate(args)) {
+ const RegisterInfo *reg_info = reg_ctx_sp->GetRegisterInfo(
+ eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1 + idx);
+ LLDB_LOG(log, "About to write arg{0} (0x{1:x}) into {2}", idx, arg,
+ reg_info->name);
+
+ if (!reg_ctx_sp->WriteRegisterFromUnsigned(reg_info, arg)) {
+ LLDB_LOG(log, "Failed to write arg{0} (0x{1:x}) into {2}", idx, arg,
+ reg_info->name);
+ return false;
+ }
+ }
+
+ if (!UpdateRegister(reg_ctx_sp.get(), eRegisterKindGeneric,
+ LLDB_REGNUM_GENERIC_PC, func_addr))
+ return false;
+ if (!UpdateRegister(reg_ctx_sp.get(), eRegisterKindGeneric,
+ LLDB_REGNUM_GENERIC_SP, sp))
+ return false;
+ if (!UpdateRegister(reg_ctx_sp.get(), eRegisterKindGeneric,
+ LLDB_REGNUM_GENERIC_RA, return_addr))
+ return false;
+
+ LLDB_LOG(log, "ABISysV_riscv::{0}() success", __FUNCTION__);
+ return true;
+}
+
+bool ABISysV_loongarch::GetArgumentValues(Thread &thread,
+ ValueList &values) const {
+ // TODO: Implement
+ return false;
+}
+
+Status ABISysV_loongarch::SetReturnValueObject(StackFrameSP &frame_sp,
+ ValueObjectSP &new_value_sp) {
+ Status result;
+ if (!new_value_sp) {
+ result = Status::FromErrorString("Empty value object for return value.");
+ return result;
+ }
+
+ CompilerType compiler_type = new_value_sp->GetCompilerType();
+ if (!compiler_type) {
+ result = Status::FromErrorString("Null clang type for return value.");
+ return result;
+ }
+
+ auto ®_ctx = *frame_sp->GetThread()->GetRegisterContext();
+
+ bool is_signed = false;
+ if (!compiler_type.IsIntegerOrEnumerationType(is_signed) &&
+ !compiler_type.IsPointerType()) {
+ result = Status::FromErrorString(
+ "We don't support returning other types at present");
+ return result;
+ }
+
+ DataExtractor data;
+ size_t num_bytes = new_value_sp->GetData(data, result);
+
+ if (result.Fail()) {
+ result = Status::FromErrorStringWithFormat(
+ "Couldn't convert return value to raw data: %s", result.AsCString());
+ return result;
+ }
+
+ size_t reg_size = m_is_la64 ? 8 : 4;
+ if (num_bytes <= 2 * reg_size) {
+ offset_t offset = 0;
+ uint64_t raw_value = data.GetMaxU64(&offset, num_bytes);
+
+ auto reg_info =
+ reg_ctx.GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1);
+ if (!reg_ctx.WriteRegisterFromUnsigned(reg_info, raw_value)) {
+ result = Status::FromErrorStringWithFormat(
+ "Couldn't write value to register %s", reg_info->name);
+ return result;
+ }
+
+ if (num_bytes <= reg_size)
+ return result; // Successfully written.
+
+ // for loongarch32, get the upper 32 bits from raw_value and write them
+ // for loongarch64, get the next 64 bits from data and write them
+ if (4 == reg_size)
+ raw_value >>= 32;
+ else
+ raw_value = data.GetMaxU64(&offset, num_bytes - reg_size);
+ reg_info =
+ reg_ctx.GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG2);
+ if (!reg_ctx.WriteRegisterFromUnsigned(reg_info, raw_value)) {
+ result = Status::FromErrorStringWithFormat(
+ "Couldn't write value to register %s", reg_info->name);
+ }
+
+ return result;
+ }
+
+ result = Status::FromErrorString(
+ "We don't support returning large integer values at present.");
+ return result;
+}
+
+template <typename T>
+static void SetInteger(Scalar &scalar, uint64_t raw_value, bool is_signed) {
+ raw_value &= std::numeric_limits<T>::max();
+ if (is_signed)
+ scalar = static_cast<typename std::make_signed<T>::type>(raw_value);
+ else
+ scalar = static_cast<T>(raw_value);
+}
+
+static bool SetSizedInteger(Scalar &scalar, uint64_t raw_value,
+ uint8_t size_in_bytes, bool is_signed) {
+ switch (size_in_bytes) {
+ default:
+ return false;
+
+ case sizeof(uint64_t):
+ SetInteger<uint64_t>(scalar, raw_value, is_signed);
+ break;
+
+ case sizeof(uint32_t):
+ SetInteger<uint32_t>(scalar, raw_value, is_signed);
+ break;
+
+ case sizeof(uint16_t):
+ SetInteger<uint16_t>(scalar, raw_value, is_signed);
+ break;
+
+ case sizeof(uint8_t):
+ SetInteger<uint8_t>(scalar, raw_value, is_signed);
+ break;
+ }
+
+ return true;
+}
+
+static bool SetSizedFloat(Scalar &scalar, uint64_t raw_value,
+ uint8_t size_in_bytes) {
+ switch (size_in_bytes) {
+ default:
+ return false;
+
+ case sizeof(uint64_t):
+ scalar = *reinterpret_cast<double *>(&raw_value);
+ break;
+
+ case sizeof(uint32_t):
+ scalar = *reinterpret_cast<float *>(&raw_value);
+ break;
+ }
+
+ return true;
+}
+
+static ValueObjectSP GetValObjFromIntRegs(Thread &thread,
+ const RegisterContextSP ®_ctx,
+ llvm::Triple::ArchType machine,
+ uint32_t type_flags,
+ uint32_t byte_size) {
+ Value value;
+ ValueObjectSP return_valobj_sp;
+ auto reg_info_a0 =
+ reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1);
+ auto reg_info_a1 =
+ reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG2);
+ uint64_t raw_value;
+
+ switch (byte_size) {
+ case sizeof(uint32_t):
+ // Read a0 to get the arg
+ raw_value = reg_ctx->ReadRegisterAsUnsigned(reg_info_a0, 0) & UINT32_MAX;
+ break;
+ case sizeof(uint64_t):
+ raw_value = reg_ctx->ReadRegisterAsUnsigned(reg_info_a0, 0);
+ break;
+ case 16: {
+ // Create the ValueObjectSP here and return
+ std::unique_ptr<DataBufferHeap> heap_data_up(
+ new DataBufferHeap(byte_size, 0));
+ const ByteOrder byte_order = thread.GetProcess()->GetByteOrder();
+ RegisterValue reg_value_a0, reg_value_a1;
+ if (reg_ctx->ReadRegister(reg_info_a0, reg_value_a0) &&
+ reg_ctx->ReadRegister(reg_info_a1, reg_value_a1)) {
+ Status error;
+ if (reg_value_a0.GetAsMemoryData(*reg_info_a0,
+ heap_data_up->GetBytes() + 0, 8,
+ byte_order, error) &&
+ reg_value_a1.GetAsMemoryData(*reg_info_a1,
+ heap_data_up->GetBytes() + 8, 8,
+ byte_order, error)) {
+ value.SetBytes(heap_data_up.release(), byte_size);
+ return ValueObjectConstResult::Create(
+ thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));
+ }
+ }
+ break;
+ }
+ default:
+ return return_valobj_sp;
+ }
+
+ if (type_flags & eTypeIsInteger) {
+ const bool is_signed = (type_flags & eTypeIsSigned) != 0;
+ if (!SetSizedInteger(value.GetScalar(), raw_value, byte_size, is_signed))
+ return return_valobj_sp;
+ } else if (type_flags & eTypeIsFloat) {
+ if (!SetSizedFloat(value.GetScalar(), raw_value, byte_size))
+ return return_valobj_sp;
+ } else
+ return return_valobj_sp;
+
+ value.SetValueType(Value::ValueType::Scalar);
+ return_valobj_sp = ValueObjectConstResult::Create(
+ thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));
+ return return_valobj_sp;
+}
+
+static ValueObjectSP GetValObjFromFPRegs(Thread &thread,
+ const RegisterContextSP ®_ctx,
+ llvm::Triple::ArchType machine,
+ uint32_t type_flags,
+ uint32_t byte_size) {
+ auto reg_info_fa0 = reg_ctx->GetRegisterInfoByName("f0");
+ bool use_fp_regs = false;
+ ValueObjectSP return_valobj_sp;
+
+ if (byte_size <= 8)
+ use_fp_regs = true;
+
+ if (use_fp_regs) {
+ uint64_t raw_value;
+ Value value;
+ raw_value = reg_ctx->ReadRegisterAsUnsigned(reg_info_fa0, 0);
+ if (!SetSizedFloat(value.GetScalar(), raw_value, byte_size))
+ return return_valobj_sp;
+ value.SetValueType(Value::ValueType::Scalar);
+ return ValueObjectConstResult::Create(thread.GetStackFrameAtIndex(0).get(),
+ value, ConstString(""));
+ }
+ // we should never reach this, but if we do, use the integer registers
+ return GetValObjFromIntRegs(thread, reg_ctx, machine, type_flags, byte_size);
+}
+
+ValueObjectSP ABISysV_loongarch::GetReturnValueObjectSimple(
+ Thread &thread, CompilerType &compiler_type) const {
+ ValueObjectSP return_valobj_sp;
+
+ if (!compiler_type)
+ return return_valobj_sp;
+
+ auto reg_ctx = thread.GetRegisterContext();
+ if (!reg_ctx)
+ return return_valobj_sp;
+
+ Value value;
+ value.SetCompilerType(compiler_type);
+
+ const uint32_t type_flags = compiler_type.GetTypeInfo();
+ const size_t byte_size = compiler_type.GetByteSize(&thread).value_or(0);
+ const ArchSpec arch = thread.GetProcess()->GetTarget().GetArchitecture();
+ const llvm::Triple::ArchType machine = arch.GetMachine();
+
+ // Integer return type.
+ if (type_flags & eTypeIsInteger) {
+ return_valobj_sp =
+ GetValObjFromIntRegs(thread, reg_ctx, machine, type_flags, byte_size);
+ return return_valobj_sp;
+ }
+ // Pointer return type.
+ if (type_flags & eTypeIsPointer) {
+ const auto *reg_info_a0 = reg_ctx->GetRegisterInfo(
+ eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1);
+ value.GetScalar() = reg_ctx->ReadRegisterAsUnsigned(reg_info_a0, 0);
+ value.SetValueType(Value::ValueType::Scalar);
+ return ValueObjectConstResult::Create(thread.GetStackFrameAtIndex(0).get(),
+ value, ConstString(""));
+ }
+ // Floating point return type.
+ if (type_flags & eTypeIsFloat) {
+ uint32_t float_count = 0;
+ bool is_complex = false;
+
+ if (compiler_type.IsFloatingPointType(float_count, is_complex) &&
+ float_count == 1 && !is_complex) {
+ return_valobj_sp =
+ GetValObjFromFPRegs(thread, reg_ctx, machine, type_flags, byte_size);
+ return return_valobj_sp;
+ }
+ }
+ return return_valobj_sp;
+}
+
+ValueObjectSP ABISysV_loongarch::GetReturnValueObjectImpl(
+ Thread &thread, CompilerType &return_compiler_type) const {
+ ValueObjectSP return_valobj_sp;
+
+ if (!return_compiler_type)
+ return return_valobj_sp;
+
+ ExecutionContext exe_ctx(thread.shared_from_this());
+ return GetReturnValueObjectSimple(thread, return_compiler_type);
+}
+
+bool ABISysV_loongarch::CreateFunctionEntryUnwindPlan(UnwindPlan &unwind_plan) {
+ unwind_plan.Clear();
+ unwind_plan.SetRegisterKind(eRegisterKindDWARF);
+
+ uint32_t pc_reg_num = loongarch_dwarf::dwarf_gpr_pc;
+ uint32_t sp_reg_num = loongarch_dwarf::dwarf_gpr_sp;
+ uint32_t ra_reg_num = loongarch_dwarf::dwarf_gpr_ra;
+
+ UnwindPlan::RowSP row(new UnwindPlan::Row);
+
+ // Define CFA as the stack pointer
+ row->GetCFAValue().SetIsRegisterPlusOffset(sp_reg_num, 0);
+
+ // Previous frame's pc is in ra
+
+ row->SetRegisterLocationToRegister(pc_reg_num, ra_reg_num, true);
+ unwind_plan.AppendRow(row);
+ unwind_plan.SetSourceName("loongarch function-entry unwind plan");
+ unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
+
+ return true;
+}
+
+bool ABISysV_loongarch::CreateDefaultUnwindPlan(UnwindPlan &unwind_pl...
[truncated]
|
Created using spr 1.3.5-bogner
Created using spr 1.3.5-bogner
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM but a LoongArch expert should give the final approval.
Created using spr 1.3.5-bogner
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. But should land after #114741.
Created using spr 1.3.5-bogner [skip ci]
This patch adds desired feature flags in JIT compiler to enable hard-float instructions if target supports them and allows to use floats and doubles in lldb expressions. Fited tests: lldb-shell :: Expr/TestAnonNamespaceParamFunc.cpp lldb-shell :: Expr/TestIRMemoryMap.test lldb-shell :: Expr/TestStringLiteralExpr.test lldb-shell :: SymbolFile/DWARF/debug-types-expressions.test Similar as llvm#99336 Depens on: llvm#114741 Reviewed By: SixWeining Pull Request: llvm#114742
This patch adds desired feature flags in JIT compiler to enable
hard-float instructions if target supports them and allows to use floats
and doubles in lldb expressions.
Fited tests:
lldb-shell :: Expr/TestAnonNamespaceParamFunc.cpp
lldb-shell :: Expr/TestIRMemoryMap.test
lldb-shell :: Expr/TestStringLiteralExpr.test
lldb-shell :: SymbolFile/DWARF/debug-types-expressions.test
Similar as #99336
Depens on: #114741