mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-02-25 05:01:24 +00:00
[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:
parent
ab69e65e02
commit
0e7c80e9fe
1 changed files with 49 additions and 16 deletions
|
@ -930,29 +930,10 @@ follow_ud_chain (udchain_t ud, function_t *func, set_t *ptr, set_t *visited)
|
|||
}
|
||||
|
||||
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 *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++) {
|
||||
udchain_t ud = func->ud_chains[i + st->first_use];
|
||||
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);
|
||||
|
@ -1169,6 +1198,8 @@ flow_build_chains (flowgraph_t *graph)
|
|||
if (st->type == st_func && statement_is_call (st)) {
|
||||
// set def later?
|
||||
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);
|
||||
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)) {
|
||||
// set def later?
|
||||
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);
|
||||
first_use[st->number] = num_ud_chains;
|
||||
|
|
Loading…
Reference in a new issue