commit 031a921a7b929d8517d720cadf04c9c4e7da3148
parent 2773bd15433e9134c064bae8fc98c009c6a19d05
Author: Drew DeVault <sir@cmpwn.com>
Date: Fri, 25 Dec 2020 16:18:54 -0500
gen: introduce function prelude, rehome allocations
This isn't super important now, but it'll matter later when we introduce
loops & branches and such what.
Diffstat:
4 files changed, 45 insertions(+), 21 deletions(-)
diff --git a/include/qbe.h b/include/qbe.h
@@ -175,11 +175,15 @@ struct qbe_func_param {
struct qbe_func_param *next;
};
+struct qbe_statements {
+ size_t ln, sz;
+ struct qbe_statement *stmts;
+};
+
struct qbe_func {
const struct qbe_type *returns;
struct qbe_func_param *params;
- size_t blen, bsiz;
- struct qbe_statement *body;
+ struct qbe_statements prelude, body;
};
enum qbe_deftype {
@@ -207,9 +211,10 @@ void qbe_append_def(struct qbe_program *prog, struct qbe_def *def);
void geni(struct qbe_statement *stmt, const struct qbe_value *out, enum qbe_instr instr, ...);
const char *genl(struct qbe_statement *stmt, uint64_t *id, const char *fmt);
void pushi(struct qbe_func *func, const struct qbe_value *out, enum qbe_instr instr, ...);
+void pushprei(struct qbe_func *func, const struct qbe_value *out, enum qbe_instr instr, ...);
const char *pushl(struct qbe_func *func, uint64_t *id, const char *fmt);
void pushc(struct qbe_func *func, const char *fmt, ...);
-void push(struct qbe_func *func, struct qbe_statement *stmt);
+void push(struct qbe_statements *stmts, struct qbe_statement *stmt);
struct qbe_value *qval_dup(const struct qbe_value *val);
diff --git a/src/emit.c b/src/emit.c
@@ -147,8 +147,13 @@ emit_func(struct qbe_def *def, FILE *out)
}
fprintf(out, ") {\n");
- for (size_t i = 0; i < def->func.blen; ++i) {
- struct qbe_statement *stmt = &def->func.body[i];
+ for (size_t i = 0; i < def->func.prelude.ln; ++i) {
+ struct qbe_statement *stmt = &def->func.prelude.stmts[i];
+ emit_stmt(stmt, out);
+ }
+
+ for (size_t i = 0; i < def->func.body.ln; ++i) {
+ struct qbe_statement *stmt = &def->func.body.stmts[i];
emit_stmt(stmt, out);
}
diff --git a/src/gen.c b/src/gen.c
@@ -56,7 +56,7 @@ alloc_temp(struct gen_context *ctx, struct qbe_value *val,
struct qbe_value size;
constl(&size, type->size);
- pushi(ctx->current, val, alloc_for_align(type->align), &size, NULL);
+ pushprei(ctx->current, val, alloc_for_align(type->align), &size, NULL);
}
static struct gen_binding *
@@ -315,7 +315,7 @@ gen_call(struct gen_context *ctx,
next = &arg->next;
}
- push(ctx->current, &call);
+ push(&ctx->current->body, &call);
}
static void
@@ -555,7 +555,9 @@ gen_function_decl(struct gen_context *ctx, const struct declaration *decl)
qdef->func.returns = qtype_for_type(ctx, fntype->func.result, false);
ctx->current = &qdef->func;
- pushl(&qdef->func, &ctx->id, "start.%d");
+ struct qbe_statement start_label = {0};
+ genl(&start_label, &ctx->id, "start.%d");
+ push(&qdef->func.prelude, &start_label);
struct qbe_func_param *param, **next = &qdef->func.params;
struct scope_object *obj = decl->func.scope->objects;
@@ -600,7 +602,7 @@ gen_function_decl(struct gen_context *ctx, const struct declaration *decl)
pushl(&qdef->func, &ctx->id, "body.%d");
gen_expression(ctx, func->body, ctx->return_value);
- push(&qdef->func, &end_label);
+ push(&qdef->func.body, &end_label);
if (fntype->func.result->storage != TYPE_STORAGE_VOID) {
struct qbe_value load = {0};
diff --git a/src/qbe.c b/src/qbe.c
@@ -209,18 +209,18 @@ genl(struct qbe_statement *stmt, uint64_t *id, const char *fmt)
}
void
-push(struct qbe_func *func, struct qbe_statement *stmt)
+push(struct qbe_statements *stmts, struct qbe_statement *stmt)
{
- if (!func->body) {
- func->bsiz = 256;
- func->blen = 0;
- func->body = xcalloc(1, sizeof(struct qbe_statement) * func->bsiz);
+ if (!stmts->stmts) {
+ stmts->sz = 256;
+ stmts->ln = 0;
+ stmts->stmts = xcalloc(1, sizeof(struct qbe_statement) * stmts->sz);
}
- if (func->blen + 1 < func->bsiz) {
- func->bsiz *= 2;
- func->body = xrealloc(func->body, func->bsiz);
+ if (stmts->ln + 1 < stmts->sz) {
+ stmts->sz *= 2;
+ stmts->stmts = xrealloc(stmts->stmts, stmts->sz);
}
- func->body[func->blen++] = *stmt;
+ stmts->stmts[stmts->ln++] = *stmt;
}
void
@@ -232,7 +232,19 @@ pushi(struct qbe_func *func, const struct qbe_value *out,
va_start(ap, instr);
va_geni(&stmt, instr, out, ap);
va_end(ap);
- push(func, &stmt);
+ push(&func->body, &stmt);
+}
+
+void
+pushprei(struct qbe_func *func, const struct qbe_value *out,
+ enum qbe_instr instr, ...)
+{
+ struct qbe_statement stmt = {0};
+ va_list ap;
+ va_start(ap, instr);
+ va_geni(&stmt, instr, out, ap);
+ va_end(ap);
+ push(&func->prelude, &stmt);
}
const char *
@@ -240,7 +252,7 @@ pushl(struct qbe_func *func, uint64_t *id, const char *fmt)
{
struct qbe_statement stmt = {0};
const char *l = genl(&stmt, id, fmt);
- push(func, &stmt);
+ push(&func->body, &stmt);
return l;
}
@@ -260,7 +272,7 @@ pushc(struct qbe_func *func, const char *fmt, ...)
va_end(ap);
stmt.comment = str;
- push(func, &stmt);
+ push(&func->body, &stmt);
}
void