This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Fix "+r,r" constraint handling in gimplifier (PR inline-asm/20314)


Hi!

The gimplifier doesn't handle inout constraints with multiple alternatives,
which leads to
error: operand constraints for 'asm' differ in number of alternatives 
errors eventhough the asm is written properly.

While looking into this, I have noticed a typo in stmt.c, which causes
constraint to be reallocated always, even if it starts with =.
When *is_inout is written into, is_inout is non-NULL, therefore the if
condition is always true.  What was really meant is *is_inout.

Ok for 4.0/HEAD if bootstrap/regtests pass?

2005-03-08  Jakub Jelinek  <jakub@redhat.com>

	PR inline-asm/20314
	* gimplify.c (gimplify_asm_expr): Handle input/output constraints
	with multiple alternatives.

	* stmt.c (parse_output_constraint): Fix a typo.

	* gcc.dg/torture/pr20314-1.c: New test.
	* gcc.dg/torture/pr20314-2.c: New test.

--- gcc/gimplify.c.jj	2005-02-19 00:27:50.000000000 +0100
+++ gcc/gimplify.c	2005-03-08 00:08:33.511583589 +0100
@@ -3330,16 +3330,81 @@ gimplify_asm_expr (tree *expr_p, tree *p
 	  char *p = xstrdup (constraint);
 	  p[0] = '=';
 	  TREE_VALUE (TREE_PURPOSE (link)) = build_string (constraint_len, p);
-	  free (p);
 
 	  /* And add a matching input constraint.  */
 	  if (allows_reg)
 	    {
 	      sprintf (buf, "%d", i);
-	      input = build_string (strlen (buf), buf);
+
+	      /* If there are multiple alternatives in the constraint,
+		 handle each of them individually.  Those that allow register
+		 will be replaced with operand number, the others will stay
+		 unchanged.  */
+	      if (strchr (p, ',') != NULL)
+		{
+		  size_t len = 0, buflen = strlen (buf);
+		  char *beg, *end, *str, *dst;
+
+		  for (beg = p + 1;;)
+		    {
+		      end = strchr (beg, ',');
+		      if (end == NULL)
+			end = strchr (beg, '\0');
+		      if ((size_t) (end - beg) < buflen)
+			len += buflen + 1;
+		      else
+			len += end - beg + 1;
+		      if (*end)
+			beg = end + 1;
+		      else
+			break;
+		    }
+
+		  str = alloca (len);
+		  for (beg = p + 1, dst = str;;)
+		    {
+		      const char *tem;
+		      bool mem_p, reg_p, inout_p;
+
+		      end = strchr (beg, ',');
+		      if (end)
+			*end = '\0';
+		      beg[-1] = '=';
+		      tem = beg - 1;
+		      parse_output_constraint (&tem, i, 0, 0,
+					       &mem_p, &reg_p, &inout_p);
+		      if (dst != str)
+			*dst++ = ',';
+		      if (reg_p)
+			{
+			  memcpy (dst, buf, buflen);
+			  dst += buflen;
+			}
+		      else
+			{
+			  if (end)
+			    len = end - beg;
+			  else
+			    len = strlen (beg);
+			  memcpy (dst, beg, len);
+			  dst += len;
+			}
+		      if (end)
+			beg = end + 1;
+		      else
+			break;
+		    }
+		  *dst = '\0';
+		  input = build_string (dst - str, str);
+		}
+	      else
+		input = build_string (strlen (buf), buf);
 	    }
 	  else
 	    input = build_string (constraint_len - 1, constraint + 1);
+
+	  free (p);
+
 	  input = build_tree_list (build_tree_list (NULL_TREE, input),
 				   unshare_expr (TREE_VALUE (link)));
 	  ASM_INPUTS (expr) = chainon (ASM_INPUTS (expr), input);
--- gcc/stmt.c.jj	2005-02-19 00:27:51.000000000 +0100
+++ gcc/stmt.c	2005-03-07 18:34:47.363511250 +0100
@@ -323,7 +323,7 @@ parse_output_constraint (const char **co
   *is_inout = (*p == '+');
 
   /* Canonicalize the output constraint so that it begins with `='.  */
-  if (p != constraint || is_inout)
+  if (p != constraint || *is_inout)
     {
       char *buf;
       size_t c_len = strlen (constraint);
--- gcc/testsuite/gcc.dg/torture/pr20314-1.c.jj	2005-03-08 00:18:03.174113642 +0100
+++ gcc/testsuite/gcc.dg/torture/pr20314-1.c	2005-03-08 00:20:16.719326348 +0100
@@ -0,0 +1,56 @@
+/* PR inline-asm/20314 */
+/* { dg-do compile { target i?86-*-* x86_64-*-* } } */
+
+int
+f1 (void)
+{
+  int x = 4, y;
+  __asm__ volatile ("" : "+r,r" (x), "=r,r" (y)
+		       : "%r,r" (x), "m,r" (8), "r,r" (2));
+  return x;
+}
+
+int
+f2 (void)
+{
+  int x = 4, y;
+  __asm__ volatile ("" : "=r,r" (x), "=r,r" (y)
+		       : "%0,0" (x), "m,r" (8), "r,r" (2));
+  return x;
+}
+
+int
+f3 (void)
+{
+  int x = 4, y;
+  __asm__ volatile ("" : "+r,r" (x), "=r,r" (y)
+		       : "%m,r" (8), "r,r" (2));
+  return x;
+}
+
+int
+f4 (void)
+{
+  int x = 4, y;
+  __asm__ volatile ("" : "+r" (x), "=r" (y)
+		       : "r" (x), "r" (8), "r" (2));
+  return x;
+}
+
+int
+f5 (void)
+{
+  int x = 4, y;
+  __asm__ volatile ("" : "=r" (x), "=r" (y)
+		       : "0" (x), "r" (8), "r" (2));
+  return x;
+}
+
+int
+f6 (void)
+{
+  int x = 4, y;
+  __asm__ volatile ("" : "+r" (x), "=r" (y)
+		       : "r" (8), "r" (2));
+  return x;
+}
--- gcc/testsuite/gcc.dg/torture/pr20314-2.c.jj	2005-03-08 00:18:24.675283811 +0100
+++ gcc/testsuite/gcc.dg/torture/pr20314-2.c	2005-03-08 00:21:20.061043847 +0100
@@ -0,0 +1,46 @@
+/* PR inline-asm/20314 */
+/* { dg-do compile { target { x86_64-*-* && lp64 } } } */
+
+int a, b, c, d, e, f, g, h, i, j, k, l;
+
+void
+f1 (void)
+{
+  __asm__ volatile (""
+		    : [a] "+r" (a), [b] "+r" (b), [c] "+r" (c), [d] "+r" (d),
+		      [e] "+r" (e), [f] "+r" (f), [g] "+r" (g), [h] "+r" (h),
+		      [i] "+r" (i), [j] "+r" (j), [k] "+r" (k), [l] "+r" (l));
+}
+
+void
+f2 (void)
+{
+  __asm__ volatile (""
+		    : [a] "+r,m" (a), [b] "+r,m" (b), [c] "+r,m" (c), [d] "+r,m" (d),
+		      [e] "+r,m" (e), [f] "+r,m" (f), [g] "+r,m" (g), [h] "+r,m" (h),
+		      [i] "+r,m" (i), [j] "+r,m" (j), [k] "+r,m" (k), [l] "+r,m" (l));
+}
+
+void
+f3 (void)
+{
+  __asm__ volatile (""
+		    : [a] "=r" (a), [b] "=r" (b), [c] "=r" (c), [d] "=r" (d),
+		      [e] "=r" (e), [f] "=r" (f), [g] "=r" (g), [h] "=r" (h),
+		      [i] "=r" (i), [j] "=r" (j), [k] "=r" (k), [l] "=r" (l)
+		    : "[a]" (a), "[b]" (b), "[c]" (c), "[d]" (d),
+		      "[e]" (e), "[f]" (f), "[g]" (g), "[h]" (h),
+		      "[i]" (i), "[j]" (j), "[k]" (k), "[l]" (l));
+}
+
+void
+f4 (void)
+{
+  __asm__ volatile (""
+		    : [a] "=r,m" (a), [b] "=r,m" (b), [c] "=r,m" (c), [d] "=r,m" (d),
+		      [e] "=r,m" (e), [f] "=r,m" (f), [g] "=r,m" (g), [h] "=r,m" (h),
+		      [i] "=r,m" (i), [j] "=r,m" (j), [k] "=r,m" (k), [l] "=r,m" (l)
+		    : "[a],m" (a), "[b],m" (b), "[c],m" (c), "[d],m" (d),
+		      "[e],m" (e), "[f],m" (f), "[g],m" (g), "[h],m" (h),
+		      "[i],m" (i), "[j],m" (j), "[k],m" (k), "[l],m" (l));
+}

	Jakub


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]