diff options
Diffstat (limited to 'bootstrap/cgen.c')
| -rw-r--r-- | bootstrap/cgen.c | 78 |
1 files changed, 73 insertions, 5 deletions
diff --git a/bootstrap/cgen.c b/bootstrap/cgen.c index aac0893..fe937d6 100644 --- a/bootstrap/cgen.c +++ b/bootstrap/cgen.c @@ -28,6 +28,9 @@ gentype(const struct type *ty) { assert(ty->length >= 0); case TYslice: case TYfn: + case TYstruct: + case TYunion: + case TYeunion: assert(ty->_cname); pri("%s", ty->_cname); return; @@ -53,6 +56,7 @@ pristring(const char *s, u64 n) { } static void genexpr(struct expr *expr); +static void geniniex(struct expr *ex); void pri(const char *fmt, ...) { @@ -115,6 +119,9 @@ pri(const char *fmt, ...) { case 'e': genexpr(va_arg(ap, struct expr *)); break; + case 'n': + geniniex(va_arg(ap, struct expr *)); + break; default: fprintf(outfp, "pri(): bad fmt '%%%c'\n", c); abort(); @@ -127,6 +134,25 @@ pri(const char *fmt, ...) { static void genblock(struct blockstmt block); static void +geniniex(struct expr *ex) { + if (ex->t == Ezeroini) + pri("{0}"); + else { + assert(ex->t == Eini); + pri("{ "); + for (int i = 0; i < ex->ini.args.n; ++i) { + struct iniarg *arg = &ex->ini.args.d[i]; + if (ex->ty->t == TYarr) + pri("[%I] = %e, ", arg->idx, arg->ex); + else + pri(".%s = %e, ", arg->fld, arg->ex); + } + + pri("}"); + } +} + +static void genexpr(struct expr *ex) { const struct type *ty = unconstify(ex->ty); switch (ex->t) { @@ -194,6 +220,15 @@ genexpr(struct expr *ex) { ty = ex->ty->enu.intty; goto intlit; break; + case Ezeroini: + if (ty->t == TYarr || ty->t == TYstruct) + pri("((%t){0})", ty); + else + pri("((%t)0)", ty); + break; + case Eini: + pri("((%t)%n)", ty, ex); + break; } } @@ -218,8 +253,16 @@ genstmt(struct stmt *stmt) { switch (decl.t) { case Dlet: pri("%t %s", decl.var.ty, decl.name); - if (decl.var.ini) - pri(" = %e", decl.var.ini); + if (decl.var.ini) { + pri(" = "); + if ((decl.var.ty->t == TYstruct || decl.var.ty->t == TYarr) + && (decl.var.ini->t == Ezeroini || decl.var.ini->t == Eini)) + { + geniniex(decl.var.ini); + } else { + pri("%e", decl.var.ini); + } + } pri(";\n"); break; case Dfn: @@ -300,6 +343,7 @@ liftnestedex(struct expr *ex) { switch (ex->t) { case Eintlit: case Eflolit: case Estrlit: case Eboolit: case Enullit: case Ename: + case Ezeroini: case Eenumval: break; case Eprefix: @@ -332,6 +376,10 @@ liftnestedex(struct expr *ex) { case Eas: liftnestedex(ex->child); break; + case Eini: + for (int i = 0; i < ex->ini.args.n; ++i) + liftnestedex(&ex->ini.args.d[i].ex); + break; } } @@ -461,12 +509,13 @@ static void defctype(const struct type *ty, void *_) { static int id; char **cname = (char **)&ty->_cname; + const char *kind; if (!ty->_cname) switch (ty->t) { case TYvoid: case TYbool: case TYint: case TYfloat: - case TYptr: + case TYptr: case TYenum: return; case TYarr: assert(ty->length >= 0); @@ -495,8 +544,27 @@ defctype(const struct type *ty, void *_) { pri("..."); pri(");\n"); break; - case TYenum: - *cname = xasprintf("__ty%d", id++); + case TYstruct: + kind = "struct"; + goto agg; + case TYunion: + kind = "union"; + agg: + *cname = xasprintf("__ty%s%d", ty->agg.name ? ty->agg.name : "", id++); + pri("typedef %s %s %s;\n", kind, *cname, *cname); + if (!ty->agg.fwd) { + pri("%s %s {\n", kind, *cname); + for (int i = 0; i < ty->agg.flds.n; ++i) { + struct aggfield fld = ty->agg.flds.d[i]; + pri("%t %s;\n", fld.ty, fld.name); + } + pri("};\n"); + pri("_Static_assert(sizeof(%s) == %U);\n", *cname, (long long)ty->size); + pri("_Static_assert(__alignof__(%s) == %U);\n", *cname, (long long)ty->align); + } + break; + case TYeunion: + break; } } |