[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;
struct type_s *type; ///< possibly override def's type
int size; ///< for structures
struct expr_s *expr; ///< expression generating this operand
union {
struct def_s *def;
struct ex_value_s *value;
@ -115,14 +116,16 @@ struct dstring_s;
const char *optype_str (op_type_e type) __attribute__((const));
operand_t *def_operand (struct def_s *def, struct type_s *type);
operand_t *return_operand (struct type_s *type);
operand_t *value_operand (struct ex_value_s *value);
operand_t *def_operand (struct def_s *def, struct type_s *type,
struct expr_s *expr);
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));
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 (*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);
sblock_t *new_sblock (void);

View file

@ -821,7 +821,7 @@ static operand_t *
fix_op_type (operand_t *op, type_t *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;
}
@ -882,7 +882,8 @@ generate_moveps (dag_t *dag, sblock_t *block, dagnode_t *dagnode)
offset = dstDef->offset;
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);
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);
type = get_type (dagnode->label->expr);
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 {
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;
ex_pointer_t *ptr = &s->opc->o.value->v.pointer;
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);
if (operands)
operands[0] = op;

View file

@ -273,11 +273,12 @@ new_statement (st_type_t type, const char *opcode, expr_t *expr)
}
static operand_t *
new_operand (op_type_e op)
new_operand (op_type_e op, expr_t *expr)
{
operand_t *operand;
ALLOC (256, operand_t, operands, operand);
operand->op_type = op;
operand->expr = expr;
return operand;
}
@ -311,13 +312,13 @@ free_sblock (sblock_t *sblock)
}
operand_t *
def_operand (def_t *def, type_t *type)
def_operand (def_t *def, type_t *type, expr_t *expr)
{
operand_t *op;
if (!type)
type = def->type;
op = new_operand (op_def);
op = new_operand (op_def, expr);
op->type = type;
op->size = type_size (type);
op->o.def = def;
@ -325,28 +326,28 @@ def_operand (def_t *def, type_t *type)
}
operand_t *
return_operand (type_t *type)
return_operand (type_t *type, expr_t *expr)
{
symbol_t *return_symbol;
return_symbol = make_symbol (".return", &type_param, pr.symtab->space,
sc_extern);
return def_operand (return_symbol->s.def, type);
return def_operand (return_symbol->s.def, type, expr);
}
operand_t *
value_operand (ex_value_t *value)
value_operand (ex_value_t *value, expr_t *expr)
{
operand_t *op;
op = new_operand (op_value);
op = new_operand (op_value, expr);
op->type = value->type;
op->o.value = value;
return op;
}
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->type = type;
@ -412,7 +413,7 @@ tempop_visit_all (tempop_t *tempop, int overlap,
}
operand_t *
alias_operand (type_t *type, operand_t *op)
alias_operand (type_t *type, operand_t *op, expr_t *expr)
{
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"
" (%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->type = type;
aop->size = type_size (type);
@ -428,10 +429,10 @@ alias_operand (type_t *type, operand_t *op)
}
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);
return value_operand (val);
return value_operand (val, expr);
}
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') {
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;
} else {
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);
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 = new_operand (op_label, e);
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;
s = new_statement (st_expr, "&", e);
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);
*(op) = s->opc;
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);
s->opa = pointer;
s->opb = offset;
s->opc = temp_operand (&type_pointer);
s->opc = temp_operand (&type_pointer, e);
return s;
}
@ -804,7 +805,7 @@ address_statement (operand_t *value, expr_t *e)
{
statement_t *s = new_statement (st_expr, "&", e);
s->opa = value;
s->opc = temp_operand (&type_pointer);
s->opc = temp_operand (&type_pointer, e);
return s;
}
@ -819,7 +820,7 @@ expr_deref (sblock_t *sblock, expr_t *deref, operand_t **op)
&& e->e.expr.e1->type == ex_symbol) {
if (e->e.expr.e1->e.symbol->sy_type != sy_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 == '&') {
statement_t *s;
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.e2, &offs);
if (!*op)
*op = temp_operand (type);
*op = temp_operand (type, e);
if (low_level_type (type) == ev_void) {
operand_t *src_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->opa = src_addr;
s->opb = short_operand (type_size (type));
s->opb = short_operand (type_size (type), e);
s->opc = dst_addr;
sblock_add_statement (sblock, s);
} 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) {
ex_pointer_t *ptr = &e->e.value->v.pointer;
*op = def_operand (alias_def (ptr->def, ptr->type, ptr->val),
ptr->type);
ptr->type, e);
} else {
statement_t *s;
operand_t *ptr = 0;
sblock = statement_subexpr (sblock, e, &ptr);
if (!*op)
*op = temp_operand (type);
*op = temp_operand (type, e);
s = new_statement (st_expr, ".", deref);
s->opa = ptr;
s->opb = short_operand (0);
s->opb = short_operand (0, e);
s->opc = *op;
sblock_add_statement (sblock, s);
}
@ -919,7 +920,7 @@ expr_alias (sblock_t *sblock, expr_t *e, operand_t **op)
}
}
if (!top) {
top = temp_operand (type);
top = temp_operand (type, e);
top->o.tempop.alias = aop;
top->o.tempop.offset = offset;
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;
while (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) {
*op = value_operand (aop->o.value);
*op = value_operand (aop->o.value, e);
(*op)->type = type;
} else {
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.e2, &s->opb);
if (!*op)
*op = temp_operand (e->e.expr.type);
*op = temp_operand (e->e.expr.type, e);
s->opc = *op;
sblock_add_statement (sblock, s);
break;
@ -989,7 +990,7 @@ expr_cast (sblock_t *sblock, expr_t *e, operand_t **op)
if (is_scalar (src_type) && is_scalar (type)) {
operand_t *src = 0;
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->opa = src;
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);
sblock = statement_subexpr (sblock, e->e.expr.e1, &s->opa);
if (!*op)
*op = temp_operand (e->e.expr.type);
*op = temp_operand (e->e.expr.type, e);
s->opc = *op;
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;
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) {
*op = value_operand (sym->s.value);
*op = value_operand (sym->s.value, e);
} 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 {
internal_error (e, "unexpected symbol type: %s for %s",
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)
{
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;
return sblock;
}
@ -1151,7 +1152,7 @@ expr_vector_e (sblock_t *sblock, expr_t *e, operand_t **op)
static sblock_t *
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;
}
@ -1414,7 +1415,7 @@ statement_uexpr (sblock_t *sblock, expr_t *e)
}
s = new_statement (st_func, opcode, e);
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_add_statement (sblock, s);
@ -1718,7 +1719,7 @@ check_final_block (sblock_t *sblock)
s = new_statement (st_func, "<RETURN_V>", 0);
if (options.traditional || options.code.progsversion == PROG_ID_VERSION) {
s->opcode = save_string ("<RETURN>");
s->opa = return_operand (&type_void);
s->opa = return_operand (&type_void, 0);
}
sblock_add_statement (sblock, s);
}