mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-10 15:22:04 +00:00
[qfcc] Set up the function stack frame
Still need to get the base register index into the instructions, but I think this is it for basic code generation. I should be able to start testing Ruamoko properly fairly soon :)
This commit is contained in:
parent
3df46d197f
commit
79bd4dd724
6 changed files with 105 additions and 3 deletions
|
@ -238,6 +238,17 @@ typedef struct {
|
|||
struct expr_s *ret_val;
|
||||
} ex_return_t;
|
||||
|
||||
typedef struct {
|
||||
short mode; ///< currently must be 0
|
||||
short offset; ///< amount by which stack will be adjusted
|
||||
} ex_adjstk_t;
|
||||
|
||||
typedef struct {
|
||||
short mode; ///< currently must be 0
|
||||
short reg; ///< base register to load
|
||||
struct expr_s *with; ///< value to load
|
||||
} ex_with_t;
|
||||
|
||||
#define POINTER_VAL(p) (((p).def ? (p).def->offset : 0) + (p).val)
|
||||
|
||||
typedef struct expr_s {
|
||||
|
@ -269,6 +280,8 @@ typedef struct expr_s {
|
|||
ex_assign_t assign; ///< assignment expr params
|
||||
ex_branch_t branch; ///< branch expr params
|
||||
ex_return_t retrn; ///< return expr params
|
||||
ex_adjstk_t adjstk; ///< stack adjust param
|
||||
ex_with_t with; ///< with expr param
|
||||
struct type_s *nil; ///< type for nil if known
|
||||
} e;
|
||||
} expr_t;
|
||||
|
@ -688,6 +701,8 @@ expr_t *new_address_expr (struct type_s *lvtype, expr_t *lvalue,
|
|||
expr_t *offset);
|
||||
expr_t *new_assign_expr (expr_t *dst, expr_t *src);
|
||||
expr_t *new_return_expr (expr_t *ret_val);
|
||||
expr_t *new_adjstk_expr (int mode, int offset);
|
||||
expr_t *new_with_expr (int mode, int reg, expr_t *val);
|
||||
|
||||
/** Create an expression of the correct type that references the specified
|
||||
parameter slot.
|
||||
|
|
|
@ -59,5 +59,7 @@ EX_EXPR(address) ///< address of an lvalue expression (::ex_address_t)
|
|||
EX_EXPR(assign) ///< assignment of src expr to dst expr (::ex_assing_t)
|
||||
EX_EXPR(branch) ///< branch expression (::ex_branch_t)
|
||||
EX_EXPR(return) ///< return expression (::ex_return_t)
|
||||
EX_EXPR(adjstk) ///< stack adjust expression (::ex_adjstk_t)
|
||||
EX_EXPR(with) ///< with expression (::ex_with_t)
|
||||
|
||||
///@}
|
||||
|
|
|
@ -219,6 +219,8 @@ get_type (expr_t *e)
|
|||
type = e->e.branch.ret_type;
|
||||
break;
|
||||
case ex_labelref:
|
||||
case ex_adjstk:
|
||||
case ex_with:
|
||||
return &type_void;
|
||||
case ex_memset:
|
||||
return e->e.memset.type;
|
||||
|
@ -512,7 +514,16 @@ copy_expr (expr_t *e)
|
|||
case ex_return:
|
||||
n = new_expr ();
|
||||
*n = *e;
|
||||
n->e.retrn.ret_val = copy_expr (n->e.retrn.ret_val);
|
||||
n->e.retrn.ret_val = copy_expr (e->e.retrn.ret_val);
|
||||
return n;
|
||||
case ex_adjstk:
|
||||
n = new_expr ();
|
||||
*n = *e;
|
||||
return n;
|
||||
case ex_with:
|
||||
n = new_expr ();
|
||||
*n = *e;
|
||||
n->e.with.with = copy_expr (e->e.with.with);
|
||||
return n;
|
||||
case ex_count:
|
||||
break;
|
||||
|
@ -1344,6 +1355,27 @@ new_return_expr (expr_t *ret_val)
|
|||
return retrn;
|
||||
}
|
||||
|
||||
expr_t *
|
||||
new_adjstk_expr (int mode, int offset)
|
||||
{
|
||||
expr_t *adj = new_expr ();
|
||||
adj->type = ex_adjstk;
|
||||
adj->e.adjstk.mode = mode;
|
||||
adj->e.adjstk.offset = offset;
|
||||
return adj;
|
||||
}
|
||||
|
||||
expr_t *
|
||||
new_with_expr (int mode, int reg, expr_t *val)
|
||||
{
|
||||
expr_t *with = new_expr ();
|
||||
with->type = ex_with;
|
||||
with->e.with.mode = mode;
|
||||
with->e.with.reg = reg;
|
||||
with->e.with.with = val;
|
||||
return with;
|
||||
}
|
||||
|
||||
static expr_t *
|
||||
param_expr (const char *name, type_t *type)
|
||||
{
|
||||
|
@ -1653,6 +1685,8 @@ has_function_call (expr_t *e)
|
|||
case ex_value:
|
||||
case ex_compound:
|
||||
case ex_memset:
|
||||
case ex_adjstk:
|
||||
case ex_with:
|
||||
return 0;
|
||||
case ex_count:
|
||||
break;
|
||||
|
@ -1745,6 +1779,8 @@ unary_expr (int op, expr_t *e)
|
|||
case ex_memset:
|
||||
case ex_selector:
|
||||
case ex_return:
|
||||
case ex_adjstk:
|
||||
case ex_with:
|
||||
internal_error (e, "unexpected expression type");
|
||||
case ex_uexpr:
|
||||
if (e->e.expr.op == '-') {
|
||||
|
@ -1847,6 +1883,8 @@ unary_expr (int op, expr_t *e)
|
|||
case ex_memset:
|
||||
case ex_selector:
|
||||
case ex_return:
|
||||
case ex_adjstk:
|
||||
case ex_with:
|
||||
internal_error (e, "unexpected expression type");
|
||||
case ex_bool:
|
||||
return new_bool_expr (e->e.bool.false_list,
|
||||
|
@ -1927,6 +1965,8 @@ unary_expr (int op, expr_t *e)
|
|||
case ex_memset:
|
||||
case ex_selector:
|
||||
case ex_return:
|
||||
case ex_adjstk:
|
||||
case ex_with:
|
||||
internal_error (e, "unexpected expression type");
|
||||
case ex_uexpr:
|
||||
if (e->e.expr.op == '~')
|
||||
|
|
|
@ -138,6 +138,8 @@ is_lvalue (const expr_t *expr)
|
|||
case ex_error:
|
||||
case ex_selector:
|
||||
case ex_return:
|
||||
case ex_adjstk:
|
||||
case ex_with:
|
||||
break;
|
||||
case ex_count:
|
||||
internal_error (expr, "invalid expression");
|
||||
|
|
|
@ -673,9 +673,21 @@ build_code_function (symbol_t *fsym, expr_t *state_expr, expr_t *statements)
|
|||
state_expr->next = statements;
|
||||
statements = state_expr;
|
||||
}
|
||||
if (options.code.progsversion == PROG_VERSION) {
|
||||
}
|
||||
function_t *func = fsym->s.func;
|
||||
if (options.code.progsversion == PROG_VERSION) {
|
||||
expr_t *e;
|
||||
e = new_with_expr (2, 1, new_short_expr (0));
|
||||
e->next = statements;
|
||||
e->file = func->def->file;
|
||||
e->line = func->def->line;
|
||||
statements = e;
|
||||
|
||||
e = new_adjstk_expr (0, 0);
|
||||
e->next = statements;
|
||||
e->file = func->def->file;
|
||||
e->line = func->def->line;
|
||||
statements = e;
|
||||
}
|
||||
emit_function (func, statements);
|
||||
if (options.code.progsversion < PROG_VERSION) {
|
||||
// stitch parameter and locals data together with parameters coming
|
||||
|
@ -699,6 +711,13 @@ build_code_function (symbol_t *fsym, expr_t *state_expr, expr_t *statements)
|
|||
merge_spaces (space, func->locals->space, 4);
|
||||
func->locals->space = space;
|
||||
|
||||
// allocate 0 words to force alignment
|
||||
defspace_alloc_aligned_highwater (space, 0, 4);
|
||||
|
||||
dstatement_t *st = &pr.code->code[func->code];
|
||||
if (st->op == OP_ADJSTK) {
|
||||
st->b = -space->size;
|
||||
}
|
||||
merge_spaces (space, func->parameters->space, 4);
|
||||
func->parameters->space = space;
|
||||
}
|
||||
|
|
|
@ -1235,6 +1235,28 @@ statement_return (sblock_t *sblock, expr_t *e)
|
|||
return sblock;
|
||||
}
|
||||
|
||||
static sblock_t *
|
||||
statement_adjstk (sblock_t *sblock, expr_t *e)
|
||||
{
|
||||
statement_t *s = new_statement (st_func, "adjstk", e);
|
||||
s->opa = short_operand (e->e.adjstk.mode, e);
|
||||
s->opb = short_operand (e->e.adjstk.offset, e);
|
||||
|
||||
sblock_add_statement (sblock, s);
|
||||
return sblock;
|
||||
}
|
||||
|
||||
static sblock_t *
|
||||
statement_with (sblock_t *sblock, expr_t *e)
|
||||
{
|
||||
statement_t *s = new_statement (st_func, "with", e);
|
||||
s->opa = short_operand (e->e.with.mode, e);
|
||||
s->opc = short_operand (e->e.with.reg, e);
|
||||
sblock = statement_subexpr (sblock, e->e.with.with, &s->opb);
|
||||
sblock_add_statement (sblock, s);
|
||||
return sblock;
|
||||
}
|
||||
|
||||
static statement_t *
|
||||
lea_statement (operand_t *pointer, operand_t *offset, expr_t *e)
|
||||
{
|
||||
|
@ -1930,6 +1952,8 @@ statement_slist (sblock_t *sblock, expr_t *e)
|
|||
[ex_assign] = statement_assign,
|
||||
[ex_branch] = statement_branch,
|
||||
[ex_return] = statement_return,
|
||||
[ex_adjstk] = statement_adjstk,
|
||||
[ex_with] = statement_with,
|
||||
};
|
||||
|
||||
for (/**/; e; e = e->next) {
|
||||
|
|
Loading…
Reference in a new issue