[PATCH] libcxxabi/unwind: Add support for ARM EHABI _Unwind_VRS_Set/Get/Pop methods.

Dana Jansens danakj at google.com
Mon Jun 2 10:02:08 PDT 2014


Hi Nick,

This patch builds on my previous patch[1] (using the config.h #define) to
provide the virtual register set methods from the ARM EHABI ssection 7.5.
Please have a look when you are able.

Thanks,
Dana

[1]
http://lists.cs.uiuc.edu/pipermail/cfe-commits/Week-of-Mon-20140602/106818.html
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20140602/65a07e7f/attachment.html>
-------------- next part --------------
commit 20307b83127d76f5374ec69341aad2c63ae7d347
Author: Dana Jansens <danakj at chromium.org>
Date:   Mon Jun 2 12:53:02 2014 -0400

    unwind: Add the _Unwind_Get/Set/Pop methods from ARM EHABI.
    
    These methods are defined in section 7.5 of the ARM EHABI.
    We implement and export them in this patch. Future patches
    can make use of these methods for implementing the byte-code
    interpreter of the personality routines.
    
    Change-Id: Iaa8d6b19e348e518fd29b1accf2713d443180143

diff --git a/libcxxabi/src/Unwind/UnwindLevel1.c b/libcxxabi/src/Unwind/UnwindLevel1.c
index b2e93c7..3c6ca54 100644
--- a/libcxxabi/src/Unwind/UnwindLevel1.c
+++ b/libcxxabi/src/Unwind/UnwindLevel1.c
@@ -492,4 +492,199 @@ _Unwind_DeleteException(struct _Unwind_Exception *exception_object) {
                                            exception_object);
 }
 
