harec

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

commit a2713249b19b81223cac003d65a94bbd597fe19a
parent a60d3783c8fec5fc133cc1bddd8552e48c1399a1
Author: Drew DeVault <sir@cmpwn.com>
Date:   Fri, 15 Jan 2021 12:44:14 -0500

gen: generate qbe type for tagged unions

Diffstat:
Minclude/qbe.h | 1+
Msrc/emit.c | 7++++++-
Msrc/qtype.c | 54++++++++++++++++++++++++++++++++++++++++++++++++++----
3 files changed, 57 insertions(+), 5 deletions(-)

diff --git a/include/qbe.h b/include/qbe.h @@ -30,6 +30,7 @@ struct qbe_type { // Aggregate types only: char *name; size_t align; + bool is_union; struct qbe_field fields; const struct type *base; }; diff --git a/src/emit.c b/src/emit.c @@ -40,6 +40,9 @@ emit_type(const struct qbe_def *def, FILE *out) const struct qbe_field *field = &def->type.fields; while (field) { + if (def->type.is_union) { + fprintf(out, " {"); + } if (field->type) { fprintf(out, " "); emit_qtype(field->type, true, out); @@ -47,7 +50,9 @@ emit_type(const struct qbe_def *def, FILE *out) if (field->count) { fprintf(out, " %zu", field->count); } - if (field->next) { + if (def->type.is_union) { + fprintf(out, " }"); + } else if (field->next) { fprintf(out, ","); } field = field->next; diff --git a/src/qtype.c b/src/qtype.c @@ -94,6 +94,42 @@ qxtype_for_type(const struct type *type) } static const struct qbe_type * +tagged_qtype(struct gen_context *ctx, const struct type *type) +{ + int n = snprintf(NULL, 0, "tags.%zd", ctx->id); + char *name = xcalloc(1, n + 1); + snprintf(name, n + 1, "tags.%zd", ctx->id); + ++ctx->id; + + struct qbe_def *def = xcalloc(1, sizeof(struct qbe_def)); + def->kind = Q_TYPE; + def->name = name; + def->exported = false; + def->type.stype = Q__AGGREGATE; + def->type.base = type; + def->type.name = name; + def->type.align = SIZE_UNDEFINED; + def->type.is_union = true; + + struct qbe_field *field = &def->type.fields; + for (const struct type_tagged_union *tu = &type->tagged; + tu; tu = tu->next) { + if (tu->type->size == 0) { + continue; + } + field->type = qtype_for_type(ctx, tu->type, true); + field->count = 1; + if (tu->next) { + field->next = xcalloc(1, sizeof(struct qbe_field)); + field = field->next; + } + } + + qbe_append_def(ctx->out, def); + return &def->type; +} + +static const struct qbe_type * lookup_aggregate(struct gen_context *ctx, const struct type *type) { for (struct qbe_def *def = ctx->out->defs; def; def = def->next) { @@ -116,9 +152,9 @@ lookup_aggregate(struct gen_context *ctx, const struct type *type) ++ctx->id; struct qbe_def *def = xcalloc(1, sizeof(struct qbe_def)); - def->kind = Q_TYPE, - def->name = name, - def->exported = false, + def->kind = Q_TYPE; + def->name = name; + def->exported = false; def->type.stype = Q__AGGREGATE; def->type.base = type; def->type.name = name; @@ -148,8 +184,18 @@ lookup_aggregate(struct gen_context *ctx, const struct type *type) field->type = &qbe_long; // XXX: ARCH field->count = 3; break; - case TYPE_STORAGE_ENUM: case TYPE_STORAGE_TAGGED_UNION: + def->type.align = type->align; + field->type = &qbe_long; // XXX: ARCH + field->count = 1; + if (type->size != builtin_type_size.size) { + field->next = xcalloc(1, sizeof(struct qbe_field)); + field = field->next; + field->type = tagged_qtype(ctx, type); + field->count = 1; + } + break; + case TYPE_STORAGE_ENUM: assert(0); // TODO case TYPE_STORAGE_ARRAY: case TYPE_STORAGE_ALIAS: