[Lldb-commits] [lldb] r285662 - Fix a bug where the EmulateInstructionARM64 handling of STP/LDP instructions

Jason Molenda via lldb-commits lldb-commits at lists.llvm.org
Mon Oct 31 18:26:55 PDT 2016


Author: jmolenda
Date: Mon Oct 31 20:26:54 2016
New Revision: 285662

URL: http://llvm.org/viewvc/llvm-project?rev=285662&view=rev
Log:
Fix a bug where the EmulateInstructionARM64 handling of STP/LDP instructions
for floating point registers was not recording them correctly.  I needed to
change the EmulateInstructionARM64 unwind plans from using the DWARF 
register numbering scheme to using the LLDB register numbering scheme
(because dwarf doesn't define register numbers for the 64-bit "d" registers).
Updated the EmulateInstructionARM64 unit tests to work with the LLDB
register numbering scheme and added a unit test to check the floating
point register spills & restores are correctly recorded.

https://reviews.llvm.org/D25864
<rdar://problem/28745483> 

Modified:
    lldb/trunk/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp
    lldb/trunk/unittests/UnwindAssembly/InstEmulation/TestArm64InstEmulation.cpp

Modified: lldb/trunk/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp?rev=285662&r1=285661&r2=285662&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp (original)
+++ lldb/trunk/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp Mon Oct 31 20:26:54 2016
@@ -21,7 +21,24 @@
 
 #include "Plugins/Process/Utility/ARMDefines.h"
 #include "Plugins/Process/Utility/ARMUtils.h"
-#include "Utility/ARM64_DWARF_Registers.h"
+#include "Plugins/Process/Utility/lldb-arm64-register-enums.h"
+
+#define GPR_OFFSET(idx) ((idx)*8)
+#define GPR_OFFSET_NAME(reg) 0
+#define FPU_OFFSET(idx) ((idx)*16)
+#define FPU_OFFSET_NAME(reg) 0
+#define EXC_OFFSET_NAME(reg) 0
+#define DBG_OFFSET_NAME(reg) 0
+#define DBG_OFFSET_NAME(reg) 0
+#define DEFINE_DBG(re, y)                                                      \
+  "na", nullptr, 8, 0, lldb::eEncodingUint, lldb::eFormatHex,                  \
+      {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,          \
+       LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},                              \
+      nullptr, nullptr, nullptr, 0
+
+#define DECLARE_REGISTER_INFOS_ARM64_STRUCT
+
+#include "Plugins/Process/Utility/RegisterInfos_arm64.h"
 
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/Support/MathExtras.h" // for SignExtend32 template function
@@ -32,6 +49,13 @@
 using namespace lldb;
 using namespace lldb_private;
 
+static bool LLDBTableGetRegisterInfo(uint32_t reg_num, RegisterInfo &reg_info) {
+  if (reg_num >= llvm::array_lengthof(g_register_infos_arm64_le))
+    return false;
+  reg_info = g_register_infos_arm64_le[reg_num];
+  return true;
+}
+
 #define No_VFP 0
 #define VFPv1 (1u << 1)
 #define VFPv2 (1u << 2)
@@ -168,41 +192,33 @@ bool EmulateInstructionARM64::GetRegiste
   if (reg_kind == eRegisterKindGeneric) {
     switch (reg_num) {
     case LLDB_REGNUM_GENERIC_PC:
-      reg_kind = eRegisterKindDWARF;
-      reg_num = arm64_dwarf::pc;
+      reg_kind = eRegisterKindLLDB;
+      reg_num = gpr_pc_arm64;
       break;
     case LLDB_REGNUM_GENERIC_SP:
-      reg_kind = eRegisterKindDWARF;
-      reg_num = arm64_dwarf::sp;
+      reg_kind = eRegisterKindLLDB;
+      reg_num = gpr_sp_arm64;
       break;
     case LLDB_REGNUM_GENERIC_FP:
-      reg_kind = eRegisterKindDWARF;
-      reg_num = arm64_dwarf::fp;
+      reg_kind = eRegisterKindLLDB;
+      reg_num = gpr_fp_arm64;
       break;
     case LLDB_REGNUM_GENERIC_RA:
-      reg_kind = eRegisterKindDWARF;
-      reg_num = arm64_dwarf::lr;
+      reg_kind = eRegisterKindLLDB;
+      reg_num = gpr_lr_arm64;
       break;
     case LLDB_REGNUM_GENERIC_FLAGS:
-      // There is no DWARF register number for the CPSR right now...
-      reg_info.name = "cpsr";
-      reg_info.alt_name = NULL;
-      reg_info.byte_size = 4;
-      reg_info.byte_offset = 0;
-      reg_info.encoding = eEncodingUint;
-      reg_info.format = eFormatHex;
-      for (uint32_t i = 0; i < lldb::kNumRegisterKinds; ++i)
-        reg_info.kinds[reg_kind] = LLDB_INVALID_REGNUM;
-      reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FLAGS;
-      return true;
+      reg_kind = eRegisterKindLLDB;
+      reg_num = gpr_cpsr_arm64;
+      break;
 
     default:
       return false;
     }
   }
 
-  if (reg_kind == eRegisterKindDWARF)
-    return arm64_dwarf::GetRegisterInfo(reg_num, reg_info);
+  if (reg_kind == eRegisterKindLLDB)
+    return LLDBTableGetRegisterInfo(reg_num, reg_info);
   return false;
 }
 
@@ -429,12 +445,8 @@ bool EmulateInstructionARM64::EvaluateIn
   bool success = false;
   //    if (m_opcode_cpsr == 0 || m_ignore_conditions == false)
   //    {
