mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-22 04:21:51 +00:00
[qfcc] Take memset/move size into account for use/def
This fixed the bogus uninitialized variable working in b648c353f
This commit is contained in:
parent
b648c353ff
commit
c066e638e5
3 changed files with 79 additions and 49 deletions
|
@ -257,15 +257,6 @@ void initialize_def (struct symbol_s *sym,
|
|||
struct expr_s *init, struct defspace_s *space,
|
||||
storage_class_t storage, struct symtab_s *symtab);
|
||||
|
||||
/** Determine if two defs overlap.
|
||||
|
||||
\param d1 The first def to check. May be an alias def.
|
||||
\param d2 The second def to check. May be an alias def.
|
||||
\return 1 if the defs overlap, 2 if \a d1 fully overlaps \a d2,
|
||||
otherwise 0.
|
||||
*/
|
||||
int def_overlap (def_t *d1, def_t *d2) __attribute__((pure));
|
||||
|
||||
/** Convenience function for obtaining a def's actual offset.
|
||||
|
||||
Takes care of an alias def's relative offset.
|
||||
|
@ -317,6 +308,11 @@ int def_size (def_t *def) __attribute__((pure));
|
|||
*/
|
||||
int def_visit_all (def_t *def, int overlap,
|
||||
int (*visit) (def_t *, void *), void *data);
|
||||
|
||||
int def_visit_overlaps (def_t *def, int offset, int size, int overlap,
|
||||
def_t *skip,
|
||||
int (*visit) (def_t *, void *), void *data);
|
||||
|
||||
///@}
|
||||
|
||||
#endif//__def_h
|
||||
|
|
|
@ -690,36 +690,16 @@ initialize_def (symbol_t *sym, expr_t *init, defspace_t *space,
|
|||
sym->s.def->initializer = init;
|
||||
}
|
||||
|
||||
int
|
||||
def_overlap (def_t *d1, def_t *d2)
|
||||
static int
|
||||
def_overlap (def_t *d, int offset, int size)
|
||||
{
|
||||
int offs1, size1;
|
||||
int offs2, size2;
|
||||
defspace_t *s1 = d1->space;
|
||||
defspace_t *s2 = d2->space;
|
||||
int d_offset = d->offset;
|
||||
int d_size = type_size (d->type);
|
||||
|
||||
if (d1->alias)
|
||||
s1 = d1->alias->space;
|
||||
if (d2->alias)
|
||||
s2 = d2->alias->space;
|
||||
/// Defs in different spaces never overlap.
|
||||
if (s1 != s2)
|
||||
return 0;
|
||||
|
||||
offs1 = d1->offset;
|
||||
if (d1->alias)
|
||||
offs1 += d1->alias->offset;
|
||||
size1 = type_size (d1->type);
|
||||
|
||||
offs2 = d2->offset;
|
||||
if (d2->alias)
|
||||
offs2 += d2->alias->offset;
|
||||
size2 = type_size (d2->type);
|
||||
|
||||
if (offs1 <= offs2 && offs1 + size1 >= offs2 + size2)
|
||||
return 2; // d1 fully overlaps d2
|
||||
if (offs1 < offs2 + size2 && offs2 < offs1 + size1)
|
||||
return 1; // d1 and d2 at least partially overlap
|
||||
if (d_offset >= offset && d_offset + d_size <= offset + size)
|
||||
return 2; // d is fully overlapped by the range
|
||||
if (d_offset < offset + size && offset < d_offset + d_size)
|
||||
return 1; // d is partially overlapped by the range range
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -738,6 +718,23 @@ def_size (def_t *def)
|
|||
return type_size (def->type);
|
||||
}
|
||||
|
||||
int
|
||||
def_visit_overlaps (def_t *def, int offset, int size, int overlap, def_t *skip,
|
||||
int (*visit) (def_t *, void *), void *data)
|
||||
{
|
||||
int ret;
|
||||
|
||||
for (def = def->alias_defs; def; def = def->next) {
|
||||
if (def == skip)
|
||||
continue;
|
||||
if (overlap && def_overlap (def, offset, size) < overlap)
|
||||
continue;
|
||||
if ((ret = visit (def, data)))
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
def_visit_all (def_t *def, int overlap,
|
||||
int (*visit) (def_t *, void *), void *data)
|
||||
|
@ -755,13 +752,8 @@ def_visit_all (def_t *def, int overlap,
|
|||
} else {
|
||||
overlap = 0;
|
||||
}
|
||||
for (def = def->alias_defs; def; def = def->next) {
|
||||
if (def == start_def)
|
||||
continue;
|
||||
if (overlap && def_overlap (def, start_def) < overlap)
|
||||
continue;
|
||||
if ((ret = visit (def, data)))
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
int offset = start_def->offset;
|
||||
int size = start_def->type ? type_size (start_def->type) : 0;
|
||||
return def_visit_overlaps (def, offset, size, overlap, start_def,
|
||||
visit, data);
|
||||
}
|
||||
|
|
|
@ -835,6 +835,35 @@ flow_add_op_var (set_t *set, operand_t *op, int ol)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
flow_add_op_var_size (set_t *set, operand_t *op, int size, int ol)
|
||||
{
|
||||
flowvar_t *var;
|
||||
|
||||
if (!set)
|
||||
return;
|
||||
if (!(var = flow_get_var (op)))
|
||||
return;
|
||||
set_add (set, var->number);
|
||||
|
||||
if (op->op_type == op_temp) {
|
||||
//bug (0, "temp op");
|
||||
tempop_visit_all (&op->tempop, ol, flow_tempop_add_aliases, set);
|
||||
} else if (op->op_type == op_def) {
|
||||
def_t *def = op->def;
|
||||
def_t *skip = def->alias ? def : 0;
|
||||
int offset = def->alias ? def->offset : 0;
|
||||
if (def->alias) {
|
||||
def = def->alias;
|
||||
}
|
||||
if (size == -1) {
|
||||
size = type_size (def->type) - offset;
|
||||
}
|
||||
def_visit_overlaps (def, offset, size, ol, skip,
|
||||
flow_def_add_aliases, set);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
flowvar_def_add_use (def_t *def, void *data)
|
||||
{
|
||||
|
@ -1494,6 +1523,7 @@ flow_analyze_statement (statement_t *s, set_t *use, set_t *def, set_t *kill,
|
|||
operand_t *operands[FLOW_OPERANDS])
|
||||
{
|
||||
int i, calln = -1;
|
||||
int size;
|
||||
operand_t *src_op = 0;
|
||||
operand_t *res_op = 0;
|
||||
operand_t *aux_op1 = 0;
|
||||
|
@ -1566,19 +1596,31 @@ flow_analyze_statement (statement_t *s, set_t *use, set_t *def, set_t *kill,
|
|||
flow_add_op_var (use, s->opa, 1);
|
||||
flow_add_op_var (use, s->opb, 1);
|
||||
aux_op1 = s->opb;
|
||||
if (s->type != st_ptrassign && s->opb->op_type == op_value) {
|
||||
if (is_short (s->opb->type)) {
|
||||
size = s->opb->value->v.short_val;
|
||||
} else if (is_int (s->opb->type)) {
|
||||
size = s->opb->value->v.int_val;
|
||||
} else {
|
||||
print_type (s->opb->type);
|
||||
internal_error (s->expr, "unexpected type for memset/move");
|
||||
}
|
||||
} else {
|
||||
size = -1;
|
||||
}
|
||||
if (!strcmp (s->opcode, "move")
|
||||
|| !strcmp (s->opcode, "memset")) {
|
||||
flow_add_op_var (def, s->opc, 6);
|
||||
flow_add_op_var_size (def, s->opc, size, 2);
|
||||
src_op = s->opa;
|
||||
res_op = s->opc;
|
||||
} else if (!strcmp (s->opcode, "movep")) {
|
||||
flow_add_op_var (use, s->opc, 6);
|
||||
flow_add_op_var_size (use, s->opc, size, 2);
|
||||
aux_op3 = flow_analyze_pointer_operand (s->opa, use);
|
||||
res_op = flow_analyze_pointer_operand (s->opc, def);
|
||||
src_op = s->opa;
|
||||
aux_op2 = s->opc;
|
||||
} else if (!strcmp (s->opcode, "memsetp")) {
|
||||
flow_add_op_var (use, s->opc, 6);
|
||||
flow_add_op_var_size (use, s->opc, size, 2);
|
||||
res_op = flow_analyze_pointer_operand (s->opc, def);
|
||||
src_op = s->opa;
|
||||
aux_op2 = s->opc;
|
||||
|
|
Loading…
Reference in a new issue