aboutsummaryrefslogtreecommitdiff
path: root/libgcc
diff options
context:
space:
mode:
authorrsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4>2018-01-13 17:56:52 +0000
committerrsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4>2018-01-13 17:56:52 +0000
commit599c8d3e6b63b359647f40cbfd53568655694f6d (patch)
treecbbcda2f43cf257940616199a72d7b22c5d92a50 /libgcc
parent2f0761be7ddb39be28392562517387d6955fc124 (diff)
SVE unwinding
This patch adds support for unwinding frames that use the SVE pseudo VG register. We want this register to act like a normal register if the CFI explicitly sets it, but want to provide a default value otherwise. Computing the default value requires an SVE target, so we only want to compute it on demand. aarch64_vg uses a hard-coded .inst in order to avoid a build dependency on binutils 2.28 or later. 2018-01-13 Richard Sandiford <richard.sandiford@linaro.org> gcc/ * doc/tm.texi.in (DWARF_LAZY_REGISTER_VALUE): Document. * doc/tm.texi: Regenerate. libgcc/ * config/aarch64/value-unwind.h (aarch64_vg): New function. (DWARF_LAZY_REGISTER_VALUE): Define. * unwind-dw2.c (_Unwind_GetGR): Use DWARF_LAZY_REGISTER_VALUE to provide a fallback register value. gcc/testsuite/ * g++.target/aarch64/sve/aarch64-sve.exp: New harness. * g++.target/aarch64/sve/catch_1.C: New test. * g++.target/aarch64/sve/catch_2.C: Likewise. * g++.target/aarch64/sve/catch_3.C: Likewise. * g++.target/aarch64/sve/catch_4.C: Likewise. * g++.target/aarch64/sve/catch_5.C: Likewise. * g++.target/aarch64/sve/catch_6.C: Likewise. Reviewed-by: James Greenhalgh <james.greenhalgh@arm.com> git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@256615 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libgcc')
-rw-r--r--libgcc/ChangeLog7
-rw-r--r--libgcc/config/aarch64/value-unwind.h16
-rw-r--r--libgcc/unwind-dw2.c16
3 files changed, 35 insertions, 4 deletions
diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog
index 25625efaf33..85738df894f 100644
--- a/libgcc/ChangeLog
+++ b/libgcc/ChangeLog
@@ -1,3 +1,10 @@
+2018-01-13 Richard Sandiford <richard.sandiford@linaro.org>
+
+ * config/aarch64/value-unwind.h (aarch64_vg): New function.
+ (DWARF_LAZY_REGISTER_VALUE): Define.
+ * unwind-dw2.c (_Unwind_GetGR): Use DWARF_LAZY_REGISTER_VALUE
+ to provide a fallback register value.
+
2018-01-08 Michael Meissner <meissner@linux.vnet.ibm.com>
* config/rs6000/quad-float128.h (IBM128_TYPE): Explicitly use
diff --git a/libgcc/config/aarch64/value-unwind.h b/libgcc/config/aarch64/value-unwind.h
index 8458a3d7d24..e15396250b0 100644
--- a/libgcc/config/aarch64/value-unwind.h
+++ b/libgcc/config/aarch64/value-unwind.h
@@ -23,3 +23,19 @@
#if defined __aarch64__ && !defined __LP64__
# define REG_VALUE_IN_UNWIND_CONTEXT
#endif
+
+/* Return the value of the pseudo VG register. This should only be
+ called if we know this is an SVE host. */
+static inline int
+aarch64_vg (void)
+{
+ register int vg asm ("x0");
+ /* CNTD X0. */
+ asm (".inst 0x04e0e3e0" : "=r" (vg));
+ return vg;
+}
+
+/* Lazily provide a value for VG, so that we don't try to execute SVE
+ instructions unless we know they're needed. */
+#define DWARF_LAZY_REGISTER_VALUE(REGNO, VALUE) \
+ ((REGNO) == AARCH64_DWARF_VG && ((*VALUE) = aarch64_vg (), 1))
diff --git a/libgcc/unwind-dw2.c b/libgcc/unwind-dw2.c
index a83ca2fbcf4..de9310f524f 100644
--- a/libgcc/unwind-dw2.c
+++ b/libgcc/unwind-dw2.c
@@ -216,12 +216,12 @@ _Unwind_IsExtendedContext (struct _Unwind_Context *context)
|| (context->flags & EXTENDED_CONTEXT_BIT));
}
-/* Get the value of register INDEX as saved in CONTEXT. */
+/* Get the value of register REGNO as saved in CONTEXT. */
inline _Unwind_Word
-_Unwind_GetGR (struct _Unwind_Context *context, int index)
+_Unwind_GetGR (struct _Unwind_Context *context, int regno)
{
- int size;
+ int size, index;
_Unwind_Context_Reg_Val val;
#ifdef DWARF_ZERO_REG
@@ -229,7 +229,7 @@ _Unwind_GetGR (struct _Unwind_Context *context, int index)
return 0;
#endif
- index = DWARF_REG_TO_UNWIND_COLUMN (index);
+ index = DWARF_REG_TO_UNWIND_COLUMN (regno);
gcc_assert (index < (int) sizeof(dwarf_reg_size_table));
size = dwarf_reg_size_table[index];
val = context->reg[index];
@@ -237,6 +237,14 @@ _Unwind_GetGR (struct _Unwind_Context *context, int index)
if (_Unwind_IsExtendedContext (context) && context->by_value[index])
return _Unwind_Get_Unwind_Word (val);
+#ifdef DWARF_LAZY_REGISTER_VALUE
+ {
+ _Unwind_Word value;
+ if (DWARF_LAZY_REGISTER_VALUE (regno, &value))
+ return value;
+ }
+#endif
+
/* This will segfault if the register hasn't been saved. */
if (size == sizeof(_Unwind_Ptr))
return * (_Unwind_Ptr *) (_Unwind_Internal_Ptr) val;