-  //        m_opcode_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric,
-  //        // use eRegisterKindDWARF is we ever get a cpsr DWARF register
-  //        number
-  //                                              LLDB_REGNUM_GENERIC_FLAGS,
-  //                                              // use arm64_dwarf::cpsr if we
-  //                                              ever get one
+  //        m_opcode_cpsr = ReadRegisterUnsigned (eRegisterKindLLDB,
+  //                                              gpr_cpsr_arm64,
   //                                              0,
   //                                              &success);
   //    }
@@ -447,7 +459,7 @@ bool EmulateInstructionARM64::EvaluateIn
   uint32_t orig_pc_value = 0;
   if (auto_advance_pc) {
     orig_pc_value =
-        ReadRegisterUnsigned(eRegisterKindDWARF, arm64_dwarf::pc, 0, &success);
+        ReadRegisterUnsigned(eRegisterKindLLDB, gpr_pc_arm64, 0, &success);
     if (!success)
       return false;
   }
@@ -459,7 +471,7 @@ bool EmulateInstructionARM64::EvaluateIn
 
   if (auto_advance_pc) {
     uint32_t new_pc_value =
-        ReadRegisterUnsigned(eRegisterKindDWARF, arm64_dwarf::pc, 0, &success);
+        ReadRegisterUnsigned(eRegisterKindLLDB, gpr_pc_arm64, 0, &success);
     if (!success)
       return false;
 
@@ -467,7 +479,7 @@ bool EmulateInstructionARM64::EvaluateIn
       EmulateInstruction::Context context;
       context.type = eContextAdvancePC;
       context.SetNoArgs();
-      if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, arm64_dwarf::pc,
+      if (!WriteRegisterUnsigned(context, eRegisterKindLLDB, gpr_pc_arm64,
                                  orig_pc_value + 4))
         return false;
     }
@@ -478,18 +490,18 @@ bool EmulateInstructionARM64::EvaluateIn
 bool EmulateInstructionARM64::CreateFunctionEntryUnwind(
     UnwindPlan &unwind_plan) {
   unwind_plan.Clear();
-  unwind_plan.SetRegisterKind(eRegisterKindDWARF);
+  unwind_plan.SetRegisterKind(eRegisterKindLLDB);
 
   UnwindPlan::RowSP row(new UnwindPlan::Row);
 
   // Our previous Call Frame Address is the stack pointer
-  row->GetCFAValue().SetIsRegisterPlusOffset(arm64_dwarf::sp, 0);
+  row->GetCFAValue().SetIsRegisterPlusOffset(gpr_sp_arm64, 0);
 
   unwind_plan.AppendRow(row);
   unwind_plan.SetSourceName("EmulateInstructionARM64");
   unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
   unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolYes);
-  unwind_plan.SetReturnAddressRegister(arm64_dwarf::lr);
+  unwind_plan.SetReturnAddressRegister(gpr_lr_arm64);
   return true;
 }
 
@@ -497,7 +509,7 @@ uint32_t EmulateInstructionARM64::GetFra
   if (m_arch.GetTriple().isAndroid())
     return LLDB_INVALID_REGNUM; // Don't use frame pointer on android
 
-  return arm64_dwarf::fp;
+  return gpr_fp_arm64;
 }
 
 bool EmulateInstructionARM64::UsingAArch32() {
@@ -664,8 +676,8 @@ bool EmulateInstructionARM64::EmulateADD
     return false; // UNDEFINED;
   }
   uint64_t result;
-  uint64_t operand1 = ReadRegisterUnsigned(eRegisterKindDWARF,
-                                           arm64_dwarf::x0 + n, 0, &success);
+  uint64_t operand1 =
+      ReadRegisterUnsigned(eRegisterKindLLDB, gpr_x0_arm64 + n, 0, &success);
   uint64_t operand2 = imm;
   bit carry_in;
 
@@ -690,28 +702,26 @@ bool EmulateInstructionARM64::EmulateADD
 
   Context context;
   RegisterInfo reg_info_Rn;
-  if (arm64_dwarf::GetRegisterInfo(n, reg_info_Rn))
+  if (GetRegisterInfo(eRegisterKindLLDB, n, reg_info_Rn))
     context.SetRegisterPlusOffset(reg_info_Rn, imm);
 
-  if (n == GetFramePointerRegisterNumber() && d == arm64_dwarf::sp &&
-      !setflags) {
+  if (n == GetFramePointerRegisterNumber() && d == gpr_sp_arm64 && !setflags) {
     // 'mov sp, fp' - common epilogue instruction, CFA is now in terms
     // of the stack pointer, instead of frame pointer.
     context.type = EmulateInstruction::eContextRestoreStackPointer;
-  } else if ((n == arm64_dwarf::sp || n == GetFramePointerRegisterNumber()) &&
-             d == arm64_dwarf::sp && !setflags) {
+  } else if ((n == gpr_sp_arm64 || n == GetFramePointerRegisterNumber()) &&
+             d == gpr_sp_arm64 && !setflags) {
     context.type = EmulateInstruction::eContextAdjustStackPointer;
-  } else if (d == GetFramePointerRegisterNumber() && n == arm64_dwarf::sp &&
+  } else if (d == GetFramePointerRegisterNumber() && n == gpr_sp_arm64 &&
              !setflags) {
     context.type = EmulateInstruction::eContextSetFramePointer;
   } else {
     context.type = EmulateInstruction::eContextImmediate;
   }
 
-  // If setflags && d == arm64_dwarf::sp then d = WZR/XZR. See CMN, CMP
-  if (!setflags || d != arm64_dwarf::sp)
-    WriteRegisterUnsigned(context, eRegisterKindDWARF, arm64_dwarf::x0 + d,
-                          result);
+  // If setflags && d == gpr_sp_arm64 then d = WZR/XZR. See CMN, CMP
+  if (!setflags || d != gpr_sp_arm64)
+    WriteRegisterUnsigned(context, eRegisterKindLLDB, gpr_x0_arm64 + d, result);
 
   return false;
 }
