diff --git a/tools/qfcc/include/statements.h b/tools/qfcc/include/statements.h index 26904db3d..8ee8a16f4 100644 --- a/tools/qfcc/include/statements.h +++ b/tools/qfcc/include/statements.h @@ -73,17 +73,20 @@ typedef struct operand_s { 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)). + assignment (write to dereference pointer), move (special case of + assignment), 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_move, ///< memcpy (c, a, b); c and a are direct def references + st_ptrmove, ///< memcpy (c, a, b); c and a are pointers + st_memset, ///< memset (c, a, b); c is direct def reference + st_ptrmemset, ///< memset (c, a, b); c is pointer 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 diff --git a/tools/qfcc/source/dags.c b/tools/qfcc/source/dags.c index f1e1edde7..e594ca2ae 100644 --- a/tools/qfcc/source/dags.c +++ b/tools/qfcc/source/dags.c @@ -49,8 +49,10 @@ #include "dags.h" #include "diagnostic.h" +#include "dot.h" #include "flow.h" #include "function.h" +#include "options.h" #include "qfcc.h" #include "statements.h" #include "strpool.h" @@ -133,6 +135,11 @@ daglabel_string (daglabel_t *label) // operand_string might use quote_string, which returns a pointer to // a static variable. dstring_copystr (str, operand_string (label->op)); +#if 0 + if (label->op->type) { + dstring_appendstr (str, label->op->type->encoding); + } +#endif return quote_string (str->str); } @@ -730,10 +737,13 @@ dag_create (flownode_t *flownode) int i; dag_make_children (dag, s, operands, children); - if (s->type == st_flow || s->type == st_func) - for (i = 0; i < 3; i++) - if (children[i]) + if (s->type == st_flow || s->type == st_func) { + for (i = 0; i < 3; i++) { + if (children[i]) { dag_make_var_live (live_vars, operands[i + 1]); + } + } + } op = opcode_label (dag, s->opcode, s->expr); n = children[0]; if (s->type != st_assign @@ -759,7 +769,12 @@ dag_create (flownode_t *flownode) labels = malloc (dag->num_labels * sizeof (daglabel_t *)); memcpy (labels, dag->labels, dag->num_labels * sizeof (daglabel_t *)); dag->labels = labels; - +#if 0 + if (options.block_dot.dags) { + flownode->dag = dag; + dump_dot ("raw-dags", flownode->graph, dump_dot_flow_dags); + } +#endif dag_remove_dead_vars (dag, live_vars); dag_sort_nodes (dag); set_delete (live_vars); @@ -972,6 +987,9 @@ dag_gencode (dag_t *dag, sblock_t *block, dagnode_t *dagnode) dst = operands[0]; break; case st_move: + case st_ptrmove: + case st_memset: + case st_ptrmemset: if (!strcmp (dagnode->label->opcode, "")) { dst = generate_moves (dag, block, dagnode); break; diff --git a/tools/qfcc/source/flow.c b/tools/qfcc/source/flow.c index adf417989..ac554d0a2 100644 --- a/tools/qfcc/source/flow.c +++ b/tools/qfcc/source/flow.c @@ -1116,6 +1116,9 @@ flow_analyze_statement (statement_t *s, set_t *use, set_t *def, set_t *kill, break; case st_ptrassign: case st_move: + case st_ptrmove: + case st_memset: + case st_ptrmemset: flow_add_op_var (use, s->opa, 1); flow_add_op_var (use, s->opb, 1); if (!strcmp (s->opcode, "") diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index ac5d6d6f0..78173ac0b 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -758,7 +758,7 @@ expr_assign_copy (sblock_t *sblock, expr_t *e, operand_t **op, operand_t *src) const char **opcode_set = opcode_sets[0]; const char *opcode; int need_ptr = 0; - //operand_t *dummy; + st_type_t type = st_move; if ((src && src->op_type == op_nil) || src_expr->type == ex_nil) { // switch to memset because nil is type agnostic 0 and structures @@ -769,6 +769,7 @@ expr_assign_copy (sblock_t *sblock, expr_t *e, operand_t **op, operand_t *src) if (op) { *op = nil_operand (dst_type, src_expr); } + type = st_memset; if (is_indirect (dst_expr)) { goto dereference_dst; } @@ -815,9 +816,10 @@ dereference_dst: opcode = opcode_set[0]; } else { opcode = opcode_set[1]; + type++; // from st_move/st_memset to st_ptrmove/st_ptrmemset } - s = new_statement (st_move, opcode, e); + s = new_statement (type, opcode, e); s->opa = src; s->opb = size; s->opc = dst; @@ -932,7 +934,8 @@ 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 (st_move, convert_op (e->e.expr.op), e); + s = new_statement (e->e.expr.op == 'm' ? st_move : st_ptrmove, + convert_op (e->e.expr.op), e); s->opa = src; s->opb = size; s->opc = dst; @@ -1068,7 +1071,7 @@ expr_deref (sblock_t *sblock, expr_t *deref, operand_t **op) dst_addr = operand_address (*op, e); - s = new_statement (st_move, "", deref); + s = new_statement (st_ptrmove, "", deref); s->opa = src_addr; //FIXME large types s->opb = short_operand (type_size (type), e);