OSDN Git Service

PR inline-asm/16194
authoramylaar <amylaar@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 9 Feb 2006 19:17:09 +0000 (19:17 +0000)
committeramylaar <amylaar@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 9 Feb 2006 19:17:09 +0000 (19:17 +0000)
gcc:
* tree.h (decl_overlaps_hard_reg_set_p) Don't declare.
(tree_overlaps_hard_reg_set): Declare.
* stmt.c (decl_overlaps_hard_reg_set_p): Now static.  Change return
type and signature to match function type expected by walk_tree.
(tree_overlaps_hard_reg_set): New function.
(decl_conflicts_with_clobbers_p): Rename to:
(tree_conflicts_with_clobbers_p).  Take HARD_REG_SET * argument.
Use tree_overlaps_hard_reg_set.  Changed caller.
* doc/tm.texi (TARGET_MD_ASM_CLOBBERS): Replace
decl_overlaps_hard_reg_set_p with tree_overlaps_hard_reg_set.
* cris.c (cris_md_asm_clobbers): Likewise.

gcc/testsuite:
* gcc.dg/pr16194.c: New test.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@110810 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/cris/cris.c
gcc/doc/tm.texi
gcc/stmt.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/pr16194.c [new file with mode: 0644]
gcc/tree.h

index 31ab02d..763e081 100644 (file)
@@ -1,3 +1,18 @@
+2006-02-09  J"orn Rennecke <joern.rennecke@st.com>
+
+       PR inline-asm/16194
+       * tree.h (decl_overlaps_hard_reg_set_p) Don't declare.
+       (tree_overlaps_hard_reg_set): Declare.
+       * stmt.c (decl_overlaps_hard_reg_set_p): Now static.  Change return
+       type and signature to match function type expected by walk_tree.
+       (tree_overlaps_hard_reg_set): New function.
+       (decl_conflicts_with_clobbers_p): Rename to:
+       (tree_conflicts_with_clobbers_p).  Take HARD_REG_SET * argument.
+       Use tree_overlaps_hard_reg_set.  Changed caller.
+       * doc/tm.texi (TARGET_MD_ASM_CLOBBERS): Replace
+       decl_overlaps_hard_reg_set_p with tree_overlaps_hard_reg_set.
+       * cris.c (cris_md_asm_clobbers): Likewise.
+
 2006-02-09  Bernd Schmidt  <bernd.schmidt@analog.com>
 
        * reload1.c (emit_input_reload_insns): Delete code that tries to
index 01b9b15..dc0c163 100644 (file)
@@ -3462,7 +3462,7 @@ cris_md_asm_clobbers (tree outputs, tree inputs, tree in_clobbers)
         impossible constraints.  */
       if (strchr (TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (t))),
                  'h') != NULL
-         || decl_overlaps_hard_reg_set_p (val, mof_set))
+         || tree_overlaps_hard_reg_set (val, &mof_set) != NULL_TREE)
        return clobbers;
     }
 
@@ -3472,7 +3472,7 @@ cris_md_asm_clobbers (tree outputs, tree inputs, tree in_clobbers)
 
       if (strchr (TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (t))),
                  'h') != NULL
-         || decl_overlaps_hard_reg_set_p (val, mof_set))
+         || tree_overlaps_hard_reg_set (val, &mof_set) != NULL_TREE)
        return clobbers;
     }
 
index d60fc13..5a04430 100644 (file)
@@ -9337,7 +9337,7 @@ It should return the result of the last @code{tree_cons} used to add a
 clobber.  The @var{outputs}, @var{inputs} and @var{clobber} lists are the
 corresponding parameters to the asm and may be inspected to avoid
 clobbering a register that is an input or output of the asm.  You can use
-@code{decl_overlaps_hard_reg_set_p}, declared in @file{tree.h}, to test
+@code{tree_overlaps_hard_reg_set}, declared in @file{tree.h}, to test
 for overlap with regards to asm-declared registers.
 @end deftypefn
 
index da2f750..3bb4f42 100644 (file)
@@ -105,7 +105,7 @@ static int cost_table_initialized;
 #define COST_TABLE(I)  cost_table_[(unsigned HOST_WIDE_INT) ((I) + 1)]
 \f
 static int n_occurrences (int, const char *);
