aboutsummaryrefslogtreecommitdiff
path: root/bootstrap/cgen.c
diff options
context:
space:
mode:
authorlemon <lsof@mailbox.org>2022-08-04 07:39:23 +0200
committerlemon <lsof@mailbox.org>2022-08-04 07:39:23 +0200
commitbb1d4b4a3e51a06fb0530dfc271a97a6cd88cc73 (patch)
treef300325814bc30e64f858ee313b8260a14d8df90 /bootstrap/cgen.c
parent1625c50f0c0e4b1c7ba01a5df5713efaf6dce606 (diff)
stuff
Diffstat (limited to 'bootstrap/cgen.c')
-rw-r--r--bootstrap/cgen.c139
1 files changed, 113 insertions, 26 deletions
diff --git a/bootstrap/cgen.c b/bootstrap/cgen.c
index 6445bf8..938e8f3 100644
--- a/bootstrap/cgen.c
+++ b/bootstrap/cgen.c
@@ -73,7 +73,9 @@ pri(const char *fmt, ...) {
break;
case 'c':
ch = bswap32(va_arg(ap, int));
- while (ch) {
+ if (ch == 0)
+ fputc(ch, outfp);
+ else while (ch) {
if (ch & 0xFF)
fputc(ch, outfp);
ch >>= 8;
@@ -143,16 +145,16 @@ genexpr(struct expr *ex) {
pri("NULL");
break;
case Ename:
- if (ex->ref->t == Dfn && ex->ref->_cname && *ex->ref->_cname)
+ if ((ex->ref->t == Dfn || ex->ref->t == Dstatic) && *ex->ref->_cname)
pri("%s", *ex->ref->_cname);
else
pri("%s", ex->ref->name);
break;
case Eprefix:
- pri("%c(%e)", ex->unop.op, ex->unop.child);
+ pri("(%c(%e))", ex->unop.op, ex->unop.child);
break;
case Epostfix:
- pri("(%e)%c", ex->unop.op, ex->unop.child);
+ pri("(%e)%c", ex->unop.child, ex->unop.op);
break;
case Ebinop:
pri("(%e %c %e)", ex->binop.lhs, ex->binop.op, ex->binop.rhs);
@@ -172,14 +174,24 @@ genexpr(struct expr *ex) {
case Eindex:
pri("%e[%e]", ex->index.lhs, ex->index.rhs);
break;
-
+ case Eblock:
+ pri("(\n");
+ genblock(ex->block);
+ pri(")");
+ break;
+ default:
+ assert(0);
}
}
-static void genfn(const char *cname, struct fn *fn);
+static void genfn(bool externp, const char *cname, struct fn *fn);
+static void genstatic(bool externp, const char *cname, struct var *var);
static void
genstmt(struct stmt *stmt) {
+ const char *p = fileid2path(stmt->span.fileid);
+ if (stmt->t != Sblock)
+ pri("#line %d %S\n", stmt->span.line, p, (u64)strlen(p));
switch (stmt->t) {
case Sblock:
genblock(stmt->block);
@@ -191,7 +203,7 @@ genstmt(struct stmt *stmt) {
case Sdecl:
; struct decl decl = stmt->decl;
switch (decl.t) {
- case Dvar:
+ case Dlet:
pri("%t %s", decl.var.ty, decl.name);
if (decl.var.ini)
pri(" = %e", decl.var.ini);
@@ -199,7 +211,11 @@ genstmt(struct stmt *stmt) {
break;
case Dfn:
if (decl.externp)
- genfn(decl.fn.name, &decl.fn);
+ genfn(1, decl.fn.name, &decl.fn);
+ break;
+ case Dstatic:
+ if (decl.externp)
+ genstatic(1, decl.name, &decl.var);
break;
case Dtype: case Dmacro:
break;
@@ -218,15 +234,29 @@ genstmt(struct stmt *stmt) {
genblock(stmt->loop.body);
break;
case Sfor:
- pri("for (");
+ pri("for (\n");
if (stmt->loop.ini)
genstmt(stmt->loop.ini);
pri("%e;", &stmt->loop.test);
if (stmt->loop.next)
- pri(" %e", &stmt->loop.next);
+ pri(" %e", stmt->loop.next);
pri(")");
genblock(stmt->loop.body);
+ break;
case Siswitch:
+ pri("switch (%e) {", &stmt->iswitch.test);
+ for (int i = 0; i < stmt->iswitch.cs.n; ++i) {
+ struct iswitchcase c = stmt->iswitch.cs.d[i];
+ for (int i = 0; i < c.es.n; ++i)
+ pri("case %e: ", &c.es.d[i]);
+ genblock(c.t);
+ pri("break;\n");
+ }
+ if (stmt->iswitch.f) {
+ pri("default: ");
+ genblock(*stmt->iswitch.f);
+ }
+ pri("}\n");
break;
case Sreturn:
pri("return");
@@ -245,16 +275,51 @@ genblock(struct blockstmt block) {
pri("}\n");
}
-static void
-liftnestedex(struct expr *expr) {
- // TODO implement when statement expressions exist
- //switch (expr->t) {
- //}
-}
-
#define blocktostmt(Block) \
&(struct stmt) {Sblock, .block = Block}
+
+static void liftnested(struct stmt *stmt);
+// lift nested fns and static vars
+
+static void
+liftnestedex(struct expr *ex) {
+ switch (ex->t) {
+ case Eintlit: case Eflolit: case Estrlit:
+ case Eboolit: case Enullit: case Ename:
+ break;
+ case Eprefix:
+ liftnestedex(ex->unop.child);
+ break;
+ case Epostfix:
+ liftnestedex(ex->unop.child);
+ break;
+ case Ebinop:
+ liftnestedex(ex->binop.lhs);
+ liftnestedex(ex->binop.rhs);
+ break;
+ case Econd:
+ liftnestedex(ex->cond.test);
+ liftnestedex(ex->cond.t);
+ liftnestedex(ex->cond.f);
+ break;
+ case Ecall:
+ liftnestedex(ex->call.callee);
+ for (int i = 0; i < ex->call.args.n; ++i)
+ liftnestedex(&ex->call.args.d[i]);
+ break;
+ case Eindex:
+ liftnestedex(ex->index.lhs);
+ liftnestedex(ex->index.rhs);
+ break;
+ case Eblock:
+ liftnested(blocktostmt(ex->block));
+ break;
+ default:
+ assert(0);
+ }
+}
+
static void // lift nested fns and static vars
liftnested(struct stmt *stmt) {
static int id;
@@ -273,10 +338,17 @@ liftnested(struct stmt *stmt) {
case Dfn:
if (stmt->decl.fn.body) {
*stmt->decl._cname = xasprintf("__f%s_%d", stmt->decl.fn.name, id++);
- genfn(*stmt->decl._cname, &stmt->decl.fn);
+ genfn(stmt->decl.externp, *stmt->decl._cname, &stmt->decl.fn);
}
break;
- case Dvar:
+ case Dstatic:
+ if (!stmt->decl.externp) {
+ assert(stmt->decl.var.ini);
+ *stmt->decl._cname = xasprintf("__s%s_%d", stmt->decl.name, id++);
+ genstatic(stmt->decl.externp, *stmt->decl._cname, &stmt->decl.var);
+ }
+ break;
+ case Dlet:
liftnestedex(stmt->decl.var.ini);
break;
default:
@@ -312,10 +384,10 @@ liftnested(struct stmt *stmt) {
}
static void
-genfn(const char *cname, struct fn *fn) {
+genfn(bool externp, const char *cname, struct fn *fn) {
liftnested(fn->body);
- if (fn->body)
- pri("\n");
+ if (!externp)
+ pri("static ");
pri("%t %s(", fn->retty, cname);
for (int i = 0; i < fn->params.n; ++i) {
pri("%t %s", fn->params.d[i].ty, fn->params.d[i].name);
@@ -330,22 +402,37 @@ genfn(const char *cname, struct fn *fn) {
} else {
genblock(fn->body->block);
}
+}
+static void
+genstatic(bool externp, const char *cname, struct var *var) {
+ if (externp && !var->ini)
+ pri("extern ");
+ else if (!externp)
+ pri("static ");
+ pri("%t %s",var->ty, cname);
+ if (var->ini)
+ pri(" = %e", var->ini);
+ pri(";\n");
}
static void
gendecl(struct decl *decl, bool toplevel) {
+ const char *p = fileid2path(decl->span.fileid);
switch (decl->t) {
case Dfn:
- if (!decl->externp)
- pri("static ");
+ pri("#line %d %S\n", decl->span.line, p, (u64)strlen(p));
if (decl->fn.body)
assert(toplevel);
if (!*decl->_cname)
*decl->_cname = (char *)decl->fn.name;
- genfn(*decl->_cname, &decl->fn);
+ genfn(decl->externp, *decl->_cname, &decl->fn);
+ break;
+ case Dstatic:
+ pri("#line %d %S\n", decl->span.line, p, (u64)strlen(p));
+ genstatic(decl->externp, *decl->_cname ? *decl->_cname : decl->name, &decl->var);
break;
- case Dvar:
+ case Dlet:
assert(!toplevel);
break;
case Dtype: