scc

simple c99 compiler
git clone git://git.simple-cc.org/scc
Log | Files | Refs | Submodules | README | 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 }