-static bool decl_conflicts_with_clobbers_p (tree, const HARD_REG_SET);
+static bool tree_conflicts_with_clobbers_p (tree, HARD_REG_SET *);
 static void expand_nl_goto_receiver (void);
 static bool check_operand_nalternatives (tree, tree);
 static bool check_unique_operand_names (tree, tree);
@@ -558,49 +558,66 @@ parse_input_constraint (const char **constraint_p, int input_num,
   return true;
 }
 
-/* Return true iff there's an overlap between REGS and DECL, where DECL
-   can be an asm-declared register.  */
+/* Return DECL iff there's an overlap between *REGS and DECL, where DECL
+   can be an asm-declared register.  Called via walk_tree.  */
 
-bool
-decl_overlaps_hard_reg_set_p (tree decl, const HARD_REG_SET regs)
+static tree
+decl_overlaps_hard_reg_set_p (tree *declp, int *walk_subtrees ATTRIBUTE_UNUSED,
+                             void *data)
 {
-  if ((TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == PARM_DECL)
-      && DECL_REGISTER (decl)
-      && REG_P (DECL_RTL (decl))
-      && REGNO (DECL_RTL (decl)) < FIRST_PSEUDO_REGISTER)
+  tree decl = *declp;
+  const HARD_REG_SET *regs = data;
+
+  if (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == PARM_DECL)
     {
-      rtx reg = DECL_RTL (decl);
-      unsigned int regno;
-
-      for (regno = REGNO (reg);
-          regno < (REGNO (reg)
-                   + hard_regno_nregs[REGNO (reg)][GET_MODE (reg)]);
-          regno++)
-       if (TEST_HARD_REG_BIT (regs, regno))
-         return true;
+      if (DECL_REGISTER (decl)
+         && REG_P (DECL_RTL (decl))
+         && REGNO (DECL_RTL (decl)) < FIRST_PSEUDO_REGISTER)
+       {
+         rtx reg = DECL_RTL (decl);
+         unsigned int regno;
+
+         for (regno = REGNO (reg);
+              regno < (REGNO (reg)
+                       + hard_regno_nregs[REGNO (reg)][GET_MODE (reg)]);
+              regno++)
+           if (TEST_HARD_REG_BIT (*regs, regno))
+             return decl;
+       }
+      walk_subtrees = 0;
     }
-
-  return false;
+  else if (TYPE_P (decl))
+    walk_subtrees = 0;
+  return NULL_TREE;
 }
 
+/* If there is an overlap between *REGS and DECL, return the first overlap
+   found.  */
+tree
+tree_overlaps_hard_reg_set (tree decl, HARD_REG_SET *regs)
+{
+  return walk_tree (&decl, decl_overlaps_hard_reg_set_p, regs, NULL);
+}
 
 /* Check for overlap between registers marked in CLOBBERED_REGS and
-   anything inappropriate in DECL.  Emit error and return TRUE for error,
-   FALSE for ok.  */
+   anything inappropriate in T.  Emit error and return the register
+   variable definition for error, NULL_TREE for ok.  */
 
 static bool
-decl_conflicts_with_clobbers_p (tree decl, const HARD_REG_SET clobbered_regs)
+tree_conflicts_with_clobbers_p (tree t, HARD_REG_SET *clobbered_regs)
 {
   /* Conflicts between asm-declared register variables and the clobber
      list are not allowed.  */
-  if (decl_overlaps_hard_reg_set_p (decl, clobbered_regs))
+  tree overlap = tree_overlaps_hard_reg_set (t, clobbered_regs);
+
+  if (overlap)
     {
       error ("asm-specifier for variable %qs conflicts with asm clobber list",
-            IDENTIFIER_POINTER (DECL_NAME (decl)));
+            IDENTIFIER_POINTER (DECL_NAME (overlap)));
 
       /* Reset registerness to stop multiple errors emitted for a single
         variable.  */
-      DECL_REGISTER (decl) = 0;
+      DECL_REGISTER (overlap) = 0;
       return true;
     }
 
