commit 6afeca7d7c61dc99d4074752573484662465a928
parent 837831a8ebd350f24d4d305ebfa41bca7b45d510
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date: Mon, 30 Dec 2024 21:05:39 +0100
cc2: Transform switch() into a if-else chain
This is the first step, and it is the simpler implementation
of a switch but it is not very efficient with a big number
of cases.
Diffstat:
7 files changed, 134 insertions(+), 47 deletions(-)
diff --git a/src/cmd/scc-cc/cc2/amd64-sysv/cgen.c b/src/cmd/scc-cc/cc2/amd64-sysv/cgen.c
@@ -7,7 +7,7 @@ genasm(void)
{
}
-void
-genaddr(void)
+Node *
+tsethi(Node *np)
{
}
diff --git a/src/cmd/scc-cc/cc2/cc2.h b/src/cmd/scc-cc/cc2/cc2.h
@@ -160,7 +160,7 @@ struct type {
unsigned long size;
unsigned align;
unsigned short id;
- short flags;
+ unsigned short flags;
};
struct symbol {
@@ -236,6 +236,7 @@ extern void parse(void);
/* cgen.c */
extern void genaddr(void);
extern void genasm(void);
+extern Node *tsethi(Node *);
/* peep.c */
extern void peephole(void);
@@ -280,6 +281,7 @@ extern void freesym(Symbol *sym);
/* cfg.c */
extern void gencfg(void);
extern void cleancfg(void);
+extern Node *sethi(Node *);
/* globals */
extern Symbol *curfun;
diff --git a/src/cmd/scc-cc/cc2/cfg.c b/src/cmd/scc-cc/cc2/cfg.c
@@ -4,6 +4,7 @@
* code is not needed in qbe targets.
*/
#include <assert.h>
+#include <limits.h>
#include <stdlib.h>
#include <string.h>
@@ -19,9 +20,6 @@
#define PRTREE(msg) (enadebug ? prforest(msg) : NULL)
#endif
-/* TODO: ignore OCASE, OBSWITCH, ODEFAULT for now */
-#define NBLOCKS 10
-
struct cfg {
int nr;
Block *entryb, *exitb;
@@ -290,3 +288,112 @@ cleancfg(void)
free(cfg.blocks);
memset(&cfg, 0, sizeof(cfg));
}
+
+static Node *
+swtch_if(Node *idx)
+{
+ Node *tmpvar, *next, *tmp, *np;
+ Symbol *deflabel = NULL;
+
+ tmpvar = tmpnode(&idx->type);
+ idx->right = idx->left;
+ idx->right = tmpvar;
+ idx->op = OASSIG;
+
+ for (np = idx->next; ; np = next) {
+ next = np->next;
+ switch (np->op) {
+ case OESWITCH:
+ if (!deflabel)
+ deflabel = np->u.sym;
+ np->op = OJMP;
+ np->u.sym = deflabel;
+ return sethi(idx);
+ case OCASE:
+ np->op = OBRANCH;
+ tmp = node(OEQ);
+ tmp->type = idx->type;
+ tmp->left = np->left;
+ tmp->right = tmpvar;
+ np->left = tmp;
+ break;
+ case ODEFAULT:
+ deflabel = np->u.sym;
+ deltree(unlinkstmt(np));
+ break;
+ default:
+ abort();
+ }
+ }
+}
+
+static Node *
+swtch(Node *np)
+{
+ int n;
+ TINT min, max, val;
+ Node *p, *def = NULL;
+
+ min = TINT_MAX;
+ min = max = n = 0;
+ for (p = np->next; p->op != OESWITCH; p = p->next) {
+ if (p->op == ODEFAULT) {
+ def = np;
+ } else {
+ val = np->left->u.i;
+ if (val > max)
+ max = val;
+ if (val < min)
+ min = val;
+ }
+ ++n;
+ }
+
+ return swtch_if(np);
+}
+
+Node *
+sethi(Node *np)
+{
+ Node *l, *r;
+
+ if (!np)
+ return np;
+
+ np->complex = 0;
+ np->address = 0;
+
+ switch (np->op) {
+ case OBSWITCH:
+ np = swtch(np);
+ break;
+ default:
+ np = tsethi(np);
+ }
+
+ l = np->left;
+ r = np->right;
+
+ if (np->address > 10)
+ return np;
+ if (l)
+ np->complex = l->complex;
+ if (r) {
+ int d = np->complex - r->complex;
+
+ if (d == 0)
+ ++np->complex;
+ else if (d < 0)
+ np->complex = r->complex;
+ }
+ if (np->complex == 0)
+ ++np->complex;
+
+ return np;
+}
+
+void
+genaddr(void)
+{
+ apply(sethi);
+}
diff --git a/src/cmd/scc-cc/cc2/code.c b/src/cmd/scc-cc/cc2/code.c
@@ -141,7 +141,7 @@ label2node(Node *np, Symbol *sym)
Node *
tmpnode(Type *tp)
{
- char flags;
+ unsigned short flags;
Symbol *sym;
Node *np;
diff --git a/src/cmd/scc-cc/cc2/i386-sysv/cgen.c b/src/cmd/scc-cc/cc2/i386-sysv/cgen.c
@@ -8,7 +8,7 @@ genasm(void)
{
}
-void
-genaddr(void)
+Node *
+tsethi(Node *np)
{
}
diff --git a/src/cmd/scc-cc/cc2/qbe/cgen.c b/src/cmd/scc-cc/cc2/qbe/cgen.c
@@ -159,8 +159,8 @@ complex(Node *np)
return np;
}
-static Node *
-sethi(Node *np)
+Node *
+tsethi(Node *np)
{
Node *l, *r;
@@ -189,8 +189,8 @@ sethi(Node *np)
goto binary;
default:
binary:
- l = sethi(l);
- r = sethi(r);
+ l = tsethi(l);
+ r = tsethi(r);
break;
}
np->left = l;
@@ -599,7 +599,7 @@ assign(Node *np)
aux.left = ret;
aux.right = r;
aux.type = np->type;
- r = rhs(sethi(&aux));
+ r = rhs(tsethi(&aux));
break;
default:
/* assign abbreviation */
@@ -611,7 +611,7 @@ assign(Node *np)
aux.right = r;
aux.type = int32type;
aux.address = np->address;
- ret = r = sethi(rhs(&aux));
+ ret = r = tsethi(rhs(&aux));
break;
}
@@ -620,7 +620,7 @@ assign(Node *np)
aux.right = r;
aux.type = np->type;
aux.address = np->address;
- r = sethi(&aux);
+ r = tsethi(&aux);
case 0:
lhs_rhs(&l, &r);
ret = r;
@@ -830,5 +830,5 @@ genasm(void)
void
genaddr(void)
{
- apply(sethi);
+ apply(tsethi);
}
diff --git a/src/cmd/scc-cc/cc2/z80-scc/cgen.c b/src/cmd/scc-cc/cc2/z80-scc/cgen.c
@@ -567,16 +567,11 @@ cgen(Node *np)
* STATIC => 12 (value)
* CONST => 20 $value
*/
-static Node *
-sethi(Node *np)
+Node *
+tsethi(Node *np)
{
Node *l, *r;
- if (!np)
- return np;
-
- np->complex = 0;
- np->address = 0;
l = np->left;
r = np->right;
switch (np->op) {
@@ -593,36 +588,19 @@ sethi(Node *np)
np->address = 20;
break;
default:
- sethi(l);
- sethi(r);
+ l = sethi(l);
+ r = sethi(r);
break;
}
- if (np->address > 10)
- return np;
- if (l)
- np->complex = l->complex;
- if (r) {
- int d = np->complex - r->complex;
-
- if (d == 0)
- ++np->complex;
- else if (d < 0)
- np->complex = r->complex;
- }
- if (np->complex == 0)
- ++np->complex;
+ np->left = l;
+ np->right = r;
+
return np;
}
void
genasm(void)
{
- apply(fbody(), cgen);
-}
-
-void
-genaddr(void)
-{
- apply(sethi);
+ apply(cgen);
}