stmt.c - scc - simple c99 compiler
(HTM) git clone git://git.simple-cc.org/scc
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) Submodules
(DIR) README
(DIR) LICENSE
---
stmt.c (7197B)
---
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
11 Symbol *curfun;
12
13 static void stmt(Symbol *lbreak, Symbol *lcont, Switch *lswitch);
14
15 static void
16 branch(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
30 static void
31 label(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
53 static void
54 stmtexp(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
72 static Node *
73 condition(int neg)
74 {
75 Node *np;
76
77 expect('(');
78 np = condexpr(neg);
79 expect(')');
80
81 return np;
82 }
83
84 static void
85 While(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
109 static void
110 For(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
159 static void
160 Dowhile(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
186 static void
187 Return(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
210 static void
211 Break(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
222 static void
223 Continue(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
234 static void
235 Goto(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
254 static void
255 Swtch(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
279 static void
280 Case(Symbol *lbreak, Symbol *lcont, Switch *sw)
281 {
282 Node *np;
283 Symbol *label;
284
285 expect(CASE);
286 if ((np = constexpr()) == 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
303 static void
304 Default(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
318 static void
319 If(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
340 static void
341 blockit(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
358 void
359 compound(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
378 static void
379 stmt(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 }