665 lines · cpp
1//===-- ABISysV_loongarch.cpp----------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "ABISysV_loongarch.h"10 11#include <array>12#include <limits>13#include <sstream>14 15#include "llvm/ADT/StringRef.h"16#include "llvm/IR/DerivedTypes.h"17#include "llvm/Support/MathExtras.h"18 19#include "Utility/LoongArch_DWARF_Registers.h"20#include "lldb/Core/PluginManager.h"21#include "lldb/Core/Value.h"22#include "lldb/Target/RegisterContext.h"23#include "lldb/Target/StackFrame.h"24#include "lldb/Target/Thread.h"25#include "lldb/Utility/LLDBLog.h"26#include "lldb/Utility/RegisterValue.h"27#include "lldb/ValueObject/ValueObjectConstResult.h"28 29#define DEFINE_REG_NAME(reg_num) ConstString(#reg_num).GetCString()30#define DEFINE_REG_NAME_STR(reg_name) ConstString(reg_name).GetCString()31 32// The ABI is not a source of such information as size, offset, encoding, etc.33// of a register. Just provides correct dwarf and eh_frame numbers.34 35#define DEFINE_GENERIC_REGISTER_STUB(dwarf_num, generic_num) \36 { \37 DEFINE_REG_NAME(dwarf_num), \38 DEFINE_REG_NAME_STR(nullptr), \39 0, \40 0, \41 eEncodingInvalid, \42 eFormatDefault, \43 {dwarf_num, dwarf_num, generic_num, LLDB_INVALID_REGNUM, dwarf_num}, \44 nullptr, \45 nullptr, \46 nullptr, \47 }48 49#define DEFINE_REGISTER_STUB(dwarf_num) \50 DEFINE_GENERIC_REGISTER_STUB(dwarf_num, LLDB_INVALID_REGNUM)51 52using namespace lldb;53using namespace lldb_private;54 55LLDB_PLUGIN_DEFINE_ADV(ABISysV_loongarch, ABILoongArch)56 57namespace {58namespace dwarf {59enum regnums {60 r0,61 r1,62 ra = r1,63 r2,64 r3,65 sp = r3,66 r4,67 r5,68 r6,69 r7,70 r8,71 r9,72 r10,73 r11,74 r12,75 r13,76 r14,77 r15,78 r16,79 r17,80 r18,81 r19,82 r20,83 r21,84 r22,85 fp = r22,86 r23,87 r24,88 r25,89 r26,90 r27,91 r28,92 r29,93 r30,94 r31,95 pc96};97 98static const std::array<RegisterInfo, 33> g_register_infos = {99 {DEFINE_REGISTER_STUB(r0),100 DEFINE_GENERIC_REGISTER_STUB(r1, LLDB_REGNUM_GENERIC_RA),101 DEFINE_REGISTER_STUB(r2),102 DEFINE_GENERIC_REGISTER_STUB(r3, LLDB_REGNUM_GENERIC_SP),103 DEFINE_GENERIC_REGISTER_STUB(r4, LLDB_REGNUM_GENERIC_ARG1),104 DEFINE_GENERIC_REGISTER_STUB(r5, LLDB_REGNUM_GENERIC_ARG2),105 DEFINE_GENERIC_REGISTER_STUB(r6, LLDB_REGNUM_GENERIC_ARG3),106 DEFINE_GENERIC_REGISTER_STUB(r7, LLDB_REGNUM_GENERIC_ARG4),107 DEFINE_GENERIC_REGISTER_STUB(r8, LLDB_REGNUM_GENERIC_ARG5),108 DEFINE_GENERIC_REGISTER_STUB(r9, LLDB_REGNUM_GENERIC_ARG6),109 DEFINE_GENERIC_REGISTER_STUB(r10, LLDB_REGNUM_GENERIC_ARG7),110 DEFINE_GENERIC_REGISTER_STUB(r11, LLDB_REGNUM_GENERIC_ARG8),111 DEFINE_REGISTER_STUB(r12),112 DEFINE_REGISTER_STUB(r13),113 DEFINE_REGISTER_STUB(r14),114 DEFINE_REGISTER_STUB(r15),115 DEFINE_REGISTER_STUB(r16),116 DEFINE_REGISTER_STUB(r17),117 DEFINE_REGISTER_STUB(r18),118 DEFINE_REGISTER_STUB(r19),119 DEFINE_REGISTER_STUB(r20),120 DEFINE_REGISTER_STUB(r21),121 DEFINE_GENERIC_REGISTER_STUB(r22, LLDB_REGNUM_GENERIC_FP),122 DEFINE_REGISTER_STUB(r23),123 DEFINE_REGISTER_STUB(r24),124 DEFINE_REGISTER_STUB(r25),125 DEFINE_REGISTER_STUB(r26),126 DEFINE_REGISTER_STUB(r27),127 DEFINE_REGISTER_STUB(r28),128 DEFINE_REGISTER_STUB(r29),129 DEFINE_REGISTER_STUB(r30),130 DEFINE_REGISTER_STUB(r31),131 DEFINE_GENERIC_REGISTER_STUB(pc, LLDB_REGNUM_GENERIC_PC)}};132} // namespace dwarf133} // namespace134 135// Number of argument registers (the base integer calling convention136// provides 8 argument registers, a0-a7)137static constexpr size_t g_regs_for_args_count = 8U;138 139const RegisterInfo *ABISysV_loongarch::GetRegisterInfoArray(uint32_t &count) {140 count = dwarf::g_register_infos.size();141 return dwarf::g_register_infos.data();142}143 144//------------------------------------------------------------------145// Static Functions146//------------------------------------------------------------------147 148ABISP149ABISysV_loongarch::CreateInstance(ProcessSP process_sp, const ArchSpec &arch) {150 llvm::Triple::ArchType machine = arch.GetTriple().getArch();151 152 if (llvm::Triple::loongarch32 != machine &&153 llvm::Triple::loongarch64 != machine)154 return ABISP();155 156 ABISysV_loongarch *abi =157 new ABISysV_loongarch(std::move(process_sp), MakeMCRegisterInfo(arch));158 if (abi)159 abi->SetIsLA64(llvm::Triple::loongarch64 == machine);160 return ABISP(abi);161}162 163static bool UpdateRegister(RegisterContext *reg_ctx,164 const lldb::RegisterKind reg_kind,165 const uint32_t reg_num, const addr_t value) {166 Log *log = GetLog(LLDBLog::Expressions);167 168 const RegisterInfo *reg_info = reg_ctx->GetRegisterInfo(reg_kind, reg_num);169 170 LLDB_LOG(log, "Writing {0}: 0x{1:x}", reg_info->name,171 static_cast<uint64_t>(value));172 if (!reg_ctx->WriteRegisterFromUnsigned(reg_info, value)) {173 LLDB_LOG(log, "Writing {0}: failed", reg_info->name);174 return false;175 }176 return true;177}178 179static void LogInitInfo(Log &log, const Thread &thread, addr_t sp,180 addr_t func_addr, addr_t return_addr,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" << sp185 << ", func_addr = 0x" << func_addr << ", return_addr = 0x" << return_addr;186 187 for (auto [idx, arg] : enumerate(args))188 ss << ", arg" << std::dec << idx << " = 0x" << std::hex << arg;189 ss << ")";190 log.PutString(ss.str());191}192 193bool ABISysV_loongarch::PrepareTrivialCall(Thread &thread, addr_t sp,194 addr_t func_addr, addr_t return_addr,195 llvm::ArrayRef<addr_t> args) const {196 Log *log = GetLog(LLDBLog::Expressions);197 if (log)198 LogInitInfo(*log, thread, sp, func_addr, return_addr, args);199 200 const auto reg_ctx_sp = thread.GetRegisterContext();201 if (!reg_ctx_sp) {202 LLDB_LOG(log, "Failed to get RegisterContext");203 return false;204 }205 206 if (args.size() > g_regs_for_args_count) {207 LLDB_LOG(log, "Function has {0} arguments, but only {1} are allowed!",208 args.size(), g_regs_for_args_count);209 return false;210 }211 212 // Write arguments to registers213 for (auto [idx, arg] : enumerate(args)) {214 const RegisterInfo *reg_info = reg_ctx_sp->GetRegisterInfo(215 eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1 + idx);216 LLDB_LOG(log, "About to write arg{0} ({1:x}) into {2}", idx, arg,217 reg_info->name);218 219 if (!reg_ctx_sp->WriteRegisterFromUnsigned(reg_info, arg)) {220 LLDB_LOG(log, "Failed to write arg{0} ({1:x}) into {2}", idx, arg,221 reg_info->name);222 return false;223 }224 }225 226 if (!UpdateRegister(reg_ctx_sp.get(), eRegisterKindGeneric,227 LLDB_REGNUM_GENERIC_PC, func_addr))228 return false;229 if (!UpdateRegister(reg_ctx_sp.get(), eRegisterKindGeneric,230 LLDB_REGNUM_GENERIC_SP, sp))231 return false;232 if (!UpdateRegister(reg_ctx_sp.get(), eRegisterKindGeneric,233 LLDB_REGNUM_GENERIC_RA, return_addr))234 return false;235 236 LLDB_LOG(log, "ABISysV_loongarch::{0}() success", __FUNCTION__);237 return true;238}239 240bool ABISysV_loongarch::GetArgumentValues(Thread &thread,241 ValueList &values) const {242 // TODO: Implement243 return false;244}245 246Status ABISysV_loongarch::SetReturnValueObject(StackFrameSP &frame_sp,247 ValueObjectSP &new_value_sp) {248 Status result;249 if (!new_value_sp) {250 result = Status::FromErrorString("Empty value object for return value.");251 return result;252 }253 254 CompilerType compiler_type = new_value_sp->GetCompilerType();255 if (!compiler_type) {256 result = Status::FromErrorString("Null clang type for return value.");257 return result;258 }259 260 auto ®_ctx = *frame_sp->GetThread()->GetRegisterContext();261 262 bool is_signed = false;263 if (!compiler_type.IsIntegerOrEnumerationType(is_signed) &&264 !compiler_type.IsPointerType()) {265 result = Status::FromErrorString(266 "We don't support returning other types at present");267 return result;268 }269 270 DataExtractor data;271 size_t num_bytes = new_value_sp->GetData(data, result);272 273 if (result.Fail()) {274 result = Status::FromErrorStringWithFormat(275 "Couldn't convert return value to raw data: %s", result.AsCString());276 return result;277 }278 279 size_t reg_size = m_is_la64 ? 8 : 4;280 // Currently, we only support sizeof(data) <= 2 * reg_size.281 // 1. If the (`size` <= reg_size), the `data` will be returned through `ARG1`.282 // 2. If the (`size` > reg_size && `size` <= 2 * reg_size), the `data` will be283 // returned through a pair of registers (ARG1 and ARG2), and the lower-ordered284 // bits in the `ARG1`.285 if (num_bytes > 2 * reg_size) {286 result = Status::FromErrorString(287 "We don't support returning large integer values at present.");288 return result;289 }290 291 offset_t offset = 0;292 uint64_t raw_value = data.GetMaxU64(&offset, num_bytes);293 // According to psABI, i32 (no matter signed or unsigned) should be294 // sign-extended in register.295 if (4 == num_bytes && m_is_la64)296 raw_value = llvm::SignExtend64<32>(raw_value);297 auto reg_info =298 reg_ctx.GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1);299 if (!reg_ctx.WriteRegisterFromUnsigned(reg_info, raw_value)) {300 result = Status::FromErrorStringWithFormat(301 "Couldn't write value to register %s", reg_info->name);302 return result;303 }304 305 if (num_bytes <= reg_size)306 return result; // Successfully written.307 308 // For loongarch32, get the upper 32 bits from raw_value and write them.309 // For loongarch64, get the next 64 bits from data and write them.310 if (4 == reg_size)311 raw_value >>= 32;312 else313 raw_value = data.GetMaxU64(&offset, num_bytes - reg_size);314 315 reg_info =316 reg_ctx.GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG2);317 if (!reg_ctx.WriteRegisterFromUnsigned(reg_info, raw_value))318 result = Status::FromErrorStringWithFormat(319 "Couldn't write value to register %s", reg_info->name);320 321 return result;322}323 324template <typename T>325static void SetInteger(Scalar &scalar, uint64_t raw_value, bool is_signed) {326 static_assert(std::is_unsigned<T>::value, "T must be an unsigned type.");327 raw_value &= std::numeric_limits<T>::max();328 if (is_signed)329 scalar = static_cast<typename std::make_signed<T>::type>(raw_value);330 else331 scalar = static_cast<T>(raw_value);332}333 334static bool SetSizedInteger(Scalar &scalar, uint64_t raw_value,335 uint8_t size_in_bytes, bool is_signed) {336 switch (size_in_bytes) {337 default:338 return false;339 340 case sizeof(uint64_t):341 SetInteger<uint64_t>(scalar, raw_value, is_signed);342 break;343 344 case sizeof(uint32_t):345 SetInteger<uint32_t>(scalar, raw_value, is_signed);346 break;347 348 case sizeof(uint16_t):349 SetInteger<uint16_t>(scalar, raw_value, is_signed);350 break;351 352 case sizeof(uint8_t):353 SetInteger<uint8_t>(scalar, raw_value, is_signed);354 break;355 }356 357 return true;358}359 360static bool SetSizedFloat(Scalar &scalar, uint64_t raw_value,361 uint8_t size_in_bytes) {362 switch (size_in_bytes) {363 default:364 return false;365 366 case sizeof(uint64_t):367 scalar = *reinterpret_cast<double *>(&raw_value);368 break;369 370 case sizeof(uint32_t):371 scalar = *reinterpret_cast<float *>(&raw_value);372 break;373 }374 375 return true;376}377 378static ValueObjectSP GetValObjFromIntRegs(Thread &thread,379 const RegisterContextSP ®_ctx,380 llvm::Triple::ArchType machine,381 uint32_t type_flags,382 uint32_t byte_size) {383 Value value;384 ValueObjectSP return_valobj_sp;385 auto *reg_info_a0 =386 reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1);387 auto *reg_info_a1 =388 reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG2);389 uint64_t raw_value = 0;390 391 switch (byte_size) {392 case sizeof(uint32_t):393 // Read a0 to get the arg394 raw_value = reg_ctx->ReadRegisterAsUnsigned(reg_info_a0, 0) & UINT32_MAX;395 break;396 case sizeof(uint64_t):397 // Read a0 to get the arg on loongarch64, a0 and a1 on loongarch32398 if (llvm::Triple::loongarch32 == machine) {399 raw_value = reg_ctx->ReadRegisterAsUnsigned(reg_info_a0, 0) & UINT32_MAX;400 raw_value |=401 (reg_ctx->ReadRegisterAsUnsigned(reg_info_a1, 0) & UINT32_MAX) << 32U;402 } else {403 raw_value = reg_ctx->ReadRegisterAsUnsigned(reg_info_a0, 0);404 }405 break;406 case 16: {407 // Read a0 and a1 to get the arg on loongarch64, not supported on408 // loongarch32409 if (llvm::Triple::loongarch32 == machine)410 return return_valobj_sp;411 412 // Create the ValueObjectSP here and return413 std::unique_ptr<DataBufferHeap> heap_data_up(414 new DataBufferHeap(byte_size, 0));415 const ByteOrder byte_order = thread.GetProcess()->GetByteOrder();416 RegisterValue reg_value_a0, reg_value_a1;417 if (reg_ctx->ReadRegister(reg_info_a0, reg_value_a0) &&418 reg_ctx->ReadRegister(reg_info_a1, reg_value_a1)) {419 Status error;420 if (reg_value_a0.GetAsMemoryData(*reg_info_a0,421 heap_data_up->GetBytes() + 0, 8,422 byte_order, error) &&423 reg_value_a1.GetAsMemoryData(*reg_info_a1,424 heap_data_up->GetBytes() + 8, 8,425 byte_order, error)) {426 value.SetBytes(heap_data_up.release(), byte_size);427 return ValueObjectConstResult::Create(428 thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));429 }430 }431 break;432 }433 default:434 return return_valobj_sp;435 }436 437 if (type_flags & eTypeIsInteger) {438 if (!SetSizedInteger(value.GetScalar(), raw_value, byte_size,439 type_flags & eTypeIsSigned))440 return return_valobj_sp;441 } else if (type_flags & eTypeIsFloat) {442 if (!SetSizedFloat(value.GetScalar(), raw_value, byte_size))443 return return_valobj_sp;444 } else445 return return_valobj_sp;446 447 value.SetValueType(Value::ValueType::Scalar);448 return_valobj_sp = ValueObjectConstResult::Create(449 thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));450 return return_valobj_sp;451}452 453static ValueObjectSP GetValObjFromFPRegs(Thread &thread,454 const RegisterContextSP ®_ctx,455 llvm::Triple::ArchType machine,456 uint32_t type_flags,457 uint32_t byte_size) {458 auto *reg_info_fa0 = reg_ctx->GetRegisterInfoByName("f0");459 bool use_fp_regs = false;460 ValueObjectSP return_valobj_sp;461 462 if (byte_size <= 8)463 use_fp_regs = true;464 465 if (use_fp_regs) {466 uint64_t raw_value;467 Value value;468 raw_value = reg_ctx->ReadRegisterAsUnsigned(reg_info_fa0, 0);469 if (!SetSizedFloat(value.GetScalar(), raw_value, byte_size))470 return return_valobj_sp;471 value.SetValueType(Value::ValueType::Scalar);472 return ValueObjectConstResult::Create(thread.GetStackFrameAtIndex(0).get(),473 value, ConstString(""));474 }475 // we should never reach this, but if we do, use the integer registers476 return GetValObjFromIntRegs(thread, reg_ctx, machine, type_flags, byte_size);477}478 479ValueObjectSP ABISysV_loongarch::GetReturnValueObjectSimple(480 Thread &thread, CompilerType &compiler_type) const {481 ValueObjectSP return_valobj_sp;482 483 if (!compiler_type)484 return return_valobj_sp;485 486 auto reg_ctx = thread.GetRegisterContext();487 if (!reg_ctx)488 return return_valobj_sp;489 490 Value value;491 value.SetCompilerType(compiler_type);492 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();498 499 if (type_flags & eTypeIsInteger) {500 return_valobj_sp =501 GetValObjFromIntRegs(thread, reg_ctx, machine, type_flags, byte_size);502 return return_valobj_sp;503 }504 if (type_flags & eTypeIsPointer) {505 const auto *reg_info_a0 = reg_ctx->GetRegisterInfo(506 eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1);507 value.GetScalar() = reg_ctx->ReadRegisterAsUnsigned(reg_info_a0, 0);508 value.SetValueType(Value::ValueType::Scalar);509 return ValueObjectConstResult::Create(thread.GetStackFrameAtIndex(0).get(),510 value, ConstString(""));511 }512 if (type_flags & eTypeIsFloat) {513 bool is_complex = false;514 515 if (compiler_type.IsFloatingPointType(is_complex) &&516 !(type_flags & eTypeIsVector) && !is_complex) {517 return_valobj_sp =518 GetValObjFromFPRegs(thread, reg_ctx, machine, type_flags, byte_size);519 return return_valobj_sp;520 }521 }522 return return_valobj_sp;523}524 525ValueObjectSP ABISysV_loongarch::GetReturnValueObjectImpl(526 Thread &thread, CompilerType &return_compiler_type) const {527 ValueObjectSP return_valobj_sp;528 529 if (!return_compiler_type)530 return return_valobj_sp;531 532 ExecutionContext exe_ctx(thread.shared_from_this());533 return GetReturnValueObjectSimple(thread, return_compiler_type);534}535 536UnwindPlanSP ABISysV_loongarch::CreateFunctionEntryUnwindPlan() {537 uint32_t pc_reg_num = loongarch_dwarf::dwarf_gpr_pc;538 uint32_t sp_reg_num = loongarch_dwarf::dwarf_gpr_sp;539 uint32_t ra_reg_num = loongarch_dwarf::dwarf_gpr_ra;540 541 UnwindPlan::Row row;542 543 // Define CFA as the stack pointer544 row.GetCFAValue().SetIsRegisterPlusOffset(sp_reg_num, 0);545 546 // Previous frame's pc is in ra547 row.SetRegisterLocationToRegister(pc_reg_num, ra_reg_num, true);548 549 auto plan_sp = std::make_shared<UnwindPlan>(eRegisterKindDWARF);550 plan_sp->AppendRow(std::move(row));551 plan_sp->SetSourceName("loongarch function-entry unwind plan");552 plan_sp->SetSourcedFromCompiler(eLazyBoolNo);553 return plan_sp;554}555 556UnwindPlanSP ABISysV_loongarch::CreateDefaultUnwindPlan() {557 uint32_t pc_reg_num = LLDB_REGNUM_GENERIC_PC;558 uint32_t fp_reg_num = LLDB_REGNUM_GENERIC_FP;559 560 UnwindPlan::Row row;561 562 // Define the CFA as the current frame pointer value.563 row.GetCFAValue().SetIsRegisterPlusOffset(fp_reg_num, 0);564 565 int reg_size = 4;566 if (m_is_la64)567 reg_size = 8;568 569 // Assume the ra reg (return pc) and caller's frame pointer570 // have been spilled to stack already.571 row.SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, reg_size * -2, true);572 row.SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, reg_size * -1, true);573 574 auto plan_sp = std::make_shared<UnwindPlan>(eRegisterKindGeneric);575 plan_sp->AppendRow(std::move(row));576 plan_sp->SetSourceName("loongarch default unwind plan");577 plan_sp->SetSourcedFromCompiler(eLazyBoolNo);578 plan_sp->SetUnwindPlanValidAtAllInstructions(eLazyBoolNo);579 return plan_sp;580}581 582bool ABISysV_loongarch::RegisterIsVolatile(const RegisterInfo *reg_info) {583 return !RegisterIsCalleeSaved(reg_info);584}585 586bool ABISysV_loongarch::RegisterIsCalleeSaved(const RegisterInfo *reg_info) {587 if (!reg_info)588 return false;589 590 const char *name = reg_info->name;591 ArchSpec arch = GetProcessSP()->GetTarget().GetArchitecture();592 uint32_t arch_flags = arch.GetFlags();593 // Floating point registers are only callee saved when using594 // F or D hardware floating point ABIs.595 bool is_hw_fp = (arch_flags & ArchSpec::eLoongArch_abi_mask) != 0;596 597 return llvm::StringSwitch<bool>(name)598 // integer ABI names599 .Cases({"ra", "sp", "fp"}, true)600 .Cases({"s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9"}, true)601 // integer hardware names602 .Cases({"r1", "r3", "r22"}, true)603 .Cases({"r23", "r24", "r25", "r26", "r27", "r28", "r29", "r30", "31"},604 true)605 // floating point ABI names606 .Cases({"fs0", "fs1", "fs2", "fs3", "fs4", "fs5", "fs6", "fs7"}, is_hw_fp)607 // floating point hardware names608 .Cases({"f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31"}, is_hw_fp)609 .Default(false);610}611 612void ABISysV_loongarch::Initialize() {613 PluginManager::RegisterPlugin(GetPluginNameStatic(),614 "System V ABI for LoongArch targets",615 CreateInstance);616}617 618void ABISysV_loongarch::Terminate() {619 PluginManager::UnregisterPlugin(CreateInstance);620}621 622static uint32_t GetGenericNum(llvm::StringRef name) {623 return llvm::StringSwitch<uint32_t>(name)624 .Case("pc", LLDB_REGNUM_GENERIC_PC)625 .Cases({"ra", "r1"}, LLDB_REGNUM_GENERIC_RA)626 .Cases({"sp", "r3"}, LLDB_REGNUM_GENERIC_SP)627 .Cases({"fp", "r22"}, LLDB_REGNUM_GENERIC_FP)628 .Cases({"a0", "r4"}, LLDB_REGNUM_GENERIC_ARG1)629 .Cases({"a1", "r5"}, LLDB_REGNUM_GENERIC_ARG2)630 .Cases({"a2", "r6"}, LLDB_REGNUM_GENERIC_ARG3)631 .Cases({"a3", "r7"}, LLDB_REGNUM_GENERIC_ARG4)632 .Cases({"a4", "r8"}, LLDB_REGNUM_GENERIC_ARG5)633 .Cases({"a5", "r9"}, LLDB_REGNUM_GENERIC_ARG6)634 .Cases({"a6", "r10"}, LLDB_REGNUM_GENERIC_ARG7)635 .Cases({"a7", "r11"}, LLDB_REGNUM_GENERIC_ARG8)636 .Default(LLDB_INVALID_REGNUM);637}638 639void ABISysV_loongarch::AugmentRegisterInfo(640 std::vector<lldb_private::DynamicRegisterInfo::Register> ®s) {641 lldb_private::RegInfoBasedABI::AugmentRegisterInfo(regs);642 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"}};652 653 for (auto it : llvm::enumerate(regs)) {654 llvm::StringRef reg_name = it.value().name.GetStringRef();655 656 // Set alt name for certain registers for convenience657 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);660 661 // Set generic regnum so lldb knows what the PC, etc is662 it.value().regnum_generic = GetGenericNum(reg_name);663 }664}665