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);