scc

simple C compiler
git clone git://git.2f30.org/scc
Log | Files | Refs | README | LICENSE

commit de14dcda8c70cba2b4833cb4ede3269156e9d754
parent abe4b5dfa83c017b1311fb5d541bdb4c77b2010e
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Thu, 26 May 2016 09:38:47 +0200

[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.

Diffstat:
Mcc2/arch/qbe/cgen.c | 4++--
Mcc2/cc2.h | 7+++++--
Mcc2/parser.c | 79++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------
3 files changed, 67 insertions(+), 23 deletions(-)

diff --git a/cc2/arch/qbe/cgen.c b/cc2/arch/qbe/cgen.c @@ -387,8 +387,8 @@ cgen(Node *np) return NULL; case OCASE: case ODEFAULT: - case OTABLE: - case OSWITCH: + case OESWITCH: + case OBSWITCH: default: abort(); } diff --git a/cc2/cc2.h b/cc2/cc2.h @@ -99,8 +99,8 @@ enum op { OELOOP = 'e', OCASE = 'v', ODEFAULT = 'f', - OTABLE = 't', - OSWITCH = 's', + OBSWITCH = 's', + OESWITCH = 't', }; enum nerrors { @@ -116,6 +116,9 @@ enum nerrors { 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 }; diff --git a/cc2/parser.c b/cc2/parser.c @@ -30,10 +30,18 @@ union tokenop { 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 @@ static struct decoc { ['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,13 +334,55 @@ oreturn(char *token, union tokenop u) } 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); 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 @@ jump(char *token, union tokenop u) } 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 @@ stmt(void) { Node *np; + if (empty()) + return; np = pop(); if (ininit) { data(np);