scc

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

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

  1#include <stddef.h>
  2#include <setjmp.h>
  3
  4#include <scc/cstd.h>
  5#include <scc/scc.h>
  6#include "cc1.h"
  7
  8#define NEGATE   1
  9#define NONEGATE 0
 10
 11Symbol *curfun;
 12
 13static void stmt(Symbol *lbreak, Symbol *lcont, Switch *lswitch);
 14
 15static void
 16branch(Symbol *label, Node *np)
 17{
 18	if (!np) {
 19		emit(OJUMP, label);
 20	} else if ((np->flags & NCONST) == 0) {
 21		emit(OBRANCH, label);
 22		emit(OEXPR, np);
 23	} else {
 24		if (np->sym->u.i != 0)
 25			emit(OJUMP, label);
 26		freetree(np);
 27	}
 28}
 29
 30static void
 31label(void)
 32{
 33	Symbol *sym;
 34
 35	switch (yytoken) {
 36	case IDEN:
 37	case TYPEIDEN:
 38		sym = lookup(NS_LABEL, yytext, ALLOC);
 39		if (sym->flags & SDEFINED)
 40			error("label '%s' already defined", yytext);
 41		if ((sym->flags & SDECLARED) == 0)
 42			sym = install(NS_LABEL, sym);
 43		sym->flags |= SDEFINED;
 44		emit(OLABEL, sym);
 45		next();
 46		expect(':');
 47		break;
 48	default:
 49		unexpected();
 50	}
 51}
 52
 53static void
 54stmtexp(Symbol *lbreak, Symbol *lcont, Switch *lswitch)
 55{
 56	Node *np;
 57
 58	if (accept(';'))
 59		return;
 60	if (yytoken == IDEN && ahead() == ':') {
 61		label();
 62		stmt(lbreak, lcont, lswitch);
 63		return;
 64	}
 65	np = simplify(expr());
 66	if ((np->flags & NEFFECT) == 0)
 67		warn("expression without side effects");
 68	emit(OEXPR, np);
 69	expect(';');
 70}
 71
 72static Node *
 73condition(int neg)
 74{
 75	Node *np;
 76
 77	expect('(');
 78	np = condexpr(neg);
 79	expect(')');
 80
 81	return np;
 82}
 83
 84static void
 85While(Symbol *lbreak, Symbol *lcont, Switch *lswitch)
 86{
 87	Symbol *begin;
 88	Node *np;
 89
 90	begin = newlabel();
 91	lcont = newlabel();
 92	lbreak = newlabel();
 93
 94	expect(WHILE);
 95	np = condition(NONEGATE);
 96
 97	emit(OJUMP, lcont);
 98
 99	emit(OLABEL, begin);
100	emit(OBLOOP, NULL);
101	stmt(lbreak, lcont, lswitch);
102	emit(OLABEL, lcont);
103	emit(OELOOP, NULL);
104	branch(begin, np);
105
106	emit(OLABEL, lbreak);
107}
108
109static void
110For(Symbol *lbreak, Symbol *lcont, Switch *lswitch)
111{
112	Symbol *begin, *cond;
113	Node *econd, *einc;
114
115	begin = newlabel();
116	lcont = newlabel();
117	cond = newlabel();
118	lbreak = newlabel();
119
120	pushctx();
121
122	expect(FOR);
123	expect('(');
124	switch (yytoken) {
125	case TYPE:
126	case TYPEIDEN:
127	case TQUALIFIER:
128	case SCLASS:
129		decl();
130		break;
131	default:
132		emit(OEXPR, simplify(expr()));
133	case ';':
134		expect(';');
135		break;
136	}
137	econd = (yytoken != ';') ? condexpr(NONEGATE) : NULL;
138	expect(';');
139	einc = (yytoken != ')') ? simplify(expr()) : NULL;
140	expect(')');
141
142	if (econd)
143		emit(OJUMP, cond);
144
145	emit(OLABEL, begin);
146	emit(OBLOOP, NULL);
147	stmt(lbreak, lcont, lswitch);
148	emit(OLABEL, lcont);
149	emit(OEXPR, einc);
150	emit(OLABEL, cond);
151	emit(OELOOP, NULL);
152	branch(begin, econd);
153
154	emit(OLABEL, lbreak);
155
156	popctx();
157}
158
159static void
160Dowhile(Symbol *lbreak, Symbol *lcont, Switch *lswitch)
161{
162	Symbol *begin;
163	Node *np;
164
165	begin = newlabel();
166	lcont = newlabel();
167	lbreak = newlabel();
168
169	expect(DO);
170
171	emit(OLABEL, begin);
172	emit(OBLOOP, NULL);
173
174	stmt(lbreak, lcont, lswitch);
175	expect(WHILE);
176	np = condition(NONEGATE);
177	expect(';');
178
179	emit(OLABEL, lcont);
180	emit(OELOOP, NULL);
181	branch(begin, np);
182
183	emit(OLABEL, lbreak);
184}
185
186static void
187Return(Symbol *lbreak, Symbol *lcont, Switch *lswitch)
188{
189	Node *np = NULL;
190	Type *tp = curfun->type->type;
191
192	expect(RETURN);
193	if (yytoken != ';')
194		np = simplify(decay(expr()));
195	expect(';');
196
197	if (!np && tp != voidtype)
198		warn("function returning non void returns no value");
199	else if (np && np->type != tp) {
200		if (tp == voidtype)
201			warn("function returning void returns a value");
202		else if ((np = convert(np, tp, 0)) == NULL)
203			errorp("incorrect type in return");
204	}
205
206	emit(ORET, NULL);
207	emit(OEXPR, np);
208}
209
210static void
211Break(Symbol *lbreak, Symbol *lcont, Switch *lswitch)
212{
213	expect(BREAK);
214	if (!lbreak) {
215		errorp("break statement not within loop or switch");
216	} else {
217		emit(OJUMP, lbreak);
218		expect(';');
219	}
220}
221
222static void
223Continue(Symbol *lbreak, Symbol *lcont, Switch *lswitch)
224{
225	expect(CONTINUE);
226	if (!lcont) {
227		errorp("continue statement not within loop");
228	} else {
229		emit(OJUMP, lcont);
230		expect(';');
231	}
232}
233
234static void
235Goto(Symbol *lbreak, Symbol *lcont, Switch *lswitch)
236{
237	Symbol *sym;
238
239	namespace = NS_LABEL;
240	next();
241	namespace = NS_IDEN;
242
243	if (yytoken != IDEN)
244		unexpected();
245	sym = yylval.sym;
246	if ((sym->flags & SDECLARED) == 0)
247		sym = install(NS_LABEL, sym);
248	sym->flags |= SUSED;
249	emit(OJUMP, sym);
250	next();
251	expect(';');
252}
253
254static void
255Swtch(Symbol *obr, Symbol *lcont, Switch *osw)
256{
257	Switch sw = {0};
258	Node *cond;
259	Symbol *lbreak;
260
261	expect(SWITCH);
262
263	expect ('(');
264	cond = simplify(convert(expr(), inttype, 0));
265	if (cond == NULL) {
266		errorp("incorrect type in switch statement");
267		cond = constnode(zero);
268	}
269	expect (')');
270
271	lbreak = newlabel();
272	emit(OBSWITCH, NULL);
273	emit(OEXPR, cond);
274	stmt(lbreak, lcont, &sw);
275	emit(OESWITCH, lbreak);
276	emit(OLABEL, lbreak);
277}
278
279static void
280Case(Symbol *lbreak, Symbol *lcont, Switch *sw)
281{
282	Node *np;
283	Symbol *label;
284
285	expect(CASE);
286	if ((np = iconstexpr()) == NULL)
287		errorp("case label does not reduce to an integer constant");
288	if (!sw) {
289		errorp("case label not within a switch statement");
290	} else if (sw->nr >= 0 && ++sw->nr == NR_SWITCH) {
291		errorp("too many case labels for a switch statement");
292		sw->nr = -1;
293	}
294	expect(':');
295
296	label = newlabel();
297	emit(OCASE, label);
298	emit(OEXPR, np);
299	emit(OLABEL, label);
300	stmt(lbreak, lcont, sw);
301}
302
303static void
304Default(Symbol *lbreak, Symbol *lcont, Switch *sw)
305{
306	Symbol *label = newlabel();
307
308	if (sw->hasdef)
309		errorp("multiple default labels in one switch");
310	sw->hasdef = 1;
311	expect(DEFAULT);
312	expect(':');
313	emit(ODEFAULT, label);
314	emit(OLABEL, label);
315	stmt(lbreak, lcont, sw);
316}
317
318static void
319If(Symbol *lbreak, Symbol *lcont, Switch *lswitch)
320{
321	Symbol *end, *lelse;
322	Node *np;
323
324	lelse = newlabel();
325	expect(IF);
326	np = condition(NEGATE);
327	branch(lelse, np);
328	stmt(lbreak, lcont, lswitch);
329	if (accept(ELSE)) {
330		end = newlabel();
331		emit(OJUMP, end);
332		emit(OLABEL, lelse);
333		stmt(lbreak, lcont, lswitch);
334		emit(OLABEL, end);
335	} else {
336		emit(OLABEL, lelse);
337	}
338}
339
340static void
341blockit(Symbol *lbreak, Symbol *lcont, Switch *lswitch)
342{
343	switch (yytoken) {
344	case TYPEIDEN:
345		if (ahead() == ':')
346			goto parse_stmt;
347	case TYPE:
348	case TQUALIFIER:
349	case SCLASS:
350		decl();
351		return;
352	default:
353	parse_stmt:
354		stmt(lbreak, lcont, lswitch);
355	}
356}
357
358void
359compound(Symbol *lbreak, Symbol *lcont, Switch *lswitch)
360{
361	static int nested;
362
363	pushctx();
364	expect('{');
365
366	if (nested == NR_BLOCK)
367		error("too many nesting levels of compound statements");
368
369	++nested;
370	while (yytoken != '}')
371		blockit(lbreak, lcont, lswitch);
372	--nested;
373
374	popctx();
375	expect('}');
376}
377
378static void
379stmt(Symbol *lbreak, Symbol *lcont, Switch *lswitch)
380{
381	switch (yytoken) {
382	case '{':
383		compound(lbreak, lcont, lswitch);
384		break;
385	case RETURN:
386		Return(lbreak, lcont, lswitch);
387		break;
388	case WHILE:
389		While(lbreak, lcont, lswitch);
390		break;
391	case FOR:
392		For(lbreak, lcont, lswitch);
393		break;
394	case DO:
395		Dowhile(lbreak, lcont, lswitch);
396		break;
397	case IF:
398		If(lbreak, lcont, lswitch);
399		break;
400	case BREAK:
401		Break(lbreak, lcont, lswitch);
402		break;
403	case CONTINUE:
404		Continue(lbreak, lcont, lswitch);
405		break;
406	case GOTO:
407		Goto(lbreak, lcont, lswitch);
408		break;
409	case SWITCH:
410		Swtch(lbreak, lcont, lswitch);
411		break;
412	case CASE:
413		Case(lbreak, lcont, lswitch);
414		break;
415	case DEFAULT:
416		Default(lbreak, lcont, lswitch);
417		break;
418	default:
419		stmtexp(lbreak, lcont, lswitch);
420	}
421}