scc

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

stmt.c (6934B)


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