scc

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

commit 79bfc94dd4d53e3f66e6e96d44ca8666d7294c62
parent 536603d56b036bcf87e0678ce8c5e760d9b17b97
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Tue, 31 Dec 2024 16:16:04 +0100

cc2: Keep track of switch parameters

It is easy to keep track of these parameters while we parse,
and it is better to not discard this information because we
can use it later to emit the code for the switch.

Diffstat:
Minclude/bits/scc/scc.h | 2++
Msrc/cmd/scc-cc/cc2/cc2.h | 12++++++++++++
Msrc/cmd/scc-cc/cc2/cfg.c | 18++++++++++++++++++
Msrc/cmd/scc-cc/cc2/parser.c | 32+++++++++++++++++++-------------
Msrc/cmd/scc-cc/cc2/qbe/stubs.c | 6++++++
5 files changed, 57 insertions(+), 13 deletions(-)

diff --git a/include/bits/scc/scc.h b/include/bits/scc/scc.h @@ -14,6 +14,8 @@ extern int enadebug; #define TUINT unsigned long long #define TUINT_MAX ULLONG_MAX #define TINT_MAX LLONG_MAX +#define TUINT_MIN ULLONG_MIN +#define TINT_MIN LLONG_MIN #define TFLOAT double #define SIZET size_t diff --git a/src/cmd/scc-cc/cc2/cc2.h b/src/cmd/scc-cc/cc2/cc2.h @@ -155,6 +155,16 @@ typedef struct symbol Symbol; typedef struct addr Addr; typedef struct inst Inst; typedef struct block Block; +typedef struct swtch Swtch; + +struct swtch { + int nr; + TINT min, max; + Node *defnode; + Node *first; + Node *last; + Swtch *next; +}; struct type { unsigned long size; @@ -191,6 +201,7 @@ struct node { TFLOAT f; char *s; Symbol *sym; + Swtch *swtch; int reg; int subop; long off; @@ -282,6 +293,7 @@ extern void freesym(Symbol *sym); extern void gencfg(void); extern void cleancfg(void); extern Node *sethi(Node *); +extern Swtch *newswitch(Swtch *); /* globals */ extern Symbol *curfun; diff --git a/src/cmd/scc-cc/cc2/cfg.c b/src/cmd/scc-cc/cc2/cfg.c @@ -28,6 +28,7 @@ struct cfg { }; static struct cfg cfg; +static Swtch *switchlist; #ifndef NDEBUG #include <stdio.h> @@ -285,8 +286,15 @@ gencfg(void) void cleancfg(void) { + Swtch *p, *next; + free(cfg.blocks); memset(&cfg, 0, sizeof(cfg)); + + for (p = switchlist; p; p = next) { + next = p; + free(p); + } } static Node * @@ -396,6 +404,16 @@ swtch(Node *np) abort(); } +Swtch * +newswitch(Swtch *swt) +{ + Swtch *p = xmalloc(sizeof(*p)); + + *p = *swt; + p->next = switchlist; + return switchlist = p; +} + Node * sethi(Node *np) { diff --git a/src/cmd/scc-cc/cc2/parser.c b/src/cmd/scc-cc/cc2/parser.c @@ -24,14 +24,8 @@ union tokenop { unsigned op; }; -struct swtch { - int nr; - Node *first; - Node *last; -}; - Node *laststmt; -static struct swtch swtbl[NR_BLOCK], *swp = swtbl; +static Swtch swtbl[NR_BLOCK], *swp = swtbl; static Symbol *lastfun; typedef void parsefun(char *, union tokenop); @@ -347,7 +341,8 @@ oreturn(char *token, union tokenop u) static void waft(Node *np) { - struct swtch *cur; + TINT val; + Swtch *cur; if (swp == swtbl) error(EWTACKU); @@ -356,20 +351,31 @@ waft(Node *np) addstmt(np); waftstmt(cur->last); cur->last = np; - cur->nr++; + if (np->op == ODEFAULT) { + cur->defnode = np; + } else if (np->op != OESWITCH) { + cur->nr++; + val = np->left->u.i; + if (val < cur->min) + cur->min = val; + if (val > cur->max) + cur->max = val; + } } static void bswitch(char *token, union tokenop u) { - struct swtch *cur; + Swtch *cur; Node *np = node(u.op); if (swp == &swtbl[NR_BLOCK]) error(EWTACKO); cur = swp++; cur->nr = 0; - + cur->min = TINT_MAX; + cur->max = TINT_MIN; + cur->defnode = NULL; eval(strtok(NULL, "\t\n")); np->left = pop(); @@ -379,14 +385,14 @@ bswitch(char *token, union tokenop u) static void eswitch(char *token, union tokenop u) { - struct swtch *cur; + Swtch *cur; if (swp == swtbl) error(EWTACKU); jump(token, u); waft(pop()); cur = --swp; - cur->first->u.i = cur->nr; + cur->first->u.swtch = newswitch(cur); } static void diff --git a/src/cmd/scc-cc/cc2/qbe/stubs.c b/src/cmd/scc-cc/cc2/qbe/stubs.c @@ -20,3 +20,9 @@ void cleancfg(void) { } + +Swtch * +newswitch(Swtch *swt) +{ + return NULL; +}