scc

A fork of https://git.simple-cc.org/scc/ for Qute

git clone https://git.8pit.net/scc.git

  1#include <limits.h>
  2#include <stdlib.h>
  3
  4#include <scc/scc.h>
  5
  6#include "cc2.h"
  7
  8static Swtch *list = NULL;
  9
 10static Node *
 11swtch_if(Node *np)
 12{
 13	Type *tp;
 14	Swtch *swt;
 15	Node **cases, **bp, *tmpvar, *p;
 16
 17	swt = np->u.swtch;
 18	tp = &np->left->type;
 19
 20	tmpvar = tmpnode(tp, NULL);
 21	np->type = *tp;
 22	np->right = np->left;
 23	np->left = tmpvar;
 24	np->op = OASSIG;
 25	np->u.subop = 0;
 26
 27	cases = swt->cases;
 28	for (bp = cases; bp < &cases[swt->nr]; ++bp) {
 29		Node *eq, *tmp = tmpnode(tp, tmpvar->u.sym);
 30
 31		p = *bp;
 32		eq = node(OEQ);
 33		eq->type = *tp;
 34		eq->left = p->left;
 35		eq->right = tmp;
 36		*bp = NULL;
 37
 38		p->left = eq;
 39		p->op = OBRANCH;
 40		addstmt(p);
 41	}
 42	p = swtchdefault(swt);
 43	p->op = OJMP;
 44	addstmt(p);
 45
 46	free(cases);
 47	swt->cases = NULL;
 48
 49	return sethi(np);
 50}
 51
 52static Node *
 53swtch_dir(Node *np, long long min, long long max)
 54{
 55	int i;
 56	long long cur, nval;
 57	Swtch *swt;
 58	Symbol *tbl;
 59	Node *p, *def, **cases;
 60
 61	tbl = getsym(TMPSYM);
 62	tbl->kind = SLOCAL;
 63	tbl->type = ptrtype;
 64	tbl->type.flags |= INITF;
 65	defglobal(tbl);
 66
 67	swt = np->u.swtch;
 68	cases = swt->cases;
 69
 70	def = swtchdefault(swt);
 71	def->type = ptrtype;
 72	def->op = OLABEL;
 73
 74	i = 0;
 75	p = NULL;
 76	for (cur = min; cur <= max; ++cur) {
 77		if (!p && i < swt->nr) {
 78			p = cases[i++];
 79			p->type = ptrtype;
 80			p->op = OLABEL;
 81			nval = p->left->u.i;
 82		}
 83		if (p && nval == cur) {
 84			data(p);
 85			p = NULL;
 86		} else {
 87			data(def);
 88		}
 89	}
 90	endinit();
 91
 92	return np;
 93}
 94
 95Node *
 96swtch(Node *np)
 97{
 98	Swtch *swt;
 99	int n;
100	long long min, max, range;
101
102	swt = np->u.swtch;
103	min = swt->min;
104	max = swt->max;
105	range = max - min + 1;
106	n = swt->nr;
107
108	if (n < mach.swtchif)
109		return swtch_if(np);
110	return swtch_dir(np, min, max);
111}
112
113Node *
114swtchdefault(Swtch *swt)
115{
116	Node *np;
117
118	np = swt->defnode;
119	if (!np)
120		np = swt->eswtch;
121	return np;
122}
123
124Swtch *
125newswtch(Swtch *swt)
126{
127	Swtch *p = xmalloc(sizeof(*p));
128
129	*p = *swt;
130	p->next = list;
131	return list = p;
132}
133
134void
135cleanswtch(void)
136{
137	Swtch *p, *next;
138	Node **bp, **cases;
139
140	for (p = list; p; p = next) {
141		next = p->next;
142		cases = p->cases;
143		if (cases) {
144			for (bp = cases; bp < &cases[p->nr]; ++p)
145				deltree(*bp);
146			free(cases);
147		}
148		free(p);
149	}
150	list = NULL;
151}