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:
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);
}