diff mbox series

[12/18] asm: parse constraints

Message ID 20190927234322.5157-15-luc.vanoostenryck@gmail.com (mailing list archive)
State Mainlined, archived
Headers show
Series add missing expansion of ASM operands | expand

Commit Message

Luc Van Oostenryck Sept. 27, 2019, 11:43 p.m. UTC
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>
---
 evaluate.c   | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++--
 expression.h |  6 +++++
 2 files changed, 80 insertions(+), 2 deletions(-)
diff mbox series

Patch

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 {