diff options
-rw-r--r-- | stmt.c | 29 | ||||
-rw-r--r-- | test/do-loop.qbe | 24 | ||||
-rw-r--r-- | test/for-loop.qbe | 13 | ||||
-rw-r--r-- | test/varargs.qbe | 15 |
4 files changed, 49 insertions, 32 deletions
@@ -24,6 +24,27 @@ gotolabel(struct func *f) return true; } +/* controlling expression of loops and if-statements */ +static struct expr * +ctrlexpr(struct scope *s) +{ + struct expr *e; + struct type *t; + + e = expr(s); + t = e->type; + if (!(t->prop & PROPSCALAR)) + error(&tok.loc, "controlling expression must have scalar type"); + /* + Ideally we would just do this conversion unconditionally, + but QBE is not currently able to optimize the conversion + away for int. + */ + if (t->prop & PROPFLOAT || t->size > 4) + e = exprconvert(e, &typebool); + return e; +} + /* 6.8 Statements and blocks */ void stmt(struct func *f, struct scope *s) @@ -91,7 +112,7 @@ stmt(struct func *f, struct scope *s) next(); s = mkscope(s); expect(TLPAREN, "after 'if'"); - e = exprconvert(expr(s), &typebool); + e = ctrlexpr(s); v = funcexpr(f, e); delexpr(e); expect(TRPAREN, "after expression"); @@ -154,7 +175,7 @@ stmt(struct func *f, struct scope *s) next(); s = mkscope(s); expect(TLPAREN, "after 'while'"); - e = exprconvert(expr(s), &typebool); + e = ctrlexpr(s); expect(TRPAREN, "after expression"); label[0] = mkblock("while_cond"); @@ -192,7 +213,7 @@ stmt(struct func *f, struct scope *s) expect(TWHILE, "after 'do' statement"); expect(TLPAREN, "after 'while'"); funclabel(f, label[1]); - e = exprconvert(expr(s), &typebool); + e = ctrlexpr(s); expect(TRPAREN, "after expression"); v = funcexpr(f, e); @@ -221,7 +242,7 @@ stmt(struct func *f, struct scope *s) funclabel(f, label[0]); if (tok.kind != TSEMICOLON) { - e = exprconvert(expr(s), &typebool); + e = ctrlexpr(s); v = funcexpr(f, e); funcjnz(f, v, label[1], label[3]); delexpr(e); diff --git a/test/do-loop.qbe b/test/do-loop.qbe index 2f0e12a..0d383e4 100644 --- a/test/do-loop.qbe +++ b/test/do-loop.qbe @@ -9,22 +9,20 @@ function w $main() { @do_body.3 %.3 =w loadsw %.1 %.4 =w ceqw %.3, 1 - %.5 =w cnew %.4, 0 - jnz %.5, @if_true.6, @if_false.7 + jnz %.4, @if_true.6, @if_false.7 @if_true.6 jmp @do_cond.4 @if_false.7 - %.6 =w loadsw %.2 - %.7 =w add %.6, 1 - storew %.7, %.2 + %.5 =w loadsw %.2 + %.6 =w add %.5, 1 + storew %.6, %.2 @do_cond.4 - %.8 =w loadsw %.1 - %.9 =w sub %.8, 1 - storew %.9, %.1 - %.10 =w cnew %.8, 0 - jnz %.10, @do_body.3, @do_join.5 + %.7 =w loadsw %.1 + %.8 =w sub %.7, 1 + storew %.8, %.1 + jnz %.7, @do_body.3, @do_join.5 @do_join.5 - %.11 =w loadsw %.2 - %.12 =w cnew %.11, 2 - ret %.12 + %.9 =w loadsw %.2 + %.10 =w cnew %.9, 2 + ret %.10 } diff --git a/test/for-loop.qbe b/test/for-loop.qbe index 588f488..56b38b1 100644 --- a/test/for-loop.qbe +++ b/test/for-loop.qbe @@ -7,15 +7,14 @@ function $f() { @for_cond.3 %.2 =w loadsw %.1 %.3 =w csltw %.2, 10 - %.4 =w cnew %.3, 0 - jnz %.4, @for_body.4, @for_join.6 + jnz %.3, @for_body.4, @for_join.6 @for_body.4 - %.5 =w loadsw %.1 - call $g(w %.5) + %.4 =w loadsw %.1 + call $g(w %.4) @for_cont.5 - %.6 =w loadsw %.1 - %.7 =w add %.6, 1 - storew %.7, %.1 + %.5 =w loadsw %.1 + %.6 =w add %.5, 1 + storew %.6, %.1 jmp @for_cond.3 @for_join.6 ret diff --git a/test/varargs.qbe b/test/varargs.qbe index cb3542a..2a760d6 100644 --- a/test/varargs.qbe +++ b/test/varargs.qbe @@ -8,15 +8,14 @@ function $f(w %.1, ...) { vastart %.3 @while_cond.3 %.4 =w loadsw %.2 - %.5 =w cnew %.4, 0 - jnz %.5, @while_body.4, @while_join.5 + jnz %.4, @while_body.4, @while_join.5 @while_body.4 - %.6 =w vaarg %.3 - %.7 =s vaarg %.3 - %.8 =l vaarg %.3 - %.9 =w loadsw %.2 - %.10 =w sub %.9, 1 - storew %.10, %.2 + %.5 =w vaarg %.3 + %.6 =s vaarg %.3 + %.7 =l vaarg %.3 + %.8 =w loadsw %.2 + %.9 =w sub %.8, 1 + storew %.9, %.2 jmp @while_cond.3 @while_join.5 ret |