@@ -804,19 +814,18 @@ bool EmulateInstructionARM64::EmulateLDP
   RegisterInfo reg_info_base;
   RegisterInfo reg_info_Rt;
   RegisterInfo reg_info_Rt2;
-  if (!GetRegisterInfo(eRegisterKindDWARF, arm64_dwarf::x0 + n, reg_info_base))
+  if (!GetRegisterInfo(eRegisterKindLLDB, gpr_x0_arm64 + n, reg_info_base))
     return false;
 
   if (vector) {
-    if (!GetRegisterInfo(eRegisterKindDWARF, arm64_dwarf::v0 + n, reg_info_Rt))
+    if (!GetRegisterInfo(eRegisterKindLLDB, fpu_d0_arm64 + t, reg_info_Rt))
       return false;
-    if (!GetRegisterInfo(eRegisterKindDWARF, arm64_dwarf::v0 + n, reg_info_Rt2))
+    if (!GetRegisterInfo(eRegisterKindLLDB, fpu_d0_arm64 + t2, reg_info_Rt2))
       return false;
   } else {
-    if (!GetRegisterInfo(eRegisterKindDWARF, arm64_dwarf::x0 + t, reg_info_Rt))
+    if (!GetRegisterInfo(eRegisterKindLLDB, gpr_x0_arm64 + t, reg_info_Rt))
       return false;
-    if (!GetRegisterInfo(eRegisterKindDWARF, arm64_dwarf::x0 + t2,
-                         reg_info_Rt2))
+    if (!GetRegisterInfo(eRegisterKindLLDB, gpr_x0_arm64 + t2, reg_info_Rt2))
       return false;
   }
 
@@ -824,10 +833,10 @@ bool EmulateInstructionARM64::EmulateLDP
   if (n == 31) {
     // CheckSPAlignment();
     address =
-        ReadRegisterUnsigned(eRegisterKindDWARF, arm64_dwarf::sp, 0, &success);
+        ReadRegisterUnsigned(eRegisterKindLLDB, gpr_sp_arm64, 0, &success);
   } else
-    address = ReadRegisterUnsigned(eRegisterKindDWARF, arm64_dwarf::x0 + n, 0,
-                                   &success);
+    address =
+        ReadRegisterUnsigned(eRegisterKindLLDB, gpr_x0_arm64 + n, 0, &success);
 
   wb_address = address + idx;
   if (a_mode != AddrMode_POST)
@@ -991,10 +1000,10 @@ bool EmulateInstructionARM64::EmulateLDR
 
   if (n == 31)
     address =
-        ReadRegisterUnsigned(eRegisterKindDWARF, arm64_dwarf::sp, 0, &success);
+        ReadRegisterUnsigned(eRegisterKindLLDB, gpr_sp_arm64, 0, &success);
   else
-    address = ReadRegisterUnsigned(eRegisterKindDWARF, arm64_dwarf::x0 + n, 0,
-                                   &success);
+    address =
+        ReadRegisterUnsigned(eRegisterKindLLDB, gpr_x0_arm64 + n, 0, &success);
 
   if (!success)
     return false;
@@ -1003,11 +1012,11 @@ bool EmulateInstructionARM64::EmulateLDR
     address += offset;
 
   RegisterInfo reg_info_base;
-  if (!GetRegisterInfo(eRegisterKindDWARF, arm64_dwarf::x0 + n, reg_info_base))
+  if (!GetRegisterInfo(eRegisterKindLLDB, gpr_x0_arm64 + n, reg_info_base))
     return false;
 
   RegisterInfo reg_info_Rt;
-  if (!GetRegisterInfo(eRegisterKindDWARF, arm64_dwarf::x0 + t, reg_info_Rt))
+  if (!GetRegisterInfo(eRegisterKindLLDB, gpr_x0_arm64 + t, reg_info_Rt))
     return false;
 
   Context context;
@@ -1096,8 +1105,7 @@ bool EmulateInstructionARM64::EmulateB(c
   switch (branch_type) {
   case BranchType_CALL: {
     addr_t x30 = pc + 4;
-    if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, arm64_dwarf::x30,
-                               x30))
+    if (!WriteRegisterUnsigned(context, eRegisterKindLLDB, gpr_lr_arm64, x30))
       return false;
   } break;
   case BranchType_JMP:
@@ -1158,8 +1166,8 @@ bool EmulateInstructionARM64::EmulateCBZ
   bool is_zero = Bit32(opcode, 24) == 0;
   int32_t offset = llvm::SignExtend64<21>(Bits32(opcode, 23, 5) << 2);
 
-  const uint64_t operand = ReadRegisterUnsigned(
-      eRegisterKindDWARF, arm64_dwarf::x0 + t, 0, &success);
+  const uint64_t operand =
+      ReadRegisterUnsigned(eRegisterKindLLDB, gpr_x0_arm64 + t, 0, &success);
   if (!success)
     return false;
 
@@ -1194,8 +1202,8 @@ bool EmulateInstructionARM64::EmulateTBZ
   uint32_t bit_val = Bit32(opcode, 24);
   int64_t offset = llvm::SignExtend64<16>(Bits32(opcode, 18, 5) << 2);
 
-  const uint64_t operand = ReadRegisterUnsigned(
-      eRegisterKindDWARF, arm64_dwarf::x0 + t, 0, &success);
+  const uint64_t operand =
+      ReadRegisterUnsigned(eRegisterKindLLDB, gpr_x0_arm64 + t, 0, &success);
   if (!success)
     return false;
 

