diff options
| author | 2022-08-07 22:36:57 +0200 | |
|---|---|---|
| committer | 2022-08-07 22:36:57 +0200 | |
| commit | 96ef1857bac446f4e065e7c10530213e361d726a (patch) | |
| tree | 2c5241e4f7cf03d3498ff3114ca315ea076c855c /bootstrap/cgen.c | |
| parent | e305f71c3cbd685eacb77451b3728b2cac492d71 (diff) | |
add tagged unions
Diffstat (limited to 'bootstrap/cgen.c')
| -rw-r--r-- | bootstrap/cgen.c | 54 |
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; } |