varasm: Reject soft frame or arg pointer registers for register vars [PR92469]
authorJakub Jelinek <jakub@redhat.com>
Sun, 13 Dec 2020 16:08:08 +0000 (17:08 +0100)
committerJakub Jelinek <jakub@redhat.com>
Sun, 13 Dec 2020 16:08:08 +0000 (17:08 +0100)
The following patch rejects frame, argp and retarg registers (unless they are equal
to hard frame pointer registers or if they aren't eliminable) from local or global
register vars.
These are just internal implementation details eliminated later into hard
frame pointer or stack pointer and using them as register variable leads
to numerous ICEs.

2020-12-13  Jakub Jelinek  <jakub@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/testsuite/gcc.target/i386/pr79804.c
gcc/testsuite/gcc.target/i386/pr88178.c
gcc/testsuite/gcc.target/i386/pr92469.c [new file with mode: 0644]
gcc/varasm.c

index 08d1a3ea1f1c82eea6fae30d405866b00d7fe5a5..fcfcef751677dd3eccf60393febe7b710270ade2 100644 (file)
@@ -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));
+}
index a5fbd35bd8fca1457950f6097f2ed20f8c747020..622e1c2074cdf2affaec1c95c397aa43679d1e4e 100644 (file)
@@ -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 (file)
index 0000000..8cff36b
--- /dev/null
@@ -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;
+}
index 5b2e123b0da470a96a0e334108424a60234cd4db..c5487a78b130eee8a210c48774284da8c2f2b8ed 100644 (file)
@@ -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
        {