Modified: lldb/trunk/unittests/UnwindAssembly/InstEmulation/TestArm64InstEmulation.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/UnwindAssembly/InstEmulation/TestArm64InstEmulation.cpp?rev=285662&r1=285661&r2=285662&view=diff
==============================================================================
--- lldb/trunk/unittests/UnwindAssembly/InstEmulation/TestArm64InstEmulation.cpp (original)
+++ lldb/trunk/unittests/UnwindAssembly/InstEmulation/TestArm64InstEmulation.cpp Mon Oct 31 20:26:54 2016
@@ -14,7 +14,6 @@
 #include <vector>
 
 #include "Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.h"
-#include "Utility/ARM64_DWARF_Registers.h"
 
 #include "lldb/Core/Address.h"
 #include "lldb/Core/AddressRange.h"
@@ -24,6 +23,7 @@
 
 #include "Plugins/Disassembler/llvm/DisassemblerLLVMC.h"
 #include "Plugins/Instruction/ARM64/EmulateInstructionARM64.h"
+#include "Plugins/Process/Utility/lldb-arm64-register-enums.h"
 #include "llvm/Support/TargetSelect.h"
 
 using namespace lldb;
@@ -93,59 +93,59 @@ TEST_F(TestArm64InstEmulation, TestSimpl
   // CFA=sp +0
   row_sp = unwind_plan.GetRowForFunctionOffset(0);
   EXPECT_EQ(0ull, row_sp->GetOffset());
-  EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == arm64_dwarf::sp);
+  EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_sp_arm64);
   EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
   EXPECT_EQ(0, row_sp->GetCFAValue().GetOffset());
 
   // CFA=sp+16 => fp=[CFA-16] lr=[CFA-8]
   row_sp = unwind_plan.GetRowForFunctionOffset(4);
   EXPECT_EQ(4ull, row_sp->GetOffset());
-  EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == arm64_dwarf::sp);
+  EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_sp_arm64);
   EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
   EXPECT_EQ(16, row_sp->GetCFAValue().GetOffset());
 
-  EXPECT_TRUE(row_sp->GetRegisterInfo(arm64_dwarf::fp, regloc));
+  EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_fp_arm64, regloc));
   EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
   EXPECT_EQ(-16, regloc.GetOffset());
 
-  EXPECT_TRUE(row_sp->GetRegisterInfo(arm64_dwarf::lr, regloc));
+  EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_lr_arm64, regloc));
   EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
   EXPECT_EQ(-8, regloc.GetOffset());
 
   // CFA=fp+16 => fp=[CFA-16] lr=[CFA-8]
   row_sp = unwind_plan.GetRowForFunctionOffset(8);
   EXPECT_EQ(8ull, row_sp->GetOffset());
-  EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == arm64_dwarf::fp);
+  EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_fp_arm64);
   EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
   EXPECT_EQ(16, row_sp->GetCFAValue().GetOffset());
 
-  EXPECT_TRUE(row_sp->GetRegisterInfo(arm64_dwarf::fp, regloc));
+  EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_fp_arm64, regloc));
   EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
   EXPECT_EQ(-16, regloc.GetOffset());
 
-  EXPECT_TRUE(row_sp->GetRegisterInfo(arm64_dwarf::lr, regloc));
+  EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_lr_arm64, regloc));
   EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
   EXPECT_EQ(-8, regloc.GetOffset());
 
   // CFA=sp+16 => fp=[CFA-16] lr=[CFA-8]
   row_sp = unwind_plan.GetRowForFunctionOffset(16);
   EXPECT_EQ(16ull, row_sp->GetOffset());
-  EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == arm64_dwarf::sp);
+  EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_sp_arm64);
   EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
   EXPECT_EQ(16, row_sp->GetCFAValue().GetOffset());
 
-  EXPECT_TRUE(row_sp->GetRegisterInfo(arm64_dwarf::fp, regloc));
+  EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_fp_arm64, regloc));
   EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
   EXPECT_EQ(-16, regloc.GetOffset());
 
-  EXPECT_TRUE(row_sp->GetRegisterInfo(arm64_dwarf::lr, regloc));
+  EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_lr_arm64, regloc));
   EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
   EXPECT_EQ(-8, regloc.GetOffset());
 
   // CFA=sp +0 => fp= <same> lr= <same>
   row_sp = unwind_plan.GetRowForFunctionOffset(20);
   EXPECT_EQ(20ull, row_sp->GetOffset());
-  EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == arm64_dwarf::sp);
+  EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_sp_arm64);
   EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
   EXPECT_EQ(0, row_sp->GetCFAValue().GetOffset());
 }
@@ -210,35 +210,35 @@ TEST_F(TestArm64InstEmulation, TestMediu
   // 0: CFA=sp +0 =>
   row_sp = unwind_plan.GetRowForFunctionOffset(0);
   EXPECT_EQ(0ull, row_sp->GetOffset());
-  EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == arm64_dwarf::sp);
+  EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_sp_arm64);
   EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
   EXPECT_EQ(0, row_sp->GetCFAValue().GetOffset());
 
   // 4: CFA=sp+48 => x21=[CFA-40] x22=[CFA-48]
   row_sp = unwind_plan.GetRowForFunctionOffset(4);
   EXPECT_EQ(4ull, row_sp->GetOffset());
-  EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == arm64_dwarf::sp);
+  EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_sp_arm64);
   EXPECT_EQ(48, row_sp->GetCFAValue().GetOffset());
 
-  EXPECT_TRUE(row_sp->GetRegisterInfo(arm64_dwarf::x21, regloc));
+  EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_x21_arm64, regloc));
   EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
   EXPECT_EQ(-40, regloc.GetOffset());
 
