scc

Simple C99 Compiler
Log | Files | Refs | README | LICENSE

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:
cc1.h | 3++-
code.c | 28++++++++++++++++++++++++++++
expr.c | 2+-
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 +} +