scc

simple c99 compiler
git clone git://git.simple-cc.org/scc
Log | Files | Refs | Submodules | README | LICENSE

stmt.c (7065B)


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