harec

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

commit e9acfa8ee777ea3290553af54079c79c8ff4e62e
parent 4d40b91c5b4fee2b07fe95b666392f3d03667011
Author: Drew DeVault <sir@cmpwn.com>
Date:   Sun, 26 Sep 2021 10:18:45 +0200

gen: struct/union type info

Diffstat:
Msrc/gen.c | 97++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
Mtests/34-reflect.ha | 43+++++++++++++++++++++++++++++++++++++++++++
Mtypes/reflect.ha | 2+-
3 files changed, 140 insertions(+), 2 deletions(-)

diff --git a/src/gen.c b/src/gen.c @@ -3605,9 +3605,104 @@ gen_type_info(struct gen_context *ctx, item->value = constl(len); break; case STORAGE_STRUCT: + case STORAGE_UNION: + *repr_name = "struct_union"; + 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 = constw(type->storage == STORAGE_STRUCT ? 0 : 1); + item->value.type = &qbe_byte; + item->next = xcalloc(1, sizeof(struct qbe_data_item)); + item = item->next; + + item->type = QD_ZEROED; + item->zeroed = 7; + 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 struct_field *field = type->struct_union.fields; + field; field = field->next) { + if (field->name) { + size_t l = strlen(field->name); + struct qbe_def *sdef = xcalloc(1, sizeof(struct qbe_def)); + sdef->name = gen_name(ctx, "strdata.%d"); + sdef->kind = Q_DATA; + sdef->data.items.type = QD_STRING; + sdef->data.items.str = xcalloc(1, l); + sdef->data.items.sz = l; + memcpy(sdef->data.items.str, field->name, l); + qbe_append_def(ctx->out, sdef); + + subitem->value.kind = QV_GLOBAL; + subitem->value.type = &qbe_long; + subitem->value.name = strdup(sdef->name); + subitem->next = xcalloc(1, sizeof(struct qbe_data_item)); + subitem = subitem->next; + subitem->type = QD_VALUE; + subitem->value = constl(l); + subitem->next = xcalloc(1, sizeof(struct qbe_data_item)); + subitem = subitem->next; + subitem->type = QD_VALUE; + subitem->value = constl(l); + } else { + subitem->value = constl(0); + subitem->next = xcalloc(1, sizeof(struct qbe_data_item)); + subitem = subitem->next; + subitem->type = QD_VALUE; + subitem->value = constl(0); + subitem->next = xcalloc(1, sizeof(struct qbe_data_item)); + subitem = subitem->next; + subitem->type = QD_VALUE; + subitem->value = constl(0); + } + + subitem->next = xcalloc(1, sizeof(struct qbe_data_item)); + subitem = subitem->next; + + subitem->type = QD_VALUE; + subitem->value = constl(field->offset); + subitem->next = xcalloc(1, sizeof(struct qbe_data_item)); + subitem = subitem->next; + + ref = mktyperef(ctx, field->type); + subitem->type = QD_VALUE; + subitem->value.kind = QV_GLOBAL; + subitem->value.type = &qbe_long; + subitem->value.name = ref.name; + if (field->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_TAGGED: case STORAGE_TUPLE: - case STORAGE_UNION: // XXX: Temporary code to make sure code in the wild builds // while we flesh out these types item->value = constw(0); diff --git a/tests/34-reflect.ha b/tests/34-reflect.ha @@ -124,6 +124,48 @@ fn functions() void = { assert(func.flags == types::func_flags::NORETURN); }; +fn struct_union() void = { + let ty = types::reflect(type(struct { + x: int, + y: int, + })); + assert(ty.sz == size(int) * 2); + assert(ty.al == size(int)); + let su = ty.repr as types::struct_union; + assert(su.kind == types::struct_kind::STRUCT); + assert(len(su.fields) == 2); + assert(su.fields[0].name == "x"); + assert(su.fields[0].offs == 0); + assert(su.fields[0].type_ == type(int)); + assert(su.fields[1].name == "y"); + assert(su.fields[1].offs == 4); + assert(su.fields[1].type_ == type(int)); + + let ty = types::reflect(type(union { + x: int, + y: int, + })); + let su = ty.repr as types::struct_union; + assert(su.kind == types::struct_kind::UNION); + assert(len(su.fields) == 2); + assert(su.fields[0].name == "x"); + assert(su.fields[0].offs == 0); + assert(su.fields[1].name == "y"); + assert(su.fields[1].offs == 0); + + let ty = types::reflect(type(struct { + x: int, + y: int, + struct { + z: int, + }, + })); + let su = ty.repr as types::struct_union; + assert(len(su.fields) == 3); + assert(su.fields[2].name == ""); + assert(su.fields[2].offs == 8); +}; + export fn main() void = { builtins(); aliases(); @@ -132,4 +174,5 @@ export fn main() void = { slices(); pointers(); functions(); + struct_union(); }; diff --git a/types/reflect.ha b/types/reflect.ha @@ -99,7 +99,7 @@ export type pointer = struct { export type slice_repr = type; // Indicates if a [[_struct]] was declared as a struct or union type. -export type struct_kind = enum { +export type struct_kind = enum uint { STRUCT, UNION, };