diff options
-rw-r--r-- | gcc/testsuite/gcc.target/i386/pr79804.c | 6 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/pr88178.c | 2 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/pr92469.c | 24 | ||||
-rw-r--r-- | gcc/varasm.c | 26 |
4 files changed, 54 insertions, 4 deletions
diff --git a/gcc/testsuite/gcc.target/i386/pr79804.c b/gcc/testsuite/gcc.target/i386/pr79804.c index 08d1a3e..fcfcef7 100644 --- a/gcc/testsuite/gcc.target/i386/pr79804.c +++ b/gcc/testsuite/gcc.target/i386/pr79804.c @@ -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)); +} diff --git a/gcc/testsuite/gcc.target/i386/pr88178.c b/gcc/testsuite/gcc.target/i386/pr88178.c index a5fbd35..622e1c2 100644 --- a/gcc/testsuite/gcc.target/i386/pr88178.c +++ b/gcc/testsuite/gcc.target/i386/pr88178.c @@ -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" } */ } diff --git a/gcc/testsuite/gcc.target/i386/pr92469.c b/gcc/testsuite/gcc.target/i386/pr92469.c new file mode 100644 index 0000000..8cff36b --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr92469.c @@ -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; +} diff --git a/gcc/varasm.c b/gcc/varasm.c index 5b2e123..c5487a7 100644 --- a/gcc/varasm.c +++ b/gcc/varasm.c @@ -1371,6 +1371,23 @@ ultimate_transparent_alias_target (tree *alias) 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. @@ -1473,6 +1490,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 { |