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:
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;
+}