shithub: scc

Download patch

ref: 3e1d484b33d59c87095ce175ac7fa180bc422132
parent: be91e9ff3d8d1d06cc92490d7bc1786823068d7c
author: Roberto E. Vargas Caballero <k0ga@shike2.com>
date: Thu May 26 05:38:47 EDT 2016

[cc2] Addapt cc2 to new switch IR

In the new switch IR all the jump table is written interlaced
with the body statements, and this code moves all the switch
related statements in order to get them at the beginning and
in consecutive positions.

--- a/cc2/arch/qbe/cgen.c
+++ b/cc2/arch/qbe/cgen.c
@@ -387,8 +387,8 @@
 		return NULL;
 	case OCASE:
 	case ODEFAULT:
-	case OTABLE:
-	case OSWITCH:
+	case OESWITCH:
+	case OBSWITCH:
 	default:
 		abort();
 	}
--- a/cc2/cc2.h
+++ b/cc2/cc2.h
@@ -99,8 +99,8 @@
 	OELOOP   = 'e',
 	OCASE    = 'v',
 	ODEFAULT = 'f',
-	OTABLE   = 't',
-	OSWITCH  = 's',
+	OBSWITCH = 's',
+	OESWITCH = 't',
 };
 
 enum nerrors {
@@ -116,6 +116,9 @@
 	ELNBLNE,       /* line without new line */
 	EFERROR,       /* error reading from file:%s*/
 	EBADID,        /* incorrect symbol id */
+	EWTACKO,       /* switch stack overflow */
+	EWTACKU,       /* switch stack underflow */
+	ENOSWTC,       /* Out of switch statement */
 	ENUMERR
 };
 
--- a/cc2/parser.c
+++ b/cc2/parser.c
@@ -30,10 +30,18 @@
 	unsigned op;
 };
 
+struct swtch {
+	int nr;
+	Node *last;
+};
+
+static struct swtch swtbl[NR_BLOCK], *swp = swtbl;
+
 typedef void parsefun(char *, union tokenop);
 static parsefun type, symbol, getname, unary, binary, ternary, call,
                 constant, composed, binit, einit,
-                jump, oreturn, loop, assign, casetbl;
+                jump, oreturn, loop, assign,
+                ocase, bswitch, eswitch;
 
 typedef void evalfun(void);
 static evalfun vardecl, beginfun, endfun, endpars, stmt,
@@ -123,22 +131,21 @@
 	['b']   = {     NULL,    loop, .u.op =        OBLOOP},
 	['e']   = {     NULL,    loop, .u.op =        OELOOP},
 
-	['v']   = {     NULL,    jump, .u.op =         OCASE},
-	['s']   = {     NULL,    jump, .u.op =       OSWITCH},
-
-	['f']   = {     NULL, casetbl, .u.op =      ODEFAULT},
-	['t']   = {     NULL, casetbl, .u.op =        OTABLE}
+	['v']   = {     NULL,   ocase, .u.op =         OCASE},
+	['f']   = {     NULL,   ocase, .u.op =      ODEFAULT},
+	['t']   = {     NULL, eswitch, .u.op =      OESWITCH},
+	['s']   = {     NULL, bswitch, .u.op =      OBSWITCH},
 };
 
 static int sclass, inpars, ininit, endf, lineno;
 static void *stack[STACKSIZ], **sp = stack;
 
-static void
+static Node *
 push(void *elem)
 {
 	if (sp == stack[STACKSIZ])
 		error(ESTACKO);
-	*sp++ = elem;
+	return *sp++ = elem;
 }
 
 static void *
@@ -327,6 +334,48 @@
 }
 
 static void
+waft(Node *np)
+{
+	Node *p;
+
+	if (swp == swtbl)
+		error(EWTACKU);
+	p = swp[-1].last;
+
+	np->next = p->next;
+	np->prev = p;
+	p->next = np;
+	swp[-1].last = np;
+}
+
+static void
+bswitch(char *token, union tokenop u)
+{
+	if (swp++ == &swtbl[NR_BLOCK+1])
+		error(EWTACKO);
+	jump(token, u);
+	swp->nr = 0;
+	swp->last = push(pop());
+}
+
+static void
+eswitch(char *token, union tokenop u)
+{
+	if (swp == swtbl)
+		error(EWTACKU);
+	jump(token, u);
+	waft(pop());
+	--swp;
+}
+
+static void
+ocase(char *token, union tokenop u)
+{
+	jump(token, u);
+	waft(pop());
+}
+
+static void
 jump(char *token, union tokenop u)
 {
 	Node *aux, *np = newnode(u.op);
@@ -333,7 +382,7 @@
 
 	eval(strtok(NULL, "\t\n"));
 
-	if (u.op != OJMP)
+	if (u.op == OBRANCH || u.op == OCASE)
 		np->left = pop();
 	aux = pop();
 	np->u.sym = aux->u.sym;
@@ -342,16 +391,6 @@
 }
 
 static void
-casetbl(char *token, union tokenop u)
-{
-	Node *np = newnode(u.op);
-
-	eval(strtok(NULL, "\t\n"));
-	np->left = pop();
-	push(np);
-}
-
-static void
 loop(char *token, union tokenop u)
 {
 	push(newnode(u.op));
@@ -564,6 +603,8 @@
 {
 	Node *np;
 
+	if (empty())
+		return;
 	np = pop();
 	if (ininit) {
 		data(np);