On Thu, Dec 10, 2020 at 12:00:17PM +0100, Jakub Jelinek wrote: > So, would it be better to check for one of FRAME_POINTER_REGNUM, > ARG_POINTER_REGNUM or RETURN_ADDRESS_POINTER_REGNUM if they > are mentioned in (from part of pairs in) ELIMINABLE_REGS?
In patch form now: 2020-12-10 Jakub Jelinek <ja...@redhat.com> PR target/92469 * varasm.c (eliminable_regno_p): New function. (make_decl_rtl): Reject asm vars for frame and argp if they are different from hard frame pointer. * gcc.target/i386/pr92469.c: New test. * gcc.target/i386/pr79804.c: Adjust expected diagnostics. * gcc.target/i386/pr88178.c: Expect an error. --- gcc/varasm.c.jj 2020-12-04 10:53:56.314043883 +0100 +++ gcc/varasm.c 2020-12-10 16:02:48.273074206 +0100 @@ -1370,6 +1370,23 @@ ultimate_transparent_alias_target (tree return target; } +/* Return true if REGNUM is mentioned in ELIMINABLE_REGS as a from + register number. */ + +static bool +eliminable_regno_p (int regnum) +{ + static const struct + { + const int from; + const int to; + } eliminables[] = ELIMINABLE_REGS; + for (size_t i = 0; i < ARRAY_SIZE (eliminables); i++) + if (regnum == eliminables[i].from) + return true; + return false; +} + /* Create the DECL_RTL for a VAR_DECL or FUNCTION_DECL. DECL should have static storage duration. In other words, it should not be an automatic variable, including PARM_DECLs. @@ -1472,6 +1489,15 @@ make_decl_rtl (tree decl) else if (!targetm.hard_regno_mode_ok (reg_number, mode)) error ("register specified for %q+D isn%'t suitable for data type", decl); + else if (reg_number != HARD_FRAME_POINTER_REGNUM + && (reg_number == FRAME_POINTER_REGNUM +#ifdef RETURN_ADDRESS_POINTER_REGNUM + || reg_number == RETURN_ADDRESS_POINTER_REGNUM +#endif + || reg_number == ARG_POINTER_REGNUM) + && eliminable_regno_p (reg_number)) + error ("register specified for %q+D is an internal GCC " + "implementation detail", decl); /* Now handle properly declared static register variables. */ else { --- gcc/testsuite/gcc.target/i386/pr92469.c.jj 2020-12-09 13:41:50.497501433 +0100 +++ gcc/testsuite/gcc.target/i386/pr92469.c 2020-12-09 13:41:30.416724986 +0100 @@ -0,0 +1,24 @@ +/* PR target/92469 */ +/* { dg-do compile } */ +/* { dg-options "-O0" } */ + +void +foo (void) +{ + register int x asm ("frame"); /* { dg-error "register specified for 'x' is an internal GCC implementation detail" } */ + int y = x; +} + +void +bar (void) +{ + register int x asm ("19"); /* { dg-error "register specified for 'x' is an internal GCC implementation detail" } */ + int y = x; +} + +void +baz (void) +{ + register int x asm ("argp"); /* { dg-error "register specified for 'x' is an internal GCC implementation detail" } */ + int y = x; +} --- gcc/testsuite/gcc.target/i386/pr79804.c.jj 2020-01-12 11:54:37.976389828 +0100 +++ gcc/testsuite/gcc.target/i386/pr79804.c 2020-12-10 10:11:53.948939322 +0100 @@ -4,7 +4,7 @@ void foo (void) { - register int r19 asm ("19"); + register int r19 asm ("19"); /* { dg-error "register specified for 'r19' is an internal GCC implementation detail" } */ - asm volatile ("# %0" : "=r"(r19)); /* { dg-error "invalid use of register" } */ -} /* { dg-error "cannot be used in 'asm' here" } */ + asm volatile ("# %0" : "=r"(r19)); +} --- gcc/testsuite/gcc.target/i386/pr88178.c.jj 2020-01-12 11:54:37.983389722 +0100 +++ gcc/testsuite/gcc.target/i386/pr88178.c 2020-12-10 10:12:30.140535022 +0100 @@ -4,5 +4,5 @@ void foo (void) { - register int r19 asm ("19"); + register int r19 asm ("19"); /* { dg-error "register specified for 'r19' is an internal GCC implementation detail" } */ } Jakub