@@ -827,7 +844,7 @@ expand_asm_operands (tree string, tree outputs, tree inputs,
          inout_opnum[ninout++] = i;
        }
 
-      if (decl_conflicts_with_clobbers_p (val, clobbered_regs))
+      if (tree_conflicts_with_clobbers_p (val, &clobbered_regs))
        clobber_conflict_found = 1;
     }
 
@@ -923,7 +940,7 @@ expand_asm_operands (tree string, tree outputs, tree inputs,
        = gen_rtx_ASM_INPUT (TYPE_MODE (type), 
                             ggc_strdup (constraints[i + noutputs]));
 
-      if (decl_conflicts_with_clobbers_p (val, clobbered_regs))
+      if (tree_conflicts_with_clobbers_p (val, &clobbered_regs))
        clobber_conflict_found = 1;
     }
 
index 8be7f5d..59778df 100644 (file)
@@ -1,3 +1,8 @@
+2006-02-09  J"orn Rennecke <joern.rennecke@st.com>
+
+       PR inline-asm/16194
+       * gcc.dg/pr16194.c: New test.
+
 2006-02-09  Rainer Orth  <ro@TechFak.Uni-Bielefeld.DE>
 
        * ada/acats/run_acats: Use portable variant of "$@".
diff --git a/gcc/testsuite/gcc.dg/pr16194.c b/gcc/testsuite/gcc.dg/pr16194.c
new file mode 100644 (file)
index 0000000..44f34a4
--- /dev/null
@@ -0,0 +1,67 @@
+/* { dg-do compile } */
+/* { dg-options "-O" } */
+/* { dg-bogus "internal compiler error" "ICE" { target *-*-* } 0 } */
+
+#define ASMDECL __asm (REG);
+#define CLOBBER_LIST : REG
+#define INP_CLOBBER_LIST : CLOBBER_LIST
+#if defined (__alpha__)
+# define REG "$1"
+#elif defined (__CRIS__) || defined (__sh__)
+# define REG "r10"
+#elif defined (__i386__)
+# define REG "%eax"
+#elif defined (__MMIX__)
+# define REG "$8"
+#elif defined (__powerpc__) || defined (__PPC__) || defined (__ppc__) \
+        || defined (__POWERPC__) || defined (PPC) || defined (_IBMR2)
+# define REG "6"
+#elif defined (__x86_64__)
+# define REG "rax"
+#else
+  /* Make this test harmless for any target not recognized above.  */
+# undef ASMDECL
+# define ASMDECL
+# define REG "conflict"
+# undef CLOBBER_LIST
+# define CLOBBER_LIST
+# undef INP_CLOBBER_LIST
+# define INP_CLOBBER_LIST
+#endif
+
+struct A
+{
+  int a;
+};
+
+struct B
+{
+  struct A b[3];
+};
+
+struct C
+{
+  struct B c;
+};
+
+void bug (void)
+{
+  register char* dst ASMDECL;
+  __asm__ ("":"=g"(*dst): : REG); /* { dg-error "conflict" } */
+}
+
+/* The tree optimizers currently prevent us from finding an overlap -
+   we end up using a copy of dst rather than dst.
+   But at least make sure we don't get an ICE.  */
+void bug2 (void)
+{
+  register char* dst ASMDECL;
+  __asm__ ("": :"g"(*dst) CLOBBER_LIST);
+}
+
+void
+foo (void)
+{
+  register struct C *dst ASMDECL;
+  __asm__ ("" : "=g"(dst->c.b[1].a) INP_CLOBBER_LIST);
+}
index b4e390d..7d17daf 100644 (file)
@@ -4382,7 +4382,7 @@ extern void expand_decl (tree);
 extern void expand_anon_union_decl (tree, tree, tree);
 #ifdef HARD_CONST
 /* Silly ifdef to avoid having all includers depend on hard-reg-set.h.  */
-extern bool decl_overlaps_hard_reg_set_p (tree, const HARD_REG_SET);
+extern tree tree_overlaps_hard_reg_set (tree, HARD_REG_SET *);
 #endif
 
 /* In gimplify.c.  */