scc

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

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:
Msrc/cmd/scc-cc/cc2/amd64-sysv/cgen.c | 4++--
Msrc/cmd/scc-cc/cc2/cc2.h | 4+++-
Msrc/cmd/scc-cc/cc2/cfg.c | 113++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
Msrc/cmd/scc-cc/cc2/code.c | 2+-
Msrc/cmd/scc-cc/cc2/i386-sysv/cgen.c | 4++--
Msrc/cmd/scc-cc/cc2/qbe/cgen.c | 16++++++++--------
Msrc/cmd/scc-cc/cc2/z80-scc/cgen.c | 38++++++++------------------------------
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); }