aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/testsuite/gcc.target/i386/pr79804.c6
-rw-r--r--gcc/testsuite/gcc.target/i386/pr88178.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/pr92469.c24
-rw-r--r--gcc/varasm.c26
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
{