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 13 /* 14 * isolate name 15 */ 16 for(n1 = nn;; n1 = n1->left) { 17 if(n1 == Z) { 18 diag(nn, "cant find function name"); 19 return; 20 } 21 if(n1->op == ONAME) 22 break; 23 } 24 nearln = nn->lineno; 25 gpseudo(ATEXT, n1->sym, nodconst(stkoff)); 26 sp = p; 27 28 /* 29 * isolate first argument 30 */ 31 if(REGARG) { 32 if(typesuv[thisfn->link->etype]) { 33 nod1 = *nodret->left; 34 nodreg(&nod, &nod1, REGARG); 35 gopcode(OAS, &nod, Z, &nod1); 36 } else 37 if(firstarg && typechlp[firstargtype->etype]) { 38 nod1 = *nodret->left; 39 nod1.sym = firstarg; 40 nod1.type = firstargtype; 41 nod1.xoffset = align(0, firstargtype, Aarg1); 42 nod1.etype = firstargtype->etype; 43 nodreg(&nod, &nod1, REGARG); 44 gopcode(OAS, &nod, Z, &nod1); 45 } 46 } 47 48 retok = 0; 49 gen(n); 50 if(!retok) 51 if(thisfn->link->etype != TVOID) 52 warn(Z, "no return at end of function: %s", n1->sym->name); 53 noretval(3); 54 gbranch(ORETURN); 55 56 if(!debug['N'] || debug['R'] || debug['P']) 57 regopt(sp); 58 59 sp->to.offset += maxargsafe; 60 } 61 62 void 63 gen(Node *n) 64 { 65 Node *l, nod; 66 Prog *sp, *spc, *spb; 67 Case *cn; 68 long sbc, scc; 69 int o; 70 71 loop: 72 if(n == Z) 73 return; 74 nearln = n->lineno; 75 o = n->op; 76 if(debug['G']) 77 if(o != OLIST) 78 print("%L %O\n", nearln, o); 79 80 retok = 0; 81 switch(o) { 82 83 default: 84 complex(n); 85 cgen(n, Z); 86 break; 87 88 case OLIST: 89 gen(n->left); 90 91 rloop: 92 n = n->right; 93 goto loop; 94 95 case ORETURN: 96 retok = 1; 97 complex(n); 98 if(n->type == T) 99 break; 100 l = n->left; 101 if(l == Z) { 102 noretval(3); 103 gbranch(ORETURN); 104 break; 105 } 106 if(typesuv[n->type->etype]) { 107 sugen(l, nodret, n->type->width); 108 noretval(3); 109 gbranch(ORETURN); 110 break; 111 } 112 regret(&nod, n); 113 cgen(l, &nod); 114 regfree(&nod); 115 if(typefd[n->type->etype]) 116 noretval(1); 117 else 118 noretval(2); 119 gbranch(ORETURN); 120 break; 121 122 case OLABEL: 123 l = n->left; 124 if(l) { 125 l->pc = pc; 126 if(l->label) 127 patch(l->label, pc); 128 } 129 gbranch(OGOTO); /* prevent self reference in reg */ 130 patch(p, pc); 131 goto rloop; 132 133 case OGOTO: 134 retok = 1; 135 n = n->left; 136 if(n == Z) 137 return; 138 if(n->complex == 0) { 139 diag(Z, "label undefined: %s", n->sym->name); 140 return; 141 } 142 gbranch(OGOTO); 143 if(n->pc) { 144 patch(p, n->pc); 145 return; 146 } 147 if(n->label) 148 patch(n->label, pc-1); 149 n->label = p; 150 return; 151 152 case OCASE: 153 l = n->left; 154 if(cases == C) 155 diag(n, "case/default outside a switch"); 156 if(l == Z) { 157 cas(); 158 cases->val = 0; 159 cases->def = 1; 160 cases->label = pc; 161 goto rloop; 162 } 163 complex(l); 164 if(l->type == T) 165 goto rloop; 166 if(l->op == OCONST) 167 if(typechl[l->type->etype]) { 168 cas(); 169 cases->val = l->vconst; 170 cases->def = 0; 171 cases->label = pc; 172 goto rloop; 173 } 174 diag(n, "case expression must be integer constant"); 175 goto rloop; 176 177 case OSWITCH: 178 l = n->left; 179 complex(l); 180 if(l->type == T) 181 break; 182 if(!typechl[l->type->etype]) { 183 diag(n, "switch expression must be integer"); 184 break; 185 } 186 187 gbranch(OGOTO); /* entry */ 188 sp = p; 189 190 cn = cases; 191 cases = C; 192 cas(); 193 194 sbc = breakpc; 195 breakpc = pc; 196 gbranch(OGOTO); 197 spb = p; 198 199 gen(n->right); 200 gbranch(OGOTO); 201 patch(p, breakpc); 202 203 patch(sp, pc); 204 regalloc(&nod, l, Z); 205 nod.type = types[TLONG]; 206 cgen(l, &nod); 207 doswit(&nod); 208 regfree(&nod); 209 patch(spb, pc); 210 211 cases = cn; 212 breakpc = sbc; 213 break; 214 215 case OWHILE: 216 case ODWHILE: 217 l = n->left; 218 gbranch(OGOTO); /* entry */ 219 sp = p; 220 221 scc = continpc; 222 continpc = pc; 223 gbranch(OGOTO); 224 spc = p; 225 226 sbc = breakpc; 227 breakpc = pc; 228 gbranch(OGOTO); 229 spb = p; 230 231 patch(spc, pc); 232 if(n->op == OWHILE) 233 patch(sp, pc); 234 bcomplex(l); /* test */ 235 patch(p, breakpc); 236 237 if(n->op == ODWHILE) 238 patch(sp, pc); 239 gen(n->right); /* body */ 240 gbranch(OGOTO); 241 patch(p, continpc); 242 243 patch(spb, pc); 244 continpc = scc; 245 breakpc = sbc; 246 break; 247 248 case OFOR: 249 l = n->left; 250 gen(l->right->left); /* init */ 251 gbranch(OGOTO); /* entry */ 252 sp = p; 253 254 scc = continpc; 255 continpc = pc; 256 gbranch(OGOTO); 257 spc = p; 258 259 sbc = breakpc; 260 breakpc = pc; 261 gbranch(OGOTO); 262 spb = p; 263 264 patch(spc, pc); 265 gen(l->right->right); /* inc */ 266 patch(sp, pc); 267 if(l->left != Z) { /* test */ 268 bcomplex(l->left); 269 patch(p, breakpc); 270 } 271 gen(n->right); /* body */ 272 gbranch(OGOTO); 273 patch(p, continpc); 274 275 patch(spb, pc); 276 continpc = scc; 277 breakpc = sbc; 278 break; 279 280 case OCONTINUE: 281 if(continpc < 0) { 282 diag(n, "continue not in a loop"); 283 break; 284 } 285 gbranch(OGOTO); 286 patch(p, continpc); 287 break; 288 289 case OBREAK: 290 if(breakpc < 0) { 291 diag(n, "break not in a loop"); 292 break; 293 } 294 gbranch(OGOTO); 295 patch(p, breakpc); 296 break; 297 298 case OIF: 299 l = n->left; 300 bcomplex(l); 301 sp = p; 302 if(n->right->left != Z) 303 gen(n->right->left); 304 if(n->right->right != Z) { 305 gbranch(OGOTO); 306 patch(sp, pc); 307 sp = p; 308 gen(n->right->right); 309 } 310 patch(sp, pc); 311 break; 312 313 case OSET: 314 case OUSED: 315 usedset(n->left, o); 316 break; 317 } 318 } 319 320 void 321 usedset(Node *n, int o) 322 { 323 if(n->op == OLIST) { 324 usedset(n->left, o); 325 usedset(n->right, o); 326 return; 327 } 328 complex(n); 329 switch(n->op) { 330 case OADDR: /* volatile */ 331 gins(ANOP, n, Z); 332 break; 333 case ONAME: 334 if(o == OSET) 335 gins(ANOP, Z, n); 336 else 337 gins(ANOP, n, Z); 338 break; 339 } 340 } 341 342 void 343 noretval(int n) 344 { 345 346 if(n & 1) { 347 gins(ANOP, Z, Z); 348 p->to.type = D_REG; 349 p->to.reg = REGRET; 350 } 351 if(n & 2) { 352 gins(ANOP, Z, Z); 353 p->to.type = D_FREG; 354 p->to.reg = FREGRET; 355 } 356 } 357 358 void 359 testshift(Node *n) 360 { 361 ulong c3; 362 int o, s1, s2, c1, c2; 363 364 if(!typechlp[n->type->etype]) 365 return; 366 switch(n->op) { 367 default: 368 return; 369 case OASHL: 370 s1 = 0; 371 break; 372 case OLSHR: 373 s1 = 1; 374 break; 375 case OASHR: 376 s1 = 2; 377 break; 378 } 379 if(n->right->op != OCONST) 380 return; 381 if(n->left->op != OAND) 382 return; 383 if(n->left->right->op != OCONST) 384 return; 385 switch(n->left->left->op) { 386 default: 387 return; 388 case OASHL: 389 s2 = 0; 390 break; 391 case OLSHR: 392 s2 = 1; 393 break; 394 case OASHR: 395 s2 = 2; 396 break; 397 } 398 if(n->left->left->right->op != OCONST) 399 return; 400 401 c1 = n->right->vconst; 402 c2 = n->left->left->right->vconst; 403 c3 = n->left->right->vconst; 404 405 /* 406 if(debug['h']) 407 print("%.3o %ld %ld %d #%.lux\n", 408 (s1<<3)|s2, c1, c2, topbit(c3), c3); 409 */ 410 411 o = n->op; 412 switch((s1<<3)|s2) { 413 case 000: /* (((e <<u c2) & c3) <<u c1) */ 414 c3 >>= c2; 415 c1 += c2; 416 if(c1 >= 32) 417 break; 418 goto rewrite1; 419 420 case 002: /* (((e >>s c2) & c3) <<u c1) */ 421 if(topbit(c3) >= (32-c2)) 422 break; 423 case 001: /* (((e >>u c2) & c3) <<u c1) */ 424 if(c1 > c2) { 425 c3 <<= c2; 426 c1 -= c2; 427 o = OASHL; 428 goto rewrite1; 429 } 430 c3 <<= c1; 431 if(c1 == c2) 432 goto rewrite0; 433 c1 = c2-c1; 434 o = OLSHR; 435 goto rewrite2; 436 437 case 022: /* (((e >>s c2) & c3) >>s c1) */ 438 if(c2 <= 0) 439 break; 440 case 012: /* (((e >>s c2) & c3) >>u c1) */ 441 if(topbit(c3) >= (32-c2)) 442 break; 443 goto s11; 444 case 021: /* (((e >>u c2) & c3) >>s c1) */ 445 if(topbit(c3) >= 31 && c2 <= 0) 446 break; 447 goto s11; 448 case 011: /* (((e >>u c2) & c3) >>u c1) */ 449 s11: 450 c3 <<= c2; 451 c1 += c2; 452 if(c1 >= 32) 453 break; 454 o = OLSHR; 455 goto rewrite1; 456 457 case 020: /* (((e <<u c2) & c3) >>s c1) */ 458 if(topbit(c3) >= 31) 459 break; 460 case 010: /* (((e <<u c2) & c3) >>u c1) */ 461 c3 >>= c1; 462 if(c1 == c2) 463 goto rewrite0; 464 if(c1 > c2) { 465 c1 -= c2; 466 goto rewrite2; 467 } 468 c1 = c2 - c1; 469 o = OASHL; 470 goto rewrite2; 471 } 472 return; 473 474 rewrite0: /* get rid of both shifts */ 475 *n = *n->left; 476 n->left = n->left->left; 477 n->right->vconst = c3; 478 return; 479 rewrite1: /* get rid of lower shift */ 480 n->left->left = n->left->left->left; 481 n->left->right->vconst = c3; 482 n->right->vconst = c1; 483 n->op = o; 484 return; 485 rewrite2: /* get rid of upper shift */ 486 *n = *n->left; 487 n->right->vconst = c3; 488 n->left->right->vconst = c1; 489 n->left->op = o; 490 return; 491 } 492 493 /* 494 * calculate addressability as follows 495 * CONST ==> 20 $value 496 * NAME ==> 10 name 497 * REGISTER ==> 11 register 498 * INDREG ==> 12 *[(reg)+offset] 499 * &10 ==> 2 $name 500 * ADD(2, 20) ==> 2 $name+offset 501 * ADD(3, 20) ==> 3 $(reg)+offset 502 * &12 ==> 3 $(reg)+offset 503 * *11 ==> 11 ?? 504 * *2 ==> 10 name 505 * *3 ==> 12 *(reg)+offset 506 * calculate complexity (number of registers) 507 */ 508 void 509 xcom(Node *n) 510 { 511 Node *l, *r; 512 int t; 513 514 if(n == Z) 515 return; 516 l = n->left; 517 r = n->right; 518 n->addable = 0; 519 n->complex = 0; 520 switch(n->op) { 521 case OCONST: 522 n->addable = 20; 523 return; 524 525 case OREGISTER: 526 n->addable = 11; 527 return; 528 529 case OINDREG: 530 n->addable = 12; 531 return; 532 533 case ONAME: 534 n->addable = 10; 535 return; 536 537 case OADDR: 538 xcom(l); 539 if(l->addable == 10) 540 n->addable = 2; 541 if(l->addable == 12) 542 n->addable = 3; 543 break; 544 545 case OIND: 546 xcom(l); 547 if(l->addable == 11) 548 n->addable = 12; 549 if(l->addable == 3) 550 n->addable = 12; 551 if(l->addable == 2) 552 n->addable = 10; 553 break; 554 555 case OADD: 556 xcom(l); 557 xcom(r); 558 if(l->addable == 20) { 559 if(r->addable == 2) 560 n->addable = 2; 561 if(r->addable == 3) 562 n->addable = 3; 563 } 564 if(r->addable == 20) { 565 if(l->addable == 2) 566 n->addable = 2; 567 if(l->addable == 3) 568 n->addable = 3; 569 } 570 break; 571 572 case OASLMUL: 573 case OASMUL: 574 xcom(l); 575 xcom(r); 576 t = vlog(r); 577 if(t >= 0) { 578 n->op = OASASHL; 579 r->vconst = t; 580 r->type = types[TINT]; 581 } 582 break; 583 584 case OMUL: 585 case OLMUL: 586 xcom(l); 587 xcom(r); 588 t = vlog(r); 589 if(t >= 0) { 590 n->op = OASHL; 591 r->vconst = t; 592 r->type = types[TINT]; 593 goto shift; 594 } 595 t = vlog(l); 596 if(t >= 0) { 597 n->op = OASHL; 598 n->left = r; 599 n->right = l; 600 r = l; 601 l = n->left; 602 r->vconst = t; 603 r->type = types[TINT]; 604 goto shift; 605 } 606 break; 607 608 case OASLDIV: 609 xcom(l); 610 xcom(r); 611 t = vlog(r); 612 if(t >= 0) { 613 n->op = OASLSHR; 614 r->vconst = t; 615 r->type = types[TINT]; 616 } 617 break; 618 619 case OLDIV: 620 xcom(l); 621 xcom(r); 622 t = vlog(r); 623 if(t >= 0) { 624 n->op = OLSHR; 625 r->vconst = t; 626 r->type = types[TINT]; 627 goto shift; 628 } 629 break; 630 631 case OASLMOD: 632 xcom(l); 633 xcom(r); 634 t = vlog(r); 635 if(t >= 0) { 636 n->op = OASAND; 637 r->vconst--; 638 } 639 break; 640 641 case OLMOD: 642 xcom(l); 643 xcom(r); 644 t = vlog(r); 645 if(t >= 0) { 646 n->op = OAND; 647 r->vconst--; 648 } 649 break; 650 651 case OLSHR: 652 case OASHL: 653 case OASHR: 654 xcom(l); 655 xcom(r); 656 shift: 657 testshift(n); 658 break; 659 660 default: 661 if(l != Z) 662 xcom(l); 663 if(r != Z) 664 xcom(r); 665 break; 666 } 667 if(n->addable >= 10) 668 return; 669 670 if(l != Z) 671 n->complex = l->complex; 672 if(r != Z) { 673 if(r->complex == n->complex) 674 n->complex = r->complex+1; 675 else 676 if(r->complex > n->complex) 677 n->complex = r->complex; 678 } 679 if(n->complex == 0) 680 n->complex++; 681 682 if(com64(n)) 683 return; 684 685 switch(n->op) { 686 case OFUNC: 687 n->complex = FNX; 688 break; 689 690 case OADD: 691 case OXOR: 692 case OAND: 693 case OOR: 694 case OEQ: 695 case ONE: 696 /* 697 * immediate operators, make const on right 698 */ 699 if(l->op == OCONST) { 700 n->left = r; 701 n->right = l; 702 } 703 break; 704 } 705 } 706 707 void 708 bcomplex(Node *n) 709 { 710 711 complex(n); 712 if(n->type != T) 713 if(tcompat(n, T, n->type, tnot)) 714 n->type = T; 715 if(n->type != T) { 716 bool64(n); 717 boolgen(n, 1, Z); 718 } else 719 gbranch(OGOTO); 720 } 721