aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2019-01-18 03:32:38 +0100
committerLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2019-09-27 02:17:34 +0200
commit46471e07907092f13f389869f617078285f61ae0 (patch)
tree6b4ced97f48fe0f0e74b0325fc2154eb2e03760c
parent92116940a9b101f818f6dc12e3a5cd5fa77da325 (diff)
downloadsparse-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.c76
-rw-r--r--expression.h6
2 files changed, 80 insertions, 2 deletions
diff --git a/evaluate.c b/evaluate.c
index 7cc695c7..4c5c2c25 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 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 {