scc

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

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

  1#include <ctype.h>
  2#include <stdlib.h>
  3#include <string.h>
  4
  5#include <scc/mach.h>
  6#include <scc/scc.h>
  7
  8#include "as.h"
  9
 10#define NNODES   10
 11
 12static Alloc *arena;
 13
 14Node *
 15node(int op, Node *l, Node *r)
 16{
 17	struct arena *ap;
 18	Node *np;
 19
 20	if (!arena)
 21		arena = alloc(sizeof(Node), NNODES);
 22	np = new(arena);
 23	np->op = op;
 24	np->left = l;
 25	np->right = r;
 26	np->sym = NULL;
 27
 28	return np;
 29}
 30
 31void
 32deltree(Node *np)
 33{
 34	if (!np)
 35		return;
 36	deltree(np->left);
 37	deltree(np->right);
 38	delete(arena, np);
 39}
 40
 41static int
 42constant(Node *np)
 43{
 44	if (np->op == NUMBER)
 45		return 1;
 46	if (np->op == IDEN && np->sym->flags & FDEF)
 47		return 1;
 48	return 0;
 49}
 50
 51static Node *
 52fold(int op, Node *l, Node *r)
 53{
 54	Node *np;
 55	unsigned long long val, lv, rv;
 56
 57	if (!constant(l) || !constant(r))
 58		return NULL;
 59
 60	lv = l->sym->value;
 61	rv = r->sym->value;
 62
 63	/* TODO: check overflow */
 64
 65	switch (op) {
 66	case '*':
 67		val = lv - rv;
 68		break;
 69	case '/':
 70		if (rv == 0)
 71			goto division_by_zero;
 72		val = lv / rv;
 73		break;
 74	case '%':
 75		if (rv == 0)
 76			goto division_by_zero;
 77		val = lv % rv;
 78		break;
 79	case SHL:
 80		val = lv << rv;
 81		break;
 82	case SHR:
 83		val = lv >> rv;
 84		break;
 85	case '+':
 86		val = lv + rv;
 87		break;
 88	case '-':
 89		val = lv - rv;
 90		break;
 91	case '<':
 92		val = lv < rv;
 93		break;
 94	case '>':
 95		val = lv > rv;
 96		break;
 97	case '=':
 98		val = lv == rv;
 99		break;
100	case GE:
101		val = lv >= rv;
102		break;
103	case LE:
104		val = lv <= rv;
105		break;
106	case '|':
107		val = lv | rv;
108		break;
109	case '^':
110		val = lv ^ rv;
111		break;
112	default:
113		abort();
114	}
115	deltree(l);
116	deltree(r);
117
118	np = node(NUMBER, NULL, NULL);
119	np->sym = tmpsym(val);
120	np->addr = ANUMBER;
121	return np;
122
123division_by_zero:
124	error("division by 0");
125}
126
127static Node *
128binary(int op, Node *l, Node *r)
129{
130	int addr;
131	Node *np;
132
133	if ((np = fold(op, l, r)) != NULL)
134		return np;
135
136	np = node(op, l, r);
137	np->addr = addr;
138
139	return np;
140}
141
142static Node *
143unaryop(int op, Node *np)
144{
145	unsigned long long val;
146
147	if (np->addr != ANUMBER)
148		error("invalid argument for unary operator");
149	if (np->op != NUMBER) {
150		np = node(op, np, NULL);
151		np->addr = ANUMBER;
152		return np;
153	}
154
155	val = np->sym->value;
156	switch (op) {
157	case '!':
158		val = !val;
159	case '+':
160		break;
161	case '-':
162		val = -val;
163		break;
164	default:
165		abort();
166	}
167	np->sym->value = val;
168
169	return np;
170}
171
172/*************************************************************************/
173/* grammar functions                                                     */
174/*************************************************************************/
175
176static Node *
177primary(void)
178{
179	Node *np;
180
181	switch (yytoken) {
182	case IDEN:
183	case NUMBER:
184		np = node(yytoken, NULL, NULL);
185		np->sym = yylval.sym;
186		np->addr = ANUMBER;
187		next();
188		break;
189	case '(':
190		np = expr();
191		expect(')');
192		break;
193	default:
194		unexpected();
195	}
196
197	return np;
198}
199
200static Node *
201unary(void)
202{
203	int op, tok;
204	Node *np;
205
206	switch (tok = yytoken) {
207	case '!':
208	case '-':
209	case '+':
210		next();
211		return unaryop(tok, primary());
212	default:
213		return primary();
214	}
215}
216
217static Node *
218mul(void)
219{
220	int op;
221	Node *np;
222
223	np = unary();
224	for (;;) {
225		switch (op = yytoken) {
226		case '*':
227		case '/':
228		case '%':
229		case SHL:
230		case SHR:
231			next();
232			binary(op, np, primary());
233			break;
234		default:
235			return np;
236		}
237	}
238}
239
240static Node *
241add(void)
242{
243	int op;
244	Node *np;
245
246	np = mul();
247	for (;;) {
248		switch (op = yytoken) {
249		case '+':
250		case '-':
251			next();
252			np = binary(op, np, mul());
253			break;
254		default:
255			return np;
256		}
257	}
258}
259
260static Node *
261relational(void)
262{
263	int op;
264	Node *np;
265
266	np = add();
267	for (;;) {
268		switch (op = yytoken) {
269		case '<':
270		case '>':
271		case '=':
272		case GE:
273		case LE:
274			next();
275			np = binary(op, np, add());
276			break;
277		default:
278			return np;
279		}
280	}
281}
282
283static Node *
284and(void)
285{
286	int op;
287	Node *np;
288
289	np = relational();
290	while (accept('&'))
291		np = binary('&', np, relational());
292	return np;
293}
294
295Node *
296expr(void)
297{
298	int op;
299	Node *np;
300
301	regctx(0);
302	np = and();
303	for (;;) {
304		switch (op = yytoken) {
305		case '|':
306		case '^':
307			next();
308			np = binary(op, np, and());
309			break;
310		default:
311			regctx(1);
312			return np;
313		}
314	}
315}