scc

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

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

  1#include <scc/scc.h>
  2
  3#include "cc2.h"
  4
  5static Node *
  6assignnode(Type *tp, Node *lhs, Node *rhs)
  7{
  8	Node *np;
  9
 10	np = node(OASSIG);
 11	np->type = *tp;
 12	np->left = lhs;
 13	np->right = rhs;
 14	return sethi(np);
 15}
 16
 17static Node *
 18branchnode(Node *cond, Symbol *sym)
 19{
 20	Node *np;
 21	int op = cond ? OBRANCH : OJMP;
 22
 23	np = node(op);
 24	np->op = op;
 25	np->left = sethi(cond);
 26	np->u.sym = sym;
 27	sym->refcnt++;
 28
 29	return np;
 30}
 31
 32static Node *
 33boolean(Node *cond, Symbol *strue, Symbol *sfalse)
 34{
 35	Symbol *label;
 36	Node *p, *l = cond->left, *r = cond->right;
 37
 38	switch (cond->op) {
 39	case ONEG:
 40		l = boolean(l, sfalse, strue);
 41		break;
 42	case OAND:
 43		label = newlabel();
 44		l = boolean(l, label, sfalse);
 45		prestmt(labelstmt(NULL, label));
 46		r = boolean(r, strue, sfalse);
 47		break;
 48	case OOR:
 49		label = newlabel();
 50		l = boolean(l, strue, label);
 51		prestmt(labelstmt(NULL, label));
 52		r = boolean(r, strue, sfalse);
 53		break;
 54	default:
 55		prestmt(branchnode(cond, strue));
 56		prestmt(branchnode(NULL, sfalse));
 57		return NULL;
 58	}
 59
 60	cond->left = l;
 61	cond->right = r;
 62	return cond;
 63}
 64
 65Node *
 66logicexpr(Node *np)
 67{
 68	Node *tmpvar, *p, *zero, *one;
 69	Type *tp = &np->type;
 70	Symbol *strue, *sfalse, *phi, *tmpsym;
 71
 72	strue = newlabel();
 73	sfalse = newlabel();
 74	phi = newlabel();
 75
 76	boolean(np, strue, sfalse);
 77
 78	tmpvar = tmpnode(tp, NULL);
 79	tmpsym = tmpvar->u.sym;
 80	zero = constnode(NULL, 0, tp);
 81	one = constnode(NULL, 1, tp);
 82
 83	p = assignnode(tp, tmpnode(tp, tmpsym), one);
 84	prestmt(labelstmt(p, strue));
 85
 86	prestmt(branchnode(NULL, phi));
 87
 88	p = assignnode(tp, tmpnode(tp, tmpsym), zero);
 89	prestmt(labelstmt(p, sfalse));
 90
 91	prestmt(labelstmt(NULL, phi));
 92
 93	return sethi(tmpvar);
 94}
 95
 96static void
 97comma(Node *np)
 98{
 99	if (np->op != OCOMMA) {
100		prestmt(sethi(np));
101	} else {
102		comma(np->left);
103		prestmt(sethi(np->right));
104		delnode(np);
105	}
106}
107
108static Node *
109ternary(Node *np)
110{
111	Type *tp;
112	Node *tmpvar, *colon, *p;
113	Symbol *tmpsym, *strue, *sfalse, *phi;
114
115	strue = newlabel();
116	sfalse = newlabel();
117	phi = newlabel();
118	boolean(np->left, strue, sfalse);
119
120	tp = &np->type;
121	colon = np->right;
122	tmpvar = tmpnode(tp, NULL);
123	tmpsym = tmpvar->u.sym;
124
125	prestmt(labelstmt(NULL, strue));
126	p = assignnode(tp, tmpnode(tp, tmpsym), sethi(colon->left));
127	prestmt(p);
128	prestmt(branchnode(NULL, phi));
129
130	prestmt(labelstmt(NULL, sfalse));
131	p = assignnode(tp, tmpnode(tp, tmpsym), sethi(colon->right));
132	prestmt(p);
133
134	prestmt(labelstmt(NULL, phi));
135
136	return sethi(tmpvar);
137}
138
139static Node *
140replace(Node *what, Node *with)
141{
142	Node *prev, *next;
143	Symbol *label;
144
145	label = what->label;
146	next = what->next, prev = what->prev;
147
148	*what = *with;
149	delnode(with);
150	what->next = next, what->prev = prev;
151	what->label = label;
152
153	return sethi(what);
154}
155
156Node *
157sethi(Node *np)
158{
159	int op;
160	Node *next, *l, *r;
161
162	if (!np)
163		return np;
164
165	np->complex = 0;
166	np->address = 0;
167
168	switch (np->op) {
169	case OBSWITCH:
170		np = swtch(np);
171		break;
172	case OBRANCH:
173		next = np->next;
174		if (!next->label)
175			labelstmt(next, NULL);
176
177		op = np->left->op;
178		if (op != ONEG && op != OOR && op != OAND) {
179			sethi(np->left);
180			return np;
181		}
182
183		boolean(np->left, np->u.sym, next->label);
184		np->u.sym->refcnt--;
185		return NULL;
186	case OCOMMA:
187		r = np->right;
188		comma(np->left);
189		return replace(np, r);
190	case OASK:
191		return replace(np, ternary(np));
192	case ONEG:
193	case OAND:
194	case OOR:
195		return replace(np, logicexpr(np));
196	default:
197		np = tsethi(np);
198		break;
199	}
200
201	l = np->left;
202	r = np->right;
203
204	if (np->address > 10)
205		return np;
206	if (l)
207		np->complex = l->complex;
208	if (r) {
209		int d = np->complex - r->complex;
210
211		if (d == 0)
212			++np->complex;
213		else if (d < 0)
214			np->complex = r->complex;
215	}
216	if (np->complex == 0)
217		++np->complex;
218
219	return np;
220}
221
222static Node *
223presethi(Node *np)
224{
225	/* just in case ... */
226	savelabel();
227	return sethi(np);
228}
229
230void
231genaddr(void)
232{
233	apply(presethi);
234	PRTREE("after sethi");
235}