commit 1b88738358055b47dcc0220615d74a10db3f9a9e
parent 05f17977b358ab385e0c0043697f05cbff51b672
Author: Drew DeVault <sir@cmpwn.com>
Date: Thu, 1 Jul 2021 14:18:07 -0400
gen: expand type support somewhat
Signed-off-by: Drew DeVault <sir@cmpwn.com>
Diffstat:
4 files changed, 105 insertions(+), 25 deletions(-)
diff --git a/include/gen.h b/include/gen.h
@@ -20,6 +20,7 @@ struct gen_temp {
struct gen_arch {
const struct qbe_type *ptr;
+ const struct qbe_type *sz;
};
struct gen_context {
@@ -41,11 +42,11 @@ void gen(const struct unit *unit,
// qinstr.c
enum qbe_instr alloc_for_align(size_t align);
-enum qbe_instr store_for_type(const struct type *type);
-enum qbe_instr load_for_type(const struct type *type);
+enum qbe_instr store_for_type(struct gen_context *ctx, const struct type *type);
+enum qbe_instr load_for_type(struct gen_context *ctx, const struct type *type);
// qtype.c
const struct qbe_type *qtype_lookup(struct gen_context *ctx,
- const struct type *type);
+ const struct type *type, bool xtype);
#endif
diff --git a/src/gen.c b/src/gen.c
@@ -18,14 +18,14 @@ gen_name(struct gen_context *ctx, const char *fmt)
return str;
}
-// Initializes a qval with a reference to a gen temporary.
+// Initializes a qval with a qbe temporary for a given gen temporary.
static void
qval_temp(struct gen_context *ctx,
- struct qbe_value *out,
- const struct gen_temp *temp)
+ struct qbe_value *out,
+ const struct gen_temp *temp)
{
out->kind = QV_TEMPORARY;
- out->type = qtype_lookup(ctx, temp->type);
+ out->type = qtype_lookup(ctx, temp->type, false);
out->name = temp->name;
}
@@ -60,7 +60,7 @@ load_temp(struct gen_context *ctx,
struct qbe_value *out,
const struct gen_temp *temp)
{
- const struct qbe_type *qtype = qtype_lookup(ctx, temp->type);
+ const struct qbe_type *qtype = qtype_lookup(ctx, temp->type, true);
assert(qtype->stype != Q__VOID);
out->kind = QV_TEMPORARY;
@@ -73,7 +73,7 @@ load_temp(struct gen_context *ctx,
struct qbe_value addr;
qval_temp(ctx, &addr, temp);
- enum qbe_instr instr = load_for_type(temp->type);
+ enum qbe_instr instr = load_for_type(ctx, temp->type);
pushi(ctx->current, out, instr, &addr, NULL);
}
}
@@ -142,7 +142,7 @@ gen_expr_constant(struct gen_context *ctx,
abort(); // Invariant
}
- enum qbe_instr instr = store_for_type(expr->result);
+ enum qbe_instr instr = store_for_type(ctx, expr->result);
pushi(ctx->current, NULL, instr, &qval, &qout, NULL);
}
@@ -251,7 +251,7 @@ gen_function_decl(struct gen_context *ctx, const struct declaration *decl)
if (type_dealias(fntype->func.result)->storage != STORAGE_VOID) {
ctx->rval = alloc_temp(ctx, fntype->func.result, "rval.%d");
- qdef->func.returns = qtype_lookup(ctx, fntype->func.result);
+ qdef->func.returns = qtype_lookup(ctx, fntype->func.result, true);
} else {
qdef->func.returns = &qbe_void;
}
@@ -299,6 +299,7 @@ gen(const struct unit *unit, struct type_store *store, struct qbe_program *out)
.ns = unit->ns,
.arch = {
.ptr = &qbe_long,
+ .sz = &qbe_long,
},
};
ctx.out->next = &ctx.out->defs;
diff --git a/src/qinstr.c b/src/qinstr.c
@@ -1,7 +1,9 @@
#include <assert.h>
#include <stdlib.h>
+#include "gen.h"
#include "qbe.h"
#include "types.h"
+#include "type_store.h"
enum qbe_instr
alloc_for_align(size_t align)
@@ -19,7 +21,7 @@ alloc_for_align(size_t align)
}
enum qbe_instr
-store_for_type(const struct type *type)
+store_for_type(struct gen_context *ctx, const struct type *type)
{
switch (type->storage) {
case STORAGE_CHAR:
@@ -43,13 +45,28 @@ store_for_type(const struct type *type)
return Q_STORES;
case STORAGE_F64:
return Q_STORED;
- case STORAGE_ENUM:
- case STORAGE_POINTER:
case STORAGE_SIZE:
+ switch (ctx->arch.sz->stype) {
+ case Q_LONG:
+ return Q_STOREL;
+ default:
+ assert(0);
+ }
+ break;
+ case STORAGE_POINTER:
case STORAGE_UINTPTR:
- assert(0); // TODO
+ switch (ctx->arch.ptr->stype) {
+ case Q_LONG:
+ return Q_STOREL;
+ default:
+ assert(0);
+ }
+ break;
+ case STORAGE_ENUM:
+ return store_for_type(ctx, builtin_type_for_storage(
+ type->_enum.storage, false));
case STORAGE_ALIAS:
- return store_for_type(type->alias.type);
+ return store_for_type(ctx, type->alias.type);
case STORAGE_ARRAY:
case STORAGE_FCONST:
case STORAGE_FUNCTION:
@@ -68,7 +85,7 @@ store_for_type(const struct type *type)
}
enum qbe_instr
-load_for_type(const struct type *type)
+load_for_type(struct gen_context *ctx, const struct type *type)
{
switch (type->storage) {
case STORAGE_I8:
@@ -95,13 +112,28 @@ load_for_type(const struct type *type)
return Q_LOADS;
case STORAGE_F64:
return Q_LOADD;
- case STORAGE_ENUM:
- case STORAGE_POINTER:
case STORAGE_SIZE:
+ switch (ctx->arch.sz->stype) {
+ case Q_LONG:
+ return Q_LOADL;
+ default:
+ assert(0);
+ }
+ break;
+ case STORAGE_POINTER:
case STORAGE_UINTPTR:
- assert(0); // TODO
+ switch (ctx->arch.ptr->stype) {
+ case Q_LONG:
+ return Q_LOADL;
+ default:
+ assert(0);
+ }
+ break;
+ case STORAGE_ENUM:
+ return load_for_type(ctx, builtin_type_for_storage(
+ type->_enum.storage, false));
case STORAGE_ALIAS:
- return store_for_type(type->alias.type);
+ return load_for_type(ctx, type->alias.type);
case STORAGE_ARRAY:
case STORAGE_FCONST:
case STORAGE_FUNCTION:
diff --git a/src/qtype.c b/src/qtype.c
@@ -1,12 +1,58 @@
#include <assert.h>
+#include <stdlib.h>
#include "gen.h"
#include "qbe.h"
#include "types.h"
const struct qbe_type *qtype_lookup(
struct gen_context *ctx,
- const struct type *type) {
- // TODO
- assert(type->storage == STORAGE_INT);
- return &qbe_word;
+ const struct type *type,
+ bool xtype) {
+ switch (type->storage) {
+ case STORAGE_U8:
+ case STORAGE_I8:
+ case STORAGE_CHAR:
+ return xtype ? &qbe_byte : &qbe_word;
+ case STORAGE_I16:
+ case STORAGE_U16:
+ return xtype ? &qbe_half : &qbe_word;
+ case STORAGE_I32:
+ case STORAGE_U32:
+ case STORAGE_INT:
+ case STORAGE_UINT:
+ case STORAGE_RUNE:
+ case STORAGE_BOOL:
+ return &qbe_word;
+ case STORAGE_U64:
+ case STORAGE_I64:
+ return &qbe_long;
+ case STORAGE_SIZE:
+ return ctx->arch.sz;
+ case STORAGE_UINTPTR:
+ case STORAGE_POINTER:
+ return ctx->arch.ptr;
+ case STORAGE_F32:
+ return &qbe_single;
+ case STORAGE_F64:
+ return &qbe_double;
+ case STORAGE_ENUM:
+ assert(0); // TODO
+ case STORAGE_ALIAS:
+ return qtype_lookup(ctx, type->alias.type, xtype);
+ case STORAGE_ARRAY:
+ case STORAGE_SLICE:
+ case STORAGE_STRING:
+ case STORAGE_STRUCT:
+ case STORAGE_TAGGED:
+ case STORAGE_TUPLE:
+ case STORAGE_UNION:
+ assert(0); // TODO
+ case STORAGE_VOID:
+ case STORAGE_FUNCTION:
+ case STORAGE_NULL:
+ case STORAGE_FCONST:
+ case STORAGE_ICONST:
+ abort(); // Invariant
+ }
+ abort(); // Invariant
}