aboutsummaryrefslogtreecommitdiff
path: root/bootstrap/cgen.c
diff options
context:
space:
mode:
authorlemon <lsof@mailbox.org>2022-08-07 22:36:57 +0200
committerlemon <lsof@mailbox.org>2022-08-07 22:36:57 +0200
commit96ef1857bac446f4e065e7c10530213e361d726a (patch)
tree2c5241e4f7cf03d3498ff3114ca315ea076c855c /bootstrap/cgen.c
parente305f71c3cbd685eacb77451b3728b2cac492d71 (diff)
add tagged unions
Diffstat (limited to 'bootstrap/cgen.c')
-rw-r--r--bootstrap/cgen.c54
1 files changed, 50 insertions, 4 deletions
diff --git a/bootstrap/cgen.c b/bootstrap/cgen.c
index df5ccbc..8bea8bc 100644
--- a/bootstrap/cgen.c
+++ b/bootstrap/cgen.c
@@ -153,6 +153,20 @@ geniniex(struct expr *ex) {
}
static void
+geneuiniex(struct expr *ex) {
+ if (ex->t == Ezeroini)
+ pri("{0}");
+ else {
+ assert(ex->t == Eeuini);
+ if (ex->euini.ini)
+ pri("{ /* %s */ %I, .u.%s = %e }", ex->euini.fnam, ex->euini.tag,
+ ex->euini.fnam, ex->euini.ini);
+ else
+ pri("{ /* %s */ %I }", ex->euini.fnam, ex->euini.tag);
+ }
+}
+
+static void
genexpr(struct expr *ex) {
const struct type *ty = unconstify(ex->ty);
struct decl *decl;
@@ -237,7 +251,7 @@ genexpr(struct expr *ex) {
case Eget:
pri("%e%s%s", ex->get.lhs, ex->get.lhs->ty->t == TYptr ? "->" : ".", ex->get.fld);
break;
- case Emcall:
+ case Emcall:
decl = container_of(ex->mcall.met, struct decl, fn);
assert(*decl->_cname);
pri("%s(", *decl->_cname);
@@ -248,7 +262,7 @@ genexpr(struct expr *ex) {
}
pri(")");
break;
- case Eslice:
+ case Eslice:
;static int id;
// TODO range assertions
pri("({ %t __start%d = %e; ", ex->slice.start->ty, id, ex->slice.start);
@@ -256,9 +270,14 @@ genexpr(struct expr *ex) {
ex->ty, ex->slice.lhs, ex->slice.lhs->ty->t == TYslice ? ".ptr" : "", id, ex->slice.end, id);
++id;
break;
- case Elen:
+ case Elen:
pri("%e.len", ex->child);
break;
+ case Eeuini:
+ pri("((%t)", ty);
+ geneuiniex(ex);
+ pri(")");
+ break;
}
}
@@ -285,10 +304,12 @@ genstmt(struct stmt *stmt) {
pri("%t %s_%d", decl.var.ty, decl.name, decl.var.id);
if (decl.var.ini) {
pri(" = ");
- if ((decl.var.ty->t == TYstruct || decl.var.ty->t == TYarr)
+ if ((decl.var.ty->t == TYstruct || decl.var.ty->t == TYunion || decl.var.ty->t == TYarr)
&& (decl.var.ini->t == Ezeroini || decl.var.ini->t == Eini))
{
geniniex(decl.var.ini);
+ } else if (decl.var.ty->t == TYeunion) {
+ geneuiniex(decl.var.ini);
} else {
pri("%e", decl.var.ini);
}
@@ -425,6 +446,9 @@ liftnestedex(struct expr *ex) {
liftnestedex(ex->slice.start);
liftnestedex(ex->slice.end);
break;
+ case Eeuini:
+ liftnestedex(ex->euini.ini);
+ break;
}
}
@@ -631,6 +655,28 @@ defctype(const struct type *ty, void *_) {
liftdecl(ty->agg.decls.d[i]);
break;
case TYeunion:
+ if (ty->konst) {
+ defctype(unconstify(ty), NULL);
+ *cname = (char *)unconstify(ty)->_cname;
+ break;
+ }
+ *cname = xasprintf("__ty%s%d", ty->agg.name ? ty->agg.name : "", id++);
+ pri("typedef struct %s %s;\n", *cname, *cname);
+ if (!ty->agg.fwd) {
+ pri("struct %s {\n", *cname);
+ pri("%t t;\n", ty->agg.enumty);
+ pri("union {\n", ty->agg.enumty);
+ for (int i = 0; i < ty->agg.flds.n; ++i) {
+ struct aggfield *fld = &ty->agg.flds.d[i];
+ if (fld->ty)
+ pri("%t %s;\n", fld->ty, fld->name);
+ }
+ pri("} u;\n};\n");
+ pri("_Static_assert(sizeof(%s) == %U, \"sizeof(%t) == %U\");\n",
+ *cname, (u64)ty->size, ty, (u64)ty->size);
+ pri("_Static_assert(__alignof__(%s) == %U, \"__alignof__(%t) == %U\");\n",
+ *cname, (u64)ty->align, ty, (u64)ty->align);
+ }
break;
}