From dbc3af4fc620aeb6fbf088e961fe8658bbd959c7 Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Sat, 13 Jan 2018 17:56:52 +0000 Subject: 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 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 From-SVN: r256615 --- libgcc/ChangeLog | 7 +++++++ libgcc/config/aarch64/value-unwind.h | 16 ++++++++++++++++ libgcc/unwind-dw2.c | 16 ++++++++++++---- 3 files changed, 35 insertions(+), 4 deletions(-) (limited to 'libgcc') diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog index 25625ef..85738df 100644 --- a/libgcc/ChangeLog +++ b/libgcc/ChangeLog @@ -1,3 +1,10 @@ +2018-01-13 Richard Sandiford + + * 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 * 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 8458a3d..e1539625 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 a83ca2f..de9310f 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; -- cgit v1.1