-  EXPECT_TRUE(row_sp->GetRegisterInfo(arm64_dwarf::x22, regloc));
+  EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_x22_arm64, regloc));
   EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
   EXPECT_EQ(-48, regloc.GetOffset());
 
   // 8: CFA=sp+48 => x19=[CFA-24] x20=[CFA-32] x21=[CFA-40] x22=[CFA-48]
   row_sp = unwind_plan.GetRowForFunctionOffset(8);
   EXPECT_EQ(8ull, row_sp->GetOffset());
-  EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == arm64_dwarf::sp);
+  EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_sp_arm64);
   EXPECT_EQ(48, row_sp->GetCFAValue().GetOffset());
 
-  EXPECT_TRUE(row_sp->GetRegisterInfo(arm64_dwarf::x19, regloc));
+  EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_x19_arm64, regloc));
   EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
   EXPECT_EQ(-24, regloc.GetOffset());
 
-  EXPECT_TRUE(row_sp->GetRegisterInfo(arm64_dwarf::x20, regloc));
+  EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_x20_arm64, regloc));
   EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
   EXPECT_EQ(-32, regloc.GetOffset());
 
@@ -246,14 +246,14 @@ TEST_F(TestArm64InstEmulation, TestMediu
   // fp=[CFA-16] lr=[CFA-8]
   row_sp = unwind_plan.GetRowForFunctionOffset(12);
   EXPECT_EQ(12ull, row_sp->GetOffset());
-  EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == arm64_dwarf::sp);
+  EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_sp_arm64);
   EXPECT_EQ(48, row_sp->GetCFAValue().GetOffset());
 
-  EXPECT_TRUE(row_sp->GetRegisterInfo(arm64_dwarf::fp, regloc));
+  EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_fp_arm64, regloc));
   EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
   EXPECT_EQ(-16, regloc.GetOffset());
 
-  EXPECT_TRUE(row_sp->GetRegisterInfo(arm64_dwarf::lr, regloc));
+  EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_lr_arm64, regloc));
   EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
   EXPECT_EQ(-8, regloc.GetOffset());
 
@@ -261,7 +261,7 @@ TEST_F(TestArm64InstEmulation, TestMediu
   // fp=[CFA-16] lr=[CFA-8]
   row_sp = unwind_plan.GetRowForFunctionOffset(16);
   EXPECT_EQ(16ull, row_sp->GetOffset());
-  EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == arm64_dwarf::fp);
+  EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_fp_arm64);
   EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
   EXPECT_EQ(16, row_sp->GetCFAValue().GetOffset());
 
@@ -269,7 +269,7 @@ TEST_F(TestArm64InstEmulation, TestMediu
   // fp=[CFA-16] lr=[CFA-8]
   row_sp = unwind_plan.GetRowForFunctionOffset(28);
   EXPECT_EQ(28ull, row_sp->GetOffset());
-  EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == arm64_dwarf::sp);
+  EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_sp_arm64);
   EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
   EXPECT_EQ(48, row_sp->GetCFAValue().GetOffset());
 
@@ -280,10 +280,10 @@ TEST_F(TestArm64InstEmulation, TestMediu
 
   // I'd prefer if these restored registers were cleared entirely instead of set
   // to IsSame...
-  EXPECT_TRUE(row_sp->GetRegisterInfo(arm64_dwarf::fp, regloc));
+  EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_fp_arm64, regloc));
   EXPECT_TRUE(regloc.IsSame());
 
-  EXPECT_TRUE(row_sp->GetRegisterInfo(arm64_dwarf::lr, regloc));
+  EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_lr_arm64, regloc));
   EXPECT_TRUE(regloc.IsSame());
 
   // 36: CFA=sp+48 => x19= <same> x20= <same> x21=[CFA-40] x22=[CFA-48] fp=
@@ -291,24 +291,24 @@ TEST_F(TestArm64InstEmulation, TestMediu
   row_sp = unwind_plan.GetRowForFunctionOffset(36);
   EXPECT_EQ(36ull, row_sp->GetOffset());
 
-  EXPECT_TRUE(row_sp->GetRegisterInfo(arm64_dwarf::x19, regloc));
+  EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_x19_arm64, regloc));
   EXPECT_TRUE(regloc.IsSame());
 
-  EXPECT_TRUE(row_sp->GetRegisterInfo(arm64_dwarf::x20, regloc));
+  EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_x20_arm64, regloc));
   EXPECT_TRUE(regloc.IsSame());
 
   // 40: CFA=sp +0 => x19= <same> x20= <same> x21= <same> x22= <same> fp= <same>
   // lr= <same>
   row_sp = unwind_plan.GetRowForFunctionOffset(40);
   EXPECT_EQ(40ull, row_sp->GetOffset());
-  EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == arm64_dwarf::sp);
+  EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_sp_arm64);
   EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
   EXPECT_EQ(0, row_sp->GetCFAValue().GetOffset());
 
-  EXPECT_TRUE(row_sp->GetRegisterInfo(arm64_dwarf::x21, regloc));
+  EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_x21_arm64, regloc));
   EXPECT_TRUE(regloc.IsSame());
 
-  EXPECT_TRUE(row_sp->GetRegisterInfo(arm64_dwarf::x22, regloc));
+  EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_x22_arm64, regloc));
   EXPECT_TRUE(regloc.IsSame());
 }
 
@@ -364,45 +364,45 @@ TEST_F(TestArm64InstEmulation, TestFrame
   // 0: CFA=sp +0 =>
   row_sp = unwind_plan.GetRowForFunctionOffset(0);
   EXPECT_EQ(0ull, row_sp->GetOffset());
-  EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == arm64_dwarf::sp);
+  EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_sp_arm64);
   EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
   EXPECT_EQ(0, row_sp->GetCFAValue().GetOffset());
 
   row_sp = unwind_plan.GetRowForFunctionOffset(32);
