harec

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

commit 6ddc4027de2150ce98235cb07e597361faad4c6c
parent 979d6741cf53234c43c1d885c7e973db365ce659
Author: Drew DeVault <sir@cmpwn.com>
Date:   Sat, 25 Sep 2021 11:35:59 +0200

gen: flesh out type info emit somewhat

Diffstat:
Minclude/types.h | 11++++++-----
Mrt/strcmp.ha | 7+------
Msrc/check.c | 15+++++++++------
Msrc/gen.c | 224++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
Msrc/type_store.c | 2++
Msrc/typedef.c | 8++++----
6 files changed, 239 insertions(+), 28 deletions(-)

diff --git a/include/types.h b/include/types.h @@ -5,22 +5,22 @@ #include "identifier.h" enum type_storage { - // Scalar types + // Built-in types + // The order of these is important STORAGE_BOOL, STORAGE_CHAR, STORAGE_ENUM, STORAGE_F32, STORAGE_F64, - STORAGE_FCONST, STORAGE_I16, STORAGE_I32, STORAGE_I64, STORAGE_I8, - STORAGE_ICONST, STORAGE_INT, STORAGE_NULL, STORAGE_RUNE, STORAGE_SIZE, + STORAGE_STRING, STORAGE_U16, STORAGE_U32, STORAGE_U64, @@ -28,18 +28,19 @@ enum type_storage { STORAGE_UINT, STORAGE_UINTPTR, STORAGE_VOID, - // Aggregate types + // Other types STORAGE_ALIAS, STORAGE_ARRAY, STORAGE_FUNCTION, STORAGE_POINTER, STORAGE_SLICE, - STORAGE_STRING, STORAGE_STRUCT, STORAGE_TAGGED, STORAGE_TUPLE, STORAGE_UNION, STORAGE_TYPE, + STORAGE_FCONST, + STORAGE_ICONST, }; struct type; diff --git a/rt/strcmp.ha b/rt/strcmp.ha @@ -1,14 +1,9 @@ -type string = struct { - data: *[*]u8, - length: size, - capacity: size, -}; - export fn strcmp(_a: str, _b: str) bool = { if (len(_a) != len(_b)) { return false; }; let a = (&_a: *string).data, b = (&_b: *string).data; + let a = a: *[*]u8, b = b: *[*]u8; for (let i = 0z; i < len(_a); i += 1) { if (a[i] != b[i]) { return false; diff --git a/src/check.c b/src/check.c @@ -820,7 +820,8 @@ check_expr_binarithm(struct context *ctx, if (!type_is_numeric(p) && type_dealias(p)->storage != STORAGE_POINTER && type_dealias(p)->storage != STORAGE_STRING && type_dealias(p)->storage != STORAGE_BOOL - && type_dealias(p)->storage != STORAGE_RUNE) { + && type_dealias(p)->storage != STORAGE_RUNE + && type_dealias(p)->storage != STORAGE_TYPE) { error(ctx, aexpr->loc, expr, "Cannot perform equality test on %s type", type_storage_unparse(type_dealias(p)->storage)); @@ -2975,12 +2976,14 @@ static struct declaration * check_type(struct context *ctx, const struct ast_decl *adecl) { - const struct type *type = - type_store_lookup_atype(ctx->store, adecl->type.type); struct declaration *decl = xcalloc(1, sizeof(struct declaration)); - decl->type = DECL_TYPE; - decl->_type = type; mkident(ctx, &decl->ident, &adecl->type.ident); + decl->type = DECL_TYPE; + const struct type *type = + type_store_lookup_atype(ctx->store, adecl->type.type); + const struct type *alias = + type_store_lookup_alias(ctx->store, &decl->ident, type, decl->exported); + decl->_type = alias; return decl; } @@ -3131,7 +3134,7 @@ type_is_specified(struct context *ctx, const struct ast_type *atype) } return true; case STORAGE_TYPE: - assert(0); // TODO + return true; } assert(0); // Unreachable } diff --git a/src/gen.c b/src/gen.c @@ -2503,11 +2503,14 @@ gen_expr_tuple_at(struct gen_context *ctx, } } +static void gen_type_info(struct gen_context *ctx, + const struct type *type, struct qbe_data_item *item); + static struct gen_value -gen_expr_type(struct gen_context *ctx, - const struct expression *expr) +mktyperef(struct gen_context *ctx, const struct type *type) { - const struct type *type = expr->_type.type; + size_t n; + char *name; switch (type->storage) { case STORAGE_BOOL: case STORAGE_CHAR: @@ -2533,14 +2536,21 @@ gen_expr_type(struct gen_context *ctx, // Built-ins return (struct gen_value){ .kind = GV_GLOBAL, - .type = expr->result, + .type = type_store_type(ctx->store), .name = mkrttype(type->storage), }; case STORAGE_FCONST: case STORAGE_ICONST: abort(); // Invariant case STORAGE_ALIAS: - assert(0); // TODO: Emit typeinfo (in gen_decl_type) + n = snprintf(NULL, 0, "type.%u", type->id); + name = xcalloc(1, n + 1); + snprintf(name, n + 1, "type.%u", type->id); + return (struct gen_value){ + .kind = GV_GLOBAL, + .type = type_store_type(ctx->store), + .name = name, + }; case STORAGE_ARRAY: case STORAGE_FUNCTION: case STORAGE_POINTER: @@ -2550,12 +2560,25 @@ gen_expr_type(struct gen_context *ctx, case STORAGE_TAGGED: case STORAGE_TUPLE: case STORAGE_UNION: - assert(0); // TODO: Emit typeinfo (here) + // TODO: Emit typeinfo (here) + return (struct gen_value){ + .kind = GV_GLOBAL, + .type = type_store_type(ctx->store), + .name = "TODO", + }; } abort(); // Unreachable } static struct gen_value +gen_expr_type(struct gen_context *ctx, + const struct expression *expr) +{ + const struct type *type = expr->_type.type; + return mktyperef(ctx, type); +} + +static struct gen_value gen_expr_unarithm(struct gen_context *ctx, const struct expression *expr) { @@ -3213,6 +3236,191 @@ gen_global_decl(struct gen_context *ctx, const struct declaration *decl) qbe_append_def(ctx->out, qdef); } +static struct qbe_data_item * +gen_ident_data(struct gen_context *ctx, + const struct identifier *ident, + struct qbe_data_item *item, + size_t *n) +{ + if (ident->ns != NULL) { + item = gen_ident_data(ctx, ident->ns, item, n); + item->next = xcalloc(1, sizeof(struct qbe_data_item)); + item = item->next; + } + + size_t l = strlen(ident->name); + struct qbe_def *def = xcalloc(1, sizeof(struct qbe_def)); + def->name = gen_name(ctx, "strdata.%d"); + def->kind = Q_DATA; + def->data.items.type = QD_STRING; + def->data.items.str = xcalloc(1, l); + def->data.items.sz = l; + memcpy(def->data.items.str, ident->name, l); + qbe_append_def(ctx->out, def); + + 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(l); + item->next = xcalloc(1, sizeof(struct qbe_data_item)); + item = item->next; + item->type = QD_VALUE; + item->value = constl(l); + *n = *n + 1; + return item; +} + +static void +gen_type_info(struct gen_context *ctx, + const struct type *type, + struct qbe_data_item *item) +{ + assert(builtin_type_uint.size == 4); // XXX: Is this ever not true? + item->type = QD_VALUE; + item->value = constw(type->id); + 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->size); + item->next = xcalloc(1, sizeof(struct qbe_data_item)); + item = item->next; + + item->type = QD_VALUE; + item->value = constl(type->align); + item->next = xcalloc(1, sizeof(struct qbe_data_item)); + item = item->next; + + item->type = QD_VALUE; + item->value = constw(type->flags); + 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; + + struct identifier ns = { .name = "types" }; + struct type repr = { + .storage = STORAGE_ALIAS, + .alias = { + .ident = { + .ns = &ns, + }, + }, + }; + char **repr_name = &repr.alias.ident.name; + item->type = QD_VALUE; + + switch (type->storage) { + case STORAGE_FCONST: + case STORAGE_ICONST: + case STORAGE_BOOL: + case STORAGE_CHAR: + case STORAGE_F32: + case STORAGE_F64: + case STORAGE_I16: + case STORAGE_I32: + case STORAGE_I64: + case STORAGE_I8: + case STORAGE_INT: + case STORAGE_NULL: + case STORAGE_RUNE: + case STORAGE_SIZE: + case STORAGE_U16: + case STORAGE_U32: + case STORAGE_U64: + case STORAGE_U8: + case STORAGE_UINT: + case STORAGE_UINTPTR: + case STORAGE_VOID: + abort(); // Invariant + case STORAGE_ALIAS: + *repr_name = "alias"; + 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; + + struct qbe_def *def = xcalloc(1, sizeof(struct qbe_def)); + def->name = gen_name(ctx, "sldata.%d"); + def->kind = Q_DATA; + + size_t len = 0; + struct qbe_data_item *subitem = &def->data.items; + gen_ident_data(ctx, &type->alias.ident, subitem, &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); + + item->next = xcalloc(1, sizeof(struct qbe_data_item)); + item = item->next; + + struct gen_value ref = mktyperef(ctx, type->alias.type); + item->type = QD_VALUE; + item->value.kind = QV_GLOBAL; + item->value.type = &qbe_long; + item->value.name = ref.name; + break; + case STORAGE_ENUM: + case STORAGE_ARRAY: + case STORAGE_FUNCTION: + case STORAGE_POINTER: + case STORAGE_SLICE: + case STORAGE_STRING: + 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; + } +} + +static void +gen_type_decl(struct gen_context *ctx, const struct declaration *decl) +{ + const struct type *type = decl->_type; + struct qbe_def *qdef = xcalloc(1, sizeof(struct qbe_def)); + qdef->kind = Q_DATA; + qdef->exported = decl->exported; + + size_t n = snprintf(NULL, 0, "type.%u", type->id); + qdef->name = xcalloc(1, n + 1); + snprintf(qdef->name, n + 1, "type.%u", type->id); + + gen_type_info(ctx, type, &qdef->data.items); + qbe_append_def(ctx->out, qdef); +} + static void gen_decl(struct gen_context *ctx, const struct declaration *decl) { @@ -3223,8 +3431,10 @@ gen_decl(struct gen_context *ctx, const struct declaration *decl) case DECL_GLOBAL: gen_global_decl(ctx, decl); break; - case DECL_CONST: case DECL_TYPE: + gen_type_decl(ctx, decl); + break; + case DECL_CONST: break; // Nothing to do } } diff --git a/src/type_store.c b/src/type_store.c @@ -988,6 +988,8 @@ type_store_type(struct type_store *store) { struct type type = { .storage = STORAGE_TYPE, + .size = 8, // XXX: ARCH + .align = 8, }; return type_store_lookup_type(store, &type); } diff --git a/src/typedef.c b/src/typedef.c @@ -215,6 +215,8 @@ emit_type(const struct type *type, FILE *out) case STORAGE_NULL: case STORAGE_RUNE: case STORAGE_SIZE: + case STORAGE_STRING: + case STORAGE_TYPE: case STORAGE_U16: case STORAGE_U32: case STORAGE_U64: @@ -222,7 +224,6 @@ emit_type(const struct type *type, FILE *out) case STORAGE_UINT: case STORAGE_UINTPTR: case STORAGE_VOID: - case STORAGE_STRING: fprintf(out, "%s", type_storage_unparse(type->storage)); break; case STORAGE_POINTER: @@ -316,8 +317,6 @@ emit_type(const struct type *type, FILE *out) } fprintf(out, ")"); break; - case STORAGE_TYPE: - assert(0); // TODO case STORAGE_FCONST: case STORAGE_ICONST: assert(0); // Invariant @@ -405,7 +404,8 @@ emit_decl_type(struct declaration *decl, FILE *out) { char *ident = identifier_unparse(&decl->ident); fprintf(out, "export type %s = ", ident); - emit_exported_type(decl->_type, out); + assert(decl->_type->storage == STORAGE_ALIAS); + emit_exported_type(decl->_type->alias.type, out); fprintf(out, "; // size: %zd, align: %zd, id: %u\n", decl->_type->size, decl->_type->align, decl->_type->id); }