commit 919f683654be6fe0e0a7b19adc144d3a84f089b2
parent b4a75db28d8358ead5216591676f1c2e5867ebb4
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date: Thu, 24 Apr 2014 08:32:21 +0200
Add while statements
These statements are transformed into do-while statements because
you save a jump in every iteration.
Diffstat:
M | cc1.h | | | 3 | ++- |
M | code.c | | | 28 | ++++++++++++++++++++++++++++ |
M | expr.c | | | 2 | +- |
M | stmt.c | | | 45 | +++++++++++++++++++++++++++++++++++++++++++-- |
4 files changed, 74 insertions(+), 4 deletions(-)
diff --git a/cc1.h b/cc1.h
@@ -228,7 +228,8 @@ extern void
emitdcl(Symbol *), emitsframe(Symbol *), emiteframe(Symbol *),
emitsym(Node *), emitunary(Node *),
emitbin(Node *), emitexp(Node *),
- emitprint(Node *);
+ emitprint(Node *), emitlabel(Symbol *), emitjump(Symbol *, Node *),
+ emitbloop(void), emiteloop(void);
extern Node
*node(void (*code)(Node *),
diff --git a/code.c b/code.c
@@ -206,6 +206,34 @@ emitret(Type *tp)
emittype(tp);
}
+void
+emitlabel(Symbol *sym)
+{
+ printf("L%d\n", sym->id);
+}
+
+void
+emitbloop(void)
+{
+ puts("\td");
+}
+
+void
+emiteloop(void)
+{
+ puts("\tb");
+}
+
+void
+emitjump(Symbol *sym, Node *np)
+{
+ printf("\tj\tL%d", sym->id);
+ if (!np)
+ putchar('\n');
+ else
+ emitexp(np);
+}
+
Node *
castcode(Node *child, Type *tp)
{
diff --git a/expr.c b/expr.c
@@ -307,7 +307,7 @@ error:
error(err);
}
-static Node *
+Node *
iszero(Node *np)
{
if (ISNODECMP(np))
diff --git a/stmt.c b/stmt.c
@@ -8,8 +8,20 @@
Symbol *curfun;
extern Node *convert(Node *np, Type *tp1, char iscast);
+extern Node * iszero(Node *np);
static void stmt(Symbol *lbreak, Symbol *lcont, Symbol *lswitch);
+static Symbol *
+label(char *s)
+{
+ if (!s)
+ s = "";
+ else if (lookup(s, NS_LABEL))
+ error("label '%s' already defined", s);
+
+ return install(s, NS_LABEL);
+}
+
static Node *
stmtexp(void)
{
@@ -18,6 +30,34 @@ stmtexp(void)
return np;
}
+static Node *
+condition(void)
+{
+ Node *np;
+
+ expect('(');
+ np = iszero(expr());
+ expect(')');
+ return np;
+}
+
+static void
+While(Symbol *lswitch)
+{
+ Symbol *begin= label(NULL), *cond = label(NULL), *end = label(NULL);
+ Node *np;
+
+ expect(WHILE);
+ np = condition();
+ emitjump(cond, NULL);
+ emitbloop();
+ emitlabel(begin);
+ stmt(begin, end, lswitch);
+ emitlabel(cond);
+ emitjump(begin, np);
+ emiteloop();
+}
+
static void
Return(void)
{
@@ -63,6 +103,8 @@ stmt(Symbol *lbreak, Symbol *lcont, Symbol *lswitch)
switch (yytoken) {
case '{': compound(lbreak, lcont, lswitch); break;
case RETURN: Return(); break;
+ case WHILE: While(lswitch); break;
default: emitexp(stmtexp()); break;
}
-}
-\ No newline at end of file
+}
+