- /* find and count input and output constraints */
- asm_constraint_t *constraint = statement->inputs;
- for( ; constraint != NULL; constraint = constraint->next) {
- int modifiers = 0;
- bool supports_memop = false;
- for(const char *c = constraint->constraints; *c != 0; ++c) {
- /* TODO: improve error messages */
- switch(*c) {
- case '?':
- case '!':
- panic("multiple alternative assembler constraints not "
- "supported");
- case 'm':
- case 'o':
- case 'V':
- case '<':
- case '>':
- case 'X':
- supports_memop = true;
- obstack_1grow(&asm_obst, *c);
- break;
- case '=':
- if(modifiers & ASM_MODIFIER_READ_WRITE)
- panic("inconsistent register constraints");
- modifiers |= ASM_MODIFIER_WRITE_ONLY;
- break;
- case '+':
- if(modifiers & ASM_MODIFIER_WRITE_ONLY)
- panic("inconsistent register constraints");
- modifiers |= ASM_MODIFIER_READ_WRITE;
- break;
- case '&':
- modifiers |= ASM_MODIFIER_EARLYCLOBBER;
- panic("early clobber assembler constraint not supported yet");
- break;
- case '%':
- modifiers |= ASM_MODIFIER_COMMUTATIVE;
- panic("commutative assembler constraint not supported yet");
- break;
- case '#':
- /* skip register preferences stuff... */
- while(*c != 0 && *c != ',')
- ++c;
- break;
- case '*':
- /* skip register preferences stuff... */
- ++c;
- break;
- default:
- obstack_1grow(&asm_obst, *c);
- break;
+ size_t n_inputs = 0;
+ asm_argument_t *argument = statement->inputs;
+ for ( ; argument != NULL; argument = argument->next)
+ n_inputs++;
+ size_t n_outputs = 0;
+ argument = statement->outputs;
+ for ( ; argument != NULL; argument = argument->next)
+ n_outputs++;
+
+ unsigned next_pos = 0;
+
+ ir_node *ins[n_inputs + n_outputs + 1];
+ size_t in_size = 0;
+
+ ir_asm_constraint *tmp_in_constraints
+ = xmalloc(n_outputs * sizeof(tmp_in_constraints[0]));
+
+ const expression_t *out_exprs[n_outputs];
+ ir_node *out_addrs[n_outputs];
+ size_t out_size = 0;
+
+ argument = statement->outputs;
+ for ( ; argument != NULL; argument = argument->next) {
+ const char *constraints = argument->constraints.begin;
+ asm_constraint_flags_t asm_flags
+ = be_parse_asm_constraints(constraints);
+
+ if (asm_flags & ASM_CONSTRAINT_FLAG_NO_SUPPORT) {
+ errorf(&statement->base.source_position,
+ "some constraints in '%s' are not supported", constraints);
+ continue;
+ }
+ if (asm_flags & ASM_CONSTRAINT_FLAG_INVALID) {
+ errorf(&statement->base.source_position,
+ "some constraints in '%s' are invalid", constraints);
+ continue;
+ }
+ if (! (asm_flags & ASM_CONSTRAINT_FLAG_MODIFIER_WRITE)) {
+ errorf(&statement->base.source_position,
+ "no write flag specified for output constraints '%s'",
+ constraints);
+ continue;
+ }
+
+ unsigned pos = next_pos++;
+ if ( (asm_flags & ASM_CONSTRAINT_FLAG_SUPPORTS_IMMEDIATE)
+ || (asm_flags & ASM_CONSTRAINT_FLAG_SUPPORTS_REGISTER) ) {
+ expression_t *expr = argument->expression;
+ ir_node *addr = expression_to_addr(expr);
+ /* in+output, construct an artifical same_as constraint on the
+ * input */
+ if (asm_flags & ASM_CONSTRAINT_FLAG_MODIFIER_READ) {
+ char buf[64];
+ ir_node *value = get_value_from_lvalue(expr, addr);
+
+ snprintf(buf, sizeof(buf), "%d", pos);
+
+ ir_asm_constraint constraint;
+ constraint.pos = pos;
+ constraint.constraint = new_id_from_str(buf);
+ constraint.mode = get_ir_mode(expr->base.type);
+ tmp_in_constraints[in_size] = constraint;
+ ins[in_size] = value;
+
+ ++in_size;