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);