scc

simple c99 compiler
git clone git://git.simple-cc.org/scc
Log | Files | Refs | Submodules | README | LICENSE

commit 00d366a0535adf8b0bf934e398aae138426d7262
parent d603b01749058d99f191934ebbefb0f8a56328eb
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Tue, 31 Dec 2024 18:55:40 +0100

cc2: Add support for switch in the cfg

Switch introduces a new different type of link between basic
blocks because a single basic block can be linked with many
different basic blocks which does not fit well with the
true/false approach that we were using with basic blocks.

Diffstat:
Msrc/cmd/scc-cc/cc2/cc2.h | 2++
Msrc/cmd/scc-cc/cc2/cfg.c | 57++++++++++++++++++++++++++++++++++++++++++++++++++++++---
Msrc/cmd/scc-cc/cc2/parser.c | 6+++++-
Msrc/cmd/scc-cc/cc2/swtch.c | 1-
4 files changed, 61 insertions(+), 5 deletions(-)

diff --git a/src/cmd/scc-cc/cc2/cc2.h b/src/cmd/scc-cc/cc2/cc2.h @@ -161,6 +161,7 @@ struct swtch { int nr; TINT min, max; Node *defnode; + Node *cases; Node *first; Node *last; Swtch *next; @@ -217,6 +218,7 @@ struct block { int printed, visited; Node *entryp, *exitp; Block *true, *false; + Swtch *swtch; Block *next; }; diff --git a/src/cmd/scc-cc/cc2/cfg.c b/src/cmd/scc-cc/cc2/cfg.c @@ -29,6 +29,10 @@ static struct cfg cfg; static void prbb(Block *bb) { + Node *np; + Swtch *swt; + Block *casebb; + if (!bb || bb->printed) return; @@ -46,6 +50,28 @@ prbb(Block *bb) } prbb(bb->true); prbb(bb->false); + + swt = bb->swtch; + if (!swt) + return; + + for (np = swt->cases; np->op != OESWITCH; np = np->next) { + casebb = np->u.sym->u.stmt->bb; + + if (!np->left) { + fprintf(stderr, + "\t%d -> %d [label=\"default\"]\n", + bb->id, + casebb->id); + } else { + fprintf(stderr, + "\t%d -> %d [label=\"case %lld\"]\n", + bb->id, + casebb->id, + np->left->u.i); + } + prbb(casebb); + } } static void @@ -84,6 +110,7 @@ newbb(Node *np) bb = &cfg.blocks[cfg.nr]; bb->entryp = np; bb->exitp = NULL; + bb->swtch = NULL; bb->true = bb->false = NULL; bb->id = cfg.nr++; bb->visited = 0; @@ -95,9 +122,6 @@ newbb(Node *np) static Node * mkcfg(Node *np) { - if ((np->flags & (BBENTRY|BBEXIT)) == 0) - return np; - if (np->flags & BBENTRY) cfg.cur = np->bb; @@ -116,6 +140,12 @@ mkcfg(Node *np) case ORET: cfg.cur->true = laststmt->bb; break; + case OBSWITCH: + cfg.cur->swtch = np->u.swtch; + break; + case OESWITCH: + cfg.cur->true = NULL; + break; case OBRANCH: cfg.cur->false = np->next->bb; case OJMP: @@ -152,6 +182,9 @@ newentry(Node *np) static Node * markbb(Node *np) { + Swtch *swt; + Node *p; + switch (np->op) { case OBFUN: newentry(np); @@ -160,6 +193,14 @@ markbb(Node *np) newentry(laststmt); newentry(np->next); break; + case OBSWITCH: + swt = np->u.swtch; + for (p = swt->cases; p->op != OESWITCH; p = p->next) + newentry(p->u.sym->u.stmt); + break; + case OESWITCH: + np->flags |= BBEXIT; + break; case OBRANCH: case OJMP: newentry(np->u.sym->u.stmt); @@ -172,11 +213,21 @@ markbb(Node *np) static void visit(Block *bb) { + Node *np; + Swtch *swt; + if (!bb || bb->visited) return; bb->visited = 1; visit(bb->true); visit(bb->false); + + swt = bb->swtch; + if (!swt) + return; + + for (np = swt->cases; np->op != OESWITCH; np = np->next) + visit(np->u.sym->u.stmt->bb); } static void diff --git a/src/cmd/scc-cc/cc2/parser.c b/src/cmd/scc-cc/cc2/parser.c @@ -385,14 +385,18 @@ bswitch(char *token, union tokenop u) static void eswitch(char *token, union tokenop u) { + Node *first; Swtch *cur; if (swp == swtbl) error(EWTACKU); jump(token, u); waft(pop()); + cur = --swp; - cur->first->u.swtch = newswitch(cur); + first = cur->first; + cur->cases = first->next; + first->u.swtch = newswitch(cur); } static void diff --git a/src/cmd/scc-cc/cc2/swtch.c b/src/cmd/scc-cc/cc2/swtch.c @@ -66,7 +66,6 @@ swtch_dir(Node *np, int n, TINT min, TINT max) p->type = ptrtype; p->op = OLABEL; } - np->next = p->next; for (ip = its; ip < &its[n]; ++ip) { if (*ip == NULL)