aboutsummaryrefslogtreecommitdiff
path: root/bootstrap/cgen.c
diff options
context:
space:
mode:
authorlemon <lsof@mailbox.org>2022-08-04 22:36:59 +0200
committerlemon <lsof@mailbox.org>2022-08-04 22:36:59 +0200
commit0fec7de747d93586eda66ce190f5f3d6715421a4 (patch)
tree2c6db93b3e6d3299d530cea20dd6468cf47b43c2 /bootstrap/cgen.c
parent4b2451500b8f085321a041ebc13761a5102f0e6d (diff)
struct,unions, compound literals; mostly
Diffstat (limited to 'bootstrap/cgen.c')
-rw-r--r--bootstrap/cgen.c78
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;
}
}