github.com/razvanm/vanadium-go-1.3@v0.0.0-20160721203343-4a65068e5915/src/cmd/5c/cgen.c (about) 1 // Inferno utils/5c/cgen.c 2 // http://code.google.com/p/inferno-os/source/browse/utils/5c/cgen.c 3 // 4 // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. 5 // Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) 6 // Portions Copyright © 1997-1999 Vita Nuova Limited 7 // Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com) 8 // Portions Copyright © 2004,2006 Bruce Ellis 9 // Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) 10 // Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others 11 // Portions Copyright © 2009 The Go Authors. All rights reserved. 12 // 13 // Permission is hereby granted, free of charge, to any person obtaining a copy 14 // of this software and associated documentation files (the "Software"), to deal 15 // in the Software without restriction, including without limitation the rights 16 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17 // copies of the Software, and to permit persons to whom the Software is 18 // furnished to do so, subject to the following conditions: 19 // 20 // The above copyright notice and this permission notice shall be included in 21 // all copies or substantial portions of the Software. 22 // 23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 26 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 28 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 29 // THE SOFTWARE. 30 31 #include "gc.h" 32 #include "../../runtime/funcdata.h" 33 34 void 35 _cgen(Node *n, Node *nn, int inrel) 36 { 37 Node *l, *r; 38 Prog *p1; 39 Node nod, nod1, nod2, nod3, nod4; 40 int o, t; 41 int32 v, curs; 42 43 if(debug['g']) { 44 prtree(nn, "cgen lhs"); 45 prtree(n, "cgen"); 46 } 47 if(n == Z || n->type == T) 48 return; 49 if(typesuv[n->type->etype] && (n->op != OFUNC || nn != Z)) { 50 sugen(n, nn, n->type->width); 51 return; 52 } 53 l = n->left; 54 r = n->right; 55 o = n->op; 56 if(n->addable >= INDEXED) { 57 if(nn == Z) { 58 switch(o) { 59 default: 60 nullwarn(Z, Z); 61 break; 62 case OINDEX: 63 nullwarn(l, r); 64 break; 65 } 66 return; 67 } 68 gmove(n, nn); 69 return; 70 } 71 curs = cursafe; 72 73 if(n->complex >= FNX) 74 if(l->complex >= FNX) 75 if(r != Z && r->complex >= FNX) 76 switch(o) { 77 default: 78 regret(&nod, r, 0, 0); 79 cgen(r, &nod); 80 81 regsalloc(&nod1, r); 82 gopcode(OAS, &nod, Z, &nod1); 83 84 regfree(&nod); 85 nod = *n; 86 nod.right = &nod1; 87 cgen(&nod, nn); 88 return; 89 90 case OFUNC: 91 case OCOMMA: 92 case OANDAND: 93 case OOROR: 94 case OCOND: 95 case ODOT: 96 break; 97 } 98 99 switch(o) { 100 default: 101 diag(n, "unknown op in cgen: %O", o); 102 break; 103 104 case OAS: 105 if(l->op == OBIT) 106 goto bitas; 107 if(l->addable >= INDEXED && l->complex < FNX) { 108 if(nn != Z || r->addable < INDEXED) { 109 if(r->complex >= FNX && nn == Z) 110 regret(&nod, r, 0, 0); 111 else 112 regalloc(&nod, r, nn); 113 cgen(r, &nod); 114 gmove(&nod, l); 115 if(nn != Z) 116 gmove(&nod, nn); 117 regfree(&nod); 118 } else 119 gmove(r, l); 120 break; 121 } 122 if(l->complex >= r->complex) { 123 reglcgen(&nod1, l, Z); 124 if(r->addable >= INDEXED) { 125 gmove(r, &nod1); 126 if(nn != Z) 127 gmove(r, nn); 128 regfree(&nod1); 129 break; 130 } 131 regalloc(&nod, r, nn); 132 cgen(r, &nod); 133 } else { 134 regalloc(&nod, r, nn); 135 cgen(r, &nod); 136 reglcgen(&nod1, l, Z); 137 } 138 gmove(&nod, &nod1); 139 regfree(&nod); 140 regfree(&nod1); 141 break; 142 143 bitas: 144 n = l->left; 145 regalloc(&nod, r, nn); 146 if(l->complex >= r->complex) { 147 reglcgen(&nod1, n, Z); 148 cgen(r, &nod); 149 } else { 150 cgen(r, &nod); 151 reglcgen(&nod1, n, Z); 152 } 153 regalloc(&nod2, n, Z); 154 gopcode(OAS, &nod1, Z, &nod2); 155 bitstore(l, &nod, &nod1, &nod2, nn); 156 break; 157 158 case OBIT: 159 if(nn == Z) { 160 nullwarn(l, Z); 161 break; 162 } 163 bitload(n, &nod, Z, Z, nn); 164 gopcode(OAS, &nod, Z, nn); 165 regfree(&nod); 166 break; 167 168 case ODIV: 169 case OMOD: 170 if(nn != Z) 171 if((t = vlog(r)) >= 0) { 172 /* signed div/mod by constant power of 2 */ 173 cgen(l, nn); 174 gopcode(OGE, nodconst(0), nn, Z); 175 p1 = p; 176 if(o == ODIV) { 177 gopcode(OADD, nodconst((1<<t)-1), Z, nn); 178 patch(p1, pc); 179 gopcode(OASHR, nodconst(t), Z, nn); 180 } else { 181 gopcode(OSUB, nn, nodconst(0), nn); 182 gopcode(OAND, nodconst((1<<t)-1), Z, nn); 183 gopcode(OSUB, nn, nodconst(0), nn); 184 gbranch(OGOTO); 185 patch(p1, pc); 186 p1 = p; 187 gopcode(OAND, nodconst((1<<t)-1), Z, nn); 188 patch(p1, pc); 189 } 190 break; 191 } 192 goto muldiv; 193 194 case OSUB: 195 if(nn != Z) 196 if(l->op == OCONST) 197 if(!typefd[n->type->etype]) { 198 cgen(r, nn); 199 gopcode(o, Z, l, nn); 200 break; 201 } 202 case OADD: 203 case OAND: 204 case OOR: 205 case OXOR: 206 case OLSHR: 207 case OASHL: 208 case OASHR: 209 /* 210 * immediate operands 211 */ 212 if(nn != Z) 213 if(r->op == OCONST) 214 if(!typefd[n->type->etype]) { 215 cgen(l, nn); 216 if(r->vconst == 0) 217 if(o != OAND) 218 break; 219 if(nn != Z) 220 gopcode(o, r, Z, nn); 221 break; 222 } 223 224 case OLMUL: 225 case OLDIV: 226 case OLMOD: 227 case OMUL: 228 muldiv: 229 if(nn == Z) { 230 nullwarn(l, r); 231 break; 232 } 233 if(o == OMUL || o == OLMUL) { 234 if(mulcon(n, nn)) 235 break; 236 } 237 if(l->complex >= r->complex) { 238 regalloc(&nod, l, nn); 239 cgen(l, &nod); 240 regalloc(&nod1, r, Z); 241 cgen(r, &nod1); 242 gopcode(o, &nod1, Z, &nod); 243 } else { 244 regalloc(&nod, r, nn); 245 cgen(r, &nod); 246 regalloc(&nod1, l, Z); 247 cgen(l, &nod1); 248 gopcode(o, &nod, &nod1, &nod); 249 } 250 gopcode(OAS, &nod, Z, nn); 251 regfree(&nod); 252 regfree(&nod1); 253 break; 254 255 case OASLSHR: 256 case OASASHL: 257 case OASASHR: 258 case OASAND: 259 case OASADD: 260 case OASSUB: 261 case OASXOR: 262 case OASOR: 263 if(l->op == OBIT) 264 goto asbitop; 265 if(r->op == OCONST) 266 if(!typefd[r->type->etype]) 267 if(!typefd[n->type->etype]) { 268 if(l->addable < INDEXED) 269 reglcgen(&nod2, l, Z); 270 else 271 nod2 = *l; 272 regalloc(&nod, r, nn); 273 gopcode(OAS, &nod2, Z, &nod); 274 gopcode(o, r, Z, &nod); 275 gopcode(OAS, &nod, Z, &nod2); 276 277 regfree(&nod); 278 if(l->addable < INDEXED) 279 regfree(&nod2); 280 break; 281 } 282 283 case OASLMUL: 284 case OASLDIV: 285 case OASLMOD: 286 case OASMUL: 287 case OASDIV: 288 case OASMOD: 289 if(l->op == OBIT) 290 goto asbitop; 291 if(l->complex >= r->complex) { 292 if(l->addable < INDEXED) 293 reglcgen(&nod2, l, Z); 294 else 295 nod2 = *l; 296 regalloc(&nod1, r, Z); 297 cgen(r, &nod1); 298 } else { 299 regalloc(&nod1, r, Z); 300 cgen(r, &nod1); 301 if(l->addable < INDEXED) 302 reglcgen(&nod2, l, Z); 303 else 304 nod2 = *l; 305 } 306 307 regalloc(&nod, n, nn); 308 gmove(&nod2, &nod); 309 gopcode(o, &nod1, Z, &nod); 310 gmove(&nod, &nod2); 311 if(nn != Z) 312 gopcode(OAS, &nod, Z, nn); 313 regfree(&nod); 314 regfree(&nod1); 315 if(l->addable < INDEXED) 316 regfree(&nod2); 317 break; 318 319 asbitop: 320 regalloc(&nod4, n, nn); 321 if(l->complex >= r->complex) { 322 bitload(l, &nod, &nod1, &nod2, &nod4); 323 regalloc(&nod3, r, Z); 324 cgen(r, &nod3); 325 } else { 326 regalloc(&nod3, r, Z); 327 cgen(r, &nod3); 328 bitload(l, &nod, &nod1, &nod2, &nod4); 329 } 330 gmove(&nod, &nod4); 331 gopcode(o, &nod3, Z, &nod4); 332 regfree(&nod3); 333 gmove(&nod4, &nod); 334 regfree(&nod4); 335 bitstore(l, &nod, &nod1, &nod2, nn); 336 break; 337 338 case OADDR: 339 if(nn == Z) { 340 nullwarn(l, Z); 341 break; 342 } 343 lcgen(l, nn); 344 break; 345 346 case OFUNC: 347 if(l->complex >= FNX) { 348 if(l->op != OIND) 349 diag(n, "bad function call"); 350 351 regret(&nod, l->left, 0, 0); 352 cgen(l->left, &nod); 353 regsalloc(&nod1, l->left); 354 gopcode(OAS, &nod, Z, &nod1); 355 regfree(&nod); 356 357 nod = *n; 358 nod.left = &nod2; 359 nod2 = *l; 360 nod2.left = &nod1; 361 nod2.complex = 1; 362 cgen(&nod, nn); 363 364 return; 365 } 366 if(REGARG >= 0) 367 o = reg[REGARG]; 368 gargs(r, &nod, &nod1); 369 if(l->addable < INDEXED) { 370 reglcgen(&nod, l, Z); 371 gopcode(OFUNC, Z, Z, &nod); 372 regfree(&nod); 373 } else 374 gopcode(OFUNC, Z, Z, l); 375 if(REGARG >= 0) 376 if(o != reg[REGARG]) 377 reg[REGARG]--; 378 regret(&nod, n, l->type, 1); 379 if(nn != Z) 380 gmove(&nod, nn); 381 if(nod.op == OREGISTER) 382 regfree(&nod); 383 break; 384 385 case OIND: 386 if(nn == Z) { 387 nullwarn(l, Z); 388 break; 389 } 390 regialloc(&nod, n, nn); 391 r = l; 392 while(r->op == OADD) 393 r = r->right; 394 if(sconst(r) && (v = r->vconst+nod.xoffset) > -4096 && v < 4096) { 395 v = r->vconst; 396 r->vconst = 0; 397 cgen(l, &nod); 398 nod.xoffset += v; 399 r->vconst = v; 400 } else 401 cgen(l, &nod); 402 regind(&nod, n); 403 gopcode(OAS, &nod, Z, nn); 404 regfree(&nod); 405 break; 406 407 case OEQ: 408 case ONE: 409 case OLE: 410 case OLT: 411 case OGE: 412 case OGT: 413 case OLO: 414 case OLS: 415 case OHI: 416 case OHS: 417 if(nn == Z) { 418 nullwarn(l, r); 419 break; 420 } 421 boolgen(n, 1, nn); 422 break; 423 424 case OANDAND: 425 case OOROR: 426 boolgen(n, 1, nn); 427 if(nn == Z) 428 patch(p, pc); 429 break; 430 431 case ONOT: 432 if(nn == Z) { 433 nullwarn(l, Z); 434 break; 435 } 436 boolgen(n, 1, nn); 437 break; 438 439 case OCOMMA: 440 cgen(l, Z); 441 cgen(r, nn); 442 break; 443 444 case OCAST: 445 if(nn == Z) { 446 nullwarn(l, Z); 447 break; 448 } 449 /* 450 * convert from types l->n->nn 451 */ 452 if(nocast(l->type, n->type)) { 453 if(nocast(n->type, nn->type)) { 454 cgen(l, nn); 455 break; 456 } 457 } 458 regalloc(&nod, l, nn); 459 cgen(l, &nod); 460 regalloc(&nod1, n, &nod); 461 if(inrel) 462 gmover(&nod, &nod1); 463 else 464 gopcode(OAS, &nod, Z, &nod1); 465 gopcode(OAS, &nod1, Z, nn); 466 regfree(&nod1); 467 regfree(&nod); 468 break; 469 470 case ODOT: 471 sugen(l, nodrat, l->type->width); 472 if(nn != Z) { 473 warn(n, "non-interruptable temporary"); 474 nod = *nodrat; 475 if(!r || r->op != OCONST) { 476 diag(n, "DOT and no offset"); 477 break; 478 } 479 nod.xoffset += (int32)r->vconst; 480 nod.type = n->type; 481 cgen(&nod, nn); 482 } 483 break; 484 485 case OCOND: 486 bcgen(l, 1); 487 p1 = p; 488 cgen(r->left, nn); 489 gbranch(OGOTO); 490 patch(p1, pc); 491 p1 = p; 492 cgen(r->right, nn); 493 patch(p1, pc); 494 break; 495 496 case OPOSTINC: 497 case OPOSTDEC: 498 v = 1; 499 if(l->type->etype == TIND) 500 v = l->type->link->width; 501 if(o == OPOSTDEC) 502 v = -v; 503 if(l->op == OBIT) 504 goto bitinc; 505 if(nn == Z) 506 goto pre; 507 508 if(l->addable < INDEXED) 509 reglcgen(&nod2, l, Z); 510 else 511 nod2 = *l; 512 513 regalloc(&nod, l, nn); 514 gopcode(OAS, &nod2, Z, &nod); 515 regalloc(&nod1, l, Z); 516 if(typefd[l->type->etype]) { 517 regalloc(&nod3, l, Z); 518 if(v < 0) { 519 gopcode(OAS, nodfconst(-v), Z, &nod3); 520 gopcode(OSUB, &nod3, &nod, &nod1); 521 } else { 522 gopcode(OAS, nodfconst(v), Z, &nod3); 523 gopcode(OADD, &nod3, &nod, &nod1); 524 } 525 regfree(&nod3); 526 } else 527 gopcode(OADD, nodconst(v), &nod, &nod1); 528 gopcode(OAS, &nod1, Z, &nod2); 529 530 regfree(&nod); 531 regfree(&nod1); 532 if(l->addable < INDEXED) 533 regfree(&nod2); 534 break; 535 536 case OPREINC: 537 case OPREDEC: 538 v = 1; 539 if(l->type->etype == TIND) 540 v = l->type->link->width; 541 if(o == OPREDEC) 542 v = -v; 543 if(l->op == OBIT) 544 goto bitinc; 545 546 pre: 547 if(l->addable < INDEXED) 548 reglcgen(&nod2, l, Z); 549 else 550 nod2 = *l; 551 552 regalloc(&nod, l, nn); 553 gopcode(OAS, &nod2, Z, &nod); 554 if(typefd[l->type->etype]) { 555 regalloc(&nod3, l, Z); 556 if(v < 0) { 557 gopcode(OAS, nodfconst(-v), Z, &nod3); 558 gopcode(OSUB, &nod3, Z, &nod); 559 } else { 560 gopcode(OAS, nodfconst(v), Z, &nod3); 561 gopcode(OADD, &nod3, Z, &nod); 562 } 563 regfree(&nod3); 564 } else 565 gopcode(OADD, nodconst(v), Z, &nod); 566 gopcode(OAS, &nod, Z, &nod2); 567 568 regfree(&nod); 569 if(l->addable < INDEXED) 570 regfree(&nod2); 571 break; 572 573 bitinc: 574 if(nn != Z && (o == OPOSTINC || o == OPOSTDEC)) { 575 bitload(l, &nod, &nod1, &nod2, Z); 576 gopcode(OAS, &nod, Z, nn); 577 gopcode(OADD, nodconst(v), Z, &nod); 578 bitstore(l, &nod, &nod1, &nod2, Z); 579 break; 580 } 581 bitload(l, &nod, &nod1, &nod2, nn); 582 gopcode(OADD, nodconst(v), Z, &nod); 583 bitstore(l, &nod, &nod1, &nod2, nn); 584 break; 585 } 586 cursafe = curs; 587 return; 588 } 589 590 void 591 cgen(Node *n, Node *nn) 592 { 593 _cgen(n, nn, 0); 594 } 595 596 void 597 cgenrel(Node *n, Node *nn) 598 { 599 _cgen(n, nn, 1); 600 } 601 602 void 603 reglcgen(Node *t, Node *n, Node *nn) 604 { 605 Node *r; 606 int32 v; 607 608 regialloc(t, n, nn); 609 if(n->op == OIND) { 610 r = n->left; 611 while(r->op == OADD) 612 r = r->right; 613 if(sconst(r) && (v = r->vconst+t->xoffset) > -4096 && v < 4096) { 614 v = r->vconst; 615 r->vconst = 0; 616 lcgen(n, t); 617 t->xoffset += v; 618 r->vconst = v; 619 regind(t, n); 620 return; 621 } 622 } else if(n->op == OINDREG) { 623 if((v = n->xoffset) > -4096 && v < 4096) { 624 n->op = OREGISTER; 625 cgen(n, t); 626 t->xoffset += v; 627 n->op = OINDREG; 628 regind(t, n); 629 return; 630 } 631 } 632 lcgen(n, t); 633 regind(t, n); 634 } 635 636 void 637 reglpcgen(Node *n, Node *nn, int f) 638 { 639 Type *t; 640 641 t = nn->type; 642 nn->type = types[TLONG]; 643 if(f) 644 reglcgen(n, nn, Z); 645 else { 646 regialloc(n, nn, Z); 647 lcgen(nn, n); 648 regind(n, nn); 649 } 650 nn->type = t; 651 } 652 653 void 654 lcgen(Node *n, Node *nn) 655 { 656 Prog *p1; 657 Node nod; 658 659 if(debug['g']) { 660 prtree(nn, "lcgen lhs"); 661 prtree(n, "lcgen"); 662 } 663 if(n == Z || n->type == T) 664 return; 665 if(nn == Z) { 666 nn = &nod; 667 regalloc(&nod, n, Z); 668 } 669 switch(n->op) { 670 default: 671 if(n->addable < INDEXED) { 672 diag(n, "unknown op in lcgen: %O", n->op); 673 break; 674 } 675 nod = *n; 676 nod.op = OADDR; 677 nod.left = n; 678 nod.right = Z; 679 nod.type = types[TIND]; 680 gopcode(OAS, &nod, Z, nn); 681 break; 682 683 case OCOMMA: 684 cgen(n->left, n->left); 685 lcgen(n->right, nn); 686 break; 687 688 case OIND: 689 cgen(n->left, nn); 690 break; 691 692 case OCOND: 693 bcgen(n->left, 1); 694 p1 = p; 695 lcgen(n->right->left, nn); 696 gbranch(OGOTO); 697 patch(p1, pc); 698 p1 = p; 699 lcgen(n->right->right, nn); 700 patch(p1, pc); 701 break; 702 } 703 } 704 705 void 706 bcgen(Node *n, int true) 707 { 708 709 if(n->type == T) 710 gbranch(OGOTO); 711 else 712 boolgen(n, true, Z); 713 } 714 715 void 716 boolgen(Node *n, int true, Node *nn) 717 { 718 int o; 719 Prog *p1, *p2; 720 Node *l, *r, nod, nod1; 721 int32 curs; 722 723 if(debug['g']) { 724 prtree(nn, "boolgen lhs"); 725 prtree(n, "boolgen"); 726 } 727 curs = cursafe; 728 l = n->left; 729 r = n->right; 730 switch(n->op) { 731 732 default: 733 regalloc(&nod, n, nn); 734 cgen(n, &nod); 735 o = ONE; 736 if(true) 737 o = comrel[relindex(o)]; 738 if(typefd[n->type->etype]) { 739 gopcode(o, nodfconst(0), &nod, Z); 740 } else 741 gopcode(o, nodconst(0), &nod, Z); 742 regfree(&nod); 743 goto com; 744 745 case OCONST: 746 o = vconst(n); 747 if(!true) 748 o = !o; 749 gbranch(OGOTO); 750 if(o) { 751 p1 = p; 752 gbranch(OGOTO); 753 patch(p1, pc); 754 } 755 goto com; 756 757 case OCOMMA: 758 cgen(l, Z); 759 boolgen(r, true, nn); 760 break; 761 762 case ONOT: 763 boolgen(l, !true, nn); 764 break; 765 766 case OCOND: 767 bcgen(l, 1); 768 p1 = p; 769 bcgen(r->left, true); 770 p2 = p; 771 gbranch(OGOTO); 772 patch(p1, pc); 773 p1 = p; 774 bcgen(r->right, !true); 775 patch(p2, pc); 776 p2 = p; 777 gbranch(OGOTO); 778 patch(p1, pc); 779 patch(p2, pc); 780 goto com; 781 782 case OANDAND: 783 if(!true) 784 goto caseor; 785 786 caseand: 787 bcgen(l, true); 788 p1 = p; 789 bcgen(r, !true); 790 p2 = p; 791 patch(p1, pc); 792 gbranch(OGOTO); 793 patch(p2, pc); 794 goto com; 795 796 case OOROR: 797 if(!true) 798 goto caseand; 799 800 caseor: 801 bcgen(l, !true); 802 p1 = p; 803 bcgen(r, !true); 804 p2 = p; 805 gbranch(OGOTO); 806 patch(p1, pc); 807 patch(p2, pc); 808 goto com; 809 810 case OEQ: 811 case ONE: 812 case OLE: 813 case OLT: 814 case OGE: 815 case OGT: 816 case OHI: 817 case OHS: 818 case OLO: 819 case OLS: 820 o = n->op; 821 if(true) 822 o = comrel[relindex(o)]; 823 if(l->complex >= FNX && r->complex >= FNX) { 824 regret(&nod, r, 0, 0); 825 cgenrel(r, &nod); 826 regsalloc(&nod1, r); 827 gopcode(OAS, &nod, Z, &nod1); 828 regfree(&nod); 829 nod = *n; 830 nod.right = &nod1; 831 boolgen(&nod, true, nn); 832 break; 833 } 834 if(sconst(l)) { 835 regalloc(&nod, r, nn); 836 cgenrel(r, &nod); 837 o = invrel[relindex(o)]; 838 gopcode(o, l, &nod, Z); 839 regfree(&nod); 840 goto com; 841 } 842 if(sconst(r)) { 843 regalloc(&nod, l, nn); 844 cgenrel(l, &nod); 845 gopcode(o, r, &nod, Z); 846 regfree(&nod); 847 goto com; 848 } 849 if(l->complex >= r->complex) { 850 regalloc(&nod1, l, nn); 851 cgenrel(l, &nod1); 852 regalloc(&nod, r, Z); 853 cgenrel(r, &nod); 854 } else { 855 regalloc(&nod, r, nn); 856 cgenrel(r, &nod); 857 regalloc(&nod1, l, Z); 858 cgenrel(l, &nod1); 859 } 860 gopcode(o, &nod, &nod1, Z); 861 regfree(&nod); 862 regfree(&nod1); 863 864 com: 865 if(nn != Z) { 866 p1 = p; 867 gopcode(OAS, nodconst(1), Z, nn); 868 gbranch(OGOTO); 869 p2 = p; 870 patch(p1, pc); 871 gopcode(OAS, nodconst(0), Z, nn); 872 patch(p2, pc); 873 } 874 break; 875 } 876 cursafe = curs; 877 } 878 879 void 880 sugen(Node *n, Node *nn, int32 w) 881 { 882 Prog *p1; 883 Node nod0, nod1, nod2, nod3, nod4, *l, *r; 884 Type *t; 885 int32 pc1; 886 int i, m, c; 887 888 if(n == Z || n->type == T) 889 return; 890 if(debug['g']) { 891 prtree(nn, "sugen lhs"); 892 prtree(n, "sugen"); 893 } 894 if(nn == nodrat) 895 if(w > nrathole) 896 nrathole = w; 897 switch(n->op) { 898 case OIND: 899 if(nn == Z) { 900 nullwarn(n->left, Z); 901 break; 902 } 903 904 default: 905 goto copy; 906 907 case OCONST: 908 if(n->type && typev[n->type->etype]) { 909 if(nn == Z) { 910 nullwarn(n->left, Z); 911 break; 912 } 913 914 t = nn->type; 915 nn->type = types[TLONG]; 916 reglcgen(&nod1, nn, Z); 917 nn->type = t; 918 919 if(isbigendian) 920 gopcode(OAS, nod32const(n->vconst>>32), Z, &nod1); 921 else 922 gopcode(OAS, nod32const(n->vconst), Z, &nod1); 923 nod1.xoffset += SZ_LONG; 924 if(isbigendian) 925 gopcode(OAS, nod32const(n->vconst), Z, &nod1); 926 else 927 gopcode(OAS, nod32const(n->vconst>>32), Z, &nod1); 928 929 regfree(&nod1); 930 break; 931 } 932 goto copy; 933 934 case ODOT: 935 l = n->left; 936 sugen(l, nodrat, l->type->width); 937 if(nn != Z) { 938 warn(n, "non-interruptable temporary"); 939 nod1 = *nodrat; 940 r = n->right; 941 if(!r || r->op != OCONST) { 942 diag(n, "DOT and no offset"); 943 break; 944 } 945 nod1.xoffset += (int32)r->vconst; 946 nod1.type = n->type; 947 sugen(&nod1, nn, w); 948 } 949 break; 950 951 case OSTRUCT: 952 /* 953 * rewrite so lhs has no side effect. 954 */ 955 if(nn != Z && side(nn)) { 956 nod1 = *n; 957 nod1.type = typ(TIND, n->type); 958 regret(&nod2, &nod1, 0, 0); 959 lcgen(nn, &nod2); 960 regsalloc(&nod0, &nod1); 961 gopcode(OAS, &nod2, Z, &nod0); 962 regfree(&nod2); 963 964 nod1 = *n; 965 nod1.op = OIND; 966 nod1.left = &nod0; 967 nod1.right = Z; 968 nod1.complex = 1; 969 970 sugen(n, &nod1, w); 971 return; 972 } 973 974 r = n->left; 975 for(t = n->type->link; t != T; t = t->down) { 976 l = r; 977 if(r->op == OLIST) { 978 l = r->left; 979 r = r->right; 980 } 981 if(nn == Z) { 982 cgen(l, nn); 983 continue; 984 } 985 /* 986 * hand craft *(&nn + o) = l 987 */ 988 nod0 = znode; 989 nod0.op = OAS; 990 nod0.type = t; 991 nod0.left = &nod1; 992 nod0.right = l; 993 994 nod1 = znode; 995 nod1.op = OIND; 996 nod1.type = t; 997 nod1.left = &nod2; 998 999 nod2 = znode; 1000 nod2.op = OADD; 1001 nod2.type = typ(TIND, t); 1002 nod2.left = &nod3; 1003 nod2.right = &nod4; 1004 1005 nod3 = znode; 1006 nod3.op = OADDR; 1007 nod3.type = nod2.type; 1008 nod3.left = nn; 1009 1010 nod4 = znode; 1011 nod4.op = OCONST; 1012 nod4.type = nod2.type; 1013 nod4.vconst = t->offset; 1014 1015 ccom(&nod0); 1016 acom(&nod0); 1017 xcom(&nod0); 1018 nod0.addable = 0; 1019 1020 cgen(&nod0, Z); 1021 } 1022 break; 1023 1024 case OAS: 1025 if(nn == Z) { 1026 if(n->addable < INDEXED) 1027 sugen(n->right, n->left, w); 1028 break; 1029 } 1030 sugen(n->right, nodrat, w); 1031 warn(n, "non-interruptable temporary"); 1032 sugen(nodrat, n->left, w); 1033 sugen(nodrat, nn, w); 1034 break; 1035 1036 case OFUNC: 1037 if(!hasdotdotdot(n->left->type)) { 1038 cgen(n, Z); 1039 if(nn != Z) { 1040 curarg -= n->type->width; 1041 regret(&nod1, n, n->left->type, 1); 1042 if(nn->complex >= FNX) { 1043 regsalloc(&nod2, n); 1044 cgen(&nod1, &nod2); 1045 nod1 = nod2; 1046 } 1047 cgen(&nod1, nn); 1048 } 1049 break; 1050 } 1051 if(nn == Z) { 1052 sugen(n, nodrat, w); 1053 break; 1054 } 1055 if(nn->op != OIND) { 1056 nn = new1(OADDR, nn, Z); 1057 nn->type = types[TIND]; 1058 nn->addable = 0; 1059 } else 1060 nn = nn->left; 1061 n = new(OFUNC, n->left, new(OLIST, nn, n->right)); 1062 n->type = types[TVOID]; 1063 n->left->type = types[TVOID]; 1064 cgen(n, Z); 1065 break; 1066 1067 case OCOND: 1068 bcgen(n->left, 1); 1069 p1 = p; 1070 sugen(n->right->left, nn, w); 1071 gbranch(OGOTO); 1072 patch(p1, pc); 1073 p1 = p; 1074 sugen(n->right->right, nn, w); 1075 patch(p1, pc); 1076 break; 1077 1078 case OCOMMA: 1079 cgen(n->left, Z); 1080 sugen(n->right, nn, w); 1081 break; 1082 } 1083 return; 1084 1085 copy: 1086 if(nn == Z) 1087 return; 1088 if(n->complex >= FNX && nn->complex >= FNX) { 1089 t = nn->type; 1090 nn->type = types[TLONG]; 1091 regialloc(&nod1, nn, Z); 1092 lcgen(nn, &nod1); 1093 regsalloc(&nod2, nn); 1094 nn->type = t; 1095 1096 gopcode(OAS, &nod1, Z, &nod2); 1097 regfree(&nod1); 1098 1099 nod2.type = typ(TIND, t); 1100 1101 nod1 = nod2; 1102 nod1.op = OIND; 1103 nod1.left = &nod2; 1104 nod1.right = Z; 1105 nod1.complex = 1; 1106 nod1.type = t; 1107 1108 sugen(n, &nod1, w); 1109 return; 1110 } 1111 1112 w /= SZ_LONG; 1113 if(w <= 2) { 1114 if(n->complex > nn->complex) { 1115 reglpcgen(&nod1, n, 1); 1116 reglpcgen(&nod2, nn, 1); 1117 } else { 1118 reglpcgen(&nod2, nn, 1); 1119 reglpcgen(&nod1, n, 1); 1120 } 1121 regalloc(&nod3, ®node, Z); 1122 regalloc(&nod4, ®node, Z); 1123 nod0 = *nodconst((1<<nod3.reg)|(1<<nod4.reg)); 1124 if(w == 2 && nod1.xoffset == 0) 1125 gmovm(&nod1, &nod0, 0); 1126 else { 1127 gmove(&nod1, &nod3); 1128 if(w == 2) { 1129 nod1.xoffset += SZ_LONG; 1130 gmove(&nod1, &nod4); 1131 } 1132 } 1133 if(w == 2 && nod2.xoffset == 0) 1134 gmovm(&nod0, &nod2, 0); 1135 else { 1136 gmove(&nod3, &nod2); 1137 if(w == 2) { 1138 nod2.xoffset += SZ_LONG; 1139 gmove(&nod4, &nod2); 1140 } 1141 } 1142 regfree(&nod1); 1143 regfree(&nod2); 1144 regfree(&nod3); 1145 regfree(&nod4); 1146 return; 1147 } 1148 1149 if(n->complex > nn->complex) { 1150 reglpcgen(&nod1, n, 0); 1151 reglpcgen(&nod2, nn, 0); 1152 } else { 1153 reglpcgen(&nod2, nn, 0); 1154 reglpcgen(&nod1, n, 0); 1155 } 1156 1157 m = 0; 1158 for(c = 0; c < w && c < 4; c++) { 1159 i = tmpreg(); 1160 if (i == 0) 1161 break; 1162 reg[i]++; 1163 m |= 1<<i; 1164 } 1165 nod4 = *(nodconst(m)); 1166 if(w < 3*c) { 1167 for (; w>c; w-=c) { 1168 gmovm(&nod1, &nod4, 1); 1169 gmovm(&nod4, &nod2, 1); 1170 } 1171 goto out; 1172 } 1173 1174 regalloc(&nod3, ®node, Z); 1175 gopcode(OAS, nodconst(w/c), Z, &nod3); 1176 w %= c; 1177 1178 pc1 = pc; 1179 gmovm(&nod1, &nod4, 1); 1180 gmovm(&nod4, &nod2, 1); 1181 1182 gopcode(OSUB, nodconst(1), Z, &nod3); 1183 gopcode(OEQ, nodconst(0), &nod3, Z); 1184 p->as = ABGT; 1185 patch(p, pc1); 1186 regfree(&nod3); 1187 1188 out: 1189 if (w) { 1190 i = 0; 1191 while (c>w) { 1192 while ((m&(1<<i)) == 0) 1193 i++; 1194 m &= ~(1<<i); 1195 reg[i] = 0; 1196 c--; 1197 i++; 1198 } 1199 nod4.vconst = m; 1200 gmovm(&nod1, &nod4, 0); 1201 gmovm(&nod4, &nod2, 0); 1202 } 1203 i = 0; 1204 do { 1205 while ((m&(1<<i)) == 0) 1206 i++; 1207 reg[i] = 0; 1208 c--; 1209 i++; 1210 } while (c>0); 1211 regfree(&nod1); 1212 regfree(&nod2); 1213 }