github.com/rohankumardubey/syslog-redirector-golang@v0.0.0-20140320174030-4859f03d829a/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 "../../pkg/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]) { 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); 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); 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); 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 gpcdata(PCDATA_ArgSize, curarg); 370 if(l->addable < INDEXED) { 371 reglcgen(&nod, l, Z); 372 gopcode(OFUNC, Z, Z, &nod); 373 regfree(&nod); 374 } else 375 gopcode(OFUNC, Z, Z, l); 376 gpcdata(PCDATA_ArgSize, -1); 377 if(REGARG >= 0) 378 if(o != reg[REGARG]) 379 reg[REGARG]--; 380 if(nn != Z) { 381 regret(&nod, n); 382 gopcode(OAS, &nod, Z, nn); 383 regfree(&nod); 384 } 385 break; 386 387 case OIND: 388 if(nn == Z) { 389 nullwarn(l, Z); 390 break; 391 } 392 regialloc(&nod, n, nn); 393 r = l; 394 while(r->op == OADD) 395 r = r->right; 396 if(sconst(r) && (v = r->vconst+nod.xoffset) > -4096 && v < 4096) { 397 v = r->vconst; 398 r->vconst = 0; 399 cgen(l, &nod); 400 nod.xoffset += v; 401 r->vconst = v; 402 } else 403 cgen(l, &nod); 404 regind(&nod, n); 405 gopcode(OAS, &nod, Z, nn); 406 regfree(&nod); 407 break; 408 409 case OEQ: 410 case ONE: 411 case OLE: 412 case OLT: 413 case OGE: 414 case OGT: 415 case OLO: 416 case OLS: 417 case OHI: 418 case OHS: 419 if(nn == Z) { 420 nullwarn(l, r); 421 break; 422 } 423 boolgen(n, 1, nn); 424 break; 425 426 case OANDAND: 427 case OOROR: 428 boolgen(n, 1, nn); 429 if(nn == Z) 430 patch(p, pc); 431 break; 432 433 case ONOT: 434 if(nn == Z) { 435 nullwarn(l, Z); 436 break; 437 } 438 boolgen(n, 1, nn); 439 break; 440 441 case OCOMMA: 442 cgen(l, Z); 443 cgen(r, nn); 444 break; 445 446 case OCAST: 447 if(nn == Z) { 448 nullwarn(l, Z); 449 break; 450 } 451 /* 452 * convert from types l->n->nn 453 */ 454 if(nocast(l->type, n->type)) { 455 if(nocast(n->type, nn->type)) { 456 cgen(l, nn); 457 break; 458 } 459 } 460 regalloc(&nod, l, nn); 461 cgen(l, &nod); 462 regalloc(&nod1, n, &nod); 463 if(inrel) 464 gmover(&nod, &nod1); 465 else 466 gopcode(OAS, &nod, Z, &nod1); 467 gopcode(OAS, &nod1, Z, nn); 468 regfree(&nod1); 469 regfree(&nod); 470 break; 471 472 case ODOT: 473 sugen(l, nodrat, l->type->width); 474 if(nn != Z) { 475 warn(n, "non-interruptable temporary"); 476 nod = *nodrat; 477 if(!r || r->op != OCONST) { 478 diag(n, "DOT and no offset"); 479 break; 480 } 481 nod.xoffset += (int32)r->vconst; 482 nod.type = n->type; 483 cgen(&nod, nn); 484 } 485 break; 486 487 case OCOND: 488 bcgen(l, 1); 489 p1 = p; 490 cgen(r->left, nn); 491 gbranch(OGOTO); 492 patch(p1, pc); 493 p1 = p; 494 cgen(r->right, nn); 495 patch(p1, pc); 496 break; 497 498 case OPOSTINC: 499 case OPOSTDEC: 500 v = 1; 501 if(l->type->etype == TIND) 502 v = l->type->link->width; 503 if(o == OPOSTDEC) 504 v = -v; 505 if(l->op == OBIT) 506 goto bitinc; 507 if(nn == Z) 508 goto pre; 509 510 if(l->addable < INDEXED) 511 reglcgen(&nod2, l, Z); 512 else 513 nod2 = *l; 514 515 regalloc(&nod, l, nn); 516 gopcode(OAS, &nod2, Z, &nod); 517 regalloc(&nod1, l, Z); 518 if(typefd[l->type->etype]) { 519 regalloc(&nod3, l, Z); 520 if(v < 0) { 521 gopcode(OAS, nodfconst(-v), Z, &nod3); 522 gopcode(OSUB, &nod3, &nod, &nod1); 523 } else { 524 gopcode(OAS, nodfconst(v), Z, &nod3); 525 gopcode(OADD, &nod3, &nod, &nod1); 526 } 527 regfree(&nod3); 528 } else 529 gopcode(OADD, nodconst(v), &nod, &nod1); 530 gopcode(OAS, &nod1, Z, &nod2); 531 532 regfree(&nod); 533 regfree(&nod1); 534 if(l->addable < INDEXED) 535 regfree(&nod2); 536 break; 537 538 case OPREINC: 539 case OPREDEC: 540 v = 1; 541 if(l->type->etype == TIND) 542 v = l->type->link->width; 543 if(o == OPREDEC) 544 v = -v; 545 if(l->op == OBIT) 546 goto bitinc; 547 548 pre: 549 if(l->addable < INDEXED) 550 reglcgen(&nod2, l, Z); 551 else 552 nod2 = *l; 553 554 regalloc(&nod, l, nn); 555 gopcode(OAS, &nod2, Z, &nod); 556 if(typefd[l->type->etype]) { 557 regalloc(&nod3, l, Z); 558 if(v < 0) { 559 gopcode(OAS, nodfconst(-v), Z, &nod3); 560 gopcode(OSUB, &nod3, Z, &nod); 561 } else { 562 gopcode(OAS, nodfconst(v), Z, &nod3); 563 gopcode(OADD, &nod3, Z, &nod); 564 } 565 regfree(&nod3); 566 } else 567 gopcode(OADD, nodconst(v), Z, &nod); 568 gopcode(OAS, &nod, Z, &nod2); 569 570 regfree(&nod); 571 if(l->addable < INDEXED) 572 regfree(&nod2); 573 break; 574 575 bitinc: 576 if(nn != Z && (o == OPOSTINC || o == OPOSTDEC)) { 577 bitload(l, &nod, &nod1, &nod2, Z); 578 gopcode(OAS, &nod, Z, nn); 579 gopcode(OADD, nodconst(v), Z, &nod); 580 bitstore(l, &nod, &nod1, &nod2, Z); 581 break; 582 } 583 bitload(l, &nod, &nod1, &nod2, nn); 584 gopcode(OADD, nodconst(v), Z, &nod); 585 bitstore(l, &nod, &nod1, &nod2, nn); 586 break; 587 } 588 cursafe = curs; 589 return; 590 } 591 592 void 593 cgen(Node *n, Node *nn) 594 { 595 _cgen(n, nn, 0); 596 } 597 598 void 599 cgenrel(Node *n, Node *nn) 600 { 601 _cgen(n, nn, 1); 602 } 603 604 void 605 reglcgen(Node *t, Node *n, Node *nn) 606 { 607 Node *r; 608 int32 v; 609 610 regialloc(t, n, nn); 611 if(n->op == OIND) { 612 r = n->left; 613 while(r->op == OADD) 614 r = r->right; 615 if(sconst(r) && (v = r->vconst+t->xoffset) > -4096 && v < 4096) { 616 v = r->vconst; 617 r->vconst = 0; 618 lcgen(n, t); 619 t->xoffset += v; 620 r->vconst = v; 621 regind(t, n); 622 return; 623 } 624 } else if(n->op == OINDREG) { 625 if((v = n->xoffset) > -4096 && v < 4096) { 626 n->op = OREGISTER; 627 cgen(n, t); 628 t->xoffset += v; 629 n->op = OINDREG; 630 regind(t, n); 631 return; 632 } 633 } 634 lcgen(n, t); 635 regind(t, n); 636 } 637 638 void 639 reglpcgen(Node *n, Node *nn, int f) 640 { 641 Type *t; 642 643 t = nn->type; 644 nn->type = types[TLONG]; 645 if(f) 646 reglcgen(n, nn, Z); 647 else { 648 regialloc(n, nn, Z); 649 lcgen(nn, n); 650 regind(n, nn); 651 } 652 nn->type = t; 653 } 654 655 void 656 lcgen(Node *n, Node *nn) 657 { 658 Prog *p1; 659 Node nod; 660 661 if(debug['g']) { 662 prtree(nn, "lcgen lhs"); 663 prtree(n, "lcgen"); 664 } 665 if(n == Z || n->type == T) 666 return; 667 if(nn == Z) { 668 nn = &nod; 669 regalloc(&nod, n, Z); 670 } 671 switch(n->op) { 672 default: 673 if(n->addable < INDEXED) { 674 diag(n, "unknown op in lcgen: %O", n->op); 675 break; 676 } 677 nod = *n; 678 nod.op = OADDR; 679 nod.left = n; 680 nod.right = Z; 681 nod.type = types[TIND]; 682 gopcode(OAS, &nod, Z, nn); 683 break; 684 685 case OCOMMA: 686 cgen(n->left, n->left); 687 lcgen(n->right, nn); 688 break; 689 690 case OIND: 691 cgen(n->left, nn); 692 break; 693 694 case OCOND: 695 bcgen(n->left, 1); 696 p1 = p; 697 lcgen(n->right->left, nn); 698 gbranch(OGOTO); 699 patch(p1, pc); 700 p1 = p; 701 lcgen(n->right->right, nn); 702 patch(p1, pc); 703 break; 704 } 705 } 706 707 void 708 bcgen(Node *n, int true) 709 { 710 711 if(n->type == T) 712 gbranch(OGOTO); 713 else 714 boolgen(n, true, Z); 715 } 716 717 void 718 boolgen(Node *n, int true, Node *nn) 719 { 720 int o; 721 Prog *p1, *p2; 722 Node *l, *r, nod, nod1; 723 int32 curs; 724 725 if(debug['g']) { 726 prtree(nn, "boolgen lhs"); 727 prtree(n, "boolgen"); 728 } 729 curs = cursafe; 730 l = n->left; 731 r = n->right; 732 switch(n->op) { 733 734 default: 735 regalloc(&nod, n, nn); 736 cgen(n, &nod); 737 o = ONE; 738 if(true) 739 o = comrel[relindex(o)]; 740 if(typefd[n->type->etype]) { 741 gopcode(o, nodfconst(0), &nod, Z); 742 } else 743 gopcode(o, nodconst(0), &nod, Z); 744 regfree(&nod); 745 goto com; 746 747 case OCONST: 748 o = vconst(n); 749 if(!true) 750 o = !o; 751 gbranch(OGOTO); 752 if(o) { 753 p1 = p; 754 gbranch(OGOTO); 755 patch(p1, pc); 756 } 757 goto com; 758 759 case OCOMMA: 760 cgen(l, Z); 761 boolgen(r, true, nn); 762 break; 763 764 case ONOT: 765 boolgen(l, !true, nn); 766 break; 767 768 case OCOND: 769 bcgen(l, 1); 770 p1 = p; 771 bcgen(r->left, true); 772 p2 = p; 773 gbranch(OGOTO); 774 patch(p1, pc); 775 p1 = p; 776 bcgen(r->right, !true); 777 patch(p2, pc); 778 p2 = p; 779 gbranch(OGOTO); 780 patch(p1, pc); 781 patch(p2, pc); 782 goto com; 783 784 case OANDAND: 785 if(!true) 786 goto caseor; 787 788 caseand: 789 bcgen(l, true); 790 p1 = p; 791 bcgen(r, !true); 792 p2 = p; 793 patch(p1, pc); 794 gbranch(OGOTO); 795 patch(p2, pc); 796 goto com; 797 798 case OOROR: 799 if(!true) 800 goto caseand; 801 802 caseor: 803 bcgen(l, !true); 804 p1 = p; 805 bcgen(r, !true); 806 p2 = p; 807 gbranch(OGOTO); 808 patch(p1, pc); 809 patch(p2, pc); 810 goto com; 811 812 case OEQ: 813 case ONE: 814 case OLE: 815 case OLT: 816 case OGE: 817 case OGT: 818 case OHI: 819 case OHS: 820 case OLO: 821 case OLS: 822 o = n->op; 823 if(true) 824 o = comrel[relindex(o)]; 825 if(l->complex >= FNX && r->complex >= FNX) { 826 regret(&nod, r); 827 cgenrel(r, &nod); 828 regsalloc(&nod1, r); 829 gopcode(OAS, &nod, Z, &nod1); 830 regfree(&nod); 831 nod = *n; 832 nod.right = &nod1; 833 boolgen(&nod, true, nn); 834 break; 835 } 836 if(sconst(l)) { 837 regalloc(&nod, r, nn); 838 cgenrel(r, &nod); 839 o = invrel[relindex(o)]; 840 gopcode(o, l, &nod, Z); 841 regfree(&nod); 842 goto com; 843 } 844 if(sconst(r)) { 845 regalloc(&nod, l, nn); 846 cgenrel(l, &nod); 847 gopcode(o, r, &nod, Z); 848 regfree(&nod); 849 goto com; 850 } 851 if(l->complex >= r->complex) { 852 regalloc(&nod1, l, nn); 853 cgenrel(l, &nod1); 854 regalloc(&nod, r, Z); 855 cgenrel(r, &nod); 856 } else { 857 regalloc(&nod, r, nn); 858 cgenrel(r, &nod); 859 regalloc(&nod1, l, Z); 860 cgenrel(l, &nod1); 861 } 862 gopcode(o, &nod, &nod1, Z); 863 regfree(&nod); 864 regfree(&nod1); 865 866 com: 867 if(nn != Z) { 868 p1 = p; 869 gopcode(OAS, nodconst(1), Z, nn); 870 gbranch(OGOTO); 871 p2 = p; 872 patch(p1, pc); 873 gopcode(OAS, nodconst(0), Z, nn); 874 patch(p2, pc); 875 } 876 break; 877 } 878 cursafe = curs; 879 } 880 881 void 882 sugen(Node *n, Node *nn, int32 w) 883 { 884 Prog *p1; 885 Node nod0, nod1, nod2, nod3, nod4, *l, *r; 886 Type *t; 887 int32 pc1; 888 int i, m, c; 889 890 if(n == Z || n->type == T) 891 return; 892 if(debug['g']) { 893 prtree(nn, "sugen lhs"); 894 prtree(n, "sugen"); 895 } 896 if(nn == nodrat) 897 if(w > nrathole) 898 nrathole = w; 899 switch(n->op) { 900 case OIND: 901 if(nn == Z) { 902 nullwarn(n->left, Z); 903 break; 904 } 905 906 default: 907 goto copy; 908 909 case OCONST: 910 if(n->type && typev[n->type->etype]) { 911 if(nn == Z) { 912 nullwarn(n->left, Z); 913 break; 914 } 915 916 t = nn->type; 917 nn->type = types[TLONG]; 918 reglcgen(&nod1, nn, Z); 919 nn->type = t; 920 921 if(isbigendian) 922 gopcode(OAS, nod32const(n->vconst>>32), Z, &nod1); 923 else 924 gopcode(OAS, nod32const(n->vconst), Z, &nod1); 925 nod1.xoffset += SZ_LONG; 926 if(isbigendian) 927 gopcode(OAS, nod32const(n->vconst), Z, &nod1); 928 else 929 gopcode(OAS, nod32const(n->vconst>>32), Z, &nod1); 930 931 regfree(&nod1); 932 break; 933 } 934 goto copy; 935 936 case ODOT: 937 l = n->left; 938 sugen(l, nodrat, l->type->width); 939 if(nn != Z) { 940 warn(n, "non-interruptable temporary"); 941 nod1 = *nodrat; 942 r = n->right; 943 if(!r || r->op != OCONST) { 944 diag(n, "DOT and no offset"); 945 break; 946 } 947 nod1.xoffset += (int32)r->vconst; 948 nod1.type = n->type; 949 sugen(&nod1, nn, w); 950 } 951 break; 952 953 case OSTRUCT: 954 /* 955 * rewrite so lhs has no side effect. 956 */ 957 if(nn != Z && side(nn)) { 958 nod1 = *n; 959 nod1.type = typ(TIND, n->type); 960 regret(&nod2, &nod1); 961 lcgen(nn, &nod2); 962 regsalloc(&nod0, &nod1); 963 gopcode(OAS, &nod2, Z, &nod0); 964 regfree(&nod2); 965 966 nod1 = *n; 967 nod1.op = OIND; 968 nod1.left = &nod0; 969 nod1.right = Z; 970 nod1.complex = 1; 971 972 sugen(n, &nod1, w); 973 return; 974 } 975 976 r = n->left; 977 for(t = n->type->link; t != T; t = t->down) { 978 l = r; 979 if(r->op == OLIST) { 980 l = r->left; 981 r = r->right; 982 } 983 if(nn == Z) { 984 cgen(l, nn); 985 continue; 986 } 987 /* 988 * hand craft *(&nn + o) = l 989 */ 990 nod0 = znode; 991 nod0.op = OAS; 992 nod0.type = t; 993 nod0.left = &nod1; 994 nod0.right = l; 995 996 nod1 = znode; 997 nod1.op = OIND; 998 nod1.type = t; 999 nod1.left = &nod2; 1000 1001 nod2 = znode; 1002 nod2.op = OADD; 1003 nod2.type = typ(TIND, t); 1004 nod2.left = &nod3; 1005 nod2.right = &nod4; 1006 1007 nod3 = znode; 1008 nod3.op = OADDR; 1009 nod3.type = nod2.type; 1010 nod3.left = nn; 1011 1012 nod4 = znode; 1013 nod4.op = OCONST; 1014 nod4.type = nod2.type; 1015 nod4.vconst = t->offset; 1016 1017 ccom(&nod0); 1018 acom(&nod0); 1019 xcom(&nod0); 1020 nod0.addable = 0; 1021 1022 cgen(&nod0, Z); 1023 } 1024 break; 1025 1026 case OAS: 1027 if(nn == Z) { 1028 if(n->addable < INDEXED) 1029 sugen(n->right, n->left, w); 1030 break; 1031 } 1032 sugen(n->right, nodrat, w); 1033 warn(n, "non-interruptable temporary"); 1034 sugen(nodrat, n->left, w); 1035 sugen(nodrat, nn, w); 1036 break; 1037 1038 case OFUNC: 1039 if(nn == Z) { 1040 sugen(n, nodrat, w); 1041 break; 1042 } 1043 if(nn->op != OIND) { 1044 nn = new1(OADDR, nn, Z); 1045 nn->type = types[TIND]; 1046 nn->addable = 0; 1047 } else 1048 nn = nn->left; 1049 n = new(OFUNC, n->left, new(OLIST, nn, n->right)); 1050 n->type = types[TVOID]; 1051 n->left->type = types[TVOID]; 1052 cgen(n, Z); 1053 break; 1054 1055 case OCOND: 1056 bcgen(n->left, 1); 1057 p1 = p; 1058 sugen(n->right->left, nn, w); 1059 gbranch(OGOTO); 1060 patch(p1, pc); 1061 p1 = p; 1062 sugen(n->right->right, nn, w); 1063 patch(p1, pc); 1064 break; 1065 1066 case OCOMMA: 1067 cgen(n->left, Z); 1068 sugen(n->right, nn, w); 1069 break; 1070 } 1071 return; 1072 1073 copy: 1074 if(nn == Z) 1075 return; 1076 if(n->complex >= FNX && nn->complex >= FNX) { 1077 t = nn->type; 1078 nn->type = types[TLONG]; 1079 regialloc(&nod1, nn, Z); 1080 lcgen(nn, &nod1); 1081 regsalloc(&nod2, nn); 1082 nn->type = t; 1083 1084 gopcode(OAS, &nod1, Z, &nod2); 1085 regfree(&nod1); 1086 1087 nod2.type = typ(TIND, t); 1088 1089 nod1 = nod2; 1090 nod1.op = OIND; 1091 nod1.left = &nod2; 1092 nod1.right = Z; 1093 nod1.complex = 1; 1094 nod1.type = t; 1095 1096 sugen(n, &nod1, w); 1097 return; 1098 } 1099 1100 w /= SZ_LONG; 1101 if(w <= 2) { 1102 if(n->complex > nn->complex) { 1103 reglpcgen(&nod1, n, 1); 1104 reglpcgen(&nod2, nn, 1); 1105 } else { 1106 reglpcgen(&nod2, nn, 1); 1107 reglpcgen(&nod1, n, 1); 1108 } 1109 regalloc(&nod3, ®node, Z); 1110 regalloc(&nod4, ®node, Z); 1111 nod0 = *nodconst((1<<nod3.reg)|(1<<nod4.reg)); 1112 if(w == 2 && nod1.xoffset == 0) 1113 gmovm(&nod1, &nod0, 0); 1114 else { 1115 gmove(&nod1, &nod3); 1116 if(w == 2) { 1117 nod1.xoffset += SZ_LONG; 1118 gmove(&nod1, &nod4); 1119 } 1120 } 1121 if(w == 2 && nod2.xoffset == 0) 1122 gmovm(&nod0, &nod2, 0); 1123 else { 1124 gmove(&nod3, &nod2); 1125 if(w == 2) { 1126 nod2.xoffset += SZ_LONG; 1127 gmove(&nod4, &nod2); 1128 } 1129 } 1130 regfree(&nod1); 1131 regfree(&nod2); 1132 regfree(&nod3); 1133 regfree(&nod4); 1134 return; 1135 } 1136 1137 if(n->complex > nn->complex) { 1138 reglpcgen(&nod1, n, 0); 1139 reglpcgen(&nod2, nn, 0); 1140 } else { 1141 reglpcgen(&nod2, nn, 0); 1142 reglpcgen(&nod1, n, 0); 1143 } 1144 1145 m = 0; 1146 for(c = 0; c < w && c < 4; c++) { 1147 i = tmpreg(); 1148 if (i == 0) 1149 break; 1150 reg[i]++; 1151 m |= 1<<i; 1152 } 1153 nod4 = *(nodconst(m)); 1154 if(w < 3*c) { 1155 for (; w>c; w-=c) { 1156 gmovm(&nod1, &nod4, 1); 1157 gmovm(&nod4, &nod2, 1); 1158 } 1159 goto out; 1160 } 1161 1162 regalloc(&nod3, ®node, Z); 1163 gopcode(OAS, nodconst(w/c), Z, &nod3); 1164 w %= c; 1165 1166 pc1 = pc; 1167 gmovm(&nod1, &nod4, 1); 1168 gmovm(&nod4, &nod2, 1); 1169 1170 gopcode(OSUB, nodconst(1), Z, &nod3); 1171 gopcode(OEQ, nodconst(0), &nod3, Z); 1172 p->as = ABGT; 1173 patch(p, pc1); 1174 regfree(&nod3); 1175 1176 out: 1177 if (w) { 1178 i = 0; 1179 while (c>w) { 1180 while ((m&(1<<i)) == 0) 1181 i++; 1182 m &= ~(1<<i); 1183 reg[i] = 0; 1184 c--; 1185 i++; 1186 } 1187 nod4.vconst = m; 1188 gmovm(&nod1, &nod4, 0); 1189 gmovm(&nod4, &nod2, 0); 1190 } 1191 i = 0; 1192 do { 1193 while ((m&(1<<i)) == 0) 1194 i++; 1195 reg[i] = 0; 1196 c--; 1197 i++; 1198 } while (c>0); 1199 regfree(&nod1); 1200 regfree(&nod2); 1201 }