shithub: scc

Download patch

ref: 919f683654be6fe0e0a7b19adc144d3a84f089b2
parent: b4a75db28d8358ead5216591676f1c2e5867ebb4
author: Roberto E. Vargas Caballero <[email protected]>
date: Thu Apr 24 04:32:21 EDT 2014

Add while statements

These statements are transformed into do-while statements because
you save a jump in every iteration.

--- a/cc1.h
+++ b/cc1.h
@@ -228,7 +228,8 @@
 	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 *),
--- a/code.c
+++ b/code.c
@@ -206,6 +206,34 @@
 	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)
 {
--- a/expr.c
+++ b/expr.c
@@ -307,7 +307,7 @@
 	error(err);
 }
 
-static Node *
+Node *
 iszero(Node *np)
 {
 	if (ISNODECMP(np))
--- 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,7 +30,35 @@
 	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)
 {
 	Node *np;
@@ -63,6 +103,8 @@
 	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
+}
+