aboutsummaryrefslogtreecommitdiff
path: root/bootstrap/cgen.c
diff options
context:
space:
mode:
Diffstat (limited to 'bootstrap/cgen.c')
-rw-r--r--bootstrap/cgen.c50
1 files changed, 43 insertions, 7 deletions
diff --git a/bootstrap/cgen.c b/bootstrap/cgen.c
index d7b91b0..e047f08 100644
--- a/bootstrap/cgen.c
+++ b/bootstrap/cgen.c
@@ -730,7 +730,7 @@ gendecl(struct decl *decl, bool toplevel) {
}
static void
-defctype(const struct type *ty, void *_) {
+declctype(const struct type *ty, void *_) {
static int id;
char **cname = (char **)&ty->_cname;
const char *kind;
@@ -739,9 +739,43 @@ defctype(const struct type *ty, void *_) {
switch (ty->t) {
case TYvoid: case TYbool: case TYvalist:
case TYenum: case TYint: case TYfloat:
+ case TYptr: case TYarr: case TYslice:
+ case TYfn:
+ *(bool *)&ty->_defined = 1;
+ break;
+ case TYstruct: case TYeunion:
+ kind = "struct";
+ goto agg;
+ case TYunion:
+ kind = "union";
+ agg:
+ if (ty->konst) {
+ declctype(unconstify(ty), NULL);
+ *cname = (char *)unconstify(ty)->_cname;
+ break;
+ }
+ *(bool *)&ty->_defined = 0;
+ *cname = xasprintf("__ta%s%d", ty->agg.name ? ty->agg.name : "", id++);
+ pri("typedef %s %s %s;\n", kind, *cname, *cname);
+ }
+}
+
+#define isagg(ty) ((ty)->t == TYstruct || (ty)->t == TYunion || (ty)->t == TYenum)
+
+static void
+defctype(const struct type *ty, void *_) {
+ static int id;
+ char **cname = (char **)&ty->_cname;
+ const char *kind;
+
+ if (!ty->_cname || (!ty->_defined))
+ switch (ty->t) {
+ case TYvoid: case TYbool: case TYvalist:
+ case TYenum: case TYint: case TYfloat:
break;
case TYptr:
- defctype(ty->child, NULL);
+ if (!isagg(ty->child))
+ defctype(ty->child, NULL);
break;
case TYarr:
if (ty->length >= 0) {
@@ -757,9 +791,10 @@ defctype(const struct type *ty, void *_) {
*cname = (char *)ty2->_cname;
return;
}
- defctype(ty->child, NULL);
if (ty->_cname) break;
*cname = xasprintf("__ty%d", id++);
+ if (!isagg(ty->child))
+ defctype(ty->child, NULL);
pri("typedef struct { %t *ptr; size_t len; } %s;\n",
ty->child, *cname);
@@ -789,13 +824,13 @@ defctype(const struct type *ty, void *_) {
case TYunion:
kind = "union";
agg:
+ *(bool *)&ty->_defined = 1;
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 %s %s %s;\n", kind, *cname, *cname);
+
if (!ty->agg.fwd) {
for (int i = 0; i < ty->agg.flds.n; ++i) {
struct aggfield fld = ty->agg.flds.d[i];
@@ -816,18 +851,18 @@ defctype(const struct type *ty, void *_) {
}
break;
case TYeunion:
+ *(bool *)&ty->_defined = 1;
if (ty->konst) {
defctype(unconstify(ty), NULL);
*cname = (char *)unconstify(ty)->_cname;
break;
}
+
for (int i = 0; i < ty->agg.flds.n; ++i) {
struct aggfield *fld = &ty->agg.flds.d[i];
if (fld->ty)
defctype(fld->ty, NULL);
}
- *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);
@@ -861,6 +896,7 @@ cgen(FILE *fp, const struct comfile *cf) {
outfp = fp;
prelude();
+ visittypes(declctype, NULL);
visittypes(defctype, NULL);
for (int i = 0; i < cf->decls.n; ++i) {