[qfcc] Give lea its own statement type

This makes it much easier to check (and more robust to name changes),
allowing for effectively killing the node to which the variable being
addressed is attached. This fixes the incorrect address being used for
va_list, which is what caused double-alias to fail.
This commit is contained in:
Bill Currie 2022-02-02 18:55:01 +09:00
parent 38550922cc
commit a64f91129f
4 changed files with 23 additions and 11 deletions

View file

@ -102,6 +102,7 @@ typedef enum {
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_address, ///< lea
} st_type_t;
typedef struct statement_s {

View file

@ -282,8 +282,11 @@ dag_make_children (dag_t *dag, statement_t *s,
dagnode_t *node = dag_node (operands[i + 1]);
dagnode_t *killer = 0;
if (node && node->killed) {
if (node && (node->killed || s->type == st_address)) {
// If the node has been killed, then a new node is needed
// taking the address of a variable effectively kills the node it's
// attached to. FIXME should this be for only when the variable is
// in the attached identifiers list and is not the node's label?
killer = node->killed;
node = 0;
}
@ -1214,6 +1217,7 @@ dag_gencode (dag_t *dag, sblock_t *block, dagnode_t *dagnode)
dst = generate_assignments (dag, block, dst, var_iter, type);
}
break;
case st_address:
case st_expr:
operands[0] = make_operand (dag, block, dagnode, 0);
if (dagnode->children[1])

View file

@ -1181,15 +1181,21 @@ flow_analyze_statement (statement_t *s, set_t *use, set_t *def, set_t *kill,
switch (s->type) {
case st_none:
internal_error (s->expr, "not a statement");
case st_address:
if (s->opb) {
flow_add_op_var (use, s->opa, 1);
flow_add_op_var (use, s->opb, 1);
}
flow_add_op_var (def, s->opc, 0);
if (operands) {
operands[0] = s->opc;
operands[1] = s->opa;
operands[2] = s->opb;
}
break;
case st_expr:
flow_add_op_var (def, s->opc, 0);
if (strcmp (s->opcode, "lea") == 0) {
if (s->opb) {
flow_add_op_var (use, s->opa, 1);
}
} else {
flow_add_op_var (use, s->opa, 1);
}
flow_add_op_var (use, s->opa, 1);
if (s->opb)
flow_add_op_var (use, s->opb, 1);
if (operands) {

View file

@ -87,6 +87,7 @@ const char *st_type_names[] = {
"st_state",
"st_func",
"st_flow",
"st_address",
};
const char *
@ -744,7 +745,7 @@ expr_address (sblock_t *sblock, expr_t *e, operand_t **op)
offset = 0;
}
s = new_statement (st_expr, "lea", e);
s = new_statement (st_address, "lea", e);
sblock = statement_subexpr (sblock, lvalue, &s->opa);
if (offset) {
sblock = statement_subexpr (sblock, offset, &s->opb);
@ -1005,7 +1006,7 @@ dereference_dst:
// one directly. FIXME it was probably a mistake extracting the operand
// type from the statement expression in dags
dst_expr = expr_file_line (address_expr (dst_expr, 0), dst_expr);
s = new_statement (st_expr, "lea", dst_expr);
s = new_statement (st_address, "lea", dst_expr);
s->opa = dst;
s->opb = ofs;
s->opc = temp_operand (&type_ptr, dst_expr);
@ -1438,7 +1439,7 @@ statement_with (sblock_t *sblock, expr_t *e)
static statement_t *
lea_statement (operand_t *pointer, operand_t *offset, expr_t *e)
{
statement_t *s = new_statement (st_expr, "lea", e);
statement_t *s = new_statement (st_address, "lea", e);
s->opa = pointer;
s->opb = offset;
s->opc = temp_operand (&type_ptr, e);