target.h (init_dwarf_reg_sizes_extra): New target hook.
* target.h (init_dwarf_reg_sizes_extra): New target hook. * target-def.h (TARGET_INIT_DWARF_REG_SIZES_EXTRA): New default. * doc/tm.texi (TARGET_INIT_DWARF_REG_SIZES_EXTRA): Document. * dwarf2out.c (expand_builtin_init_dwarf_reg_sizes): Call this hook. * config/rs6000/rs6000.c (TARGET_INIT_DWARF_REG_SIZES_EXTRA, rs6000_init_dwarf_reg_sizes_extra): New. * config/rs6000/linux-unwind.h (ppc_fallback_frame_state): Support SPE register high parts. testsuite: * gcc.target/powerpc/spe-unwind-1.c, g++.dg/eh/simd-5.C: New tests. From-SVN: r122468
This commit is contained in:
parent
9c4d24932e
commit
37ea0b7e74
@ -1,3 +1,15 @@
|
||||
2007-03-02 Joseph Myers <joseph@codesourcery.com>
|
||||
|
||||
* target.h (init_dwarf_reg_sizes_extra): New target hook.
|
||||
* target-def.h (TARGET_INIT_DWARF_REG_SIZES_EXTRA): New default.
|
||||
* doc/tm.texi (TARGET_INIT_DWARF_REG_SIZES_EXTRA): Document.
|
||||
* dwarf2out.c (expand_builtin_init_dwarf_reg_sizes): Call this
|
||||
hook.
|
||||
* config/rs6000/rs6000.c (TARGET_INIT_DWARF_REG_SIZES_EXTRA,
|
||||
rs6000_init_dwarf_reg_sizes_extra): New.
|
||||
* config/rs6000/linux-unwind.h (ppc_fallback_frame_state): Support
|
||||
SPE register high parts.
|
||||
|
||||
2007-03-01 Brooks Moses <brooks.moses@codesourcery.com>
|
||||
|
||||
* Makefile.in: Add install-pdf target as
|
||||
|
@ -301,6 +301,17 @@ ppc_fallback_frame_state (struct _Unwind_Context *context,
|
||||
fs->regs.reg[VRSAVE_REGNO].loc.offset = (long) &vregs->vsave - new_cfa;
|
||||
}
|
||||
|
||||
/* If we have SPE register high-parts... we check at compile-time to
|
||||
avoid expanding the code for all other PowerPC. */
|
||||
#ifdef __SPE__
|
||||
for (i = 0; i < 32; i++)
|
||||
{
|
||||
fs->regs.reg[i + FIRST_PSEUDO_REGISTER - 1].how = REG_SAVED_OFFSET;
|
||||
fs->regs.reg[i + FIRST_PSEUDO_REGISTER - 1].loc.offset
|
||||
= (long) ®s->vregs - new_cfa + 4 * i;
|
||||
}
|
||||
#endif
|
||||
|
||||
return _URC_NO_REASON;
|
||||
}
|
||||
|
||||
|
@ -765,6 +765,7 @@ static rtx generate_set_vrsave (rtx, rs6000_stack_t *, int);
|
||||
int easy_vector_constant (rtx, enum machine_mode);
|
||||
static bool rs6000_is_opaque_type (tree);
|
||||
static rtx rs6000_dwarf_register_span (rtx);
|
||||
static void rs6000_init_dwarf_reg_sizes_extra (tree);
|
||||
static rtx rs6000_legitimize_tls_address (rtx, enum tls_model);
|
||||
static void rs6000_output_dwarf_dtprel (FILE *, int, rtx) ATTRIBUTE_UNUSED;
|
||||
static rtx rs6000_tls_get_addr (void);
|
||||
@ -1028,6 +1029,9 @@ static const char alt_reg_names[][8] =
|
||||
#undef TARGET_DWARF_REGISTER_SPAN
|
||||
#define TARGET_DWARF_REGISTER_SPAN rs6000_dwarf_register_span
|
||||
|
||||
#undef TARGET_INIT_DWARF_REG_SIZES_EXTRA
|
||||
#define TARGET_INIT_DWARF_REG_SIZES_EXTRA rs6000_init_dwarf_reg_sizes_extra
|
||||
|
||||
/* On rs6000, function arguments are promoted, as are function return
|
||||
values. */
|
||||
#undef TARGET_PROMOTE_FUNCTION_ARGS
|
||||
@ -20657,6 +20661,30 @@ rs6000_dwarf_register_span (rtx reg)
|
||||
gen_rtx_REG (SImode, regno + 1200)));
|
||||
}
|
||||
|
||||
/* Fill in sizes for SPE register high parts in table used by unwinder. */
|
||||
|
||||
static void
|
||||
rs6000_init_dwarf_reg_sizes_extra (tree address)
|
||||
{
|
||||
if (TARGET_SPE)
|
||||
{
|
||||
int i;
|
||||
enum machine_mode mode = TYPE_MODE (char_type_node);
|
||||
rtx addr = expand_expr (address, NULL_RTX, VOIDmode, 0);
|
||||
rtx mem = gen_rtx_MEM (BLKmode, addr);
|
||||
rtx value = gen_int_mode (4, mode);
|
||||
|
||||
for (i = 1201; i < 1232; i++)
|
||||
{
|
||||
int column = DWARF_REG_TO_UNWIND_COLUMN (i);
|
||||
HOST_WIDE_INT offset
|
||||
= DWARF_FRAME_REGNUM (column) * GET_MODE_SIZE (mode);
|
||||
|
||||
emit_move_insn (adjust_address (mem, mode, offset), value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Map internal gcc register numbers to DWARF2 register numbers. */
|
||||
|
||||
unsigned int
|
||||
|
@ -8168,6 +8168,15 @@ register in Dwarf. Otherwise, this hook should return @code{NULL_RTX}.
|
||||
If not defined, the default is to return @code{NULL_RTX}.
|
||||
@end deftypefn
|
||||
|
||||
@deftypefn {Target Hook} void TARGET_INIT_DWARF_REG_SIZES_EXTRA (tree @var{address})
|
||||
If some registers are represented in Dwarf-2 unwind information in
|
||||
multiple pieces, define this hook to fill in information about the
|
||||
sizes of those pieces in the table used by the unwinder at runtime.
|
||||
It will be called by @code{expand_builtin_init_dwarf_reg_sizes} after
|
||||
filling in a single size corresponding to each hard register;
|
||||
@var{address} is the address of the table.
|
||||
@end deftypefn
|
||||
|
||||
@deftypefn {Target Hook} bool TARGET_ASM_TTYPE (rtx @var{sym})
|
||||
This hook is used to output a reference from a frame unwinding table to
|
||||
the type_info object identified by @var{sym}. It should return @code{true}
|
||||
|
@ -498,6 +498,8 @@ expand_builtin_init_dwarf_reg_sizes (tree address)
|
||||
#ifdef DWARF_ALT_FRAME_RETURN_COLUMN
|
||||
init_return_column_size (mode, mem, DWARF_ALT_FRAME_RETURN_COLUMN);
|
||||
#endif
|
||||
|
||||
targetm.init_dwarf_reg_sizes_extra (address);
|
||||
}
|
||||
|
||||
/* Convert a DWARF call frame info. operation to its string name */
|
||||
|
@ -190,6 +190,7 @@ Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#endif
|
||||
|
||||
#define TARGET_DWARF_REGISTER_SPAN hook_rtx_rtx_null
|
||||
#define TARGET_INIT_DWARF_REG_SIZES_EXTRA hook_void_tree
|
||||
|
||||
#ifndef TARGET_ASM_FILE_START
|
||||
#define TARGET_ASM_FILE_START default_file_start
|
||||
@ -688,6 +689,7 @@ Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
TARGET_ADDRESS_COST, \
|
||||
TARGET_ALLOCATE_INITIAL_VALUE, \
|
||||
TARGET_DWARF_REGISTER_SPAN, \
|
||||
TARGET_INIT_DWARF_REG_SIZES_EXTRA, \
|
||||
TARGET_FIXED_CONDITION_CODE_REGS, \
|
||||
TARGET_CC_MODES_COMPATIBLE, \
|
||||
TARGET_MACHINE_DEPENDENT_REORG, \
|
||||
|
@ -601,6 +601,12 @@ struct gcc_target
|
||||
hook should return NULL_RTX. */
|
||||
rtx (* dwarf_register_span) (rtx);
|
||||
|
||||
/* If expand_builtin_init_dwarf_reg_sizes needs to fill in table
|
||||
entries not corresponding directly to registers below
|
||||
FIRST_PSEUDO_REGISTER, this hook should generate the necessary
|
||||
code, given the address of the table. */
|
||||
void (* init_dwarf_reg_sizes_extra) (tree);
|
||||
|
||||
/* Fetch the fixed register(s) which hold condition codes, for
|
||||
targets where it makes sense to look for duplicate assignments to
|
||||
the condition codes. This should return true if there is such a
|
||||
|
@ -1,3 +1,8 @@
|
||||
2007-03-02 Joseph Myers <joseph@codesourcery.com>
|
||||
|
||||
* gcc.target/powerpc/spe-unwind-1.c, g++.dg/eh/simd-5.C: New
|
||||
tests.
|
||||
|
||||
2007-03-01 Zdenek Dvorak <dvorakz@suse.cz>
|
||||
|
||||
* gcc.dg/tree-ssa/prefetch-4.c: New test.
|
||||
|
44
gcc/testsuite/g++.dg/eh/simd-5.C
Normal file
44
gcc/testsuite/g++.dg/eh/simd-5.C
Normal file
@ -0,0 +1,44 @@
|
||||
// Test EH with V2SI SIMD registers actually restores correct values.
|
||||
// Origin: Joseph Myers <joseph@codesourcery.com>
|
||||
// { dg-options "-O" }
|
||||
// { dg-do run { target powerpc_spe } }
|
||||
|
||||
extern "C" void abort (void);
|
||||
extern "C" int memcmp (const void *, const void *, __SIZE_TYPE__);
|
||||
typedef int __attribute__((vector_size (8))) v2si;
|
||||
|
||||
v2si a = { 1, 2 };
|
||||
v2si b = { 3, 4 };
|
||||
v2si c = { 4, 6 };
|
||||
volatile v2si r;
|
||||
v2si r2;
|
||||
|
||||
void
|
||||
f ()
|
||||
{
|
||||
register v2si v asm("r15");
|
||||
v = __builtin_spe_evaddw (b, c);
|
||||
asm volatile ("" : "+r" (v));
|
||||
r = v;
|
||||
throw 1;
|
||||
}
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
register v2si v asm("r15");
|
||||
v = __builtin_spe_evaddw (a, b);
|
||||
asm volatile ("" : "+r" (v));
|
||||
try
|
||||
{
|
||||
f ();
|
||||
}
|
||||
catch (int)
|
||||
{
|
||||
r = v;
|
||||
r2 = r;
|
||||
if (memcmp (&r2, &c, sizeof (v2si)))
|
||||
abort ();
|
||||
}
|
||||
return 0;
|
||||
}
|
116
gcc/testsuite/gcc.target/powerpc/spe-unwind-1.c
Normal file
116
gcc/testsuite/gcc.target/powerpc/spe-unwind-1.c
Normal file
@ -0,0 +1,116 @@
|
||||
/* Verify that unwinding can find SPE registers in signal frames. */
|
||||
/* Origin: Joseph Myers <joseph@codesourcery.com> */
|
||||
/* { dg-do run { target { powerpc*-*-linux* && powerpc_spe } } } */
|
||||
/* { dg-options "-fexceptions -fnon-call-exceptions -O2" } */
|
||||
|
||||
#include <unwind.h>
|
||||
#include <stdlib.h>
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
|
||||
int count;
|
||||
char *null;
|
||||
int found_reg;
|
||||
|
||||
typedef int v2si __attribute__((__vector_size__(8)));
|
||||
|
||||
v2si v1 = { 123, 234 };
|
||||
v2si v2 = { 345, 456 };
|
||||
|
||||
static _Unwind_Reason_Code
|
||||
force_unwind_stop (int version, _Unwind_Action actions,
|
||||
_Unwind_Exception_Class exc_class,
|
||||
struct _Unwind_Exception *exc_obj,
|
||||
struct _Unwind_Context *context,
|
||||
void *stop_parameter)
|
||||
{
|
||||
unsigned int reg;
|
||||
if (actions & _UA_END_OF_STACK)
|
||||
abort ();
|
||||
if (_Unwind_GetGR (context, 1215) == 123)
|
||||
found_reg = 1;
|
||||
return _URC_NO_REASON;
|
||||
}
|
||||
|
||||
static void force_unwind ()
|
||||
{
|
||||
struct _Unwind_Exception *exc = malloc (sizeof (*exc));
|
||||
memset (&exc->exception_class, 0, sizeof (exc->exception_class));
|
||||
exc->exception_cleanup = 0;
|
||||
|
||||
#ifndef __USING_SJLJ_EXCEPTIONS__
|
||||
_Unwind_ForcedUnwind (exc, force_unwind_stop, 0);
|
||||
#else
|
||||
_Unwind_SjLj_ForcedUnwind (exc, force_unwind_stop, 0);
|
||||
#endif
|
||||
|
||||
abort ();
|
||||
}
|
||||
|
||||
static void counter (void *p __attribute__((unused)))
|
||||
{
|
||||
++count;
|
||||
}
|
||||
|
||||
static void handler (void *p __attribute__((unused)))
|
||||
{
|
||||
if (count != 2)
|
||||
abort ();
|
||||
if (!found_reg)
|
||||
abort ();
|
||||
exit (0);
|
||||
}
|
||||
|
||||
static int __attribute__((noinline)) fn5 ()
|
||||
{
|
||||
char dummy __attribute__((cleanup (counter)));
|
||||
force_unwind ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void fn4 (int sig)
|
||||
{
|
||||
char dummy __attribute__((cleanup (counter)));
|
||||
/* Clobber high part without compiler's knowledge so the only saved
|
||||
copy is from the signal frame. */
|
||||
asm volatile ("evmergelo 15,15,15");
|
||||
fn5 ();
|
||||
null = NULL;
|
||||
}
|
||||
|
||||
static void fn3 ()
|
||||
{
|
||||
abort ();
|
||||
}
|
||||
|
||||
static int __attribute__((noinline)) fn2 ()
|
||||
{
|
||||
register v2si r15 asm("r15");
|
||||
r15 = v1;
|
||||
asm volatile ("" : "+r" (r15));
|
||||
*null = 0;
|
||||
fn3 ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __attribute__((noinline)) fn1 ()
|
||||
{
|
||||
signal (SIGSEGV, fn4);
|
||||
signal (SIGBUS, fn4);
|
||||
fn2 ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __attribute__((noinline)) fn0 ()
|
||||
{
|
||||
char dummy __attribute__((cleanup (handler)));
|
||||
fn1 ();
|
||||
null = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
fn0 ();
|
||||
abort ();
|
||||
}
|
Loading…
Reference in New Issue
Block a user