aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--stmt.c29
-rw-r--r--test/do-loop.qbe24
-rw-r--r--test/for-loop.qbe13
-rw-r--r--test/varargs.qbe15
4 files changed, 49 insertions, 32 deletions
diff --git a/stmt.c b/stmt.c
index 256ddd0..075feff 100644
--- a/stmt.c
+++ b/stmt.c
@@ -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