diff options
-rw-r--r-- | gcc/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/gimplify.c | 69 | ||||
-rw-r--r-- | gcc/stmt.c | 2 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/torture/pr20314-1.c | 56 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/torture/pr20314-2.c | 47 |
6 files changed, 185 insertions, 3 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 830d535..a55928f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2005-03-10 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. + 2005-03-09 Bob Wilson <bob.wilson@acm.org> * config/xtensa/xtensa.h (TRAMPOLINE_TEMPLATE): Use "no-transform" diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 93724a9..341ca7b 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -3330,16 +3330,81 @@ gimplify_asm_expr (tree *expr_p, tree *pre_p, tree *post_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, ®_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); @@ -323,7 +323,7 @@ parse_output_constraint (const char **constraint_p, int operand_num, *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); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 2f2a431..53daac0 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2005-03-10 Jakub Jelinek <jakub@redhat.com> + + PR inline-asm/20314 + * gcc.dg/torture/pr20314-1.c: New test. + * gcc.dg/torture/pr20314-2.c: New test. + 2005-03-09 Ulrich Weigand <uweigand@de.ibm.com> * gcc.dg/20050309-1.c: New test. diff --git a/gcc/testsuite/gcc.dg/torture/pr20314-1.c b/gcc/testsuite/gcc.dg/torture/pr20314-1.c new file mode 100644 index 0000000..8a69c2d --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr20314-1.c @@ -0,0 +1,56 @@ +/* PR inline-asm/20314 */ +/* { dg-do compile { target i?86-*-* x86_64-*-* powerpc*-*-* ia64-*-* } } */ + +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; +} diff --git a/gcc/testsuite/gcc.dg/torture/pr20314-2.c b/gcc/testsuite/gcc.dg/torture/pr20314-2.c new file mode 100644 index 0000000..ad1b8f9 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr20314-2.c @@ -0,0 +1,47 @@ +/* PR inline-asm/20314 */ +/* { dg-do compile { target { x86_64-*-* && lp64 } } } */ +/* { dg-do compile { target ia64-*-* powerpc*-*-* } } */ + +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)); +} |