[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:
Bill Currie 2022-01-21 18:47:12 +09:00
parent 3df46d197f
commit 79bd4dd724
6 changed files with 105 additions and 3 deletions

View file

@ -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.

View file

@ -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)
///@}

View file

@ -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 == '~')

View file

@ -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");

View file

@ -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;
}

View file

@ -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) {