summaryrefslogtreecommitdiff
path: root/gcc/gimplify.c
diff options
context:
space:
mode:
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2005-03-10 00:12:31 +0000
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2005-03-10 00:12:31 +0000
commitd72a7307684992dd4af3f7d33f42b9a02ce1195b (patch)
tree0f56e51681b1d311672d24291622c75a76181353 /gcc/gimplify.c
parentd94c522b4868377e43c124e79993103c8bc0a641 (diff)
downloadgcc-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.c69
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, &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);