mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-10 15:22:04 +00:00
[qfcc] Use auxiliary operands for move instructions
Since Ruamoko progs must use lea to get the address of a local variable, add use/def/kill references to the move instruction in order to inform flow analysis of the variable since it is otherwise lost via the resulting pointer (not an issue when direct var reference move can be used). The test and digging for the def can probably do with being more aggressive, but this did nicely as a proof of concept.
This commit is contained in:
parent
f853a449b8
commit
fbaf1456fe
3 changed files with 39 additions and 0 deletions
|
@ -629,6 +629,14 @@ int expr_integral (expr_t *e) __attribute__((pure));
|
|||
*/
|
||||
int is_constant (expr_t *e) __attribute__((pure));
|
||||
|
||||
/** Check if the expression refers to a variable.
|
||||
|
||||
\param e The expression to check.
|
||||
\return True if the expression refers to a variable (def
|
||||
expression, var symbol expression, or temp expression).
|
||||
*/
|
||||
int is_variable (expr_t *e) __attribute__((pure));
|
||||
|
||||
/** Check if the expression refers to a selector
|
||||
|
||||
\param e The expression to check.
|
||||
|
|
|
@ -956,6 +956,20 @@ is_constant (expr_t *e)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
is_variable (expr_t *e)
|
||||
{
|
||||
while (e->type == ex_alias) {
|
||||
e = e->e.alias.expr;
|
||||
}
|
||||
if (e->type == ex_def
|
||||
|| (e->type == ex_symbol && e->e.symbol->sy_type == sy_var)
|
||||
|| e->type == ex_temp) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
is_selector (expr_t *e)
|
||||
{
|
||||
|
|
|
@ -827,6 +827,9 @@ expr_assign_copy (sblock_t *sblock, expr_t *e, operand_t **op, operand_t *src)
|
|||
const char *opcode;
|
||||
int need_ptr = 0;
|
||||
st_type_t type = st_move;
|
||||
operand_t *use = 0;
|
||||
operand_t *def = 0;
|
||||
operand_t *kill = 0;
|
||||
|
||||
if ((src && src->op_type == op_nil) || src_expr->type == ex_nil) {
|
||||
// switch to memset because nil is type agnostic 0 and structures
|
||||
|
@ -859,6 +862,11 @@ expr_assign_copy (sblock_t *sblock, expr_t *e, operand_t **op, operand_t *src)
|
|||
*op = src;
|
||||
}
|
||||
if (is_indirect (dst_expr)) {
|
||||
if (is_variable (src_expr)) {
|
||||
// FIXME this probably needs to be more agressive
|
||||
// shouldn't emit code...
|
||||
sblock = statement_subexpr (sblock, src_expr, &use);
|
||||
}
|
||||
src = operand_address (src, src_expr);
|
||||
need_ptr = 1;
|
||||
}
|
||||
|
@ -867,6 +875,12 @@ expr_assign_copy (sblock_t *sblock, expr_t *e, operand_t **op, operand_t *src)
|
|||
// dst_expr and/or src_expr are dereferenced pointers, so need to
|
||||
// un-dereference dst_expr to get the pointer and switch to movep
|
||||
// or memsetp instructions.
|
||||
if (is_variable (dst_expr)) {
|
||||
// FIXME this probably needs to be more agressive
|
||||
// shouldn't emit code...
|
||||
sblock = statement_subexpr (sblock, dst_expr, &def);
|
||||
sblock = statement_subexpr (sblock, dst_expr, &kill);
|
||||
}
|
||||
dst_expr = expr_file_line (address_expr (dst_expr, 0), e);
|
||||
need_ptr = 1;
|
||||
}
|
||||
|
@ -895,6 +909,9 @@ expr_assign_copy (sblock_t *sblock, expr_t *e, operand_t **op, operand_t *src)
|
|||
s->opa = src;
|
||||
s->opb = size;
|
||||
s->opc = dst;
|
||||
s->use = use;
|
||||
s->def = def;
|
||||
s->kill = kill;
|
||||
sblock_add_statement (sblock, s);
|
||||
return sblock;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue