[qfcc] Use ud-chains for ptrmove pointer analysis

ptrmove was not treating its indirect source operand as used because the
pointer wasn't checked for its source.

This fixes part of ptrstructinit, but there's a lot more breakage in
that test: it looks like all sorts of fun with arrays.
This commit is contained in:
Bill Currie 2024-02-17 19:47:02 +09:00
parent ab69e65e02
commit 0e7c80e9fe

View file

@ -930,29 +930,10 @@ follow_ud_chain (udchain_t ud, function_t *func, set_t *ptr, set_t *visited)
} }
static void static void
flow_check_params (statement_t *st, set_t *use, set_t *def, function_t *func) flow_find_ptr (set_t *use, set_t *use_ptr, statement_t *st, function_t *func)
{ {
if (!func->ud_chains) {
return;
}
set_t *use_ptr = set_new ();
set_t *def_ptr = set_new ();
set_t *ptr = set_new (); set_t *ptr = set_new ();
set_t *visited = set_new (); set_t *visited = set_new ();
int have_use = 0;
for (operand_t *op = st->use; op; op = op->next) {
if (op->op_type == op_def && is_ptr (op->type)) {
flowvar_t *var = flow_get_var (op);
set_add (use_ptr, var->number);
have_use = 1;
const char *name = op->def->name;
if (!strncmp (name,".arg", 4) || !strncmp (name, ".param_", 7)) {
set_add (def_ptr, var->number);
}
}
}
if (have_use) {
for (int i = 0; i < st->num_use; i++) { for (int i = 0; i < st->num_use; i++) {
udchain_t ud = func->ud_chains[i + st->first_use]; udchain_t ud = func->ud_chains[i + st->first_use];
set_empty (visited); set_empty (visited);
@ -967,6 +948,54 @@ flow_check_params (statement_t *st, set_t *use, set_t *def, function_t *func)
} }
} }
} }
set_delete (visited);
set_delete (ptr);
}
static void
flow_check_params (statement_t *st, set_t *use, set_t *def, function_t *func)
{
if (!func->ud_chains) {
return;
}
set_t *use_ptr = set_new ();
set_t *def_ptr = set_new ();
int have_use = 0;
for (operand_t *op = st->use; op; op = op->next) {
if (op->op_type == op_def && is_ptr (op->type)) {
flowvar_t *var = flow_get_var (op);
set_add (use_ptr, var->number);
have_use = 1;
const char *name = op->def->name;
if (!strncmp (name,".arg", 4) || !strncmp (name, ".param_", 7)) {
set_add (def_ptr, var->number);
}
}
}
if (have_use) {
flow_find_ptr (use, use_ptr, st, func);
}
set_delete (use_ptr);
set_delete (def_ptr);
}
static void
flow_check_move (statement_t *st, set_t *use, set_t *def, function_t *func)
{
if (!func->ud_chains) {
return;
}
set_t *use_ptr = set_new ();
set_t *def_ptr = set_new ();
set_t *ptr = set_new ();
set_t *visited = set_new ();
set_add (use_ptr, flow_get_var (st->opa)->number);
set_add (def_ptr, flow_get_var (st->opc)->number);
if (use) {
flow_find_ptr (use, use_ptr, st, func);
} }
set_delete (visited); set_delete (visited);
@ -1169,6 +1198,8 @@ flow_build_chains (flowgraph_t *graph)
if (st->type == st_func && statement_is_call (st)) { if (st->type == st_func && statement_is_call (st)) {
// set def later? // set def later?
flow_check_params (st, stuse, 0, graph->func); flow_check_params (st, stuse, 0, graph->func);
} else if (st->type == st_ptrmove) {
flow_check_move (st, stuse, 0, graph->func);
} }
set_empty (tmp); set_empty (tmp);
for (set_iter_t *vi = set_first (stuse); vi; for (set_iter_t *vi = set_first (stuse); vi;
@ -1199,6 +1230,8 @@ flow_build_chains (flowgraph_t *graph)
if (st->type == st_func && statement_is_call (st)) { if (st->type == st_func && statement_is_call (st)) {
// set def later? // set def later?
flow_check_params (st, stuse, 0, graph->func); flow_check_params (st, stuse, 0, graph->func);
} else if (st->type == st_ptrmove) {
flow_check_move (st, stuse, 0, graph->func);
} }
set_empty (tmp); set_empty (tmp);
first_use[st->number] = num_ud_chains; first_use[st->number] = num_ud_chains;