scc

Simple C99 Compiler
Log | Files | Refs | README | LICENSE

stmt.c (6903B)


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