diff options
author | Luc Van Oostenryck <luc.vanoostenryck@gmail.com> | 2019-01-18 03:32:38 +0100 |
---|---|---|
committer | Luc Van Oostenryck <luc.vanoostenryck@gmail.com> | 2019-09-27 02:17:34 +0200 |
commit | 46471e07907092f13f389869f617078285f61ae0 (patch) | |
tree | 6b4ced97f48fe0f0e74b0325fc2154eb2e03760c | |
parent | 92116940a9b101f818f6dc12e3a5cd5fa77da325 (diff) | |
download | sparse-46471e07907092f13f389869f617078285f61ae0.tar.gz |
asm: parse constraints
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@gmail.com>
-rw-r--r-- | evaluate.c | 76 | ||||
-rw-r--r-- | expression.h | 6 |
2 files changed, 80 insertions, 2 deletions
@@ -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 a06bfe13..3b79e0f1 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 { |