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