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