aboutsummaryrefslogtreecommitdiff
path: root/bootstrap/cgen.c
diff options
context:
space:
mode:
authorlemon <lsof@mailbox.org>2022-08-20 06:31:06 +0200
committerlemon <lsof@mailbox.org>2022-08-20 06:31:06 +0200
commit19acdd751963e88b6e75693f947b1b1fd2912f11 (patch)
treee276d518a6eee672d3b2f32381fb41b544a9d6c7 /bootstrap/cgen.c
parent58d8abf355c1543ec6afd99189848634f51f6273 (diff)
defer
Diffstat (limited to 'bootstrap/cgen.c')
-rw-r--r--bootstrap/cgen.c40
1 files changed, 30 insertions, 10 deletions
diff --git a/bootstrap/cgen.c b/bootstrap/cgen.c
index e047f08..94ae420 100644
--- a/bootstrap/cgen.c
+++ b/bootstrap/cgen.c
@@ -318,7 +318,7 @@ 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) {
+genstmt(struct blockstmt *block, 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));
@@ -367,7 +367,7 @@ genstmt(struct stmt *stmt) {
genblock(stmt->ifelse.t);
if (stmt->ifelse.f) {
pri("else\n");
- genstmt(stmt->ifelse.f);
+ genstmt(block, stmt->ifelse.f);
}
break;
case Swhile:
@@ -384,7 +384,7 @@ genstmt(struct stmt *stmt) {
case Sfor:
pri("{\n");
for (int i = 0; i < stmt->loop.ini.n; ++i)
- genstmt(&stmt->loop.ini.d[i]);
+ genstmt(block, &stmt->loop.ini.d[i]);
pri("for (; ");
pri("%e;", &stmt->loop.test);
if (stmt->loop.next)
@@ -446,10 +446,22 @@ genstmt(struct stmt *stmt) {
pri("}\n"); pri("}\n");
break;
case Sreturn:
- pri("return");
- if (stmt->retex)
- pri(" %e", stmt->retex);
- pri(";\n");
+ pri("do { ");
+ if (stmt->ret.ex) {
+ if (stmt->ret.ex->ty->t != TYvoid)
+ pri("__auto_type __ret = ");
+ pri("%e;", stmt->ret.ex);
+ }
+ for (struct defer* defer = block->defers; defer; defer = defer->next) {
+ if (defer->age < stmt->ret.deferage) {
+ const char *p = fileid2path(defer->ex.span.fileid);
+ pri("\n#line %d %S\n", defer->ex.span.line, p, (u64)strlen(p));
+ genexpr(&defer->ex);
+ pri(";\n");
+ }
+ }
+ pri("return%s;", (stmt->ret.ex && stmt->ret.ex->ty->t != TYvoid) ? " __ret" : "");
+ pri("} while (0);\n");
break;
case Sbreak:
pri("goto _brk%d;\n", stmt->brkcon.id);
@@ -475,7 +487,7 @@ static void
genblock(struct blockstmt block) {
pri("{\n");
for (int i = 0; i < block.stmts.n; ++i)
- genstmt(&block.stmts.d[i]);
+ genstmt(&block, &block.stmts.d[i]);
pri("}\n");
}
@@ -644,8 +656,8 @@ liftnested(struct stmt *stmt) {
liftnested(blocktostmt(*stmt->iswitch.f));
break;
case Sreturn:
- if (stmt->retex)
- liftnestedex(stmt->retex);
+ if (stmt->ret.ex)
+ liftnestedex(stmt->ret.ex);
break;
case Seuswitch:
liftnestedex(&stmt->euswitch.test);
@@ -687,7 +699,15 @@ genfn(bool externp, const char *cname, struct fn *fn) {
if (!fn->body) {
pri(";\n");
} else {
+ pri("{");
genblock(fn->body->block);
+ for (struct defer* defer = fn->body->block.defers; defer; defer = defer->next) {
+ const char *p = fileid2path(defer->ex.span.fileid);
+ pri("\n#line %d %S\n", defer->ex.span.line, p, (u64)strlen(p));
+ genexpr(&defer->ex);
+ pri(";\n");
+ }
+ pri("}");
}
}