brintos

brintos / llvm-project-archived public Read only

0
0
Text · 22.8 KiB · 91b965d Raw
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 &reg_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 &reg_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 &reg_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> &regs) {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