mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-02-17 01:11:45 +00:00
Treat global variables as live at the end of a function.
.return and .param_N are not classed as global variables for data flow analysis. .return is taken care of by return statements, and .param_N by call statements. With this, the menus work up to attempting to load the menu plist. Something is corrupting zmalloc's blocks.
This commit is contained in:
parent
0dea564cb4
commit
56103f9a38
6 changed files with 61 additions and 24 deletions
|
@ -69,6 +69,7 @@ typedef struct flownode_s {
|
|||
struct set_s *successors; ///< successors of this node
|
||||
struct set_s *edges; ///< edges leaving this node to successor nodes
|
||||
struct set_s *dom; ///< dominating nodes
|
||||
struct set_s *global_vars; ///< global vars used by function
|
||||
struct {
|
||||
struct set_s *use;
|
||||
struct set_s *def;
|
||||
|
@ -102,7 +103,8 @@ void flow_analyze_statement (struct statement_s *s, struct set_s *use,
|
|||
struct set_s *def, struct set_s *kill,
|
||||
struct operand_s *operands[4]);
|
||||
void flow_build_vars (struct function_s *func);
|
||||
flowgraph_t *flow_build_graph (struct sblock_s *func);
|
||||
flowgraph_t *flow_build_graph (struct sblock_s *sblock,
|
||||
struct function_s *func);
|
||||
void flow_del_graph (flowgraph_t *graph);
|
||||
void flow_data_flow (flowgraph_t *graph);
|
||||
struct sblock_s *flow_generate (flowgraph_t *graph);
|
||||
|
|
|
@ -89,6 +89,7 @@ typedef struct function_s {
|
|||
*/
|
||||
struct flowvar_s **vars;
|
||||
int num_vars; ///< total number of variables referenced
|
||||
struct set_s *global_vars;///< set indicating which vars are global
|
||||
struct statement_s **statements;
|
||||
int num_statements;
|
||||
} function_t;
|
||||
|
|
|
@ -67,11 +67,11 @@ typedef struct symbol_s {
|
|||
struct flowvar_s *flowvar;
|
||||
struct daglabel_s *daglabel;///< dag label for this symbol
|
||||
union {
|
||||
int offset; ///< st_var (in a struct/union)
|
||||
struct def_s *def; ///< st_var
|
||||
struct ex_value_s *value; ///< st_const
|
||||
struct expr_s *expr; ///< st_expr
|
||||
struct function_s *func; ///< st_func
|
||||
int offset; ///< sy_var (in a struct/union)
|
||||
struct def_s *def; ///< sy_var
|
||||
struct ex_value_s *value; ///< sy_const
|
||||
struct expr_s *expr; ///< sy_expr
|
||||
struct function_s *func; ///< sy_func
|
||||
} s;
|
||||
} symbol_t;
|
||||
|
||||
|
|
|
@ -407,23 +407,26 @@ dag_create (flownode_t *flownode)
|
|||
lx->expr = s->expr;
|
||||
dagnode_attach_label (n, lx);
|
||||
}
|
||||
if (n->type == st_func
|
||||
&& (!strncmp (n->label->opcode, "<CALL", 5)
|
||||
|| !strncmp (n->label->opcode, "<RCALL", 6))) {
|
||||
int start, end;
|
||||
if (n->type == st_func) {
|
||||
if (!strncmp (n->label->opcode, "<CALL", 5)
|
||||
|| !strncmp (n->label->opcode, "<RCALL", 6)) {
|
||||
int start, end;
|
||||
|
||||
if (!strncmp (n->label->opcode, "<CALL", 5)) {
|
||||
start = 0;
|
||||
end = 0;
|
||||
if (n->label->opcode[5] != '>')
|
||||
end = n->label->opcode[5] - '0';
|
||||
} else {
|
||||
start = 2;
|
||||
end = n->label->opcode[6] - '0';
|
||||
}
|
||||
while (start < end) {
|
||||
set_add (live_vars, start + 1);
|
||||
start++;
|
||||
if (!strncmp (n->label->opcode, "<CALL", 5)) {
|
||||
start = 0;
|
||||
end = 0;
|
||||
if (n->label->opcode[5] != '>')
|
||||
end = n->label->opcode[5] - '0';
|
||||
} else {
|
||||
start = 2;
|
||||
end = n->label->opcode[6] - '0';
|
||||
}
|
||||
while (start < end) {
|
||||
set_add (live_vars, start + 1);
|
||||
start++;
|
||||
}
|
||||
} else if (!strncmp (n->label->opcode, "<RETURN", 7)) {
|
||||
set_union (live_vars, flownode->global_vars);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -160,6 +160,23 @@ delete_graph (flowgraph_t *graph)
|
|||
free_graphs = graph;
|
||||
}
|
||||
|
||||
static int
|
||||
flowvar_is_global (flowvar_t *var)
|
||||
{
|
||||
symbol_t *sym;
|
||||
def_t *def;
|
||||
|
||||
if (var->op->op_type != op_symbol)
|
||||
return 0;
|
||||
sym = var->op->o.symbol;
|
||||
if (sym->sy_type != sy_var)
|
||||
return 0;
|
||||
def = sym->s.def;
|
||||
if (def->local)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
flowvar_t *
|
||||
flow_get_var (operand_t *op)
|
||||
{
|
||||
|
@ -284,6 +301,12 @@ flow_build_vars (function_t *func)
|
|||
add_operand (func, s->opc);
|
||||
}
|
||||
}
|
||||
func->global_vars = set_new ();
|
||||
// mark all global vars (except .return and .param_N)
|
||||
for (i = num_flow_params; i < func->num_vars; i++) {
|
||||
if (flowvar_is_global (func->vars[i]))
|
||||
set_add (func->global_vars, i);
|
||||
}
|
||||
}
|
||||
if (num_statements) {
|
||||
func->statements = malloc (num_statements * sizeof (statement_t *));
|
||||
|
@ -333,6 +356,13 @@ flow_live_vars (flowgraph_t *graph)
|
|||
def = set_new ();
|
||||
for (st = node->sblock->statements; st; st = st->next) {
|
||||
flow_analyze_statement (st, stuse, stdef, 0, 0);
|
||||
if (st->type == st_func && !strncmp (st->opcode, "<RETURN", 7)) {
|
||||
set_t *global_vars = set_new ();
|
||||
|
||||
set_assign (global_vars, graph->func->global_vars);
|
||||
live_set_use (global_vars, use, def);
|
||||
set_delete (global_vars);
|
||||
}
|
||||
live_set_use (stuse, use, def);
|
||||
live_set_def (stdef, use, def);
|
||||
}
|
||||
|
@ -799,7 +829,7 @@ flow_build_dfst (flowgraph_t *graph)
|
|||
}
|
||||
|
||||
flowgraph_t *
|
||||
flow_build_graph (sblock_t *sblock)
|
||||
flow_build_graph (sblock_t *sblock, function_t *func)
|
||||
{
|
||||
flowgraph_t *graph;
|
||||
flownode_t *node;
|
||||
|
@ -819,6 +849,7 @@ flow_build_graph (sblock_t *sblock)
|
|||
node->successors = set_new ();
|
||||
node->edges = set_new ();
|
||||
node->dom = set_new ();
|
||||
node->global_vars = func->global_vars;
|
||||
node->id = sb->number;
|
||||
node->sblock = sb;
|
||||
graph->nodes[node->id] = node;
|
||||
|
|
|
@ -644,7 +644,7 @@ emit_function (function_t *f, expr_t *e)
|
|||
lineno_base = f->def->line;
|
||||
f->sblock = make_statements (e);
|
||||
flow_build_vars (f);
|
||||
f->graph = flow_build_graph (f->sblock);
|
||||
f->graph = flow_build_graph (f->sblock, f);
|
||||
f->graph->func = f;
|
||||
flow_data_flow (f->graph);
|
||||
f->sblock = flow_generate (f->graph);
|
||||
|
|
Loading…
Reference in a new issue