From 001e1ac05959fb651514b02e5e8afdd44665d82c Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Fri, 16 Nov 2012 16:16:06 +0900 Subject: [PATCH] Classify statements into broad types. The types are expression, assignment, pointer assignment (ie, write to a dereferenced pointer), move (special case of pointer assignment), state, function call/return, and flow control. With this classification, it will be easier (less code:) to determine which operands are inputs and which are outputs. --- tools/qfcc/include/statements.h | 24 +++++++++++++++++- tools/qfcc/source/dags.c | 2 +- tools/qfcc/source/statements.c | 44 ++++++++++++++++++--------------- 3 files changed, 48 insertions(+), 22 deletions(-) diff --git a/tools/qfcc/include/statements.h b/tools/qfcc/include/statements.h index 749b22f28..a8d8e7a62 100644 --- a/tools/qfcc/include/statements.h +++ b/tools/qfcc/include/statements.h @@ -61,8 +61,29 @@ typedef struct operand_s { } o; } operand_t; +/** Overall type of statement. + + Statement types are broken down into expressions (binary and unary, + includes address and pointer dereferencing (read)), assignment, pointer + assignment (write to dereference pointer), move (special case of pointer + assignment), state, function related (call, rcall, return and done), and + flow control (conditional branches, goto, jump (single pointer and jump + table)). +*/ +typedef enum { + st_none, ///< not a (valid) statement. Used in dags. + st_expr, ///< c = a op b; or c = op a; + st_assign, ///< b = a + st_ptrassign, ///< *b = a; or *(b + c) = a; + st_move, ///< memcpy (c, a, b); + st_state, ///< state (a, b); or state (a, b, c) + st_func, ///< call, rcall or return/done + st_flow, ///< if/ifa/ifae/ifb/ifbe/ifnot or goto or jump/jumpb +} st_type_t; + typedef struct statement_s { struct statement_s *next; + st_type_t type; const char *opcode; operand_t *opa; operand_t *opb; @@ -88,7 +109,8 @@ struct type_s; operand_t *alias_operand (operand_t *op, etype_t type); operand_t *temp_operand (struct type_s *type); sblock_t *new_sblock (void); -statement_t *new_statement (const char *opcode, struct expr_s *expr); +statement_t *new_statement (st_type_t type, const char *opcode, + struct expr_s *expr); int find_operands (statement_t *s, operand_t **x, operand_t **y, operand_t **z, operand_t **w); void sblock_add_statement (sblock_t *sblock, statement_t *statement); diff --git a/tools/qfcc/source/dags.c b/tools/qfcc/source/dags.c index e828f106d..253385345 100644 --- a/tools/qfcc/source/dags.c +++ b/tools/qfcc/source/dags.c @@ -267,7 +267,7 @@ build_statement (const char *opcode, operand_t *a, operand_t *b, operand_t *c, { if ((!a && (b || c)) || (a && !b && c)) internal_error (0, "invalid operand combo"); - statement_t *st = new_statement (opcode, expr); + statement_t *st = new_statement (st_none, opcode, expr);//FIXME st->opa = a; st->opb = b; st->opc = c; diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 8e3e9e94c..8b10f6349 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -284,10 +284,11 @@ sblock_add_statement (sblock_t *sblock, statement_t *statement) } statement_t * -new_statement (const char *opcode, expr_t *expr) +new_statement (st_type_t type, const char *opcode, expr_t *expr) { statement_t *statement; ALLOC (256, statement_t, statements, statement); + statement->type = type; statement->opcode = save_string (opcode); statement->expr = expr; return statement; @@ -463,17 +464,17 @@ statement_branch (sblock_t *sblock, expr_t *e) const char *opcode; if (e->type == ex_uexpr && e->e.expr.op == 'g') { - s = new_statement ("", e); + s = new_statement (st_flow, "", e); s->opa = new_operand (op_label); s->opa->o.label = &e->e.expr.e1->e.label; } else { if (e->e.expr.op == 'g') { - s = new_statement ("", e); + s = new_statement (st_flow, "", e); sblock = statement_subexpr (sblock, e->e.expr.e1, &s->opa); sblock = statement_subexpr (sblock, e->e.expr.e2, &s->opb); } else { opcode = convert_op (e->e.expr.op); - s = new_statement (opcode, e); + s = new_statement (st_flow, opcode, e); sblock = statement_subexpr (sblock, e->e.expr.e1, &s->opa); s->opb = new_operand (op_label); s->opb->o.label = &e->e.expr.e2->e.label; @@ -495,6 +496,7 @@ expr_assign (sblock_t *sblock, expr_t *e, operand_t **op) operand_t *dst = 0; operand_t *ofs = 0; const char *opcode = convert_op (e->e.expr.op); + st_type_t type; if (e->e.expr.op == '=') { sblock = statement_subexpr (sblock, dst_expr, &dst); @@ -505,6 +507,7 @@ expr_assign (sblock_t *sblock, expr_t *e, operand_t **op) *op = dst; if (src == dst) return sblock; + type = st_assign; } else { //FIXME this sucks. find a better way to handle both pointer //dereferences and pointer assignements @@ -525,8 +528,9 @@ expr_assign (sblock_t *sblock, expr_t *e, operand_t **op) } if (op) *op = src; + type = st_ptrassign; } - s = new_statement (opcode, e); + s = new_statement (type, opcode, e); s->opa = src; s->opb = dst; s->opc = ofs; @@ -553,7 +557,7 @@ expr_move (sblock_t *sblock, expr_t *e, operand_t **op) dst = *op; sblock = statement_subexpr (sblock, src_expr, &src); sblock = statement_subexpr (sblock, size_expr, &size); - s = new_statement (convert_op (e->e.expr.op), e); + s = new_statement (st_move, convert_op (e->e.expr.op), e); s->opa = src; s->opb = size; s->opc = dst; @@ -632,7 +636,7 @@ expr_call (sblock_t *sblock, expr_t *call, operand_t **op) arg = p; sblock = statement_subexpr (sblock, a, &arg); if (arg != p) { - s = new_statement ("=", a); + s = new_statement (st_assign, "=", a); s->opa = arg; s->opb = p; sblock_add_statement (sblock, s); @@ -641,7 +645,7 @@ expr_call (sblock_t *sblock, expr_t *call, operand_t **op) } } opcode = va ("<%sCALL%d>", pref, count); - s = new_statement (opcode, call); + s = new_statement (st_func, opcode, call); sblock = statement_subexpr (sblock, func, &s->opa); s->opb = arguments[0]; s->opc = arguments[1]; @@ -663,7 +667,7 @@ expr_address (sblock_t *sblock, expr_t *e, operand_t **op) static statement_t * lea_statement (operand_t *pointer, operand_t *offset, expr_t *e) { - statement_t *s = new_statement ("&", e); + statement_t *s = new_statement (st_expr, "&", e); s->opa = pointer; s->opb = offset; s->opc = temp_operand (&type_pointer); @@ -673,7 +677,7 @@ lea_statement (operand_t *pointer, operand_t *offset, expr_t *e) static statement_t * address_statement (operand_t *value, expr_t *e) { - statement_t *s = new_statement ("&", e); + statement_t *s = new_statement (st_expr, "&", e); s->opa = value; s->opc = temp_operand (&type_pointer); return s; @@ -712,13 +716,13 @@ expr_deref (sblock_t *sblock, expr_t *deref, operand_t **op) dst_addr = s->opc; sblock_add_statement (sblock, s); - s = new_statement ("", deref); + s = new_statement (st_move, "", deref); s->opa = src_addr; s->opb = short_operand (type_size (type)); s->opc = dst_addr; sblock_add_statement (sblock, s); } else { - s = new_statement (".", deref); + s = new_statement (st_expr, ".", deref); s->opa = ptr; s->opb = offs; s->opc = *op; @@ -735,7 +739,7 @@ expr_deref (sblock_t *sblock, expr_t *deref, operand_t **op) sblock = statement_subexpr (sblock, e, &ptr); if (!*op) *op = temp_operand (type); - s = new_statement (".", deref); + s = new_statement (st_expr, ".", deref); s->opa = ptr; s->opb = short_operand (0); s->opc = *op; @@ -776,7 +780,7 @@ expr_expr (sblock_t *sblock, expr_t *e, operand_t **op) opcode = convert_op (e->e.expr.op); if (!opcode) internal_error (e, "ice ice baby"); - s = new_statement (opcode, e); + s = new_statement (st_expr, opcode, e); sblock = statement_subexpr (sblock, e->e.expr.e1, &s->opa); sblock = statement_subexpr (sblock, e->e.expr.e2, &s->opb); if (!*op) @@ -816,7 +820,7 @@ expr_cast (sblock_t *sblock, expr_t *e, operand_t **op) operand_t *src = 0; sblock = statement_subexpr (sblock, e->e.expr.e1, &src); *op = temp_operand (e->e.expr.type); - s = new_statement ("", e); + s = new_statement (st_expr, "", e); s->opa = src; s->opc = *op; sblock_add_statement (sblock, s); @@ -869,7 +873,7 @@ expr_uexpr (sblock_t *sblock, expr_t *e, operand_t **op) opcode = convert_op (e->e.expr.op); if (!opcode) internal_error (e, "ice ice baby"); - s = new_statement (opcode, e); + s = new_statement (st_expr, opcode, e); sblock = statement_subexpr (sblock, e->e.expr.e1, &s->opa); if (!*op) *op = temp_operand (e->e.expr.type); @@ -948,7 +952,7 @@ statement_state (sblock_t *sblock, expr_t *e) { statement_t *s; - s = new_statement ("", e); + s = new_statement (st_state, "", e); sblock = statement_subexpr (sblock, e->e.state.frame, &s->opa); sblock = statement_subexpr (sblock, e->e.state.think, &s->opb); sblock = statement_subexpr (sblock, e->e.state.step, &s->opc); @@ -1157,7 +1161,7 @@ statement_uexpr (sblock_t *sblock, expr_t *e) e->e.expr.e1 = new_float_expr (0); } } - s = new_statement (opcode, e); + s = new_statement (st_func, opcode, e); if (e->e.expr.e1) sblock = statement_subexpr (sblock, e->e.expr.e1, &s->opa); sblock_add_statement (sblock, s); @@ -1295,7 +1299,7 @@ join_blocks (sblock_t *sblock, sblock_t *dest) label->e.label.next = dest->next->labels; label->e.label.used++; dest->next->labels = &label->e.label; - g = new_statement ("", 0); + g = new_statement (st_flow, "", 0); g->opa = new_operand (op_label); g->opa->o.label = &label->e.label; sblock_add_statement (dest, g); @@ -1445,7 +1449,7 @@ check_final_block (sblock_t *sblock) return_operand->type = ev_void; return_operand->o.symbol = return_symbol; } - s = new_statement (return_opcode, 0); + s = new_statement (st_func, return_opcode, 0); s->opa = return_operand; sblock_add_statement (sblock, s); }