commit 4d40b91c5b4fee2b07fe95b666392f3d03667011
parent 3ded0a2d4dee1d9715a4a85a6836be71b3bdb04e
Author: Drew DeVault <sir@cmpwn.com>
Date: Sun, 26 Sep 2021 09:46:23 +0200
gen: rig up more typeinfo structures
Diffstat:
4 files changed, 191 insertions(+), 10 deletions(-)
diff --git a/rt/Makefile b/rt/Makefile
@@ -18,7 +18,7 @@ libhart.a: harec $(libhart_srcs) $(libhart_objs) $(rtstart) types/types.o
@$(QBE) -o $@.s $@.ssa
@$(AS) -g -o $@.o $@.s
@$(AR) -csr $@ $@.o $(libhart_objs) types/types.o
- #@rm $@.o $@.s $@.ssa
+ @rm $@.o $@.s $@.ssa
clean-rt:
@rm -f libhart.a $(libhart_objs) $(rtstart)
diff --git a/src/gen.c b/src/gen.c
@@ -2503,7 +2503,7 @@ gen_expr_tuple_at(struct gen_context *ctx,
}
}
-static void gen_type_info(struct gen_context *ctx,
+static struct qbe_data_item *gen_type_info(struct gen_context *ctx,
const struct type *type, struct qbe_data_item *item);
static struct gen_value
@@ -3281,7 +3281,7 @@ gen_ident_data(struct gen_context *ctx,
return item;
}
-static void
+static struct qbe_data_item *
gen_type_info(struct gen_context *ctx,
const struct type *type,
struct qbe_data_item *item)
@@ -3333,6 +3333,7 @@ gen_type_info(struct gen_context *ctx,
size_t len = 0;
struct qbe_def *def;
struct qbe_data_item *subitem;
+ struct gen_value ref;
switch (type->storage) {
case STORAGE_FCONST:
case STORAGE_ICONST:
@@ -3348,6 +3349,8 @@ gen_type_info(struct gen_context *ctx,
case STORAGE_NULL:
case STORAGE_RUNE:
case STORAGE_SIZE:
+ case STORAGE_STRING:
+ case STORAGE_TYPE:
case STORAGE_U16:
case STORAGE_U32:
case STORAGE_U64:
@@ -3391,7 +3394,7 @@ gen_type_info(struct gen_context *ctx,
item->next = xcalloc(1, sizeof(struct qbe_data_item));
item = item->next;
- struct gen_value ref = mktyperef(ctx, type->alias.type);
+ ref = mktyperef(ctx, type->alias.type);
item->type = QD_VALUE;
item->value.kind = QV_GLOBAL;
item->value.type = &qbe_long;
@@ -3474,20 +3477,143 @@ gen_type_info(struct gen_context *ctx,
item->value = constl(len);
break;
case STORAGE_ARRAY:
- case STORAGE_FUNCTION:
- case STORAGE_POINTER:
+ *repr_name = "array";
+ item->value = constw(type_hash(&repr));
+ item->next = xcalloc(1, sizeof(struct qbe_data_item));
+ item = item->next;
+
+ item->type = QD_ZEROED;
+ item->zeroed = 4;
+ item->next = xcalloc(1, sizeof(struct qbe_data_item));
+ item = item->next;
+
+ item->type = QD_VALUE;
+ item->value = constl(type->array.length);
+ item->next = xcalloc(1, sizeof(struct qbe_data_item));
+ item = item->next;
+
+ ref = mktyperef(ctx, type->array.members);
+ item->type = QD_VALUE;
+ item->value.kind = QV_GLOBAL;
+ item->value.type = &qbe_long;
+ item->value.name = ref.name;
+ break;
case STORAGE_SLICE:
- case STORAGE_STRING:
+ *repr_name = "slice_repr";
+ item->value = constw(type_hash(&repr));
+ item->next = xcalloc(1, sizeof(struct qbe_data_item));
+ item = item->next;
+
+ item->type = QD_ZEROED;
+ item->zeroed = 4;
+ item->next = xcalloc(1, sizeof(struct qbe_data_item));
+ item = item->next;
+
+ ref = mktyperef(ctx, type->array.members);
+ item->type = QD_VALUE;
+ item->value.kind = QV_GLOBAL;
+ item->value.type = &qbe_long;
+ item->value.name = ref.name;
+ break;
+ case STORAGE_POINTER:
+ *repr_name = "pointer";
+ item->value = constw(type_hash(&repr));
+ item->next = xcalloc(1, sizeof(struct qbe_data_item));
+ item = item->next;
+
+ item->type = QD_ZEROED;
+ item->zeroed = 4;
+ item->next = xcalloc(1, sizeof(struct qbe_data_item));
+ item = item->next;
+
+ ref = mktyperef(ctx, type->pointer.referent);
+ item->type = QD_VALUE;
+ item->value.kind = QV_GLOBAL;
+ item->value.type = &qbe_long;
+ item->value.name = ref.name;
+ item->next = xcalloc(1, sizeof(struct qbe_data_item));
+ item = item->next;
+
+ item->type = QD_VALUE;
+ item->value = constw(type->pointer.flags);
+ item->value.type = &qbe_word;
+ item->next = xcalloc(1, sizeof(struct qbe_data_item));
+ item = item->next;
+
+ item->type = QD_ZEROED;
+ item->zeroed = 7;
+ break;
+ case STORAGE_FUNCTION:
+ *repr_name = "func";
+ item->value = constw(type_hash(&repr));
+ item->next = xcalloc(1, sizeof(struct qbe_data_item));
+ item = item->next;
+
+ item->type = QD_ZEROED;
+ item->zeroed = 4;
+ item->next = xcalloc(1, sizeof(struct qbe_data_item));
+ item = item->next;
+
+ ref = mktyperef(ctx, type->func.result);
+ item->type = QD_VALUE;
+ item->value.kind = QV_GLOBAL;
+ item->value.type = &qbe_long;
+ item->value.name = ref.name;
+ item->next = xcalloc(1, sizeof(struct qbe_data_item));
+ item = item->next;
+
+ item->type = QD_VALUE;
+ item->value = constw(type->func.variadism);
+ item->next = xcalloc(1, sizeof(struct qbe_data_item));
+ item = item->next;
+
+ item->type = QD_VALUE;
+ item->value = constw(type->func.flags);
+ item->next = xcalloc(1, sizeof(struct qbe_data_item));
+ item = item->next;
+
+ def = xcalloc(1, sizeof(struct qbe_def));
+ def->name = gen_name(ctx, "sldata.%d");
+ def->kind = Q_DATA;
+ subitem = &def->data.items;
+ for (struct type_func_param *param = type->func.params;
+ param; param = param->next) {
+ ref = mktyperef(ctx, param->type);
+ subitem->type = QD_VALUE;
+ subitem->value.kind = QV_GLOBAL;
+ subitem->value.type = &qbe_long;
+ subitem->value.name = ref.name;
+ if (param->next) {
+ subitem->next = xcalloc(1, sizeof(struct qbe_data_item));
+ subitem = subitem->next;
+ }
+ ++len;
+ }
+ qbe_append_def(ctx->out, def);
+
+ item->type = QD_VALUE;
+ item->value.kind = QV_GLOBAL;
+ item->value.type = &qbe_long;
+ item->value.name = strdup(def->name);
+ item->next = xcalloc(1, sizeof(struct qbe_data_item));
+ item = item->next;
+ item->type = QD_VALUE;
+ item->value = constl(len);
+ item->next = xcalloc(1, sizeof(struct qbe_data_item));
+ item = item->next;
+ item->type = QD_VALUE;
+ item->value = constl(len);
+ break;
case STORAGE_STRUCT:
case STORAGE_TAGGED:
case STORAGE_TUPLE:
case STORAGE_UNION:
- case STORAGE_TYPE:
// XXX: Temporary code to make sure code in the wild builds
// while we flesh out these types
item->value = constw(0);
break;
}
+ return item;
}
static void
diff --git a/tests/34-reflect.ha b/tests/34-reflect.ha
@@ -73,8 +73,63 @@ fn enums() void = {
};
};
+fn arrays() void = {
+ let ty = types::reflect(type([42]int));
+ assert(ty.sz == 42 * size(int));
+ assert(ty.al == size(int));
+ let ar = ty.repr as types::array;
+ assert(ar.length == 42);
+ assert(ar.members == type(int));
+};
+
+fn slices() void = {
+ let ty = types::reflect(type([]int));
+ assert(ty.sz == size(*int) + size(size) + size(size));
+ assert(ty.al == size(*int));
+ let sl = ty.repr as types::slice_repr;
+ assert(sl == type(int));
+};
+
+fn pointers() void = {
+ let ty = types::reflect(type(*int));
+ assert(ty.sz == size(*int));
+ assert(ty.al == size(*int));
+ let pt = ty.repr as types::pointer;
+ assert(pt.secondary == type(int));
+ assert(pt.flags == 0);
+
+ let ty = types::reflect(type(nullable *int));
+ assert(ty.sz == size(*int));
+ assert(ty.al == size(*int));
+ let pt = ty.repr as types::pointer;
+ assert(pt.secondary == type(int));
+ assert(pt.flags == types::pointer_flags::NULLABLE);
+};
+
+fn functions() void = {
+ let ty = types::reflect(type(fn(x: int, y: int) int));
+ assert(ty.sz == types::SIZE_UNDEFINED);
+ assert(ty.al == types::SIZE_UNDEFINED);
+ let func = ty.repr as types::func;
+ assert(func.result == type(int));
+ assert(func.variadism == types::variadism::NONE);
+ assert(func.flags == 0);
+ assert(len(func.params) == 2);
+ assert(func.params[0] == type(int));
+ assert(func.params[1] == type(int));
+
+ let ty = types::reflect(type(@noreturn fn(x: int, y: int, z: int...) int));
+ let func = ty.repr as types::func;
+ assert(func.variadism == types::variadism::HARE);
+ assert(func.flags == types::func_flags::NORETURN);
+};
+
export fn main() void = {
builtins();
aliases();
enums();
+ arrays();
+ slices();
+ pointers();
+ functions();
};
diff --git a/types/reflect.ha b/types/reflect.ha
@@ -63,7 +63,7 @@ export type enumerated = struct {
};
// Indicates the variadism of a [[func]].
-export type variadism = enum {
+export type variadism = enum uint {
NONE,
C,
HARE,
@@ -90,7 +90,7 @@ export type pointer_flags = enum u8 {
// *int
export type pointer = struct {
- referent: type,
+ secondary: type,
flags: pointer_flags,
};