diff options
author | jakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4> | 2005-03-10 00:12:31 +0000 |
---|---|---|
committer | jakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4> | 2005-03-10 00:12:31 +0000 |
commit | d72a7307684992dd4af3f7d33f42b9a02ce1195b (patch) | |
tree | 0f56e51681b1d311672d24291622c75a76181353 /gcc/gimplify.c | |
parent | d94c522b4868377e43c124e79993103c8bc0a641 (diff) | |
download | gcc-d72a7307684992dd4af3f7d33f42b9a02ce1195b.tar.gz |
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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@96222 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/gimplify.c')
-rw-r--r-- | gcc/gimplify.c | 69 |
1 files changed, 67 insertions, 2 deletions
diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 93724a9e403..341ca7baa3f 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); |