[qfcc] Add expression tracking to operands

Not much uses it yet, but it will make for better diagnostics.
This commit is contained in:
Bill Currie 2020-03-11 12:51:34 +09:00
parent 1cd5ea5732
commit 4a8854d9ed
4 changed files with 52 additions and 46 deletions

View file

@ -57,6 +57,7 @@ typedef struct operand_s {
op_type_e op_type; op_type_e op_type;
struct type_s *type; ///< possibly override def's type struct type_s *type; ///< possibly override def's type
int size; ///< for structures int size; ///< for structures
struct expr_s *expr; ///< expression generating this operand
union { union {
struct def_s *def; struct def_s *def;
struct ex_value_s *value; struct ex_value_s *value;
@ -115,14 +116,16 @@ struct dstring_s;
const char *optype_str (op_type_e type) __attribute__((const)); const char *optype_str (op_type_e type) __attribute__((const));
operand_t *def_operand (struct def_s *def, struct type_s *type); operand_t *def_operand (struct def_s *def, struct type_s *type,
operand_t *return_operand (struct type_s *type); struct expr_s *expr);
operand_t *value_operand (struct ex_value_s *value); operand_t *return_operand (struct type_s *type, struct expr_s *expr);
operand_t *value_operand (struct ex_value_s *value, struct expr_s *expr);
int tempop_overlap (tempop_t *t1, tempop_t *t2) __attribute__((pure)); int tempop_overlap (tempop_t *t1, tempop_t *t2) __attribute__((pure));
operand_t *temp_operand (struct type_s *type); operand_t *temp_operand (struct type_s *type, struct expr_s *expr);
int tempop_visit_all (tempop_t *tempop, int overlap, int tempop_visit_all (tempop_t *tempop, int overlap,
int (*visit) (tempop_t *, void *), void *data); int (*visit) (tempop_t *, void *), void *data);
operand_t *alias_operand (struct type_s *type, operand_t *op); operand_t *alias_operand (struct type_s *type, operand_t *op,
struct expr_s *expr);
void free_operand (operand_t *op); void free_operand (operand_t *op);
sblock_t *new_sblock (void); sblock_t *new_sblock (void);

View file

@ -821,7 +821,7 @@ static operand_t *
fix_op_type (operand_t *op, type_t *type) fix_op_type (operand_t *op, type_t *type)
{ {
if (op && op->op_type != op_label && op->type != type) if (op && op->op_type != op_label && op->type != type)
op = alias_operand (type, op); op = alias_operand (type, op, op->expr);
return op; return op;
} }
@ -882,7 +882,8 @@ generate_moveps (dag_t *dag, sblock_t *block, dagnode_t *dagnode)
offset = dstDef->offset; offset = dstDef->offset;
dstDef = dstDef->alias; dstDef = dstDef->alias;
} }
operands[2] = value_operand (new_pointer_val (offset, type, dstDef)); operands[2] = value_operand (new_pointer_val (offset, type, dstDef),
operands[1]->expr);
st = build_statement ("<MOVEP>", operands, var->expr); st = build_statement ("<MOVEP>", operands, var->expr);
sblock_add_statement (block, st); sblock_add_statement (block, st);
} }
@ -937,7 +938,8 @@ dag_gencode (dag_t *dag, sblock_t *block, dagnode_t *dagnode)
operands[1] = make_operand (dag, block, dagnode, 1); operands[1] = make_operand (dag, block, dagnode, 1);
type = get_type (dagnode->label->expr); type = get_type (dagnode->label->expr);
if (!(var_iter = set_first (dagnode->identifiers))) { if (!(var_iter = set_first (dagnode->identifiers))) {
operands[2] = temp_operand (get_type (dagnode->label->expr)); operands[2] = temp_operand (get_type (dagnode->label->expr),
dagnode->label->expr);
} else { } else {
daglabel_t *var = dag->labels[var_iter->element]; daglabel_t *var = dag->labels[var_iter->element];

View file

@ -1102,7 +1102,7 @@ flow_analyze_statement (statement_t *s, set_t *use, set_t *def, set_t *kill,
def_t *alias; def_t *alias;
ex_pointer_t *ptr = &s->opc->o.value->v.pointer; ex_pointer_t *ptr = &s->opc->o.value->v.pointer;
alias = alias_def (ptr->def, ptr->type, ptr->val); alias = alias_def (ptr->def, ptr->type, ptr->val);
op = def_operand (alias, ptr->type); op = def_operand (alias, ptr->type, s->opc->expr);
flow_add_op_var (def, op, 0); flow_add_op_var (def, op, 0);
if (operands) if (operands)
operands[0] = op; operands[0] = op;

View file

@ -273,11 +273,12 @@ new_statement (st_type_t type, const char *opcode, expr_t *expr)
} }
static operand_t * static operand_t *
new_operand (op_type_e op) new_operand (op_type_e op, expr_t *expr)
{ {
operand_t *operand; operand_t *operand;
ALLOC (256, operand_t, operands, operand); ALLOC (256, operand_t, operands, operand);
operand->op_type = op; operand->op_type = op;
operand->expr = expr;
return operand; return operand;
} }
@ -311,13 +312,13 @@ free_sblock (sblock_t *sblock)
} }
operand_t * operand_t *
def_operand (def_t *def, type_t *type) def_operand (def_t *def, type_t *type, expr_t *expr)
{ {
operand_t *op; operand_t *op;
if (!type) if (!type)
type = def->type; type = def->type;
op = new_operand (op_def); op = new_operand (op_def, expr);
op->type = type; op->type = type;
op->size = type_size (type); op->size = type_size (type);
op->o.def = def; op->o.def = def;
@ -325,28 +326,28 @@ def_operand (def_t *def, type_t *type)
} }
operand_t * operand_t *
return_operand (type_t *type) return_operand (type_t *type, expr_t *expr)
{ {
symbol_t *return_symbol; symbol_t *return_symbol;
return_symbol = make_symbol (".return", &type_param, pr.symtab->space, return_symbol = make_symbol (".return", &type_param, pr.symtab->space,
sc_extern); sc_extern);
return def_operand (return_symbol->s.def, type); return def_operand (return_symbol->s.def, type, expr);
} }
operand_t * operand_t *
value_operand (ex_value_t *value) value_operand (ex_value_t *value, expr_t *expr)
{ {
operand_t *op; operand_t *op;
op = new_operand (op_value); op = new_operand (op_value, expr);
op->type = value->type; op->type = value->type;
op->o.value = value; op->o.value = value;
return op; return op;
} }
operand_t * operand_t *
temp_operand (type_t *type) temp_operand (type_t *type, expr_t *expr)
{ {
operand_t *op = new_operand (op_temp); operand_t *op = new_operand (op_temp, expr);
op->o.tempop.type = type; op->o.tempop.type = type;
op->type = type; op->type = type;
@ -412,7 +413,7 @@ tempop_visit_all (tempop_t *tempop, int overlap,
} }
operand_t * operand_t *
alias_operand (type_t *type, operand_t *op) alias_operand (type_t *type, operand_t *op, expr_t *expr)
{ {
operand_t *aop; operand_t *aop;
@ -420,7 +421,7 @@ alias_operand (type_t *type, operand_t *op)
internal_error (0, "\naliasing operand with type of different size" internal_error (0, "\naliasing operand with type of different size"
" (%d, %d)", type_size (type), type_size (op->type)); " (%d, %d)", type_size (type), type_size (op->type));
} }
aop = new_operand (op_alias); aop = new_operand (op_alias, expr);
aop->o.alias = op; aop->o.alias = op;
aop->type = type; aop->type = type;
aop->size = type_size (type); aop->size = type_size (type);
@ -428,10 +429,10 @@ alias_operand (type_t *type, operand_t *op)
} }
static operand_t * static operand_t *
short_operand (short short_val) short_operand (short short_val, expr_t *expr)
{ {
ex_value_t *val = new_short_val (short_val); ex_value_t *val = new_short_val (short_val);
return value_operand (val); return value_operand (val, expr);
} }
static const char * static const char *
@ -593,7 +594,7 @@ statement_branch (sblock_t *sblock, expr_t *e)
if (e->type == ex_uexpr && e->e.expr.op == 'g') { if (e->type == ex_uexpr && e->e.expr.op == 'g') {
s = new_statement (st_flow, "<GOTO>", e); s = new_statement (st_flow, "<GOTO>", e);
s->opa = new_operand (op_label); s->opa = new_operand (op_label, e);
s->opa->o.label = &e->e.expr.e1->e.label; s->opa->o.label = &e->e.expr.e1->e.label;
} else { } else {
if (e->e.expr.op == 'g') { if (e->e.expr.op == 'g') {
@ -604,7 +605,7 @@ statement_branch (sblock_t *sblock, expr_t *e)
opcode = convert_op (e->e.expr.op); opcode = convert_op (e->e.expr.op);
s = new_statement (st_flow, opcode, e); s = new_statement (st_flow, opcode, e);
sblock = statement_subexpr (sblock, e->e.expr.e1, &s->opa); sblock = statement_subexpr (sblock, e->e.expr.e1, &s->opa);
s->opb = new_operand (op_label); s->opb = new_operand (op_label, e);
s->opb->o.label = &e->e.expr.e2->e.label; s->opb->o.label = &e->e.expr.e2->e.label;
} }
} }
@ -783,7 +784,7 @@ expr_address (sblock_t *sblock, expr_t *e, operand_t **op)
statement_t *s; statement_t *s;
s = new_statement (st_expr, "&", e); s = new_statement (st_expr, "&", e);
sblock = statement_subexpr (sblock, e->e.expr.e1, &s->opa); sblock = statement_subexpr (sblock, e->e.expr.e1, &s->opa);
s->opc = temp_operand (e->e.expr.type); s->opc = temp_operand (e->e.expr.type, e);
sblock_add_statement (sblock, s); sblock_add_statement (sblock, s);
*(op) = s->opc; *(op) = s->opc;
return sblock; return sblock;
@ -795,7 +796,7 @@ lea_statement (operand_t *pointer, operand_t *offset, expr_t *e)
statement_t *s = new_statement (st_expr, "&", e); statement_t *s = new_statement (st_expr, "&", e);
s->opa = pointer; s->opa = pointer;
s->opb = offset; s->opb = offset;
s->opc = temp_operand (&type_pointer); s->opc = temp_operand (&type_pointer, e);
return s; return s;
} }
@ -804,7 +805,7 @@ address_statement (operand_t *value, expr_t *e)
{ {
statement_t *s = new_statement (st_expr, "&", e); statement_t *s = new_statement (st_expr, "&", e);
s->opa = value; s->opa = value;
s->opc = temp_operand (&type_pointer); s->opc = temp_operand (&type_pointer, e);
return s; return s;
} }
@ -819,7 +820,7 @@ expr_deref (sblock_t *sblock, expr_t *deref, operand_t **op)
&& e->e.expr.e1->type == ex_symbol) { && e->e.expr.e1->type == ex_symbol) {
if (e->e.expr.e1->e.symbol->sy_type != sy_var) if (e->e.expr.e1->e.symbol->sy_type != sy_var)
internal_error (e, "address of non-var"); internal_error (e, "address of non-var");
*op = def_operand (e->e.expr.e1->e.symbol->s.def, type); *op = def_operand (e->e.expr.e1->e.symbol->s.def, type, e);
} else if (e->type == ex_expr && e->e.expr.op == '&') { } else if (e->type == ex_expr && e->e.expr.op == '&') {
statement_t *s; statement_t *s;
operand_t *ptr = 0; operand_t *ptr = 0;
@ -827,7 +828,7 @@ expr_deref (sblock_t *sblock, expr_t *deref, operand_t **op)
sblock = statement_subexpr (sblock, e->e.expr.e1, &ptr); sblock = statement_subexpr (sblock, e->e.expr.e1, &ptr);
sblock = statement_subexpr (sblock, e->e.expr.e2, &offs); sblock = statement_subexpr (sblock, e->e.expr.e2, &offs);
if (!*op) if (!*op)
*op = temp_operand (type); *op = temp_operand (type, e);
if (low_level_type (type) == ev_void) { if (low_level_type (type) == ev_void) {
operand_t *src_addr; operand_t *src_addr;
operand_t *dst_addr; operand_t *dst_addr;
@ -843,7 +844,7 @@ expr_deref (sblock_t *sblock, expr_t *deref, operand_t **op)
s = new_statement (st_move, "<MOVEP>", deref); s = new_statement (st_move, "<MOVEP>", deref);
s->opa = src_addr; s->opa = src_addr;
s->opb = short_operand (type_size (type)); s->opb = short_operand (type_size (type), e);
s->opc = dst_addr; s->opc = dst_addr;
sblock_add_statement (sblock, s); sblock_add_statement (sblock, s);
} else { } else {
@ -856,17 +857,17 @@ expr_deref (sblock_t *sblock, expr_t *deref, operand_t **op)
} else if (e->type == ex_value && e->e.value->lltype == ev_pointer) { } else if (e->type == ex_value && e->e.value->lltype == ev_pointer) {
ex_pointer_t *ptr = &e->e.value->v.pointer; ex_pointer_t *ptr = &e->e.value->v.pointer;
*op = def_operand (alias_def (ptr->def, ptr->type, ptr->val), *op = def_operand (alias_def (ptr->def, ptr->type, ptr->val),
ptr->type); ptr->type, e);
} else { } else {
statement_t *s; statement_t *s;
operand_t *ptr = 0; operand_t *ptr = 0;
sblock = statement_subexpr (sblock, e, &ptr); sblock = statement_subexpr (sblock, e, &ptr);
if (!*op) if (!*op)
*op = temp_operand (type); *op = temp_operand (type, e);
s = new_statement (st_expr, ".", deref); s = new_statement (st_expr, ".", deref);
s->opa = ptr; s->opa = ptr;
s->opb = short_operand (0); s->opb = short_operand (0, e);
s->opc = *op; s->opc = *op;
sblock_add_statement (sblock, s); sblock_add_statement (sblock, s);
} }
@ -919,7 +920,7 @@ expr_alias (sblock_t *sblock, expr_t *e, operand_t **op)
} }
} }
if (!top) { if (!top) {
top = temp_operand (type); top = temp_operand (type, e);
top->o.tempop.alias = aop; top->o.tempop.alias = aop;
top->o.tempop.offset = offset; top->o.tempop.offset = offset;
top->next = aop->o.tempop.alias_ops; top->next = aop->o.tempop.alias_ops;
@ -930,9 +931,9 @@ expr_alias (sblock_t *sblock, expr_t *e, operand_t **op)
def = aop->o.def; def = aop->o.def;
while (def->alias) while (def->alias)
def = def->alias; def = def->alias;
*op = def_operand (alias_def (def, type, offset), 0); *op = def_operand (alias_def (def, type, offset), 0, e);
} else if (aop->op_type == op_value) { } else if (aop->op_type == op_value) {
*op = value_operand (aop->o.value); *op = value_operand (aop->o.value, e);
(*op)->type = type; (*op)->type = type;
} else { } else {
internal_error (e, "invalid alias target: %s: %s", internal_error (e, "invalid alias target: %s: %s",
@ -970,7 +971,7 @@ expr_expr (sblock_t *sblock, expr_t *e, operand_t **op)
sblock = statement_subexpr (sblock, e->e.expr.e1, &s->opa); sblock = statement_subexpr (sblock, e->e.expr.e1, &s->opa);
sblock = statement_subexpr (sblock, e->e.expr.e2, &s->opb); sblock = statement_subexpr (sblock, e->e.expr.e2, &s->opb);
if (!*op) if (!*op)
*op = temp_operand (e->e.expr.type); *op = temp_operand (e->e.expr.type, e);
s->opc = *op; s->opc = *op;
sblock_add_statement (sblock, s); sblock_add_statement (sblock, s);
break; break;
@ -989,7 +990,7 @@ expr_cast (sblock_t *sblock, expr_t *e, operand_t **op)
if (is_scalar (src_type) && is_scalar (type)) { if (is_scalar (src_type) && is_scalar (type)) {
operand_t *src = 0; operand_t *src = 0;
sblock = statement_subexpr (sblock, e->e.expr.e1, &src); sblock = statement_subexpr (sblock, e->e.expr.e1, &src);
*op = temp_operand (e->e.expr.type); *op = temp_operand (e->e.expr.type, e);
s = new_statement (st_expr, "<CONV>", e); s = new_statement (st_expr, "<CONV>", e);
s->opa = src; s->opa = src;
s->opc = *op; s->opc = *op;
@ -1046,7 +1047,7 @@ expr_uexpr (sblock_t *sblock, expr_t *e, operand_t **op)
s = new_statement (st_expr, 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.e1, &s->opa);
if (!*op) if (!*op)
*op = temp_operand (e->e.expr.type); *op = temp_operand (e->e.expr.type, e);
s->opc = *op; s->opc = *op;
sblock_add_statement (sblock, s); sblock_add_statement (sblock, s);
} }
@ -1059,11 +1060,11 @@ expr_symbol (sblock_t *sblock, expr_t *e, operand_t **op)
symbol_t *sym = e->e.symbol; symbol_t *sym = e->e.symbol;
if (sym->sy_type == sy_var) { if (sym->sy_type == sy_var) {
*op = def_operand (sym->s.def, sym->type); *op = def_operand (sym->s.def, sym->type, e);
} else if (sym->sy_type == sy_const) { } else if (sym->sy_type == sy_const) {
*op = value_operand (sym->s.value); *op = value_operand (sym->s.value, e);
} else if (sym->sy_type == sy_func) { } else if (sym->sy_type == sy_func) {
*op = def_operand (sym->s.func->def, 0); *op = def_operand (sym->s.func->def, 0, e);
} else { } else {
internal_error (e, "unexpected symbol type: %s for %s", internal_error (e, "unexpected symbol type: %s for %s",
symtype_str (sym->sy_type), sym->name); symtype_str (sym->sy_type), sym->name);
@ -1075,7 +1076,7 @@ static sblock_t *
expr_temp (sblock_t *sblock, expr_t *e, operand_t **op) expr_temp (sblock_t *sblock, expr_t *e, operand_t **op)
{ {
if (!e->e.temp.op) if (!e->e.temp.op)
e->e.temp.op = temp_operand (e->e.temp.type); e->e.temp.op = temp_operand (e->e.temp.type, e);
*op = e->e.temp.op; *op = e->e.temp.op;
return sblock; return sblock;
} }
@ -1151,7 +1152,7 @@ expr_vector_e (sblock_t *sblock, expr_t *e, operand_t **op)
static sblock_t * static sblock_t *
expr_value (sblock_t *sblock, expr_t *e, operand_t **op) expr_value (sblock_t *sblock, expr_t *e, operand_t **op)
{ {
*op = value_operand (e->e.value); *op = value_operand (e->e.value, e);
return sblock; return sblock;
} }
@ -1414,7 +1415,7 @@ statement_uexpr (sblock_t *sblock, expr_t *e)
} }
s = new_statement (st_func, opcode, e); s = new_statement (st_func, opcode, e);
if (e->e.expr.e1) { if (e->e.expr.e1) {
s->opa = return_operand (get_type (e->e.expr.e1)); s->opa = return_operand (get_type (e->e.expr.e1), e);
sblock = statement_subexpr (sblock, e->e.expr.e1, &s->opa); sblock = statement_subexpr (sblock, e->e.expr.e1, &s->opa);
} }
sblock_add_statement (sblock, s); sblock_add_statement (sblock, s);
@ -1718,7 +1719,7 @@ check_final_block (sblock_t *sblock)
s = new_statement (st_func, "<RETURN_V>", 0); s = new_statement (st_func, "<RETURN_V>", 0);
if (options.traditional || options.code.progsversion == PROG_ID_VERSION) { if (options.traditional || options.code.progsversion == PROG_ID_VERSION) {
s->opcode = save_string ("<RETURN>"); s->opcode = save_string ("<RETURN>");
s->opa = return_operand (&type_void); s->opa = return_operand (&type_void, 0);
} }
sblock_add_statement (sblock, s); sblock_add_statement (sblock, s);
} }