From c218f6e89d7bee930ad705642cf069262432990a Mon Sep 17 00:00:00 2001 From: Joseph Myers Date: Tue, 26 Aug 2014 18:06:31 +0100 Subject: [PATCH] Fix ARM ICE for register var asm ("pc") (PR target/60606). PR target/60606 PR target/61330 * varasm.c (make_decl_rtl): Clear DECL_ASSEMBLER_NAME and DECL_HARD_REGISTER and return for invalid register specifications. * cfgexpand.c (expand_one_var): If expand_one_hard_reg_var clears DECL_HARD_REGISTER, call expand_one_error_var. * config/arm/arm.c (arm_hard_regno_mode_ok): Do not allow CC_REGNUM with non-MODE_CC modes. (arm_regno_class): Return NO_REGS for PC_REGNUM. testsuite: * gcc.dg/torture/pr60606-1.c, gcc.target/arm/pr60606-2.c, gcc.target/arm/pr60606-3.c, gcc.target/arm/pr60606-4.c: New tests. From-SVN: r214526 --- gcc/ChangeLog | 12 ++++++++++++ gcc/cfgexpand.c | 7 ++++++- gcc/config/arm/arm.c | 6 ++++++ gcc/testsuite/ChangeLog | 7 +++++++ gcc/testsuite/gcc.dg/torture/pr60606-1.c | 9 +++++++++ gcc/testsuite/gcc.target/arm/pr60606-2.c | 10 ++++++++++ gcc/testsuite/gcc.target/arm/pr60606-3.c | 9 +++++++++ gcc/testsuite/gcc.target/arm/pr60606-4.c | 9 +++++++++ gcc/varasm.c | 5 +++++ 9 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/gcc.dg/torture/pr60606-1.c create mode 100644 gcc/testsuite/gcc.target/arm/pr60606-2.c create mode 100644 gcc/testsuite/gcc.target/arm/pr60606-3.c create mode 100644 gcc/testsuite/gcc.target/arm/pr60606-4.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 6b9bc1c534d..93d29a22837 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,15 @@ +2014-08-26 Joseph Myers + + PR target/60606 + PR target/61330 + * varasm.c (make_decl_rtl): Clear DECL_ASSEMBLER_NAME and + DECL_HARD_REGISTER and return for invalid register specifications. + * cfgexpand.c (expand_one_var): If expand_one_hard_reg_var clears + DECL_HARD_REGISTER, call expand_one_error_var. + * config/arm/arm.c (arm_hard_regno_mode_ok): Do not allow + CC_REGNUM with non-MODE_CC modes. + (arm_regno_class): Return NO_REGS for PC_REGNUM. + 2014-08-26 Marek Polacek PR c/61271 diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c index 6c2b693c310..34e57b923d7 100644 --- a/gcc/cfgexpand.c +++ b/gcc/cfgexpand.c @@ -1307,7 +1307,12 @@ expand_one_var (tree var, bool toplevel, bool really_expand) else if (TREE_CODE (var) == VAR_DECL && DECL_HARD_REGISTER (var)) { if (really_expand) - expand_one_hard_reg_var (var); + { + expand_one_hard_reg_var (var); + if (!DECL_HARD_REGISTER (var)) + /* Invalid register specification. */ + expand_one_error_var (var); + } } else if (use_register_for_decl (var)) { diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index d9f38f4eeb6..11e0655ca67 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -22970,6 +22970,9 @@ arm_hard_regno_mode_ok (unsigned int regno, enum machine_mode mode) || (TARGET_HARD_FLOAT && TARGET_VFP && regno == VFPCC_REGNUM)); + if (regno == CC_REGNUM && GET_MODE_CLASS (mode) != MODE_CC) + return false; + if (TARGET_THUMB1) /* For the Thumb we only allow values bigger than SImode in registers 0 - 6, so that there is always a second low @@ -23066,6 +23069,9 @@ arm_modes_tieable_p (enum machine_mode mode1, enum machine_mode mode2) enum reg_class arm_regno_class (int regno) { + if (regno == PC_REGNUM) + return NO_REGS; + if (TARGET_THUMB1) { if (regno == STACK_POINTER_REGNUM) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index bdbb212d74c..3290e7da34e 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2014-08-26 Joseph Myers + + PR target/60606 + PR target/61330 + * gcc.dg/torture/pr60606-1.c, gcc.target/arm/pr60606-2.c, + gcc.target/arm/pr60606-3.c, gcc.target/arm/pr60606-4.c: New tests. + 2014-08-26 Dominik Vogt * gfortran.dg/bessel_7.f90: Bump allowed precision to avoid diff --git a/gcc/testsuite/gcc.dg/torture/pr60606-1.c b/gcc/testsuite/gcc.dg/torture/pr60606-1.c new file mode 100644 index 00000000000..c4afae77454 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr60606-1.c @@ -0,0 +1,9 @@ +/* { dg-do compile } */ +/* { dg-options "-ffat-lto-objects" } */ + +int +f (void) +{ + register unsigned int r asm ("no-such-register"); /* { dg-error "invalid register name" } */ + return r; +} diff --git a/gcc/testsuite/gcc.target/arm/pr60606-2.c b/gcc/testsuite/gcc.target/arm/pr60606-2.c new file mode 100644 index 00000000000..7baf88126f8 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/pr60606-2.c @@ -0,0 +1,10 @@ +/* { dg-do compile } */ +/* { dg-options "-O" } */ + +int +f (void) +{ + register unsigned pc asm ("pc"); /* { dg-error "not general enough" } */ + + return pc > 0x12345678; +} diff --git a/gcc/testsuite/gcc.target/arm/pr60606-3.c b/gcc/testsuite/gcc.target/arm/pr60606-3.c new file mode 100644 index 00000000000..60ae27db53d --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/pr60606-3.c @@ -0,0 +1,9 @@ +/* { dg-do compile } */ +/* { dg-options "-O" } */ + +int +f (void) +{ + register unsigned int r asm ("cc"); /* { dg-error "not general enough|suitable for data type" } */ + return r; +} diff --git a/gcc/testsuite/gcc.target/arm/pr60606-4.c b/gcc/testsuite/gcc.target/arm/pr60606-4.c new file mode 100644 index 00000000000..5288777a77b --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/pr60606-4.c @@ -0,0 +1,9 @@ +/* { dg-do compile } */ +/* { dg-options "-O" } */ + +int +f (void) +{ + register unsigned int r[50] asm ("r1"); /* { dg-error "suitable for a register" } */ + return r[1]; +} diff --git a/gcc/varasm.c b/gcc/varasm.c index 80a32855791..ce99a138171 100644 --- a/gcc/varasm.c +++ b/gcc/varasm.c @@ -1371,6 +1371,11 @@ make_decl_rtl (tree decl) /* As a register variable, it has no section. */ return; } + /* Avoid internal errors from invalid register + specifications. */ + SET_DECL_ASSEMBLER_NAME (decl, NULL_TREE); + DECL_HARD_REGISTER (decl) = 0; + return; } /* Now handle ordinary static variables and functions (in memory). Also handle vars declared register invalidly. */ -- 2.30.2