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