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