+#if _LIBUNWIND_SUPPORT_ARM_EHABI_UNWIND
+
+static uint64_t ValueAsBitPattern(_Unwind_VRS_DataRepresentation representation,
+                                  void* valuep) {
+  uint64_t value = 0;
+  switch (representation) {
+    case _UVRSD_UINT32:
+    case _UVRSD_FLOAT:
+      memcpy(&value, valuep, sizeof(uint32_t));
+      break;
+
+    case _UVRSD_VFPX:
+    case _UVRSD_UINT64:
+    case _UVRSD_DOUBLE:
+      memcpy(&value, valuep, sizeof(uint64_t));
+      break;
+  }
+  return value;
+}
+
+_LIBUNWIND_EXPORT _Unwind_VRS_Result
+_Unwind_VRS_Set(_Unwind_Context *context,
+                _Unwind_VRS_RegClass regclass,
+                uint32_t regno,
+                _Unwind_VRS_DataRepresentation representation,
+                void *valuep) {
+  _LIBUNWIND_TRACE_API("_Unwind_VRS_Set(context=%p, regclass=%d, reg=%d, "
+                       "rep=%d, value=0x%llX)\n", context, regclass,
+                       regno, representation,
+                       ValueAsBitPattern(representation, valuep));
+  unw_cursor_t *cursor = (unw_cursor_t *)context;
+  switch (regclass) {
+    case _UVRSC_CORE: {
+      if (representation != _UVRSD_UINT32)
+        _LIBUNWIND_ABORT("Core register representation must be _UVRSD_UINT32.");
+      return unw_set_reg(cursor, regno, *((unw_word_t*)valuep)) == UNW_ESUCCESS ?
+          _UVRSR_OK : _UVRSR_FAILED;
+    }
+    // FIXME: Are these right? See 4.7 on lazy-saving
+    case _UVRSC_WMMXD:
+    case _UVRSC_WMMXC:
+    case _UVRSC_VFP: {
+      unw_fpreg_t value;
+      switch (representation) {
+        case _UVRSD_VFPX:
+          // TODO(ajwong): What does this mean?
+          break;
+        case _UVRSD_UINT64: {
+          uint64_t tmp = *(uint64_t*)valuep;
+          memcpy(&value, &tmp, sizeof(tmp));
+          break;
+        }
+        case _UVRSD_FLOAT: {
+          float tmp = *(float*)valuep;
+          memcpy(&value, &tmp, sizeof(tmp));
+          break;
+        }
+        case _UVRSD_DOUBLE: {
+          double tmp = *(double*)valuep;
+          memcpy(&value, &tmp, sizeof(tmp));
+          break;
+        }
+        case _UVRSD_UINT32: {
+          uint32_t tmp = *(uint32_t*)valuep;
+          memcpy(&value, &tmp, sizeof(tmp));
+          break;
+        }
+        default:
+          _LIBUNWIND_ABORT("Invalid VFP data representation.");
+      }
+      return unw_set_fpreg(cursor, regno, value) == UNW_ESUCCESS ?
+          _UVRSR_OK : _UVRSR_FAILED;
+    }
+  }
+  return _UVRSR_NOT_IMPLEMENTED;
+}
+
+static _Unwind_VRS_Result _Unwind_VRS_Get_Internal(
+    _Unwind_Context *context,
+    _Unwind_VRS_RegClass regclass,
+    uint32_t regno,
+    _Unwind_VRS_DataRepresentation representation,
+    void *valuep) {
+  unw_cursor_t *cursor = (unw_cursor_t *)context;
+  switch (regclass) {
+    case _UVRSC_CORE: {
+      if (representation != _UVRSD_UINT32)
+        _LIBUNWIND_ABORT("Core register representation must be _UVRSD_UINT32.");
+      return unw_get_reg(cursor, regno, (unw_word_t*)valuep) == UNW_ESUCCESS ?
+          _UVRSR_OK : _UVRSR_FAILED;
+    }
+    case _UVRSC_WMMXD:
+    case _UVRSC_WMMXC:
+    case _UVRSC_VFP: {
+      unw_fpreg_t value;
+      if (unw_get_fpreg(cursor, regno, &value) != UNW_ESUCCESS)
+        return _UVRSR_FAILED;
+      switch (representation) {
+        case _UVRSD_VFPX:
+          // FIXME: Implement floating point support.
+          break;
+        case _UVRSD_UINT64: {
+          uint64_t tmp;
+          memcpy(&tmp, &value, sizeof(tmp));
+          *(uint64_t*)valuep = tmp;
+          break;
+        }
+        case _UVRSD_FLOAT: {
+          float tmp;
+          memcpy(&tmp, &value, sizeof(tmp));
+          *(float*)valuep = tmp;
+          break;
+        }
+        case _UVRSD_DOUBLE: {
+          double tmp;
+          memcpy(&tmp, &value, sizeof(tmp));
+          *(double*)valuep = tmp;
+          break;
+        }
+        case _UVRSD_UINT32: {
+          uint32_t tmp;
+          memcpy(&tmp, &value, sizeof(tmp));
+          *(uint32_t*)valuep = tmp;
+          break;
+        }
+        default:
+          _LIBUNWIND_ABORT("Invalid VFP data representation.");
+      }
+      return _UVRSR_OK;
+    }
+  }
+  return _UVRSR_NOT_IMPLEMENTED;
+}
+
+_LIBUNWIND_EXPORT _Unwind_VRS_Result
+_Unwind_VRS_Get(_Unwind_Context *context,
+                _Unwind_VRS_RegClass regclass,
+                uint32_t regno,
+                _Unwind_VRS_DataRepresentation representation,
+                void *valuep) {
+  _Unwind_VRS_Result result =
+      _Unwind_VRS_Get_Internal(context, regclass, regno, representation,
+                               valuep);
+  _LIBUNWIND_TRACE_API("_Unwind_VRS_Get(context=%p, regclass=%d, reg=%d, "
+                       "rep=%d, value=0x%llX, result = %d)\n", context, regclass,
+                       regno, representation,
+                       ValueAsBitPattern(representation, valuep), result);
+  return result;
+}
+
+_LIBUNWIND_EXPORT _Unwind_VRS_Result
+_Unwind_VRS_Pop(_Unwind_Context *context,
+                _Unwind_VRS_RegClass regclass,
+                uint32_t discriminator,
+                _Unwind_VRS_DataRepresentation representation) {
+  _LIBUNWIND_TRACE_API("_Unwind_VRS_Pop(context=%p, regclass=%d, "
+                       "discriminator=%d, representation=%d)\n",
+                        context, regclass, discriminator, representation);
+  if (regclass != _UVRSC_CORE || representation != _UVRSD_UINT32) {
+    // FIXME: Implement floating point support.
+    _LIBUNWIND_ABORT("during phase1 personality function said it would "
+                     "stop here, but now if phase2 it did not stop here");
+    return _UVRSR_NOT_IMPLEMENTED;
+  }
+  bool do13 = false;
+  uint32_t reg13Value = 0;
+  uint32_t* sp;
+  if (_Unwind_VRS_Get(context, _UVRSC_CORE, UNW_ARM_SP,
+                      _UVRSD_UINT32, &sp) != _UVRSR_OK) {
+    return _UVRSR_FAILED;
+  }
+  for (int i = 0; i < 16; ++i) {
+    if (!(discriminator & (1<<i)))
+      continue;
+    uint32_t value = *sp++;
+    if (i == 13) {
+      reg13Value = value;
+      do13 = true;
+    } else {
+      if (_Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_R0 + i,
+                          _UVRSD_UINT32, &value) != _UVRSR_OK) {
+        return _UVRSR_FAILED;
+      }
+    }
+  }
+  if (do13) {
+    return _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_SP,
+                           _UVRSD_UINT32, &reg13Value);
+  } else {
+    return _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_SP,
+                        _UVRSD_UINT32, &sp);
+  }
+}
+#endif  // _LIBUNWIND_SUPPORT_ARM_EHABI_UNWIND
+
 #endif // _LIBUNWIND_BUILD_ZERO_COST_APIS


More information about the cfe-commits mailing list