aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
authorLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2017-07-14 20:40:13 +0200
committerLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2017-09-17 09:47:14 +0200
commit6756731e9d22c831bc7ec2e96b1942d13d54ab84 (patch)
treedf04a88de4c31a6cfbcda3e803b447c57fd23b71
parent90859bb4e3f9ad11f76ad42e3dce84043bdc3176 (diff)
downloadsparse-dev-6756731e9d22c831bc7ec2e96b1942d13d54ab84.tar.gz
use a specific struct for asm operands
ASM operands have the following syntax: [<ident>] "<constraint>" '(' <expr> ')' For some reasons, during parsing this is stored as a sequence of 3 expressions. This has some serious disadvantages though: - <ident> has not the type of an expression - it complicates processing when compared to having a specific struct for it (need to loop & maintain some state). - <ident> is optional and stored as a null pointer when not present which is annoying, for example, if null pointers are used internally in ptr-lists to mark removed pointers. Fix this by using a specific structure to store the 3 elements of ASM operands. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
-rw-r--r--evaluate.c82
-rw-r--r--expand.c3
-rw-r--r--expression.h7
-rw-r--r--inline.c19
-rw-r--r--linearize.c42
-rw-r--r--parse.c14
-rw-r--r--show-parse.c3
7 files changed, 63 insertions, 107 deletions
diff --git a/evaluate.c b/evaluate.c
index 649e132b..2ae5432f 100644
--- a/evaluate.c
+++ b/evaluate.c
@@ -3160,6 +3160,9 @@ struct symbol *evaluate_expression(struct expression *expr)
case EXPR_SLICE:
expression_error(expr, "internal front-end error: SLICE re-evaluated");
return NULL;
+ case EXPR_ASM_OPERAND:
+ expression_error(expr, "internal front-end error: ASM_OPERAND evaluated");
+ return NULL;
}
return NULL;
}
@@ -3322,8 +3325,8 @@ static void verify_input_constraint(struct expression *expr, const char *constra
static void evaluate_asm_statement(struct statement *stmt)
{
struct expression *expr;
+ struct expression *op;
struct symbol *sym;
- int state;
expr = stmt->asm_string;
if (!expr || expr->type != EXPR_STRING) {
@@ -3331,58 +3334,41 @@ static void evaluate_asm_statement(struct statement *stmt)
return;
}
- state = 0;
- FOR_EACH_PTR(stmt->asm_outputs, expr) {
- switch (state) {
- case 0: /* Identifier */
- state = 1;
- continue;
+ FOR_EACH_PTR(stmt->asm_outputs, op) {
+ /* Identifier */
- case 1: /* Constraint */
- state = 2;
- if (!expr || expr->type != EXPR_STRING) {
- sparse_error(expr ? expr->pos : stmt->pos, "asm output constraint is not a string");
- *THIS_ADDRESS(expr) = NULL;
- continue;
- }
+ /* Constraint */
+ expr = op->constraint;
+ if (!expr || expr->type != EXPR_STRING) {
+ sparse_error(expr ? expr->pos : stmt->pos, "asm output constraint is not a string");
+ op->constraint = NULL;
+ } else
verify_output_constraint(expr, expr->string->data);
- continue;
- case 2: /* Expression */
- state = 0;
- if (!evaluate_expression(expr))
- return;
- if (!lvalue_expression(expr))
- warning(expr->pos, "asm output is not an lvalue");
- evaluate_assign_to(expr, expr->ctype);
- continue;
- }
- } END_FOR_EACH_PTR(expr);
-
- state = 0;
- FOR_EACH_PTR(stmt->asm_inputs, expr) {
- switch (state) {
- case 0: /* Identifier */
- state = 1;
- continue;
-
- case 1: /* Constraint */
- state = 2;
- if (!expr || expr->type != EXPR_STRING) {
- sparse_error(expr ? expr->pos : stmt->pos, "asm input constraint is not a string");
- *THIS_ADDRESS(expr) = NULL;
- continue;
- }
+ /* Expression */
+ expr = op->expr;
+ if (!evaluate_expression(expr))
+ return;
+ if (!lvalue_expression(expr))
+ warning(expr->pos, "asm output is not an lvalue");
+ evaluate_assign_to(expr, expr->ctype);
+ } END_FOR_EACH_PTR(op);
+
+ FOR_EACH_PTR(stmt->asm_inputs, op) {
+ /* Identifier */
+
+ /* Constraint */
+ expr = op->constraint;
+ if (!expr || expr->type != EXPR_STRING) {
+ sparse_error(expr ? expr->pos : stmt->pos, "asm input constraint is not a string");
+ op->constraint = NULL;
+ } else
verify_input_constraint(expr, expr->string->data);
- continue;
- case 2: /* Expression */
- state = 0;
- if (!evaluate_expression(expr))
- return;
- continue;
- }
- } END_FOR_EACH_PTR(expr);
+ /* Expression */
+ if (!evaluate_expression(op->expr))
+ return;
+ } END_FOR_EACH_PTR(op);
FOR_EACH_PTR(stmt->asm_clobbers, expr) {
if (!expr) {
diff --git a/expand.c b/expand.c
index f436b5b5..3c6726aa 100644
--- a/expand.c
+++ b/expand.c
@@ -1048,6 +1048,9 @@ static int expand_expression(struct expression *expr)
case EXPR_OFFSETOF:
expression_error(expr, "internal front-end error: sizeof in expansion?");
return UNSAFE;
+ case EXPR_ASM_OPERAND:
+ expression_error(expr, "internal front-end error: ASM_OPERAND in expansion?");
+ return UNSAFE;
}
return SIDE_EFFECTS;
}
diff --git a/expression.h b/expression.h
index d0f3ac92..b7095640 100644
--- a/expression.h
+++ b/expression.h
@@ -64,6 +64,7 @@ enum expression_type {
EXPR_FVALUE,
EXPR_SLICE,
EXPR_OFFSETOF,
+ EXPR_ASM_OPERAND,
};
enum {
@@ -173,6 +174,12 @@ struct expression {
struct expression *index;
};
};
+ // EXPR_ASM_OPERAND
+ struct {
+ struct ident *name;
+ struct expression *constraint;
+ struct expression *expr;
+ };
};
};
diff --git a/inline.c b/inline.c
index a3002c6b..012fb379 100644
--- a/inline.c
+++ b/inline.c
@@ -271,6 +271,12 @@ static struct expression * copy_expression(struct expression *expr)
}
break;
}
+ case EXPR_ASM_OPERAND: {
+ expr = dup_expression(expr);
+ expr->constraint = copy_expression(expr->constraint);
+ expr->expr = copy_expression(expr->expr);
+ break;
+ }
default:
warning(expr->pos, "trying to copy expression type %d", expr->type);
}
@@ -281,20 +287,9 @@ static struct expression_list *copy_asm_constraints(struct expression_list *in)
{
struct expression_list *out = NULL;
struct expression *expr;
- int state = 0;
FOR_EACH_PTR(in, expr) {
- switch (state) {
- case 0: /* identifier */
- case 1: /* constraint */
- state++;
- add_expression(&out, expr);
- continue;
- case 2: /* expression */
- state = 0;
- add_expression(&out, copy_expression(expr));
- continue;
- }
+ add_expression(&out, copy_expression(expr));
} END_FOR_EACH_PTR(expr);
return out;
}
diff --git a/linearize.c b/linearize.c
index ba76397e..905b473e 100644
--- a/linearize.c
+++ b/linearize.c
@@ -1805,12 +1805,10 @@ static void add_asm_output(struct entrypoint *ep, struct instruction *insn, stru
static pseudo_t linearize_asm_statement(struct entrypoint *ep, struct statement *stmt)
{
- int state;
struct expression *expr;
struct instruction *insn;
struct asm_rules *rules;
const char *constraint;
- struct ident *ident;
insn = alloc_instruction(OP_ASM, 0);
expr = stmt->asm_string;
@@ -1824,49 +1822,17 @@ static pseudo_t linearize_asm_statement(struct entrypoint *ep, struct statement
insn->asm_rules = rules;
/* Gather the inputs.. */
- state = 0;
- ident = NULL;
- constraint = NULL;
FOR_EACH_PTR(stmt->asm_inputs, expr) {
- switch (state) {
- case 0: /* Identifier */
- state = 1;
- ident = (struct ident *)expr;
- continue;
-
- case 1: /* Constraint */
- state = 2;
- constraint = expr ? expr->string->data : "";
- continue;
-
- case 2: /* Expression */
- state = 0;
- add_asm_input(ep, insn, expr, constraint, ident);
- }
+ constraint = expr->constraint ? expr->constraint->string->data : "";
+ add_asm_input(ep, insn, expr->expr, constraint, expr->name);
} END_FOR_EACH_PTR(expr);
add_one_insn(ep, insn);
/* Assign the outputs */
- state = 0;
- ident = NULL;
- constraint = NULL;
FOR_EACH_PTR(stmt->asm_outputs, expr) {
- switch (state) {
- case 0: /* Identifier */
- state = 1;
- ident = (struct ident *)expr;
- continue;
-
- case 1: /* Constraint */
- state = 2;
- constraint = expr ? expr->string->data : "";
- continue;
-
- case 2:
- state = 0;
- add_asm_output(ep, insn, expr, constraint, ident);
- }
+ constraint = expr->constraint ? expr->constraint->string->data : "";
+ add_asm_output(ep, insn, expr->expr, constraint, expr->name);
} END_FOR_EACH_PTR(expr);
return VOID;
diff --git a/parse.c b/parse.c
index 02a55a74..8407eb85 100644
--- a/parse.c
+++ b/parse.c
@@ -1929,24 +1929,20 @@ static struct token *expression_statement(struct token *token, struct expression
static struct token *parse_asm_operands(struct token *token, struct statement *stmt,
struct expression_list **inout)
{
- struct expression *expr;
-
/* Allow empty operands */
if (match_op(token->next, ':') || match_op(token->next, ')'))
return token->next;
do {
- struct ident *ident = NULL;
+ struct expression *op = alloc_expression(token->pos, EXPR_ASM_OPERAND);
if (match_op(token->next, '[') &&
token_type(token->next->next) == TOKEN_IDENT &&
match_op(token->next->next->next, ']')) {
- ident = token->next->next->ident;
+ op->name = token->next->next->ident;
token = token->next->next->next;
}
- add_expression(inout, (struct expression *)ident); /* UGGLEE!!! */
- token = primary_expression(token->next, &expr);
- add_expression(inout, expr);
- token = parens_expression(token, &expr, "in asm parameter");
- add_expression(inout, expr);
+ token = primary_expression(token->next, &op->constraint);
+ token = parens_expression(token, &op->expr, "in asm parameter");
+ add_expression(inout, op);
} while (match_op(token, ','));
return token;
}
diff --git a/show-parse.c b/show-parse.c
index d365d737..f97619e6 100644
--- a/show-parse.c
+++ b/show-parse.c
@@ -1169,6 +1169,9 @@ int show_expression(struct expression *expr)
case EXPR_TYPE:
warning(expr->pos, "unable to show type expression");
return 0;
+ case EXPR_ASM_OPERAND:
+ warning(expr->pos, "unable to show asm operand expression");
+ return 0;
}
return 0;
}