The details of the ASM constraint strings are needed for their validation but also for the proper evaluation of the operands. So, parse these strings and store the significant properties in struct asm_operand where they can be used for the next steps. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@xxxxxxxxx> --- evaluate.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++-- expression.h | 6 +++++ 2 files changed, 80 insertions(+), 2 deletions(-) diff --git a/evaluate.c b/evaluate.c index 7cc695c7e..4c5c2c255 100644 --- a/evaluate.c +++ b/evaluate.c @@ -3493,6 +3493,74 @@ static void evaluate_iterator(struct statement *stmt) evaluate_statement(stmt->iterator_post_statement); } + +static void parse_asm_constraint(struct asm_operand *op) +{ + struct expression *constraint = op->constraint; + const char *str = constraint->string->data; + int c; + + switch (str[0]) { + case '+': + op->is_modify = true; + /* fall-through */ + case '=': + op->is_assign = true; + str++; + break; + } + + while ((c = *str++)) { + switch (c) { + case '=': + case '+': + sparse_error(constraint->pos, "invalid ASM constraint '%c'", c); + break; + + case '&': + op->is_earlyclobber = true; + break; + case '%': + op->is_commutative = true; + break; + case 'r': + op->is_register = true; + break; + + case 'm': + case 'o': + case 'V': + case 'Q': + op->is_memory = true; + break; + + case '<': + case '>': + // FIXME: ignored for now + break; + + case ',': + // FIXME: multiple alternative constraints + break; + + case '0' ... '9': + // FIXME: numeric matching constraint? + break; + case '[': + // FIXME: symbolic matching constraint + return; + + default: + // FIXME: arch-specific (and multi-letter) constraints + break; + } + } + + // FIXME: how to deal with multi-constraint? + if (op->is_register) + op->is_memory = 0; +} + static void verify_output_constraint(struct expression *expr, const char *constraint) { switch (*constraint) { @@ -3528,8 +3596,10 @@ static void evaluate_asm_statement(struct statement *stmt) /* Constraint */ expr = op->constraint; - if (expr) + if (expr) { + parse_asm_constraint(op); verify_output_constraint(expr, expr->string->data); + } /* Expression */ expr = op->expr; @@ -3545,8 +3615,10 @@ static void evaluate_asm_statement(struct statement *stmt) /* Constraint */ expr = op->constraint; - if (expr) + if (expr) { + parse_asm_constraint(op); verify_input_constraint(expr, expr->string->data); + } /* Expression */ if (!evaluate_expression(op->expr)) diff --git a/expression.h b/expression.h index a06bfe130..3b79e0f11 100644 --- a/expression.h +++ b/expression.h @@ -139,6 +139,12 @@ struct asm_operand { struct ident *name; struct expression *constraint; struct expression *expr; + unsigned int is_assign:1; + unsigned int is_modify:1; + unsigned int is_earlyclobber:1; + unsigned int is_commutative:1; + unsigned int is_register:1; + unsigned int is_memory:1; }; struct expression { -- 2.23.0