harec

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

commit 5befc342b962af9abb3829b13a7c720552b63deb
parent 56eac2ff6b4b6750b6eeef5ae7862497758c4f50
Author: Drew DeVault <sir@cmpwn.com>
Date:   Thu,  1 Jul 2021 10:04:57 -0400

gen: basic temporary allocation

Signed-off-by: Drew DeVault <sir@cmpwn.com>

Diffstat:
Minclude/gen.h | 11+++++++++++
Minclude/qbe.h | 19+------------------
Msrc/gen.c | 83+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
Msrc/qbe.c | 5-----
Msrc/qinstr.c | 16+++++++++++++++-
5 files changed, 106 insertions(+), 28 deletions(-)

diff --git a/include/gen.h b/include/gen.h @@ -1,7 +1,9 @@ #ifndef HAREC_GEN_H #define HAREC_GEN_H +#include <stddef.h> #include "identifier.h" #include "qbe.h" +#include "types.h" enum fixed_aborts { ABORT_OOB = 0, @@ -17,7 +19,16 @@ void gen(const struct unit *unit, struct qbe_program *out); struct gen_context { struct qbe_program *out; struct identifier *ns; + struct qbe_func *current; uint64_t id; }; +struct gen_temp { + char *name; + const struct type *type; +}; + +// qinstr.c +enum qbe_instr alloc_for_align(size_t align); + #endif diff --git a/include/qbe.h b/include/qbe.h @@ -2,6 +2,7 @@ #define HAREC_QBE_H #include <stdarg.h> #include <stdbool.h> +#include <stddef.h> #include <stdint.h> enum qbe_stype { @@ -54,27 +55,9 @@ enum qbe_value_kind { QV_TEMPORARY, }; -// Represents a value which can be an argument to a QBE instruction. -// -// If the value is a non-aggregate type, indirect determines if it is a pointer -// to the value, or the value itself. -// -// let x = 10; // %x =l alloc4 4; storew 10, %x -// // qbe_value{QV_TEMPORARY, =l, true, %x} -// x; // %temp =w loadw %x -// // qbe_value{QV_TEMPORARY, =w, false, %temp} -// -// Aggregate types cannot be directly stored in temporaries, so if direct is -// set, the value is still a pointer to an aggregate type. -// -// let x = [1, 2, 3]; // %x =l alloc4 12; storew 1, %x; ... -// // qbe_value{QV_TEMPORARY, :aggregate, true, %x } -// let y = &x; // %y =l alloc8 8; storel %x, %y -// // qbe_value{QV_TEMPORARY, =l, true, %y } struct qbe_value { enum qbe_value_kind kind; const struct qbe_type *type; - bool indirect; union { char *name; uint32_t wval; diff --git a/src/gen.c b/src/gen.c @@ -4,12 +4,78 @@ #include "expr.h" #include "gen.h" #include "scope.h" +#include "types.h" #include "util.h" +static char * +gen_name(struct gen_context *ctx, const char *fmt) +{ + int n = snprintf(NULL, 0, fmt, ctx->id); + char *str = xcalloc(1, n + 1); + snprintf(str, n + 1, fmt, ctx->id); + ++ctx->id; + return str; +} + +static struct gen_temp * +alloc_temp(struct gen_context *ctx, const struct type *type, const char *fmt) +{ + assert(type->size != 0 && type->size != SIZE_UNDEFINED); + + struct gen_temp *temp = xcalloc(1, sizeof(struct gen_temp)); + temp->type = type; + temp->name = gen_name(ctx, fmt); + + // TODO: Look up qbe type + assert(type_dealias(type)->storage == STORAGE_INT); + struct qbe_value out = { + .kind = QV_TEMPORARY, + .type = &qbe_word, + .name = temp->name, + }; + struct qbe_value size; + constl(&size, type->size); + pushprei(ctx->current, &out, alloc_for_align(type->align), &size, NULL); + + return temp; +} + static void gen_expr(struct gen_context *ctx, const struct expression *expr) { - assert(0); // TODO + switch (expr->type) { + case EXPR_ACCESS: + case EXPR_ALLOC: + case EXPR_APPEND: + case EXPR_ASSERT: + case EXPR_ASSIGN: + case EXPR_BINARITHM: + case EXPR_BINDING: + case EXPR_BREAK: + case EXPR_CONTINUE: + case EXPR_CALL: + case EXPR_CAST: + case EXPR_CONSTANT: + case EXPR_DEFER: + case EXPR_DELETE: + case EXPR_FOR: + case EXPR_FREE: + case EXPR_IF: + case EXPR_INSERT: + case EXPR_LIST: + case EXPR_MATCH: + case EXPR_MEASURE: + assert(0); // TODO + case EXPR_PROPAGATE: + assert(0); // Lowered in check (XXX: for now...) + case EXPR_RETURN: + case EXPR_SLICE: + case EXPR_STRUCT: + case EXPR_SWITCH: + case EXPR_TUPLE: + case EXPR_UNARITHM: + assert(0); // TODO + } } static void @@ -28,20 +94,29 @@ gen_function_decl(struct gen_context *ctx, const struct declaration *decl) qdef->exported = decl->exported; qdef->name = decl->symbol ? strdup(decl->symbol) : ident_to_sym(&decl->ident); + ctx->current = &qdef->func; struct qbe_statement start_label = {0}; genl(&start_label, &ctx->id, "start.%d"); push(&qdef->func.prelude, &start_label); - // TODO: Allocate parameters, return value - assert(fntype->func.result->storage == STORAGE_VOID); + if (type_dealias(fntype->func.result)->storage != STORAGE_VOID) { + alloc_temp(ctx, fntype->func.result, "rval.%d"); + // TODO: Look up qbe type + assert(type_dealias(fntype->func.result)->storage == STORAGE_INT); + qdef->func.returns = &qbe_word; + } else { + qdef->func.returns = &qbe_void; + } + + // TODO: Allocate parameters assert(!func->scope->objects); - qdef->func.returns = &qbe_void; pushl(&qdef->func, &ctx->id, "body.%d"); gen_expr(ctx, func->body); qbe_append_def(ctx->out, qdef); + ctx->current = NULL; } static void diff --git a/src/qbe.c b/src/qbe.c @@ -315,7 +315,6 @@ constw(struct qbe_value *val, uint32_t w) val->kind = QV_CONST; val->type = &qbe_word; val->wval = w; - val->indirect = false; } void @@ -324,7 +323,6 @@ constl(struct qbe_value *val, uint64_t l) val->kind = QV_CONST; val->type = &qbe_long; val->lval = l; - val->indirect = false; } void @@ -333,7 +331,6 @@ consts(struct qbe_value *val, float s) val->kind = QV_CONST; val->type = &qbe_single; val->sval = s; - val->indirect = false; } void @@ -342,7 +339,6 @@ constd(struct qbe_value *val, double d) val->kind = QV_CONST; val->type = &qbe_double; val->dval = d; - val->indirect = false; } void @@ -350,5 +346,4 @@ const_void(struct qbe_value *val) { val->kind = QV_CONST; val->type = &qbe_void; - val->indirect = false; } diff --git a/src/qinstr.c b/src/qinstr.c @@ -1,2 +1,16 @@ -void placeholder_qinstr() { +#include "qbe.h" + +enum qbe_instr +alloc_for_align(size_t align) +{ + switch (align) { + case 1: + case 2: + case 4: + return Q_ALLOC4; + case 8: + return Q_ALLOC8; + default: + return Q_ALLOC16; + } }