-  EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == arm64_dwarf::sp);
+  EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_sp_arm64);
   EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
   EXPECT_EQ(0, row_sp->GetCFAValue().GetOffset());
 
-  EXPECT_FALSE(row_sp->GetRegisterInfo(arm64_dwarf::x19, regloc));
-  EXPECT_FALSE(row_sp->GetRegisterInfo(arm64_dwarf::x20, regloc));
-  EXPECT_FALSE(row_sp->GetRegisterInfo(arm64_dwarf::x21, regloc));
-  EXPECT_FALSE(row_sp->GetRegisterInfo(arm64_dwarf::x22, regloc));
-  EXPECT_FALSE(row_sp->GetRegisterInfo(arm64_dwarf::x23, regloc));
-  EXPECT_FALSE(row_sp->GetRegisterInfo(arm64_dwarf::x24, regloc));
-  EXPECT_FALSE(row_sp->GetRegisterInfo(arm64_dwarf::x25, regloc));
-  EXPECT_FALSE(row_sp->GetRegisterInfo(arm64_dwarf::x26, regloc));
-  EXPECT_FALSE(row_sp->GetRegisterInfo(arm64_dwarf::x27, regloc));
-  EXPECT_FALSE(row_sp->GetRegisterInfo(arm64_dwarf::x28, regloc));
-  EXPECT_FALSE(row_sp->GetRegisterInfo(arm64_dwarf::fp, regloc));
-  EXPECT_FALSE(row_sp->GetRegisterInfo(arm64_dwarf::lr, regloc));
+  EXPECT_FALSE(row_sp->GetRegisterInfo(gpr_x19_arm64, regloc));
+  EXPECT_FALSE(row_sp->GetRegisterInfo(gpr_x20_arm64, regloc));
+  EXPECT_FALSE(row_sp->GetRegisterInfo(gpr_x21_arm64, regloc));
+  EXPECT_FALSE(row_sp->GetRegisterInfo(gpr_x22_arm64, regloc));
+  EXPECT_FALSE(row_sp->GetRegisterInfo(gpr_x23_arm64, regloc));
+  EXPECT_FALSE(row_sp->GetRegisterInfo(gpr_x24_arm64, regloc));
+  EXPECT_FALSE(row_sp->GetRegisterInfo(gpr_x25_arm64, regloc));
+  EXPECT_FALSE(row_sp->GetRegisterInfo(gpr_x26_arm64, regloc));
+  EXPECT_FALSE(row_sp->GetRegisterInfo(gpr_x27_arm64, regloc));
+  EXPECT_FALSE(row_sp->GetRegisterInfo(gpr_x28_arm64, regloc));
+  EXPECT_FALSE(row_sp->GetRegisterInfo(gpr_fp_arm64, regloc));
+  EXPECT_FALSE(row_sp->GetRegisterInfo(gpr_lr_arm64, regloc));
 
   row_sp = unwind_plan.GetRowForFunctionOffset(36);
-  EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == arm64_dwarf::sp);
+  EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_sp_arm64);
   EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
   EXPECT_EQ(0, row_sp->GetCFAValue().GetOffset());
 
   row_sp = unwind_plan.GetRowForFunctionOffset(52);
-  EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == arm64_dwarf::sp);
+  EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_sp_arm64);
   EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
   EXPECT_EQ(0, row_sp->GetCFAValue().GetOffset());
 
   row_sp = unwind_plan.GetRowForFunctionOffset(56);
-  EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == arm64_dwarf::sp);
+  EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_sp_arm64);
   EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
   EXPECT_EQ(0, row_sp->GetCFAValue().GetOffset());
 
   row_sp = unwind_plan.GetRowForFunctionOffset(60);
-  EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == arm64_dwarf::sp);
+  EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_sp_arm64);
   EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
   EXPECT_EQ(0, row_sp->GetCFAValue().GetOffset());
 }
@@ -490,21 +490,183 @@ TEST_F(TestArm64InstEmulation, TestRegis
 
   row_sp = unwind_plan.GetRowForFunctionOffset(36);
   EXPECT_EQ(28ull, row_sp->GetOffset());
-  EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == arm64_dwarf::fp);
+  EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_fp_arm64);
   EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
   EXPECT_EQ(16, row_sp->GetCFAValue().GetOffset());
 
-  EXPECT_TRUE(row_sp->GetRegisterInfo(arm64_dwarf::x20, regloc));
+  EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_x20_arm64, regloc));
   EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
   EXPECT_EQ(-32, regloc.GetOffset());
 
   row_sp = unwind_plan.GetRowForFunctionOffset(40);
   EXPECT_EQ(28ull, row_sp->GetOffset());
-  EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == arm64_dwarf::fp);
+  EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_fp_arm64);
   EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
   EXPECT_EQ(16, row_sp->GetCFAValue().GetOffset());
 
-  EXPECT_TRUE(row_sp->GetRegisterInfo(arm64_dwarf::x20, regloc));
+  EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_x20_arm64, regloc));
   EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
   EXPECT_EQ(-32, regloc.GetOffset());
 }
