brintos

brintos / llvm-project-archived public Read only

0
0
Text · 34.0 KiB · 0dd9db0 Raw
1195 lines · cpp
1//===-- ABISysV_mips64.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_mips64.h"10 11#include "llvm/ADT/STLExtras.h"12#include "llvm/TargetParser/Triple.h"13 14#include "lldb/Core/Module.h"15#include "lldb/Core/PluginManager.h"16#include "lldb/Core/Value.h"17#include "lldb/Symbol/UnwindPlan.h"18#include "lldb/Target/Process.h"19#include "lldb/Target/RegisterContext.h"20#include "lldb/Target/StackFrame.h"21#include "lldb/Target/Target.h"22#include "lldb/Target/Thread.h"23#include "lldb/Utility/ConstString.h"24#include "lldb/Utility/DataExtractor.h"25#include "lldb/Utility/LLDBLog.h"26#include "lldb/Utility/Log.h"27#include "lldb/Utility/RegisterValue.h"28#include "lldb/Utility/Status.h"29#include "lldb/ValueObject/ValueObjectConstResult.h"30#include "lldb/ValueObject/ValueObjectMemory.h"31#include "lldb/ValueObject/ValueObjectRegister.h"32#include <optional>33 34using namespace lldb;35using namespace lldb_private;36 37LLDB_PLUGIN_DEFINE(ABISysV_mips64)38 39enum dwarf_regnums {40  dwarf_r0 = 0,41  dwarf_r1,42  dwarf_r2,43  dwarf_r3,44  dwarf_r4,45  dwarf_r5,46  dwarf_r6,47  dwarf_r7,48  dwarf_r8,49  dwarf_r9,50  dwarf_r10,51  dwarf_r11,52  dwarf_r12,53  dwarf_r13,54  dwarf_r14,55  dwarf_r15,56  dwarf_r16,57  dwarf_r17,58  dwarf_r18,59  dwarf_r19,60  dwarf_r20,61  dwarf_r21,62  dwarf_r22,63  dwarf_r23,64  dwarf_r24,65  dwarf_r25,66  dwarf_r26,67  dwarf_r27,68  dwarf_r28,69  dwarf_r29,70  dwarf_r30,71  dwarf_r31,72  dwarf_sr,73  dwarf_lo,74  dwarf_hi,75  dwarf_bad,76  dwarf_cause,77  dwarf_pc78};79 80static const RegisterInfo g_register_infos_mips64[] = {81    {"r0",82     "zero",83     8,84     0,85     eEncodingUint,86     eFormatHex,87     {dwarf_r0, dwarf_r0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,88      LLDB_INVALID_REGNUM},89     nullptr,90     nullptr,91     nullptr,92    },93    {"r1",94     "AT",95     8,96     0,97     eEncodingUint,98     eFormatHex,99     {dwarf_r1, dwarf_r1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,100      LLDB_INVALID_REGNUM},101     nullptr,102     nullptr,103     nullptr,104 105    },106    {"r2",107     "v0",108     8,109     0,110     eEncodingUint,111     eFormatHex,112     {dwarf_r2, dwarf_r2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,113      LLDB_INVALID_REGNUM},114     nullptr,115     nullptr,116     nullptr,117    },118    {"r3",119     "v1",120     8,121     0,122     eEncodingUint,123     eFormatHex,124     {dwarf_r3, dwarf_r3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,125      LLDB_INVALID_REGNUM},126     nullptr,127     nullptr,128     nullptr,129    },130    {"r4",131     nullptr,132     8,133     0,134     eEncodingUint,135     eFormatHex,136     {dwarf_r4, dwarf_r4, LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM,137      LLDB_INVALID_REGNUM},138     nullptr,139     nullptr,140     nullptr,141    },142    {"r5",143     nullptr,144     8,145     0,146     eEncodingUint,147     eFormatHex,148     {dwarf_r5, dwarf_r5, LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM,149      LLDB_INVALID_REGNUM},150     nullptr,151     nullptr,152     nullptr,153    },154    {"r6",155     nullptr,156     8,157     0,158     eEncodingUint,159     eFormatHex,160     {dwarf_r6, dwarf_r6, LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM,161      LLDB_INVALID_REGNUM},162     nullptr,163     nullptr,164     nullptr,165    },166    {"r7",167     nullptr,168     8,169     0,170     eEncodingUint,171     eFormatHex,172     {dwarf_r7, dwarf_r7, LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM,173      LLDB_INVALID_REGNUM},174     nullptr,175     nullptr,176     nullptr,177    },178    {"r8",179     nullptr,180     8,181     0,182     eEncodingUint,183     eFormatHex,184     {dwarf_r8, dwarf_r8, LLDB_REGNUM_GENERIC_ARG5, LLDB_INVALID_REGNUM,185      LLDB_INVALID_REGNUM},186     nullptr,187     nullptr,188     nullptr,189    },190    {"r9",191     nullptr,192     8,193     0,194     eEncodingUint,195     eFormatHex,196     {dwarf_r9, dwarf_r9, LLDB_REGNUM_GENERIC_ARG6, LLDB_INVALID_REGNUM,197      LLDB_INVALID_REGNUM},198     nullptr,199     nullptr,200     nullptr,201    },202    {"r10",203     nullptr,204     8,205     0,206     eEncodingUint,207     eFormatHex,208     {dwarf_r10, dwarf_r10, LLDB_REGNUM_GENERIC_ARG7, LLDB_INVALID_REGNUM,209      LLDB_INVALID_REGNUM},210     nullptr,211     nullptr,212     nullptr,213    },214    {"r11",215     nullptr,216     8,217     0,218     eEncodingUint,219     eFormatHex,220     {dwarf_r11, dwarf_r11, LLDB_REGNUM_GENERIC_ARG8, LLDB_INVALID_REGNUM,221      LLDB_INVALID_REGNUM},222     nullptr,223     nullptr,224     nullptr,225    },226    {"r12",227     nullptr,228     8,229     0,230     eEncodingUint,231     eFormatHex,232     {dwarf_r12, dwarf_r12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,233      LLDB_INVALID_REGNUM},234     nullptr,235     nullptr,236     nullptr,237    },238    {"r13",239     nullptr,240     8,241     0,242     eEncodingUint,243     eFormatHex,244     {dwarf_r13, dwarf_r13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,245      LLDB_INVALID_REGNUM},246     nullptr,247     nullptr,248     nullptr,249    },250    {"r14",251     nullptr,252     8,253     0,254     eEncodingUint,255     eFormatHex,256     {dwarf_r14, dwarf_r14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,257      LLDB_INVALID_REGNUM},258     nullptr,259     nullptr,260     nullptr,261    },262    {"r15",263     nullptr,264     8,265     0,266     eEncodingUint,267     eFormatHex,268     {dwarf_r15, dwarf_r15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,269      LLDB_INVALID_REGNUM},270     nullptr,271     nullptr,272     nullptr,273    },274    {"r16",275     nullptr,276     8,277     0,278     eEncodingUint,279     eFormatHex,280     {dwarf_r16, dwarf_r16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,281      LLDB_INVALID_REGNUM},282     nullptr,283     nullptr,284     nullptr,285    },286    {"r17",287     nullptr,288     8,289     0,290     eEncodingUint,291     eFormatHex,292     {dwarf_r17, dwarf_r17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,293      LLDB_INVALID_REGNUM},294     nullptr,295     nullptr,296     nullptr,297    },298    {"r18",299     nullptr,300     8,301     0,302     eEncodingUint,303     eFormatHex,304     {dwarf_r18, dwarf_r18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,305      LLDB_INVALID_REGNUM},306     nullptr,307     nullptr,308     nullptr,309    },310    {"r19",311     nullptr,312     8,313     0,314     eEncodingUint,315     eFormatHex,316     {dwarf_r19, dwarf_r19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,317      LLDB_INVALID_REGNUM},318     nullptr,319     nullptr,320     nullptr,321    },322    {"r20",323     nullptr,324     8,325     0,326     eEncodingUint,327     eFormatHex,328     {dwarf_r20, dwarf_r20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,329      LLDB_INVALID_REGNUM},330     nullptr,331     nullptr,332     nullptr,333    },334    {"r21",335     nullptr,336     8,337     0,338     eEncodingUint,339     eFormatHex,340     {dwarf_r21, dwarf_r21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,341      LLDB_INVALID_REGNUM},342     nullptr,343     nullptr,344     nullptr,345    },346    {"r22",347     nullptr,348     8,349     0,350     eEncodingUint,351     eFormatHex,352     {dwarf_r22, dwarf_r22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,353      LLDB_INVALID_REGNUM},354     nullptr,355     nullptr,356     nullptr,357    },358    {"r23",359     nullptr,360     8,361     0,362     eEncodingUint,363     eFormatHex,364     {dwarf_r23, dwarf_r23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,365      LLDB_INVALID_REGNUM},366     nullptr,367     nullptr,368     nullptr,369    },370    {"r24",371     nullptr,372     8,373     0,374     eEncodingUint,375     eFormatHex,376     {dwarf_r24, dwarf_r24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,377      LLDB_INVALID_REGNUM},378     nullptr,379     nullptr,380     nullptr,381    },382    {"r25",383     nullptr,384     8,385     0,386     eEncodingUint,387     eFormatHex,388     {dwarf_r25, dwarf_r25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,389      LLDB_INVALID_REGNUM},390     nullptr,391     nullptr,392     nullptr,393    },394    {"r26",395     nullptr,396     8,397     0,398     eEncodingUint,399     eFormatHex,400     {dwarf_r26, dwarf_r26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,401      LLDB_INVALID_REGNUM},402     nullptr,403     nullptr,404     nullptr,405    },406    {"r27",407     nullptr,408     8,409     0,410     eEncodingUint,411     eFormatHex,412     {dwarf_r27, dwarf_r27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,413      LLDB_INVALID_REGNUM},414     nullptr,415     nullptr,416     nullptr,417    },418    {"r28",419     "gp",420     8,421     0,422     eEncodingUint,423     eFormatHex,424     {dwarf_r28, dwarf_r28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,425      LLDB_INVALID_REGNUM},426     nullptr,427     nullptr,428     nullptr,429    },430    {"r29",431     nullptr,432     8,433     0,434     eEncodingUint,435     eFormatHex,436     {dwarf_r29, dwarf_r29, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM,437      LLDB_INVALID_REGNUM},438     nullptr,439     nullptr,440     nullptr,441    },442    {"r30",443     nullptr,444     8,445     0,446     eEncodingUint,447     eFormatHex,448     {dwarf_r30, dwarf_r30, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM,449      LLDB_INVALID_REGNUM},450     nullptr,451     nullptr,452     nullptr,453    },454    {"r31",455     nullptr,456     8,457     0,458     eEncodingUint,459     eFormatHex,460     {dwarf_r31, dwarf_r31, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM,461      LLDB_INVALID_REGNUM},462     nullptr,463     nullptr,464     nullptr,465    },466    {"sr",467     nullptr,468     4,469     0,470     eEncodingUint,471     eFormatHex,472     {dwarf_sr, dwarf_sr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM,473      LLDB_INVALID_REGNUM},474     nullptr,475     nullptr,476     nullptr,477    },478    {"lo",479     nullptr,480     8,481     0,482     eEncodingUint,483     eFormatHex,484     {dwarf_lo, dwarf_lo, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,485      LLDB_INVALID_REGNUM},486     nullptr,487     nullptr,488     nullptr,489    },490    {"hi",491     nullptr,492     8,493     0,494     eEncodingUint,495     eFormatHex,496     {dwarf_hi, dwarf_hi, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,497      LLDB_INVALID_REGNUM},498     nullptr,499     nullptr,500     nullptr,501    },502    {"bad",503     nullptr,504     8,505     0,506     eEncodingUint,507     eFormatHex,508     {dwarf_bad, dwarf_bad, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,509      LLDB_INVALID_REGNUM},510     nullptr,511     nullptr,512     nullptr,513    },514    {"cause",515     nullptr,516     8,517     0,518     eEncodingUint,519     eFormatHex,520     {dwarf_cause, dwarf_cause, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,521      LLDB_INVALID_REGNUM},522     nullptr,523     nullptr,524     nullptr,525    },526    {"pc",527     nullptr,528     8,529     0,530     eEncodingUint,531     eFormatHex,532     {dwarf_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM,533      LLDB_INVALID_REGNUM},534     nullptr,535     nullptr,536     nullptr,537    },538};539 540static const uint32_t k_num_register_infos = std::size(g_register_infos_mips64);541 542const lldb_private::RegisterInfo *543ABISysV_mips64::GetRegisterInfoArray(uint32_t &count) {544  count = k_num_register_infos;545  return g_register_infos_mips64;546}547 548size_t ABISysV_mips64::GetRedZoneSize() const { return 0; }549 550// Static Functions551 552ABISP553ABISysV_mips64::CreateInstance(lldb::ProcessSP process_sp, const ArchSpec &arch) {554  if (arch.GetTriple().isMIPS64())555    return ABISP(556        new ABISysV_mips64(std::move(process_sp), MakeMCRegisterInfo(arch)));557  return ABISP();558}559 560bool ABISysV_mips64::PrepareTrivialCall(Thread &thread, addr_t sp,561                                        addr_t func_addr, addr_t return_addr,562                                        llvm::ArrayRef<addr_t> args) const {563  Log *log = GetLog(LLDBLog::Expressions);564 565  if (log) {566    StreamString s;567    s.Printf("ABISysV_mips64::PrepareTrivialCall (tid = 0x%" PRIx64568             ", sp = 0x%" PRIx64 ", func_addr = 0x%" PRIx64569             ", return_addr = 0x%" PRIx64,570             thread.GetID(), (uint64_t)sp, (uint64_t)func_addr,571             (uint64_t)return_addr);572 573    for (size_t i = 0; i < args.size(); ++i)574      s.Printf(", arg%zd = 0x%" PRIx64, i + 1, args[i]);575    s.PutCString(")");576    log->PutString(s.GetString());577  }578 579  RegisterContext *reg_ctx = thread.GetRegisterContext().get();580  if (!reg_ctx)581    return false;582 583  const RegisterInfo *reg_info = nullptr;584 585  if (args.size() > 8) // TODO handle more than 8 arguments586    return false;587 588  for (size_t i = 0; i < args.size(); ++i) {589    reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric,590                                        LLDB_REGNUM_GENERIC_ARG1 + i);591    LLDB_LOGF(log, "About to write arg%zd (0x%" PRIx64 ") into %s", i + 1,592              args[i], reg_info->name);593    if (!reg_ctx->WriteRegisterFromUnsigned(reg_info, args[i]))594      return false;595  }596 597  // First, align the SP598 599  LLDB_LOGF(log, "16-byte aligning SP: 0x%" PRIx64 " to 0x%" PRIx64,600            (uint64_t)sp, (uint64_t)(sp & ~0xfull));601 602  sp &= ~(0xfull); // 16-byte alignment603 604  Status error;605  const RegisterInfo *pc_reg_info =606      reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);607  const RegisterInfo *sp_reg_info =608      reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);609  const RegisterInfo *ra_reg_info =610      reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA);611  const RegisterInfo *r25_info = reg_ctx->GetRegisterInfoByName("r25", 0);612  const RegisterInfo *r0_info = reg_ctx->GetRegisterInfoByName("zero", 0);613 614  LLDB_LOGF(log, "Writing R0: 0x%" PRIx64, (uint64_t)0);615 616  /* Write r0 with 0, in case we are stopped in syscall,617   * such setting prevents automatic decrement of the PC.618   * This clears the bug 23659 for MIPS.619  */620  if (!reg_ctx->WriteRegisterFromUnsigned(r0_info, (uint64_t)0))621    return false;622 623  LLDB_LOGF(log, "Writing SP: 0x%" PRIx64, (uint64_t)sp);624 625  // Set "sp" to the requested value626  if (!reg_ctx->WriteRegisterFromUnsigned(sp_reg_info, sp))627    return false;628 629  LLDB_LOGF(log, "Writing RA: 0x%" PRIx64, (uint64_t)return_addr);630 631  // Set "ra" to the return address632  if (!reg_ctx->WriteRegisterFromUnsigned(ra_reg_info, return_addr))633    return false;634 635  LLDB_LOGF(log, "Writing PC: 0x%" PRIx64, (uint64_t)func_addr);636 637  // Set pc to the address of the called function.638  if (!reg_ctx->WriteRegisterFromUnsigned(pc_reg_info, func_addr))639    return false;640 641  LLDB_LOGF(log, "Writing r25: 0x%" PRIx64, (uint64_t)func_addr);642 643  // All callers of position independent functions must place the address of644  // the called function in t9 (r25)645  if (!reg_ctx->WriteRegisterFromUnsigned(r25_info, func_addr))646    return false;647 648  return true;649}650 651bool ABISysV_mips64::GetArgumentValues(Thread &thread,652                                       ValueList &values) const {653  return false;654}655 656Status ABISysV_mips64::SetReturnValueObject(lldb::StackFrameSP &frame_sp,657                                            lldb::ValueObjectSP &new_value_sp) {658  Status error;659  if (!new_value_sp) {660    error = Status::FromErrorString("Empty value object for return value.");661    return error;662  }663 664  CompilerType compiler_type = new_value_sp->GetCompilerType();665  if (!compiler_type) {666    error = Status::FromErrorString("Null clang type for return value.");667    return error;668  }669 670  Thread *thread = frame_sp->GetThread().get();671 672  RegisterContext *reg_ctx = thread->GetRegisterContext().get();673 674  if (!reg_ctx)675    error = Status::FromErrorString("no registers are available");676 677  DataExtractor data;678  Status data_error;679  size_t num_bytes = new_value_sp->GetData(data, data_error);680  if (data_error.Fail()) {681    error = Status::FromErrorStringWithFormat(682        "Couldn't convert return value to raw data: %s",683        data_error.AsCString());684    return error;685  }686 687  const uint32_t type_flags = compiler_type.GetTypeInfo(nullptr);688 689  if (type_flags & eTypeIsScalar || type_flags & eTypeIsPointer) {690    if (type_flags & eTypeIsInteger || type_flags & eTypeIsPointer) {691      lldb::offset_t offset = 0;692 693      if (num_bytes <= 16) {694        const RegisterInfo *r2_info = reg_ctx->GetRegisterInfoByName("r2", 0);695        if (num_bytes <= 8) {696          uint64_t raw_value = data.GetMaxU64(&offset, num_bytes);697 698          if (!reg_ctx->WriteRegisterFromUnsigned(r2_info, raw_value))699            error = Status::FromErrorString("failed to write register r2");700        } else {701          uint64_t raw_value = data.GetMaxU64(&offset, 8);702          if (reg_ctx->WriteRegisterFromUnsigned(r2_info, raw_value)) {703            const RegisterInfo *r3_info =704                reg_ctx->GetRegisterInfoByName("r3", 0);705            raw_value = data.GetMaxU64(&offset, num_bytes - offset);706 707            if (!reg_ctx->WriteRegisterFromUnsigned(r3_info, raw_value))708              error = Status::FromErrorString("failed to write register r3");709          } else710            error = Status::FromErrorString("failed to write register r2");711        }712      } else {713        error = Status::FromErrorString(714            "We don't support returning longer than 128 bit "715            "integer values at present.");716      }717    } else if (type_flags & eTypeIsFloat) {718      error = Status::FromErrorString("TODO: Handle Float Types.");719    }720  } else if (type_flags & eTypeIsVector) {721    error =722        Status::FromErrorString("returning vector values are not supported");723  }724 725  return error;726}727 728ValueObjectSP ABISysV_mips64::GetReturnValueObjectSimple(729    Thread &thread, CompilerType &return_compiler_type) const {730  ValueObjectSP return_valobj_sp;731  return return_valobj_sp;732}733 734ValueObjectSP ABISysV_mips64::GetReturnValueObjectImpl(735    Thread &thread, CompilerType &return_compiler_type) const {736  ValueObjectSP return_valobj_sp;737  Value value;738  Status error;739 740  ExecutionContext exe_ctx(thread.shared_from_this());741  if (exe_ctx.GetTargetPtr() == nullptr || exe_ctx.GetProcessPtr() == nullptr)742    return return_valobj_sp;743 744  value.SetCompilerType(return_compiler_type);745 746  RegisterContext *reg_ctx = thread.GetRegisterContext().get();747  if (!reg_ctx)748    return return_valobj_sp;749 750  Target *target = exe_ctx.GetTargetPtr();751  const ArchSpec target_arch = target->GetArchitecture();752  ByteOrder target_byte_order = target_arch.GetByteOrder();753  std::optional<uint64_t> byte_size =754      llvm::expectedToOptional(return_compiler_type.GetByteSize(&thread));755  if (!byte_size)756    return return_valobj_sp;757  const uint32_t type_flags = return_compiler_type.GetTypeInfo(nullptr);758  uint32_t fp_flag =759      target_arch.GetFlags() & lldb_private::ArchSpec::eMIPS_ABI_FP_mask;760 761  const RegisterInfo *r2_info = reg_ctx->GetRegisterInfoByName("r2", 0);762  const RegisterInfo *r3_info = reg_ctx->GetRegisterInfoByName("r3", 0);763  assert(r2_info && r3_info && "Basic registers should always be present.");764 765  if (type_flags & eTypeIsScalar || type_flags & eTypeIsPointer) {766    value.SetValueType(Value::ValueType::Scalar);767 768    bool success = false;769    if (type_flags & eTypeIsInteger || type_flags & eTypeIsPointer) {770      // Extract the register context so we can read arguments from registers771      // In MIPS register "r2" (v0) holds the integer function return values772 773      uint64_t raw_value = reg_ctx->ReadRegisterAsUnsigned(r2_info, 0);774 775      const bool is_signed = (type_flags & eTypeIsSigned) != 0;776      switch (*byte_size) {777      default:778        break;779 780      case sizeof(uint64_t):781        if (is_signed)782          value.GetScalar() = (int64_t)(raw_value);783        else784          value.GetScalar() = (uint64_t)(raw_value);785        success = true;786        break;787 788      case sizeof(uint32_t):789        if (is_signed)790          value.GetScalar() = (int32_t)(raw_value & UINT32_MAX);791        else792          value.GetScalar() = (uint32_t)(raw_value & UINT32_MAX);793        success = true;794        break;795 796      case sizeof(uint16_t):797        if (is_signed)798          value.GetScalar() = (int16_t)(raw_value & UINT16_MAX);799        else800          value.GetScalar() = (uint16_t)(raw_value & UINT16_MAX);801        success = true;802        break;803 804      case sizeof(uint8_t):805        if (is_signed)806          value.GetScalar() = (int8_t)(raw_value & UINT8_MAX);807        else808          value.GetScalar() = (uint8_t)(raw_value & UINT8_MAX);809        success = true;810        break;811      }812    } else if (type_flags & eTypeIsFloat) {813      if (type_flags & eTypeIsComplex) {814        // Don't handle complex yet.815      } else if (IsSoftFloat(fp_flag)) {816        uint64_t raw_value = reg_ctx->ReadRegisterAsUnsigned(r2_info, 0);817        switch (*byte_size) {818        case 4:819          value.GetScalar() = *((float *)(&raw_value));820          success = true;821          break;822        case 8:823          value.GetScalar() = *((double *)(&raw_value));824          success = true;825          break;826        case 16:827          uint64_t result[2];828          if (target_byte_order == eByteOrderLittle) {829            result[0] = raw_value;830            result[1] = reg_ctx->ReadRegisterAsUnsigned(r3_info, 0);831            value.GetScalar() = *((long double *)(result));832          } else {833            result[0] = reg_ctx->ReadRegisterAsUnsigned(r3_info, 0);834            result[1] = raw_value;835            value.GetScalar() = *((long double *)(result));836          }837          success = true;838          break;839        }840 841      } else {842        if (*byte_size <= sizeof(long double)) {843          const RegisterInfo *f0_info = reg_ctx->GetRegisterInfoByName("f0", 0);844 845          RegisterValue f0_value;846          DataExtractor f0_data;847 848          reg_ctx->ReadRegister(f0_info, f0_value);849 850          f0_value.GetData(f0_data);851 852          lldb::offset_t offset = 0;853          if (*byte_size == sizeof(float)) {854            value.GetScalar() = (float)f0_data.GetFloat(&offset);855            success = true;856          } else if (*byte_size == sizeof(double)) {857            value.GetScalar() = (double)f0_data.GetDouble(&offset);858            success = true;859          } else if (*byte_size == sizeof(long double)) {860            const RegisterInfo *f2_info =861                reg_ctx->GetRegisterInfoByName("f2", 0);862            RegisterValue f2_value;863            DataExtractor f2_data;864            reg_ctx->ReadRegister(f2_info, f2_value);865            DataExtractor *copy_from_extractor = nullptr;866            WritableDataBufferSP data_sp(new DataBufferHeap(16, 0));867            DataExtractor return_ext(868                data_sp, target_byte_order,869                target->GetArchitecture().GetAddressByteSize());870 871            if (target_byte_order == eByteOrderLittle) {872              copy_from_extractor = &f0_data;873              copy_from_extractor->CopyByteOrderedData(874                  0, 8, data_sp->GetBytes(), *byte_size - 8, target_byte_order);875              f2_value.GetData(f2_data);876              copy_from_extractor = &f2_data;877              copy_from_extractor->CopyByteOrderedData(878                  0, 8, data_sp->GetBytes() + 8, *byte_size - 8,879                  target_byte_order);880            } else {881              copy_from_extractor = &f0_data;882              copy_from_extractor->CopyByteOrderedData(883                  0, 8, data_sp->GetBytes() + 8, *byte_size - 8,884                  target_byte_order);885              f2_value.GetData(f2_data);886              copy_from_extractor = &f2_data;887              copy_from_extractor->CopyByteOrderedData(888                  0, 8, data_sp->GetBytes(), *byte_size - 8, target_byte_order);889            }890 891            return_valobj_sp = ValueObjectConstResult::Create(892                &thread, return_compiler_type, ConstString(""), return_ext);893            return return_valobj_sp;894          }895        }896      }897    }898 899    if (success)900      return_valobj_sp = ValueObjectConstResult::Create(901          thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));902  } else if (type_flags & eTypeIsStructUnion || type_flags & eTypeIsClass ||903             type_flags & eTypeIsVector) {904    // Any structure of up to 16 bytes in size is returned in the registers.905    if (*byte_size <= 16) {906      WritableDataBufferSP data_sp(new DataBufferHeap(16, 0));907      DataExtractor return_ext(data_sp, target_byte_order,908                               target->GetArchitecture().GetAddressByteSize());909 910      RegisterValue r2_value, r3_value, f0_value, f1_value, f2_value;911      // Tracks how much bytes of r2 and r3 registers we've consumed so far912      uint32_t integer_bytes = 0;913 914      // True if return values are in FP return registers.915      bool use_fp_regs = false;916      // True if we found any non floating point field in structure.917      bool found_non_fp_field = false;918      // True if return values are in r2 register.919      bool use_r2 = false;920      // True if return values are in r3 register.921      bool use_r3 = false;922      // True if the result is copied into our data buffer923      bool sucess = false;924      std::string name;925      bool is_complex;926      const uint32_t num_children = return_compiler_type.GetNumFields();927 928      // A structure consisting of one or two FP values (and nothing else) will929      // be returned in the two FP return-value registers i.e fp0 and fp2.930      if (num_children <= 2) {931        uint64_t field_bit_offset = 0;932 933        // Check if this structure contains only floating point fields934        for (uint32_t idx = 0; idx < num_children; idx++) {935          CompilerType field_compiler_type =936              return_compiler_type.GetFieldAtIndex(idx, name, &field_bit_offset,937                                                   nullptr, nullptr);938 939          if (field_compiler_type.IsFloatingPointType(is_complex))940            use_fp_regs = true;941          else942            found_non_fp_field = true;943        }944 945        if (use_fp_regs && !found_non_fp_field) {946          // We have one or two FP-only values in this structure. Get it from947          // f0/f2 registers.948          DataExtractor f0_data, f1_data, f2_data;949          const RegisterInfo *f0_info = reg_ctx->GetRegisterInfoByName("f0", 0);950          const RegisterInfo *f1_info = reg_ctx->GetRegisterInfoByName("f1", 0);951          const RegisterInfo *f2_info = reg_ctx->GetRegisterInfoByName("f2", 0);952 953          reg_ctx->ReadRegister(f0_info, f0_value);954          reg_ctx->ReadRegister(f2_info, f2_value);955 956          f0_value.GetData(f0_data);957 958          for (uint32_t idx = 0; idx < num_children; idx++) {959            CompilerType field_compiler_type =960                return_compiler_type.GetFieldAtIndex(961                    idx, name, &field_bit_offset, nullptr, nullptr);962            std::optional<uint64_t> field_byte_width = llvm::expectedToOptional(963                field_compiler_type.GetByteSize(&thread));964            if (!field_byte_width)965              return return_valobj_sp;966 967            DataExtractor *copy_from_extractor = nullptr;968            uint64_t return_value[2];969            offset_t offset = 0;970 971            if (idx == 0) {972              // This case is for long double type.973              if (*field_byte_width == 16) {974 975                // If structure contains long double type, then it is returned976                // in fp0/fp1 registers.977                if (target_byte_order == eByteOrderLittle) {978                  return_value[0] = f0_data.GetU64(&offset);979                  reg_ctx->ReadRegister(f1_info, f1_value);980                  f1_value.GetData(f1_data);981                  offset = 0;982                  return_value[1] = f1_data.GetU64(&offset);983                } else {984                  return_value[1] = f0_data.GetU64(&offset);985                  reg_ctx->ReadRegister(f1_info, f1_value);986                  f1_value.GetData(f1_data);987                  offset = 0;988                  return_value[0] = f1_data.GetU64(&offset);989                }990 991                f0_data.SetData(return_value, *field_byte_width,992                                target_byte_order);993              }994              copy_from_extractor = &f0_data; // This is in f0, copy from995                                              // register to our result996                                              // structure997            } else {998              f2_value.GetData(f2_data);999              // This is in f2, copy from register to our result structure1000              copy_from_extractor = &f2_data;1001            }1002 1003            // Sanity check to avoid crash1004            if (!copy_from_extractor ||1005                *field_byte_width > copy_from_extractor->GetByteSize())1006              return return_valobj_sp;1007 1008            // copy the register contents into our data buffer1009            copy_from_extractor->CopyByteOrderedData(1010                0, *field_byte_width,1011                data_sp->GetBytes() + (field_bit_offset / 8), *field_byte_width,1012                target_byte_order);1013          }1014 1015          // The result is in our data buffer.  Create a variable object out of1016          // it1017          return_valobj_sp = ValueObjectConstResult::Create(1018              &thread, return_compiler_type, ConstString(""), return_ext);1019 1020          return return_valobj_sp;1021        }1022      }1023 1024      // If we reach here, it means this structure either contains more than1025      // two fields or it contains at least one non floating point type. In1026      // that case, all fields are returned in GP return registers.1027      for (uint32_t idx = 0; idx < num_children; idx++) {1028        uint64_t field_bit_offset = 0;1029        bool is_signed;1030        uint32_t padding;1031 1032        CompilerType field_compiler_type = return_compiler_type.GetFieldAtIndex(1033            idx, name, &field_bit_offset, nullptr, nullptr);1034        std::optional<uint64_t> field_byte_width =1035            llvm::expectedToOptional(field_compiler_type.GetByteSize(&thread));1036 1037        // if we don't know the size of the field (e.g. invalid type), just1038        // bail out1039        if (!field_byte_width || *field_byte_width == 0)1040          break;1041 1042        uint32_t field_byte_offset = field_bit_offset / 8;1043 1044        if (field_compiler_type.IsIntegerOrEnumerationType(is_signed) ||1045            field_compiler_type.IsPointerType() ||1046            field_compiler_type.IsFloatingPointType(is_complex)) {1047          padding = field_byte_offset - integer_bytes;1048 1049          if (integer_bytes < 8) {1050            // We have not yet consumed r2 completely.1051            if (integer_bytes + *field_byte_width + padding <= 8) {1052              // This field fits in r2, copy its value from r2 to our result1053              // structure1054              integer_bytes = integer_bytes + *field_byte_width +1055                              padding; // Increase the consumed bytes.1056              use_r2 = true;1057            } else {1058              // There isn't enough space left in r2 for this field, so this1059              // will be in r3.1060              integer_bytes = integer_bytes + *field_byte_width +1061                              padding; // Increase the consumed bytes.1062              use_r3 = true;1063            }1064          }1065          // We already have consumed at-least 8 bytes that means r2 is done,1066          // and this field will be in r3. Check if this field can fit in r3.1067          else if (integer_bytes + *field_byte_width + padding <= 16) {1068            integer_bytes = integer_bytes + *field_byte_width + padding;1069            use_r3 = true;1070          } else {1071            // There isn't any space left for this field, this should not1072            // happen as we have already checked the overall size is not1073            // greater than 16 bytes. For now, return a nullptr return value1074            // object.1075            return return_valobj_sp;1076          }1077        }1078      }1079      // Vector types up to 16 bytes are returned in GP return registers1080      if (type_flags & eTypeIsVector) {1081        if (*byte_size <= 8)1082          use_r2 = true;1083        else {1084          use_r2 = true;1085          use_r3 = true;1086        }1087      }1088 1089      if (use_r2) {1090        reg_ctx->ReadRegister(r2_info, r2_value);1091 1092        const size_t bytes_copied = r2_value.GetAsMemoryData(1093            *r2_info, data_sp->GetBytes(), r2_info->byte_size,1094            target_byte_order, error);1095        if (bytes_copied != r2_info->byte_size)1096          return return_valobj_sp;1097        sucess = true;1098      }1099      if (use_r3) {1100        reg_ctx->ReadRegister(r3_info, r3_value);1101        const size_t bytes_copied = r3_value.GetAsMemoryData(1102            *r3_info, data_sp->GetBytes() + r2_info->byte_size,1103            r3_info->byte_size, target_byte_order, error);1104 1105        if (bytes_copied != r3_info->byte_size)1106          return return_valobj_sp;1107        sucess = true;1108      }1109      if (sucess) {1110        // The result is in our data buffer.  Create a variable object out of1111        // it1112        return_valobj_sp = ValueObjectConstResult::Create(1113            &thread, return_compiler_type, ConstString(""), return_ext);1114      }1115      return return_valobj_sp;1116    }1117 1118    // Any structure/vector greater than 16 bytes in size is returned in1119    // memory. The pointer to that memory is returned in r2.1120    uint64_t mem_address = reg_ctx->ReadRegisterAsUnsigned(1121        reg_ctx->GetRegisterInfoByName("r2", 0), 0);1122 1123    // We have got the address. Create a memory object out of it1124    return_valobj_sp = ValueObjectMemory::Create(1125        &thread, "", Address(mem_address, nullptr), return_compiler_type);1126  }1127  return return_valobj_sp;1128}1129 1130UnwindPlanSP ABISysV_mips64::CreateFunctionEntryUnwindPlan() {1131  UnwindPlan::Row row;1132 1133  // Our Call Frame Address is the stack pointer value1134  row.GetCFAValue().SetIsRegisterPlusOffset(dwarf_r29, 0);1135 1136  // The previous PC is in the RA, all other registers are the same.1137  row.SetRegisterLocationToRegister(dwarf_pc, dwarf_r31, true);1138 1139  auto plan_sp = std::make_shared<UnwindPlan>(eRegisterKindDWARF);1140  plan_sp->AppendRow(std::move(row));1141  plan_sp->SetSourceName("mips64 at-func-entry default");1142  plan_sp->SetSourcedFromCompiler(eLazyBoolNo);1143  plan_sp->SetReturnAddressRegister(dwarf_r31);1144  return plan_sp;1145}1146 1147UnwindPlanSP ABISysV_mips64::CreateDefaultUnwindPlan() {1148  UnwindPlan::Row row;1149 1150  row.SetUnspecifiedRegistersAreUndefined(true);1151  row.GetCFAValue().SetIsRegisterPlusOffset(dwarf_r29, 0);1152 1153  row.SetRegisterLocationToRegister(dwarf_pc, dwarf_r31, true);1154 1155  auto plan_sp = std::make_shared<UnwindPlan>(eRegisterKindDWARF);1156  plan_sp->AppendRow(std::move(row));1157  plan_sp->SetSourceName("mips64 default unwind plan");1158  plan_sp->SetSourcedFromCompiler(eLazyBoolNo);1159  plan_sp->SetUnwindPlanValidAtAllInstructions(eLazyBoolNo);1160  plan_sp->SetUnwindPlanForSignalTrap(eLazyBoolNo);1161  return plan_sp;1162}1163 1164bool ABISysV_mips64::RegisterIsVolatile(const RegisterInfo *reg_info) {1165  return !RegisterIsCalleeSaved(reg_info);1166}1167 1168bool ABISysV_mips64::IsSoftFloat(uint32_t fp_flag) const {1169  return (fp_flag == lldb_private::ArchSpec::eMIPS_ABI_FP_SOFT);1170}1171 1172bool ABISysV_mips64::RegisterIsCalleeSaved(const RegisterInfo *reg_info) {1173  if (reg_info) {1174    // Preserved registers are :1175    // r16-r23, r28, r29, r30, r311176 1177    int reg = ((reg_info->byte_offset) / 8);1178 1179    bool save = (reg >= 16) && (reg <= 23);1180    save |= (reg >= 28) && (reg <= 31);1181 1182    return save;1183  }1184  return false;1185}1186 1187void ABISysV_mips64::Initialize() {1188  PluginManager::RegisterPlugin(1189      GetPluginNameStatic(), "System V ABI for mips64 targets", CreateInstance);1190}1191 1192void ABISysV_mips64::Terminate() {1193  PluginManager::UnregisterPlugin(CreateInstance);1194}1195