diff options
| author | 2022-08-04 07:39:23 +0200 | |
|---|---|---|
| committer | 2022-08-04 07:39:23 +0200 | |
| commit | bb1d4b4a3e51a06fb0530dfc271a97a6cd88cc73 (patch) | |
| tree | f300325814bc30e64f858ee313b8260a14d8df90 /bootstrap/cgen.c | |
| parent | 1625c50f0c0e4b1c7ba01a5df5713efaf6dce606 (diff) | |
stuff
Diffstat (limited to 'bootstrap/cgen.c')
| -rw-r--r-- | bootstrap/cgen.c | 139 |
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: |