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 }