aboutsummaryrefslogtreecommitdiff
path: root/gcc/gimplify.c
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2005-03-10 01:12:31 +0100
committerJakub Jelinek <jakub@gcc.gnu.org>2005-03-10 01:12:31 +0100
commit372d72d91786ff51a529aa3e914387c5a983acce (patch)
tree0f56e51681b1d311672d24291622c75a76181353 /gcc/gimplify.c
parentd5fc240649a04222d1b363d06b9cd749a7e260f1 (diff)
downloadgcc-372d72d91786ff51a529aa3e914387c5a983acce.zip
gcc-372d72d91786ff51a529aa3e914387c5a983acce.tar.gz
gcc-372d72d91786ff51a529aa3e914387c5a983acce.tar.bz2
re PR inline-asm/20314 (Bogus differ in number of alternatives error)
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. From-SVN: r96222
Diffstat (limited to 'gcc/gimplify.c')
-rw-r--r--gcc/gimplify.c69
1 files changed, 67 insertions, 2 deletions
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, &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);