1#include <stddef.h>2#include <setjmp.h>34#include <scc/cstd.h>5#include <scc/scc.h>6#include "cc1.h"78#define NEGATE 19#define NONEGATE 01011Symbol *curfun;1213static void stmt(Symbol *lbreak, Symbol *lcont, Switch *lswitch);1415static void16branch(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}2930static void31label(void)32{33 Symbol *sym;3435 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}5253static void54stmtexp(Symbol *lbreak, Symbol *lcont, Switch *lswitch)55{56 Node *np;5758 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}7172static Node *73condition(int neg)74{75 Node *np;7677 expect('(');78 np = condexpr(neg);79 expect(')');8081 return np;82}8384static void85While(Symbol *lbreak, Symbol *lcont, Switch *lswitch)86{87 Symbol *begin;88 Node *np;8990 begin = newlabel();91 lcont = newlabel();92 lbreak = newlabel();9394 expect(WHILE);95 np = condition(NONEGATE);9697 emit(OJUMP, lcont);9899 emit(OLABEL, begin);100 emit(OBLOOP, NULL);101 stmt(lbreak, lcont, lswitch);102 emit(OLABEL, lcont);103 emit(OELOOP, NULL);104 branch(begin, np);105106 emit(OLABEL, lbreak);107}108109static void110For(Symbol *lbreak, Symbol *lcont, Switch *lswitch)111{112 Symbol *begin, *cond;113 Node *econd, *einc;114115 begin = newlabel();116 lcont = newlabel();117 cond = newlabel();118 lbreak = newlabel();119120 pushctx();121122 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(')');141142 if (econd)143 emit(OJUMP, cond);144145 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);153154 emit(OLABEL, lbreak);155156 popctx();157}158159static void160Dowhile(Symbol *lbreak, Symbol *lcont, Switch *lswitch)161{162 Symbol *begin;163 Node *np;164165 begin = newlabel();166 lcont = newlabel();167 lbreak = newlabel();168169 expect(DO);170171 emit(OLABEL, begin);172 emit(OBLOOP, NULL);173174 stmt(lbreak, lcont, lswitch);175 expect(WHILE);176 np = condition(NONEGATE);177 expect(';');178179 emit(OLABEL, lcont);180 emit(OELOOP, NULL);181 branch(begin, np);182183 emit(OLABEL, lbreak);184}185186static void187Return(Symbol *lbreak, Symbol *lcont, Switch *lswitch)188{189 Node *np = NULL;190 Type *tp = curfun->type->type;191192 expect(RETURN);193 if (yytoken != ';')194 np = simplify(decay(expr()));195 expect(';');196197 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 }205206 emit(ORET, NULL);207 emit(OEXPR, np);208}209210static void211Break(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}221222static void223Continue(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}233234static void235Goto(Symbol *lbreak, Symbol *lcont, Switch *lswitch)236{237 Symbol *sym;238239 namespace = NS_LABEL;240 next();241 namespace = NS_IDEN;242243 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}253254static void255Swtch(Symbol *obr, Symbol *lcont, Switch *osw)256{257 Switch sw = {0};258 Node *cond;259 Symbol *lbreak;260261 expect(SWITCH);262263 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 (')');270271 lbreak = newlabel();272 emit(OBSWITCH, NULL);273 emit(OEXPR, cond);274 stmt(lbreak, lcont, &sw);275 emit(OESWITCH, lbreak);276 emit(OLABEL, lbreak);277}278279static void280Case(Symbol *lbreak, Symbol *lcont, Switch *sw)281{282 Node *np;283 Symbol *label;284285 expect(CASE);286 if ((np = iconstexpr()) == 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(':');295296 label = newlabel();297 emit(OCASE, label);298 emit(OEXPR, np);299 emit(OLABEL, label);300 stmt(lbreak, lcont, sw);301}302303static void304Default(Symbol *lbreak, Symbol *lcont, Switch *sw)305{306 Symbol *label = newlabel();307308 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}317318static void319If(Symbol *lbreak, Symbol *lcont, Switch *lswitch)320{321 Symbol *end, *lelse;322 Node *np;323324 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}339340static void341blockit(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}357358void359compound(Symbol *lbreak, Symbol *lcont, Switch *lswitch)360{361 static int nested;362363 pushctx();364 expect('{');365366 if (nested == NR_BLOCK)367 error("too many nesting levels of compound statements");368369 ++nested;370 while (yytoken != '}')371 blockit(lbreak, lcont, lswitch);372 --nested;373374 popctx();375 expect('}');376}377378static void379stmt(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}