1 #include "gc.h" 2 3 void 4 codgen(Node *n, Node *nn) 5 { 6 Prog *sp; 7 Node *n1, nod, nod1; 8 9 cursafe = 0; 10 curarg = 0; 11 maxargsafe = 0; 12 hasdoubled = 0; 13 14 /* 15 * isolate name 16 */ 17 for(n1 = nn;; n1 = n1->left) { 18 if(n1 == Z) { 19 diag(nn, "cant find function name"); 20 return; 21 } 22 if(n1->op == ONAME) 23 break; 24 } 25 nearln = nn->lineno; 26 gpseudo(ATEXT, n1->sym, nodconst(stkoff)); 27 sp = p; 28 29 if(typecmplx[thisfn->link->etype]) { 30 if(nodret == nil) { 31 nodret = new(ONAME, Z, Z); 32 nodret->sym = slookup(".ret"); 33 nodret->class = CPARAM; 34 nodret->type = types[TIND]; 35 nodret->etype = TIND; 36 nodret = new(OIND, nodret, Z); 37 } 38 n1 = nodret->left; 39 if(n1->type == T || n1->type->link != thisfn->link) { 40 n1->type = typ(TIND, thisfn->link); 41 n1->etype = n1->type->etype; 42 nodret = new(OIND, n1, Z); 43 complex(nodret); 44 } 45 } 46 47 /* 48 * isolate first argument 49 */ 50 if(REGARG >= 0) { 51 if(typecmplx[thisfn->link->etype]) { 52 nod1 = *nodret->left; 53 nodreg(&nod, &nod1, REGARG); 54 gmove(&nod, &nod1); 55 } else 56 if(firstarg && typeword[firstargtype->etype]) { 57 nod1 = znode; 58 nod1.op = ONAME; 59 nod1.sym = firstarg; 60 nod1.type = firstargtype; 61 nod1.class = CPARAM; 62 nod1.xoffset = align(0, firstargtype, Aarg1); 63 nod1.etype = firstargtype->etype; 64 xcom(&nod1); 65 nodreg(&nod, &nod1, REGARG); 66 gmove(&nod, &nod1); 67 } 68 } 69 70 canreach = 1; 71 warnreach = 1; 72 gen(n); 73 if(canreach && thisfn->link->etype != TVOID) 74 warn(Z, "no return at end of function: %s", n1->sym->name); 75 noretval(3); 76 gbranch(ORETURN); 77 78 if(!debug['N'] || debug['R'] || debug['P']) 79 regopt(sp); 80 81 if(thechar=='6' || thechar=='7' || thechar=='9' || hasdoubled) /* [sic] */ 82 maxargsafe = round(maxargsafe, 8); 83 sp->to.offset += maxargsafe; 84 } 85 86 void 87 supgen(Node *n) 88 { 89 int owarn; 90 long spc; 91 Prog *sp; 92 93 if(n == Z) 94 return; 95 suppress++; 96 owarn = warnreach; 97 warnreach = 0; 98 spc = pc; 99 sp = lastp; 100 gen(n); 101 lastp = sp; 102 pc = spc; 103 sp->link = nil; 104 suppress--; 105 warnreach = owarn; 106 } 107 108 void 109 gen(Node *n) 110 { 111 Node *l, nod; 112 Prog *sp, *spc, *spb; 113 Case *cn; 114 long sbc, scc; 115 int snbreak, sncontin; 116 int f, o, oldreach; 117 118 loop: 119 if(n == Z) 120 return; 121 nearln = n->lineno; 122 o = n->op; 123 if(debug['G']) 124 if(o != OLIST) 125 print("%L %O\n", nearln, o); 126 127 if(!canreach) { 128 switch(o) { 129 case OLABEL: 130 case OCASE: 131 case OLIST: 132 case OBREAK: 133 case OFOR: 134 case OWHILE: 135 case ODWHILE: 136 /* all handled specially - see switch body below */ 137 break; 138 default: 139 if(warnreach) { 140 warn(n, "unreachable code %O", o); 141 warnreach = 0; 142 } 143 } 144 } 145 146 switch(o) { 147 148 default: 149 complex(n); 150 cgen(n, Z); 151 break; 152 153 case OLIST: 154 gen(n->left); 155 156 rloop: 157 n = n->right; 158 goto loop; 159 160 case ORETURN: 161 canreach = 0; 162 warnreach = !suppress; 163 complex(n); 164 if(n->type == T) 165 break; 166 l = n->left; 167 if(l == Z) { 168 noretval(3); 169 gbranch(ORETURN); 170 break; 171 } 172 if(typecmplx[n->type->etype]) { 173 nod = znode; 174 nod.op = OAS; 175 nod.left = nodret; 176 nod.right = l; 177 nod.type = n->type; 178 nod.complex = l->complex; 179 cgen(&nod, Z); 180 noretval(3); 181 gbranch(ORETURN); 182 break; 183 } 184 regret(&nod, n); 185 cgen(l, &nod); 186 regfree(&nod); 187 if(typefd[n->type->etype]) 188 noretval(1); 189 else 190 noretval(2); 191 gbranch(ORETURN); 192 break; 193 194 case OLABEL: 195 canreach = 1; 196 l = n->left; 197 if(l) { 198 l->pc = pc; 199 if(l->label) 200 patch(l->label, pc); 201 } 202 gbranch(OGOTO); /* prevent self reference in reg */ 203 patch(p, pc); 204 goto rloop; 205 206 case OGOTO: 207 canreach = 0; 208 warnreach = !suppress; 209 n = n->left; 210 if(n == Z) 211 return; 212 if(n->complex == 0) { 213 diag(Z, "label undefined: %s", n->sym->name); 214 return; 215 } 216 if(suppress) 217 return; 218 gbranch(OGOTO); 219 if(n->pc) { 220 patch(p, n->pc); 221 return; 222 } 223 if(n->label) 224 patch(n->label, pc-1); 225 n->label = p; 226 return; 227 228 case OCASE: 229 canreach = 1; 230 l = n->left; 231 if(cases == C) 232 diag(n, "case/default outside a switch"); 233 if(l == Z) { 234 casf(); 235 cases->val = 0; 236 cases->def = 1; 237 cases->label = pc; 238 cases->isv = 0; 239 goto rloop; 240 } 241 complex(l); 242 if(l->type == T) 243 goto rloop; 244 if(l->op == OCONST) 245 if(typeword[l->type->etype] && l->type->etype != TIND) { 246 casf(); 247 cases->val = l->vconst; 248 cases->def = 0; 249 cases->label = pc; 250 cases->isv = typev[l->type->etype]; 251 goto rloop; 252 } 253 diag(n, "case expression must be integer constant"); 254 goto rloop; 255 256 case OSWITCH: 257 l = n->left; 258 complex(l); 259 if(l->type == T) 260 break; 261 if(!typeword[l->type->etype] || l->type->etype == TIND) { 262 diag(n, "switch expression must be integer"); 263 break; 264 } 265 266 gbranch(OGOTO); /* entry */ 267 sp = p; 268 269 cn = cases; 270 cases = C; 271 casf(); 272 273 sbc = breakpc; 274 breakpc = pc; 275 snbreak = nbreak; 276 nbreak = 0; 277 gbranch(OGOTO); 278 spb = p; 279 280 gen(n->right); /* body */ 281 if(canreach){ 282 gbranch(OGOTO); 283 patch(p, breakpc); 284 nbreak++; 285 } 286 287 patch(sp, pc); 288 regalloc(&nod, l, Z); 289 /* always signed */ 290 if(typev[l->type->etype]) 291 nod.type = types[TVLONG]; 292 else 293 nod.type = types[TLONG]; 294 cgen(l, &nod); 295 doswit(&nod); 296 regfree(&nod); 297 patch(spb, pc); 298 299 cases = cn; 300 breakpc = sbc; 301 canreach = nbreak!=0; 302 if(canreach == 0) 303 warnreach = !suppress; 304 nbreak = snbreak; 305 break; 306 307 case OWHILE: 308 case ODWHILE: 309 l = n->left; 310 gbranch(OGOTO); /* entry */ 311 sp = p; 312 313 scc = continpc; 314 continpc = pc; 315 gbranch(OGOTO); 316 spc = p; 317 318 sbc = breakpc; 319 breakpc = pc; 320 snbreak = nbreak; 321 nbreak = 0; 322 gbranch(OGOTO); 323 spb = p; 324 325 patch(spc, pc); 326 if(n->op == OWHILE) 327 patch(sp, pc); 328 bcomplex(l, Z); /* test */ 329 patch(p, breakpc); 330 if(l->op != OCONST || vconst(l) == 0) 331 nbreak++; 332 333 if(n->op == ODWHILE) 334 patch(sp, pc); 335 gen(n->right); /* body */ 336 gbranch(OGOTO); 337 patch(p, continpc); 338 339 patch(spb, pc); 340 continpc = scc; 341 breakpc = sbc; 342 canreach = nbreak!=0; 343 if(canreach == 0) 344 warnreach = !suppress; 345 nbreak = snbreak; 346 break; 347 348 case OFOR: 349 l = n->left; 350 if(!canreach && l->right->left && warnreach) { 351 warn(n, "unreachable code FOR"); 352 warnreach = 0; 353 } 354 gen(l->right->left); /* init */ 355 gbranch(OGOTO); /* entry */ 356 sp = p; 357 358 /* 359 * if there are no incoming labels in the 360 * body and the top's not reachable, warn 361 */ 362 if(!canreach && warnreach && deadheads(n)) { 363 warn(n, "unreachable code %O", o); 364 warnreach = 0; 365 } 366 367 scc = continpc; 368 continpc = pc; 369 gbranch(OGOTO); 370 spc = p; 371 372 sbc = breakpc; 373 breakpc = pc; 374 snbreak = nbreak; 375 nbreak = 0; 376 sncontin = ncontin; 377 ncontin = 0; 378 gbranch(OGOTO); 379 spb = p; 380 381 patch(spc, pc); 382 gen(l->right->right); /* inc */ 383 patch(sp, pc); 384 if(l->left != Z) { /* test */ 385 bcomplex(l->left, Z); 386 patch(p, breakpc); 387 if(l->left->op != OCONST || vconst(l->left) == 0) 388 nbreak++; 389 } 390 canreach = 1; 391 gen(n->right); /* body */ 392 if(canreach){ 393 gbranch(OGOTO); 394 patch(p, continpc); 395 ncontin++; 396 } 397 if(!ncontin && l->right->right && warnreach) { 398 warn(l->right->right, "unreachable FOR inc"); 399 warnreach = 0; 400 } 401 402 patch(spb, pc); 403 continpc = scc; 404 breakpc = sbc; 405 canreach = nbreak!=0; 406 if(canreach == 0) 407 warnreach = !suppress; 408 nbreak = snbreak; 409 ncontin = sncontin; 410 break; 411 412 case OCONTINUE: 413 if(continpc < 0) { 414 diag(n, "continue not in a loop"); 415 break; 416 } 417 gbranch(OGOTO); 418 patch(p, continpc); 419 ncontin++; 420 canreach = 0; 421 warnreach = !suppress; 422 break; 423 424 case OBREAK: 425 if(breakpc < 0) { 426 diag(n, "break not in a loop"); 427 break; 428 } 429 /* 430 * Don't complain about unreachable break statements. 431 * There are breaks hidden in yacc's output and some people 432 * write return; break; in their switch statements out of habit. 433 * However, don't confuse the analysis by inserting an 434 * unreachable reference to breakpc either. 435 */ 436 if(!canreach) 437 break; 438 gbranch(OGOTO); 439 patch(p, breakpc); 440 nbreak++; 441 canreach = 0; 442 warnreach = !suppress; 443 break; 444 445 case OIF: 446 l = n->left; 447 if(bcomplex(l, n->right)) { 448 if(typefd[l->type->etype]) 449 f = !l->fconst; 450 else 451 f = !l->vconst; 452 if(debug['c']) 453 print("%L const if %s\n", nearln, f ? "false" : "true"); 454 if(f) { 455 canreach = 1; 456 supgen(n->right->left); 457 oldreach = canreach; 458 canreach = 1; 459 gen(n->right->right); 460 /* 461 * treat constant ifs as regular ifs for 462 * reachability warnings. 463 */ 464 if(!canreach && oldreach && debug['w'] < 2) 465 warnreach = 0; 466 } 467 else { 468 canreach = 1; 469 gen(n->right->left); 470 oldreach = canreach; 471 canreach = 1; 472 supgen(n->right->right); 473 /* 474 * treat constant ifs as regular ifs for 475 * reachability warnings. 476 */ 477 if(!oldreach && canreach && debug['w'] < 2) 478 warnreach = 0; 479 canreach = oldreach; 480 } 481 } 482 else { 483 sp = p; 484 canreach = 1; 485 if(n->right->left != Z) 486 gen(n->right->left); 487 oldreach = canreach; 488 canreach = 1; 489 if(n->right->right != Z) { 490 gbranch(OGOTO); 491 patch(sp, pc); 492 sp = p; 493 gen(n->right->right); 494 } 495 patch(sp, pc); 496 canreach = canreach || oldreach; 497 if(canreach == 0) 498 warnreach = !suppress; 499 } 500 break; 501 502 case OSET: 503 case OUSED: 504 usedset(n->left, o); 505 break; 506 } 507 } 508 509 void 510 usedset(Node *n, int o) 511 { 512 if(n->op == OLIST) { 513 usedset(n->left, o); 514 usedset(n->right, o); 515 return; 516 } 517 complex(n); 518 switch(n->op) { 519 case OADDR: /* volatile */ 520 gins(ANOP, n, Z); 521 break; 522 case ONAME: 523 if(o == OSET) 524 gins(ANOP, Z, n); 525 else 526 gins(ANOP, n, Z); 527 break; 528 } 529 } 530 531 int 532 bcomplex(Node *n, Node *c) 533 { 534 535 complex(n); 536 if(n->type != T) 537 if(tcompat(n, T, n->type, tnot)) 538 n->type = T; 539 if(n->type == T) { 540 gbranch(OGOTO); 541 return 0; 542 } 543 if(c != Z && n->op == OCONST && deadheads(c)) 544 return 1; 545 bool64(n); 546 boolgen(n, 1, Z); 547 return 0; 548 } 549