+
+TEST_F(TestArm64InstEmulation, TestRegisterDoubleSpills) {
+  ArchSpec arch("arm64-apple-ios10", nullptr);
+  UnwindAssemblyInstEmulation *engine =
+      static_cast<UnwindAssemblyInstEmulation *>(
+          UnwindAssemblyInstEmulation::CreateInstance(arch));
+  ASSERT_NE(nullptr, engine);
+
+  UnwindPlan::RowSP row_sp;
+  AddressRange sample_range;
+  UnwindPlan unwind_plan(eRegisterKindLLDB);
+  UnwindPlan::Row::RegisterLocation regloc;
+
+  // this file built with clang for iOS arch arm64 optimization -Os
+  // #include <stdio.h>
+  // double foo(double in) {
+  // double arr[32];
+  // for (int i = 0; i < 32; i++)
+  //   arr[i] = in + i;
+  // for (int i = 2; i < 30; i++)
+  //   arr[i] = ((((arr[i - 1] * arr[i - 2] * 0.2) + (0.7 * arr[i])) /
+  //   ((((arr[i] * 0.73) + 0.65) * (arr[i - 1] + 0.2)) - ((arr[i + 1] + (arr[i]
+  //   * 0.32) + 0.52) / 0.3) + (0.531 * arr[i - 2]))) + ((arr[i - 1] + 5) /
+  //   ((arr[i + 2] + 0.4) / arr[i])) + (arr[5] * (0.17 + arr[7] * arr[i])) +
+  //   ((i > 5 ? (arr[i - 3]) : arr[i - 1]) * 0.263) + (((arr[i - 2] + arr[i -
+  //   1]) * 0.3252) + 3.56) - (arr[i + 1] * 0.852311)) * ((arr[i] * 85234.1345)
+  //   + (77342.451324 / (arr[i - 2] + arr[i - 1] - 73425341.33455))) + (arr[i]
+  //   * 875712013.55) - (arr[i - 1] * 0.5555) - ((arr[i] * (arr[i + 1] +
+  //   17342834.44) / 8688200123.555)) + (arr[i - 2] + 8888.888);
+  // return arr[16];
+  //}
+  // int main(int argc, char **argv) { printf("%g\n", foo(argc)); }
+
+  // so function foo() uses enough registers that it spills the callee-saved
+  // floating point registers.
+  uint8_t data[] = {
+      // prologue
+      0xef, 0x3b, 0xba, 0x6d, //  0: 0x6dba3bef   stp    d15, d14, [sp, #-0x60]!
+      0xed, 0x33, 0x01, 0x6d, //  4: 0x6d0133ed   stp    d13, d12, [sp, #0x10]
+      0xeb, 0x2b, 0x02, 0x6d, //  8: 0x6d022beb   stp    d11, d10, [sp, #0x20]
+      0xe9, 0x23, 0x03, 0x6d, // 12: 0x6d0323e9   stp    d9, d8, [sp, #0x30]
+      0xfc, 0x6f, 0x04, 0xa9, // 16: 0xa9046ffc   stp    x28, x27, [sp, #0x40]
+      0xfd, 0x7b, 0x05, 0xa9, // 20: 0xa9057bfd   stp    x29, x30, [sp, #0x50]
+      0xfd, 0x43, 0x01, 0x91, // 24: 0x910143fd   add    x29, sp, #0x50
+      0xff, 0x43, 0x04, 0xd1, // 28: 0xd10443ff   sub    sp, sp, #0x110
+
+      // epilogue
+      0xbf, 0x43, 0x01, 0xd1, // 32: 0xd10143bf   sub    sp, x29, #0x50
+      0xfd, 0x7b, 0x45, 0xa9, // 36: 0xa9457bfd   ldp    x29, x30, [sp, #0x50]
+      0xfc, 0x6f, 0x44, 0xa9, // 40: 0xa9446ffc   ldp    x28, x27, [sp, #0x40]
+      0xe9, 0x23, 0x43, 0x6d, // 44: 0x6d4323e9   ldp    d9, d8, [sp, #0x30]
+      0xeb, 0x2b, 0x42, 0x6d, // 48: 0x6d422beb   ldp    d11, d10, [sp, #0x20]
+      0xed, 0x33, 0x41, 0x6d, // 52: 0x6d4133ed   ldp    d13, d12, [sp, #0x10]
+      0xef, 0x3b, 0xc6, 0x6c, // 56: 0x6cc63bef   ldp    d15, d14, [sp], #0x60
+      0xc0, 0x03, 0x5f, 0xd6, // 60: 0xd65f03c0   ret
+  };
+
+  // UnwindPlan we expect:
+  //   0: CFA=sp +0 =>
+  //   4: CFA=sp+96 => d14=[CFA-88] d15=[CFA-96]
+  //   8: CFA=sp+96 => d12=[CFA-72] d13=[CFA-80] d14=[CFA-88] d15=[CFA-96]
+  //  12: CFA=sp+96 => d10=[CFA-56] d11=[CFA-64] d12=[CFA-72] d13=[CFA-80]
+  //  d14=[CFA-88] d15=[CFA-96]
+  //  16: CFA=sp+96 => d8=[CFA-40] d9=[CFA-48] d10=[CFA-56] d11=[CFA-64]
+  //  d12=[CFA-72] d13=[CFA-80] d14=[CFA-88] d15=[CFA-96]
+  //  20: CFA=sp+96 => x27=[CFA-24] x28=[CFA-32] d8=[CFA-40] d9=[CFA-48]
+  //  d10=[CFA-56] d11=[CFA-64] d12=[CFA-72] d13=[CFA-80] d14=[CFA-88]
+  //  d15=[CFA-96]
+  //  24: CFA=sp+96 => x27=[CFA-24] x28=[CFA-32] fp=[CFA-16] lr=[CFA-8]
+  //  d8=[CFA-40] d9=[CFA-48] d10=[CFA-56] d11=[CFA-64] d12=[CFA-72]
+  //  d13=[CFA-80] d14=[CFA-88] d15=[CFA-96]
+  //  28: CFA=fp+16 => x27=[CFA-24] x28=[CFA-32] fp=[CFA-16] lr=[CFA-8]
+  //  d8=[CFA-40] d9=[CFA-48] d10=[CFA-56] d11=[CFA-64] d12=[CFA-72]
+  //  d13=[CFA-80] d14=[CFA-88] d15=[CFA-96]
+  //  36: CFA=sp+96 => x27=[CFA-24] x28=[CFA-32] fp=[CFA-16] lr=[CFA-8]
+  //  d8=[CFA-40] d9=[CFA-48] d10=[CFA-56] d11=[CFA-64] d12=[CFA-72]
+  //  d13=[CFA-80] d14=[CFA-88] d15=[CFA-96]
+  //  40: CFA=sp+96 => x27=[CFA-24] x28=[CFA-32] d8=[CFA-40] d9=[CFA-48]
+  //  d10=[CFA-56] d11=[CFA-64] d12=[CFA-72] d13=[CFA-80] d14=[CFA-88]
+  //  d15=[CFA-96]
+  //  44: CFA=sp+96 => d8=[CFA-40] d9=[CFA-48] d10=[CFA-56] d11=[CFA-64]
+  //  d12=[CFA-72] d13=[CFA-80] d14=[CFA-88] d15=[CFA-96]
+  //  48: CFA=sp+96 => d10=[CFA-56] d11=[CFA-64] d12=[CFA-72] d13=[CFA-80]
+  //  d14=[CFA-88] d15=[CFA-96]
+  //  52: CFA=sp+96 => d12=[CFA-72] d13=[CFA-80] d14=[CFA-88] d15=[CFA-96]
+  //  56: CFA=sp+96 => d14=[CFA-88] d15=[CFA-96]
+  //  60: CFA=sp +0 =>
+
+  sample_range = AddressRange(0x1000, sizeof(data));
+
+  EXPECT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly(
+      sample_range, data, sizeof(data), unwind_plan));
+
+  //  28: CFA=fp+16 => x27=[CFA-24] x28=[CFA-32] fp=[CFA-16] lr=[CFA-8]
+  //  d8=[CFA-40] d9=[CFA-48] d10=[CFA-56] d11=[CFA-64] d12=[CFA-72]
+  //  d13=[CFA-80] d14=[CFA-88] d15=[CFA-96]
+  row_sp = unwind_plan.GetRowForFunctionOffset(28);
+  EXPECT_EQ(28ull, row_sp->GetOffset());
+  EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_fp_arm64);
+  EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
+  EXPECT_EQ(16, row_sp->GetCFAValue().GetOffset());
+
+  EXPECT_TRUE(row_sp->GetRegisterInfo(fpu_d15_arm64, regloc));
+  EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
+  EXPECT_EQ(-96, regloc.GetOffset());
+
+  EXPECT_TRUE(row_sp->GetRegisterInfo(fpu_d14_arm64, regloc));
+  EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
+  EXPECT_EQ(-88, regloc.GetOffset());
+
+  EXPECT_TRUE(row_sp->GetRegisterInfo(fpu_d13_arm64, regloc));
+  EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
+  EXPECT_EQ(-80, regloc.GetOffset());
+
+  EXPECT_TRUE(row_sp->GetRegisterInfo(fpu_d12_arm64, regloc));
+  EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
+  EXPECT_EQ(-72, regloc.GetOffset());
+
+  EXPECT_TRUE(row_sp->GetRegisterInfo(fpu_d11_arm64, regloc));
+  EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
+  EXPECT_EQ(-64, regloc.GetOffset());
+
+  EXPECT_TRUE(row_sp->GetRegisterInfo(fpu_d10_arm64, regloc));
+  EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
+  EXPECT_EQ(-56, regloc.GetOffset());
+
+  EXPECT_TRUE(row_sp->GetRegisterInfo(fpu_d9_arm64, regloc));
+  EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
+  EXPECT_EQ(-48, regloc.GetOffset());
+
+  EXPECT_TRUE(row_sp->GetRegisterInfo(fpu_d8_arm64, regloc));
+  EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
+  EXPECT_EQ(-40, regloc.GetOffset());
+
+  //  60: CFA=sp +0 =>
+  row_sp = unwind_plan.GetRowForFunctionOffset(60);
+  EXPECT_EQ(60ull, row_sp->GetOffset());
+  EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_sp_arm64);
+  EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
+  EXPECT_EQ(0, row_sp->GetCFAValue().GetOffset());
+
+  if (row_sp->GetRegisterInfo(fpu_d8_arm64, regloc))
+    EXPECT_TRUE(regloc.IsSame());
+  if (row_sp->GetRegisterInfo(fpu_d9_arm64, regloc))
+    EXPECT_TRUE(regloc.IsSame());
+  if (row_sp->GetRegisterInfo(fpu_d10_arm64, regloc))
+    EXPECT_TRUE(regloc.IsSame());
+  if (row_sp->GetRegisterInfo(fpu_d11_arm64, regloc))
+    EXPECT_TRUE(regloc.IsSame());
+  if (row_sp->GetRegisterInfo(fpu_d12_arm64, regloc))
+    EXPECT_TRUE(regloc.IsSame());
+  if (row_sp->GetRegisterInfo(fpu_d13_arm64, regloc))
+    EXPECT_TRUE(regloc.IsSame());
+  if (row_sp->GetRegisterInfo(fpu_d14_arm64, regloc))
+    EXPECT_TRUE(regloc.IsSame());
+  if (row_sp->GetRegisterInfo(fpu_d15_arm64, regloc))
+    EXPECT_TRUE(regloc.IsSame());
+  if (row_sp->GetRegisterInfo(gpr_x27_arm64, regloc))
+    EXPECT_TRUE(regloc.IsSame());
+  if (row_sp->GetRegisterInfo(gpr_x28_arm64, regloc))
+    EXPECT_TRUE(regloc.IsSame());
+}




More information about the lldb-commits mailing list