scc

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

stmt.c (6890B)


      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 = 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, expr());
    119 	case ';':
    120 		expect(';');
    121 		break;
    122 	}
    123 	econd = (yytoken != ';') ? condexpr(NONEGATE) : NULL;
    124 	expect(';');
    125 	einc = (yytoken != ')') ? 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 	stmt(lbreak, lcont, lswitch);
    160 	expect(WHILE);
    161 	np = condition(NONEGATE);
    162 	emit(OLABEL, lcont);
    163 	emit(OBRANCH, begin);
    164 	emit(OEXPR, np);
    165 	emit(OELOOP, NULL);
    166 
    167 	emit(OLABEL, lbreak);
    168 }
    169 
    170 static void
    171 Return(Symbol *lbreak, Symbol *lcont, Switch *lswitch)
    172 {
    173 	Node *np;
    174 	Type *tp = curfun->type->type;
    175 
    176 	expect(RETURN);
    177 	np = (yytoken != ';') ? decay(expr()) : NULL;
    178 	expect(';');
    179 	if (!np) {
    180 		if (tp != voidtype)
    181 			warn("function returning non void returns no value");
    182 		tp = voidtype;
    183 	} else if (np->type != tp) {
    184 		if (tp == voidtype)
    185 			warn("function returning void returns a value");
    186 		else if ((np = convert(np, tp, 0)) == NULL)
    187 			errorp("incorrect type in return");
    188 	}
    189 	emit(ORET, NULL);
    190 	emit(OEXPR, np);
    191 }
    192 
    193 static void
    194 Break(Symbol *lbreak, Symbol *lcont, Switch *lswitch)
    195 {
    196 	expect(BREAK);
    197 	if (!lbreak) {
    198 		errorp("break statement not within loop or switch");
    199 	} else {
    200 		emit(OJUMP, lbreak);
    201 		expect(';');
    202 	}
    203 }
    204 
    205 static void
    206 Continue(Symbol *lbreak, Symbol *lcont, Switch *lswitch)
    207 {
    208 	expect(CONTINUE);
    209 	if (!lcont) {
    210 		errorp("continue statement not within loop");
    211 	} else {
    212 		emit(OJUMP, lcont);
    213 		expect(';');
    214 	}
    215 }
    216 
    217 static void
    218 Goto(Symbol *lbreak, Symbol *lcont, Switch *lswitch)
    219 {
    220 	Symbol *sym;
    221 
    222 	namespace = NS_LABEL;
    223 	next();
    224 	namespace = NS_IDEN;
    225 
    226 	if (yytoken != IDEN)
    227 		unexpected();
    228 	sym = yylval.sym;
    229 	if ((sym->flags & SDECLARED) == 0)
    230 		sym = install(NS_LABEL, sym);
    231 	sym->flags |= SUSED;
    232 	emit(OJUMP, sym);
    233 	next();
    234 	expect(';');
    235 }
    236 
    237 static void
    238 Swtch(Symbol *obr, Symbol *lcont, Switch *osw)
    239 {
    240 	Switch sw = {0};
    241 	Node *cond;
    242 	Symbol *lbreak;
    243 
    244 	expect(SWITCH);
    245 
    246 	expect ('(');
    247 	if ((cond = convert(expr(), inttype, 0)) == NULL) {
    248 		errorp("incorrect type in switch statement");
    249 		cond = constnode(zero);
    250 	}
    251 	expect (')');
    252 
    253 	lbreak = newlabel();
    254 	emit(OBSWITCH, NULL);
    255 	emit(OEXPR, cond);
    256 	stmt(lbreak, lcont, &sw);
    257 	emit(OESWITCH, lbreak);
    258 	emit(OLABEL, lbreak);
    259 }
    260 
    261 static void
    262 Case(Symbol *lbreak, Symbol *lcont, Switch *sw)
    263 {
    264 	Node *np;
    265 	Symbol *label;
    266 
    267 	expect(CASE);
    268 	if ((np = constexpr()) == NULL)
    269 		errorp("case label does not reduce to an integer constant");
    270 	if (!sw) {
    271 		errorp("case label not within a switch statement");
    272 	} else if (sw->nr >= 0 && ++sw->nr == NR_SWITCH) {
    273 		errorp("too many case labels for a switch statement");
    274 		sw->nr = -1;
    275 	}
    276 	expect(':');
    277 
    278 	label = newlabel();
    279 	emit(OCASE, label);
    280 	emit(OEXPR, np);
    281 	emit(OLABEL, label);
    282 	stmt(lbreak, lcont, sw);
    283 }
    284 
    285 static void
    286 Default(Symbol *lbreak, Symbol *lcont, Switch *sw)
    287 {
    288 	Symbol *label = newlabel();
    289 
    290 	if (sw->hasdef)
    291 		errorp("multiple default labels in one switch");
    292 	sw->hasdef = 1;
    293 	expect(DEFAULT);
    294 	expect(':');
    295 	emit(ODEFAULT, label);
    296 	emit(OLABEL, label);
    297 	stmt(lbreak, lcont, sw);
    298 }
    299 
    300 static void
    301 If(Symbol *lbreak, Symbol *lcont, Switch *lswitch)
    302 {
    303 	Symbol *end, *lelse;
    304 	Node *np;
    305 
    306 	lelse = newlabel();
    307 	expect(IF);
    308 	np = condition(NEGATE);
    309 	emit(OBRANCH, lelse);
    310 	emit(OEXPR, np);
    311 	stmt(lbreak, lcont, lswitch);
    312 	if (accept(ELSE)) {
    313 		end = newlabel();
    314 		emit(OJUMP, end);
    315 		emit(OLABEL, lelse);
    316 		stmt(lbreak, lcont, lswitch);
    317 		emit(OLABEL, end);
    318 	} else {
    319 		emit(OLABEL, lelse);
    320 	}
    321 }
    322 
    323 static void
    324 blockit(Symbol *lbreak, Symbol *lcont, Switch *lswitch)
    325 {
    326 	switch (yytoken) {
    327 	case TYPEIDEN:
    328 		if (ahead() == ':')
    329 			goto parse_stmt;
    330 	case TYPE:
    331 	case TQUALIFIER:
    332 	case SCLASS:
    333 		decl();
    334 		return;
    335 	default:
    336 	parse_stmt:
    337 		stmt(lbreak, lcont, lswitch);
    338 	}
    339 }
    340 
    341 void
    342 compound(Symbol *lbreak, Symbol *lcont, Switch *lswitch)
    343 {
    344 	static int nested;
    345 
    346 	pushctx();
    347 	expect('{');
    348 
    349 	if (nested == NR_BLOCK)
    350 		error("too many nesting levels of compound statements");
    351 
    352 	++nested;
    353 	for (;;) {
    354 		if (yytoken == '}')
    355 			break;
    356 		blockit(lbreak, lcont, lswitch);
    357 	}
    358 	--nested;
    359 
    360 	popctx();
    361 	expect('}');
    362 }
    363 
    364 static void
    365 stmt(Symbol *lbreak, Symbol *lcont, Switch *lswitch)
    366 {
    367 	void (*fun)(Symbol *, Symbol *, Switch *);
    368 
    369 	switch (yytoken) {
    370 	case '{':      fun = compound; break;
    371 	case RETURN:   fun = Return;   break;
    372 	case WHILE:    fun = While;    break;
    373 	case FOR:      fun = For;      break;
    374 	case DO:       fun = Dowhile;  break;
    375 	case IF:       fun = If;       break;
    376 	case BREAK:    fun = Break;    break;
    377 	case CONTINUE: fun = Continue; break;
    378 	case GOTO:     fun = Goto;     break;
    379 	case SWITCH:   fun = Swtch;    break;
    380 	case CASE:     fun = Case;     break;
    381 	case DEFAULT:  fun = Default;  break;
    382 	default:       fun = stmtexp;  break;
    383 	}
    384 	(*fun)(lbreak, lcont, lswitch);
    385 }