commit e03bafbc84892e59bc7054b5433083d88def7298
parent 4ba09b87472e233e2a2d7858fcd4f723a8553a67
Author: Drew DeVault <sir@cmpwn.com>
Date: Sat, 31 Jul 2021 19:35:46 +0200
gen: binding expressions
Signed-off-by: Drew DeVault <sir@cmpwn.com>
Diffstat:
5 files changed, 77 insertions(+), 45 deletions(-)
diff --git a/include/gen.h b/include/gen.h
@@ -13,6 +13,11 @@ enum fixed_aborts {
ABORT_STATIC_EXCEEDED = 3,
};
+struct gen_arch {
+ const struct qbe_type *ptr;
+ const struct qbe_type *sz;
+};
+
enum gen_value_kind {
GV_CONST,
GV_GLOBAL,
@@ -31,9 +36,9 @@ struct gen_value {
};
};
-struct gen_arch {
- const struct qbe_type *ptr;
- const struct qbe_type *sz;
+struct gen_binding {
+ struct gen_value value;
+ struct gen_binding *next;
};
struct gen_context {
@@ -46,7 +51,7 @@ struct gen_context {
struct qbe_func *current;
const struct type *functype;
- const char *end;
+ struct gen_binding *bindings;
};
struct unit;
@@ -58,6 +63,7 @@ void gen(const struct unit *unit,
// genutil.c
char *gen_name(struct gen_context *ctx, const char *fmt);
struct qbe_value mkqval(struct gen_context *ctx, struct gen_value *value);
+struct qbe_value mklval(struct gen_context *ctx, struct gen_value *value);
// qinstr.c
enum qbe_instr alloc_for_align(size_t align);
diff --git a/include/qbe.h b/include/qbe.h
@@ -262,10 +262,6 @@ void push(struct qbe_statements *stmts, struct qbe_statement *stmt);
struct qbe_value *qval_dup(const struct qbe_value *val);
-void constw(struct qbe_value *val, uint32_t l);
-void constl(struct qbe_value *val, uint64_t l);
-void consts(struct qbe_value *val, float l);
-void constd(struct qbe_value *val, double l);
-void const_void(struct qbe_value *val);
+struct qbe_value constl(uint64_t l);
#endif
diff --git a/src/gen.c b/src/gen.c
@@ -13,10 +13,59 @@ static const struct gen_value gv_void = {
.type = &builtin_type_void,
};
+static void
+gen_store(struct gen_context *ctx,
+ struct gen_value object,
+ struct gen_value value)
+{
+ switch (type_dealias(object.type)->storage) {
+ case STORAGE_ARRAY:
+ case STORAGE_ENUM:
+ case STORAGE_SLICE:
+ case STORAGE_STRING:
+ case STORAGE_STRUCT:
+ case STORAGE_TAGGED:
+ case STORAGE_TUPLE:
+ case STORAGE_UNION:
+ assert(0); // TODO
+ default:
+ break; // no-op
+ }
+
+ struct qbe_value qobj = mkqval(ctx, &object),
+ qval = mkqval(ctx, &value);
+ enum qbe_instr qi = store_for_type(ctx, object.type);
+ pushi(ctx->current, NULL, qi, &qval, &qobj, NULL);
+}
+
static struct gen_value gen_expr(struct gen_context *ctx,
const struct expression *expr);
static struct gen_value
+gen_expr_binding(struct gen_context *ctx, const struct expression *expr)
+{
+ for (const struct expression_binding *binding = &expr->binding;
+ binding; binding = binding->next) {
+ const struct type *type = binding->initializer->result;
+ struct gen_binding *gb = xcalloc(1, sizeof(struct gen_binding));
+ gb->value.kind = GV_TEMP;
+ gb->value.type = type;
+ gb->value.name = gen_name(ctx, "binding.%d");
+ gb->next = ctx->bindings;
+ ctx->bindings = gb;
+
+ struct qbe_value qv = mklval(ctx, &gb->value);
+ struct qbe_value sz = constl(type->size);
+ enum qbe_instr qi = alloc_for_align(type->align);
+ pushprei(ctx->current, &qv, qi, &sz, NULL);
+
+ struct gen_value init = gen_expr(ctx, binding->initializer);
+ gen_store(ctx, gb->value, init);
+ }
+ return gv_void;
+}
+
+static struct gen_value
gen_expr_const(struct gen_context *ctx, const struct expression *expr)
{
struct gen_value val = {
@@ -102,7 +151,9 @@ gen_expr(struct gen_context *ctx, const struct expression *expr)
case EXPR_ASSERT:
case EXPR_ASSIGN:
case EXPR_BINARITHM:
+ assert(0); // TODO
case EXPR_BINDING:
+ return gen_expr_binding(ctx, expr);
case EXPR_BREAK:
case EXPR_CALL:
case EXPR_CAST:
diff --git a/src/genutil.c b/src/genutil.c
@@ -35,3 +35,11 @@ mkqval(struct gen_context *ctx, struct gen_value *value)
qval.type = qtype_lookup(ctx, value->type, true);
return qval;
}
+
+struct qbe_value
+mklval(struct gen_context *ctx, struct gen_value *value)
+{
+ struct qbe_value qval = mkqval(ctx, value);
+ qval.type = ctx->arch.ptr;
+ return qval;
+}
diff --git a/src/qbe.c b/src/qbe.c
@@ -265,41 +265,12 @@ pushc(struct qbe_func *func, const char *fmt, ...)
push(&func->body, &stmt);
}
-void
-constw(struct qbe_value *val, uint32_t w)
-{
- val->kind = QV_CONST;
- val->type = &qbe_word;
- val->wval = w;
-}
-
-void
-constl(struct qbe_value *val, uint64_t l)
-{
- val->kind = QV_CONST;
- val->type = &qbe_long;
- val->lval = l;
-}
-
-void
-consts(struct qbe_value *val, float s)
-{
- val->kind = QV_CONST;
- val->type = &qbe_single;
- val->sval = s;
-}
-
-void
-constd(struct qbe_value *val, double d)
-{
- val->kind = QV_CONST;
- val->type = &qbe_double;
- val->dval = d;
-}
-
-void
-const_void(struct qbe_value *val)
+struct qbe_value
+constl(uint64_t l)
{
- val->kind = QV_CONST;
- val->type = &qbe_void;
+ return (struct qbe_value){
+ .kind = QV_CONST,
+ .type = &qbe_long,
+ .lval = l,
+ };
}