github.com/rohankumardubey/syslog-redirector-golang@v0.0.0-20140320174030-4859f03d829a/src/cmd/6c/cgen.c (about) 1 // Inferno utils/6c/cgen.c 2 // http://code.google.com/p/inferno-os/source/browse/utils/6c/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 /* ,x/^(print|prtree)\(/i/\/\/ */ 35 int castup(Type*, Type*); 36 int vaddr(Node *n, int a); 37 38 void 39 cgen(Node *n, Node *nn) 40 { 41 Node *l, *r, *t; 42 Prog *p1; 43 Node nod, nod1, nod2, nod3, nod4; 44 int o, hardleft; 45 int32 v, curs; 46 vlong c; 47 48 if(debug['g']) { 49 prtree(nn, "cgen lhs"); 50 prtree(n, "cgen"); 51 } 52 if(n == Z || n->type == T) 53 return; 54 if(typesu[n->type->etype]) { 55 sugen(n, nn, n->type->width); 56 return; 57 } 58 l = n->left; 59 r = n->right; 60 o = n->op; 61 62 if(n->op == OEXREG || (nn != Z && nn->op == OEXREG)) { 63 gmove(n, nn); 64 return; 65 } 66 67 if(n->addable >= INDEXED) { 68 if(nn == Z) { 69 switch(o) { 70 default: 71 nullwarn(Z, Z); 72 break; 73 case OINDEX: 74 nullwarn(l, r); 75 break; 76 } 77 return; 78 } 79 gmove(n, nn); 80 return; 81 } 82 curs = cursafe; 83 84 if(l->complex >= FNX) 85 if(r != Z && r->complex >= FNX) 86 switch(o) { 87 default: 88 if(cond(o) && typesu[l->type->etype]) 89 break; 90 91 regret(&nod, r); 92 cgen(r, &nod); 93 94 regsalloc(&nod1, r); 95 gmove(&nod, &nod1); 96 97 regfree(&nod); 98 nod = *n; 99 nod.right = &nod1; 100 101 cgen(&nod, nn); 102 return; 103 104 case OFUNC: 105 case OCOMMA: 106 case OANDAND: 107 case OOROR: 108 case OCOND: 109 case ODOT: 110 break; 111 } 112 113 hardleft = l->addable < INDEXED || l->complex >= FNX; 114 switch(o) { 115 default: 116 diag(n, "unknown op in cgen: %O", o); 117 break; 118 119 case ONEG: 120 case OCOM: 121 if(nn == Z) { 122 nullwarn(l, Z); 123 break; 124 } 125 regalloc(&nod, l, nn); 126 cgen(l, &nod); 127 gopcode(o, n->type, Z, &nod); 128 gmove(&nod, nn); 129 regfree(&nod); 130 break; 131 132 case OAS: 133 if(l->op == OBIT) 134 goto bitas; 135 if(!hardleft) { 136 if(nn != Z || r->addable < INDEXED || hardconst(r)) { 137 if(r->complex >= FNX && nn == Z) 138 regret(&nod, r); 139 else 140 regalloc(&nod, r, nn); 141 cgen(r, &nod); 142 gmove(&nod, l); 143 if(nn != Z) 144 gmove(&nod, nn); 145 regfree(&nod); 146 } else 147 gmove(r, l); 148 break; 149 } 150 if(l->complex >= r->complex) { 151 if(l->op == OINDEX && immconst(r)) { 152 gmove(r, l); 153 break; 154 } 155 reglcgen(&nod1, l, Z); 156 if(r->addable >= INDEXED && !hardconst(r)) { 157 gmove(r, &nod1); 158 if(nn != Z) 159 gmove(r, nn); 160 regfree(&nod1); 161 break; 162 } 163 regalloc(&nod, r, nn); 164 cgen(r, &nod); 165 } else { 166 regalloc(&nod, r, nn); 167 cgen(r, &nod); 168 reglcgen(&nod1, l, Z); 169 } 170 gmove(&nod, &nod1); 171 regfree(&nod); 172 regfree(&nod1); 173 break; 174 175 bitas: 176 n = l->left; 177 regalloc(&nod, r, nn); 178 if(l->complex >= r->complex) { 179 reglcgen(&nod1, n, Z); 180 cgen(r, &nod); 181 } else { 182 cgen(r, &nod); 183 reglcgen(&nod1, n, Z); 184 } 185 regalloc(&nod2, n, Z); 186 gmove(&nod1, &nod2); 187 bitstore(l, &nod, &nod1, &nod2, nn); 188 break; 189 190 case OBIT: 191 if(nn == Z) { 192 nullwarn(l, Z); 193 break; 194 } 195 bitload(n, &nod, Z, Z, nn); 196 gmove(&nod, nn); 197 regfree(&nod); 198 break; 199 200 case OLSHR: 201 case OASHL: 202 case OASHR: 203 if(nn == Z) { 204 nullwarn(l, r); 205 break; 206 } 207 if(r->op == OCONST) { 208 if(r->vconst == 0) { 209 cgen(l, nn); 210 break; 211 } 212 regalloc(&nod, l, nn); 213 cgen(l, &nod); 214 if(o == OASHL && r->vconst == 1) 215 gopcode(OADD, n->type, &nod, &nod); 216 else 217 gopcode(o, n->type, r, &nod); 218 gmove(&nod, nn); 219 regfree(&nod); 220 break; 221 } 222 223 /* 224 * get nod to be D_CX 225 */ 226 if(nodreg(&nod, nn, D_CX)) { 227 regsalloc(&nod1, n); 228 gmove(&nod, &nod1); 229 cgen(n, &nod); /* probably a bug */ 230 gmove(&nod, nn); 231 gmove(&nod1, &nod); 232 break; 233 } 234 reg[D_CX]++; 235 if(nn->op == OREGISTER && nn->reg == D_CX) 236 regalloc(&nod1, l, Z); 237 else 238 regalloc(&nod1, l, nn); 239 if(r->complex >= l->complex) { 240 cgen(r, &nod); 241 cgen(l, &nod1); 242 } else { 243 cgen(l, &nod1); 244 cgen(r, &nod); 245 } 246 gopcode(o, n->type, &nod, &nod1); 247 gmove(&nod1, nn); 248 regfree(&nod); 249 regfree(&nod1); 250 break; 251 252 case OADD: 253 case OSUB: 254 case OOR: 255 case OXOR: 256 case OAND: 257 if(nn == Z) { 258 nullwarn(l, r); 259 break; 260 } 261 if(typefd[n->type->etype]) 262 goto fop; 263 if(r->op == OCONST) { 264 if(r->vconst == 0 && o != OAND) { 265 cgen(l, nn); 266 break; 267 } 268 } 269 if(n->op == OOR && l->op == OASHL && r->op == OLSHR 270 && l->right->op == OCONST && r->right->op == OCONST 271 && l->left->op == ONAME && r->left->op == ONAME 272 && l->left->sym == r->left->sym 273 && l->right->vconst + r->right->vconst == 8 * l->left->type->width) { 274 regalloc(&nod, l->left, nn); 275 cgen(l->left, &nod); 276 gopcode(OROTL, n->type, l->right, &nod); 277 gmove(&nod, nn); 278 regfree(&nod); 279 break; 280 } 281 if(n->op == OADD && l->op == OASHL && l->right->op == OCONST 282 && (r->op != OCONST || r->vconst < -128 || r->vconst > 127)) { 283 c = l->right->vconst; 284 if(c > 0 && c <= 3) { 285 if(l->left->complex >= r->complex) { 286 regalloc(&nod, l->left, nn); 287 cgen(l->left, &nod); 288 if(r->addable < INDEXED) { 289 regalloc(&nod1, r, Z); 290 cgen(r, &nod1); 291 genmuladd(&nod, &nod, 1 << c, &nod1); 292 regfree(&nod1); 293 } 294 else 295 genmuladd(&nod, &nod, 1 << c, r); 296 } 297 else { 298 regalloc(&nod, r, nn); 299 cgen(r, &nod); 300 regalloc(&nod1, l->left, Z); 301 cgen(l->left, &nod1); 302 genmuladd(&nod, &nod1, 1 << c, &nod); 303 regfree(&nod1); 304 } 305 gmove(&nod, nn); 306 regfree(&nod); 307 break; 308 } 309 } 310 if(r->addable >= INDEXED && !hardconst(r)) { 311 regalloc(&nod, l, nn); 312 cgen(l, &nod); 313 gopcode(o, n->type, r, &nod); 314 gmove(&nod, nn); 315 regfree(&nod); 316 break; 317 } 318 if(l->complex >= r->complex) { 319 regalloc(&nod, l, nn); 320 cgen(l, &nod); 321 regalloc(&nod1, r, Z); 322 cgen(r, &nod1); 323 gopcode(o, n->type, &nod1, &nod); 324 } else { 325 regalloc(&nod1, r, nn); 326 cgen(r, &nod1); 327 regalloc(&nod, l, Z); 328 cgen(l, &nod); 329 gopcode(o, n->type, &nod1, &nod); 330 } 331 gmove(&nod, nn); 332 regfree(&nod); 333 regfree(&nod1); 334 break; 335 336 case OLMOD: 337 case OMOD: 338 case OLMUL: 339 case OLDIV: 340 case OMUL: 341 case ODIV: 342 if(nn == Z) { 343 nullwarn(l, r); 344 break; 345 } 346 if(typefd[n->type->etype]) 347 goto fop; 348 if(r->op == OCONST && typechl[n->type->etype]) { /* TO DO */ 349 SET(v); 350 switch(o) { 351 case ODIV: 352 case OMOD: 353 c = r->vconst; 354 if(c < 0) 355 c = -c; 356 v = xlog2(c); 357 if(v < 0) 358 break; 359 /* fall thru */ 360 case OMUL: 361 case OLMUL: 362 regalloc(&nod, l, nn); 363 cgen(l, &nod); 364 switch(o) { 365 case OMUL: 366 case OLMUL: 367 mulgen(n->type, r, &nod); 368 break; 369 case ODIV: 370 sdiv2(r->vconst, v, l, &nod); 371 break; 372 case OMOD: 373 smod2(r->vconst, v, l, &nod); 374 break; 375 } 376 gmove(&nod, nn); 377 regfree(&nod); 378 goto done; 379 case OLDIV: 380 c = r->vconst; 381 if((c & 0x80000000) == 0) 382 break; 383 regalloc(&nod1, l, Z); 384 cgen(l, &nod1); 385 regalloc(&nod, l, nn); 386 zeroregm(&nod); 387 gins(ACMPL, &nod1, nodconst(c)); 388 gins(ASBBL, nodconst(-1), &nod); 389 regfree(&nod1); 390 gmove(&nod, nn); 391 regfree(&nod); 392 goto done; 393 } 394 } 395 396 if(o == OMUL || o == OLMUL) { 397 if(l->addable >= INDEXED) { 398 t = l; 399 l = r; 400 r = t; 401 } 402 reg[D_DX]++; // for gopcode case OMUL 403 regalloc(&nod, l, nn); 404 cgen(l, &nod); 405 if(r->addable < INDEXED || hardconst(r)) { 406 regalloc(&nod1, r, Z); 407 cgen(r, &nod1); 408 gopcode(OMUL, n->type, &nod1, &nod); 409 regfree(&nod1); 410 }else 411 gopcode(OMUL, n->type, r, &nod); /* addressible */ 412 gmove(&nod, nn); 413 regfree(&nod); 414 reg[D_DX]--; 415 break; 416 } 417 418 /* 419 * get nod to be D_AX 420 * get nod1 to be D_DX 421 */ 422 if(nodreg(&nod, nn, D_AX)) { 423 regsalloc(&nod2, n); 424 gmove(&nod, &nod2); 425 v = reg[D_AX]; 426 reg[D_AX] = 0; 427 428 if(isreg(l, D_AX)) { 429 nod3 = *n; 430 nod3.left = &nod2; 431 cgen(&nod3, nn); 432 } else 433 if(isreg(r, D_AX)) { 434 nod3 = *n; 435 nod3.right = &nod2; 436 cgen(&nod3, nn); 437 } else 438 cgen(n, nn); 439 440 gmove(&nod2, &nod); 441 reg[D_AX] = v; 442 break; 443 } 444 if(nodreg(&nod1, nn, D_DX)) { 445 regsalloc(&nod2, n); 446 gmove(&nod1, &nod2); 447 v = reg[D_DX]; 448 reg[D_DX] = 0; 449 450 if(isreg(l, D_DX)) { 451 nod3 = *n; 452 nod3.left = &nod2; 453 cgen(&nod3, nn); 454 } else 455 if(isreg(r, D_DX)) { 456 nod3 = *n; 457 nod3.right = &nod2; 458 cgen(&nod3, nn); 459 } else 460 cgen(n, nn); 461 462 gmove(&nod2, &nod1); 463 reg[D_DX] = v; 464 break; 465 } 466 reg[D_AX]++; 467 468 if(r->op == OCONST && (o == ODIV || o == OLDIV) && immconst(r) && typechl[r->type->etype]) { 469 reg[D_DX]++; 470 if(l->addable < INDEXED) { 471 regalloc(&nod2, l, Z); 472 cgen(l, &nod2); 473 l = &nod2; 474 } 475 if(o == ODIV) 476 sdivgen(l, r, &nod, &nod1); 477 else 478 udivgen(l, r, &nod, &nod1); 479 gmove(&nod1, nn); 480 if(l == &nod2) 481 regfree(l); 482 goto freeaxdx; 483 } 484 485 if(l->complex >= r->complex) { 486 cgen(l, &nod); 487 reg[D_DX]++; 488 if(o == ODIV || o == OMOD) 489 gins(typechl[l->type->etype]? ACDQ: ACQO, Z, Z); 490 if(o == OLDIV || o == OLMOD) 491 zeroregm(&nod1); 492 if(r->addable < INDEXED || r->op == OCONST) { 493 regsalloc(&nod3, r); 494 cgen(r, &nod3); 495 gopcode(o, n->type, &nod3, Z); 496 } else 497 gopcode(o, n->type, r, Z); 498 } else { 499 regsalloc(&nod3, r); 500 cgen(r, &nod3); 501 cgen(l, &nod); 502 reg[D_DX]++; 503 if(o == ODIV || o == OMOD) 504 gins(typechl[l->type->etype]? ACDQ: ACQO, Z, Z); 505 if(o == OLDIV || o == OLMOD) 506 zeroregm(&nod1); 507 gopcode(o, n->type, &nod3, Z); 508 } 509 if(o == OMOD || o == OLMOD) 510 gmove(&nod1, nn); 511 else 512 gmove(&nod, nn); 513 freeaxdx: 514 regfree(&nod); 515 regfree(&nod1); 516 break; 517 518 case OASLSHR: 519 case OASASHL: 520 case OASASHR: 521 if(r->op == OCONST) 522 goto asand; 523 if(l->op == OBIT) 524 goto asbitop; 525 if(typefd[n->type->etype]) 526 goto asand; /* can this happen? */ 527 528 /* 529 * get nod to be D_CX 530 */ 531 if(nodreg(&nod, nn, D_CX)) { 532 regsalloc(&nod1, n); 533 gmove(&nod, &nod1); 534 cgen(n, &nod); 535 if(nn != Z) 536 gmove(&nod, nn); 537 gmove(&nod1, &nod); 538 break; 539 } 540 reg[D_CX]++; 541 542 if(r->complex >= l->complex) { 543 cgen(r, &nod); 544 if(hardleft) 545 reglcgen(&nod1, l, Z); 546 else 547 nod1 = *l; 548 } else { 549 if(hardleft) 550 reglcgen(&nod1, l, Z); 551 else 552 nod1 = *l; 553 cgen(r, &nod); 554 } 555 556 gopcode(o, l->type, &nod, &nod1); 557 regfree(&nod); 558 if(nn != Z) 559 gmove(&nod1, nn); 560 if(hardleft) 561 regfree(&nod1); 562 break; 563 564 case OASAND: 565 case OASADD: 566 case OASSUB: 567 case OASXOR: 568 case OASOR: 569 asand: 570 if(l->op == OBIT) 571 goto asbitop; 572 if(typefd[l->type->etype] || typefd[r->type->etype]) 573 goto asfop; 574 if(l->complex >= r->complex) { 575 if(hardleft) 576 reglcgen(&nod, l, Z); 577 else 578 nod = *l; 579 if(!immconst(r)) { 580 regalloc(&nod1, r, nn); 581 cgen(r, &nod1); 582 gopcode(o, l->type, &nod1, &nod); 583 regfree(&nod1); 584 } else 585 gopcode(o, l->type, r, &nod); 586 } else { 587 regalloc(&nod1, r, nn); 588 cgen(r, &nod1); 589 if(hardleft) 590 reglcgen(&nod, l, Z); 591 else 592 nod = *l; 593 gopcode(o, l->type, &nod1, &nod); 594 regfree(&nod1); 595 } 596 if(nn != Z) 597 gmove(&nod, nn); 598 if(hardleft) 599 regfree(&nod); 600 break; 601 602 asfop: 603 if(l->complex >= r->complex) { 604 if(hardleft) 605 reglcgen(&nod, l, Z); 606 else 607 nod = *l; 608 if(r->addable < INDEXED){ 609 regalloc(&nod1, r, nn); 610 cgen(r, &nod1); 611 }else 612 nod1 = *r; 613 regalloc(&nod2, r, Z); 614 gmove(&nod, &nod2); 615 gopcode(o, r->type, &nod1, &nod2); 616 gmove(&nod2, &nod); 617 regfree(&nod2); 618 if(r->addable < INDEXED) 619 regfree(&nod1); 620 } else { 621 regalloc(&nod1, r, nn); 622 cgen(r, &nod1); 623 if(hardleft) 624 reglcgen(&nod, l, Z); 625 else 626 nod = *l; 627 if(o != OASMUL && o != OASADD) { 628 regalloc(&nod2, r, Z); 629 gmove(&nod, &nod2); 630 gopcode(o, r->type, &nod1, &nod2); 631 regfree(&nod1); 632 gmove(&nod2, &nod); 633 regfree(&nod2); 634 } else { 635 gopcode(o, r->type, &nod, &nod1); 636 gmove(&nod1, &nod); 637 regfree(&nod1); 638 } 639 } 640 if(nn != Z) 641 gmove(&nod, nn); 642 if(hardleft) 643 regfree(&nod); 644 break; 645 646 case OASLMUL: 647 case OASLDIV: 648 case OASLMOD: 649 case OASMUL: 650 case OASDIV: 651 case OASMOD: 652 if(l->op == OBIT) 653 goto asbitop; 654 if(typefd[n->type->etype] || typefd[r->type->etype]) 655 goto asfop; 656 if(r->op == OCONST && typechl[n->type->etype]) { 657 SET(v); 658 switch(o) { 659 case OASDIV: 660 case OASMOD: 661 c = r->vconst; 662 if(c < 0) 663 c = -c; 664 v = xlog2(c); 665 if(v < 0) 666 break; 667 /* fall thru */ 668 case OASMUL: 669 case OASLMUL: 670 if(hardleft) 671 reglcgen(&nod2, l, Z); 672 else 673 nod2 = *l; 674 regalloc(&nod, l, nn); 675 cgen(&nod2, &nod); 676 switch(o) { 677 case OASMUL: 678 case OASLMUL: 679 mulgen(n->type, r, &nod); 680 break; 681 case OASDIV: 682 sdiv2(r->vconst, v, l, &nod); 683 break; 684 case OASMOD: 685 smod2(r->vconst, v, l, &nod); 686 break; 687 } 688 havev: 689 gmove(&nod, &nod2); 690 if(nn != Z) 691 gmove(&nod, nn); 692 if(hardleft) 693 regfree(&nod2); 694 regfree(&nod); 695 goto done; 696 case OASLDIV: 697 c = r->vconst; 698 if((c & 0x80000000) == 0) 699 break; 700 if(hardleft) 701 reglcgen(&nod2, l, Z); 702 else 703 nod2 = *l; 704 regalloc(&nod1, l, nn); 705 cgen(&nod2, &nod1); 706 regalloc(&nod, l, nn); 707 zeroregm(&nod); 708 gins(ACMPL, &nod1, nodconst(c)); 709 gins(ASBBL, nodconst(-1), &nod); 710 regfree(&nod1); 711 goto havev; 712 } 713 } 714 715 if(o == OASMUL) { 716 /* should favour AX */ 717 regalloc(&nod, l, nn); 718 if(r->complex >= FNX) { 719 regalloc(&nod1, r, Z); 720 cgen(r, &nod1); 721 r = &nod1; 722 } 723 if(hardleft) 724 reglcgen(&nod2, l, Z); 725 else 726 nod2 = *l; 727 cgen(&nod2, &nod); 728 if(r->addable < INDEXED || hardconst(r)) { 729 if(r->complex < FNX) { 730 regalloc(&nod1, r, Z); 731 cgen(r, &nod1); 732 } 733 gopcode(OASMUL, n->type, &nod1, &nod); 734 regfree(&nod1); 735 } 736 else 737 gopcode(OASMUL, n->type, r, &nod); 738 if(r == &nod1) 739 regfree(r); 740 gmove(&nod, &nod2); 741 if(nn != Z) 742 gmove(&nod, nn); 743 regfree(&nod); 744 if(hardleft) 745 regfree(&nod2); 746 break; 747 } 748 749 /* 750 * get nod to be D_AX 751 * get nod1 to be D_DX 752 */ 753 if(nodreg(&nod, nn, D_AX)) { 754 regsalloc(&nod2, n); 755 gmove(&nod, &nod2); 756 v = reg[D_AX]; 757 reg[D_AX] = 0; 758 759 if(isreg(l, D_AX)) { 760 nod3 = *n; 761 nod3.left = &nod2; 762 cgen(&nod3, nn); 763 } else 764 if(isreg(r, D_AX)) { 765 nod3 = *n; 766 nod3.right = &nod2; 767 cgen(&nod3, nn); 768 } else 769 cgen(n, nn); 770 771 gmove(&nod2, &nod); 772 reg[D_AX] = v; 773 break; 774 } 775 if(nodreg(&nod1, nn, D_DX)) { 776 regsalloc(&nod2, n); 777 gmove(&nod1, &nod2); 778 v = reg[D_DX]; 779 reg[D_DX] = 0; 780 781 if(isreg(l, D_DX)) { 782 nod3 = *n; 783 nod3.left = &nod2; 784 cgen(&nod3, nn); 785 } else 786 if(isreg(r, D_DX)) { 787 nod3 = *n; 788 nod3.right = &nod2; 789 cgen(&nod3, nn); 790 } else 791 cgen(n, nn); 792 793 gmove(&nod2, &nod1); 794 reg[D_DX] = v; 795 break; 796 } 797 reg[D_AX]++; 798 reg[D_DX]++; 799 800 if(l->complex >= r->complex) { 801 if(hardleft) 802 reglcgen(&nod2, l, Z); 803 else 804 nod2 = *l; 805 cgen(&nod2, &nod); 806 if(r->op == OCONST && typechl[r->type->etype]) { 807 switch(o) { 808 case OASDIV: 809 sdivgen(&nod2, r, &nod, &nod1); 810 goto divdone; 811 case OASLDIV: 812 udivgen(&nod2, r, &nod, &nod1); 813 divdone: 814 gmove(&nod1, &nod2); 815 if(nn != Z) 816 gmove(&nod1, nn); 817 goto freelxaxdx; 818 } 819 } 820 if(o == OASDIV || o == OASMOD) 821 gins(typechl[l->type->etype]? ACDQ: ACQO, Z, Z); 822 if(o == OASLDIV || o == OASLMOD) 823 zeroregm(&nod1); 824 if(r->addable < INDEXED || r->op == OCONST || 825 !typeil[r->type->etype]) { 826 regalloc(&nod3, r, Z); 827 cgen(r, &nod3); 828 gopcode(o, l->type, &nod3, Z); 829 regfree(&nod3); 830 } else 831 gopcode(o, n->type, r, Z); 832 } else { 833 regalloc(&nod3, r, Z); 834 cgen(r, &nod3); 835 if(hardleft) 836 reglcgen(&nod2, l, Z); 837 else 838 nod2 = *l; 839 cgen(&nod2, &nod); 840 if(o == OASDIV || o == OASMOD) 841 gins(typechl[l->type->etype]? ACDQ: ACQO, Z, Z); 842 if(o == OASLDIV || o == OASLMOD) 843 zeroregm(&nod1); 844 gopcode(o, l->type, &nod3, Z); 845 regfree(&nod3); 846 } 847 if(o == OASMOD || o == OASLMOD) { 848 gmove(&nod1, &nod2); 849 if(nn != Z) 850 gmove(&nod1, nn); 851 } else { 852 gmove(&nod, &nod2); 853 if(nn != Z) 854 gmove(&nod, nn); 855 } 856 freelxaxdx: 857 if(hardleft) 858 regfree(&nod2); 859 regfree(&nod); 860 regfree(&nod1); 861 break; 862 863 fop: 864 if(l->complex >= r->complex) { 865 regalloc(&nod, l, nn); 866 cgen(l, &nod); 867 if(r->addable < INDEXED) { 868 regalloc(&nod1, r, Z); 869 cgen(r, &nod1); 870 gopcode(o, n->type, &nod1, &nod); 871 regfree(&nod1); 872 } else 873 gopcode(o, n->type, r, &nod); 874 } else { 875 /* TO DO: could do better with r->addable >= INDEXED */ 876 regalloc(&nod1, r, Z); 877 cgen(r, &nod1); 878 regalloc(&nod, l, nn); 879 cgen(l, &nod); 880 gopcode(o, n->type, &nod1, &nod); 881 regfree(&nod1); 882 } 883 gmove(&nod, nn); 884 regfree(&nod); 885 break; 886 887 asbitop: 888 regalloc(&nod4, n, nn); 889 if(l->complex >= r->complex) { 890 bitload(l, &nod, &nod1, &nod2, &nod4); 891 regalloc(&nod3, r, Z); 892 cgen(r, &nod3); 893 } else { 894 regalloc(&nod3, r, Z); 895 cgen(r, &nod3); 896 bitload(l, &nod, &nod1, &nod2, &nod4); 897 } 898 gmove(&nod, &nod4); 899 900 { /* TO DO: check floating point source */ 901 Node onod; 902 903 /* incredible grot ... */ 904 onod = nod3; 905 onod.op = o; 906 onod.complex = 2; 907 onod.addable = 0; 908 onod.type = tfield; 909 onod.left = &nod4; 910 onod.right = &nod3; 911 cgen(&onod, Z); 912 } 913 regfree(&nod3); 914 gmove(&nod4, &nod); 915 regfree(&nod4); 916 bitstore(l, &nod, &nod1, &nod2, nn); 917 break; 918 919 case OADDR: 920 if(nn == Z) { 921 nullwarn(l, Z); 922 break; 923 } 924 lcgen(l, nn); 925 break; 926 927 case OFUNC: 928 if(l->complex >= FNX) { 929 if(l->op != OIND) 930 diag(n, "bad function call"); 931 932 regret(&nod, l->left); 933 cgen(l->left, &nod); 934 regsalloc(&nod1, l->left); 935 gmove(&nod, &nod1); 936 regfree(&nod); 937 938 nod = *n; 939 nod.left = &nod2; 940 nod2 = *l; 941 nod2.left = &nod1; 942 nod2.complex = 1; 943 cgen(&nod, nn); 944 945 return; 946 } 947 gargs(r, &nod, &nod1); 948 gpcdata(PCDATA_ArgSize, curarg); 949 if(l->addable < INDEXED) { 950 reglcgen(&nod, l, nn); 951 nod.op = OREGISTER; 952 gopcode(OFUNC, n->type, Z, &nod); 953 regfree(&nod); 954 } else 955 gopcode(OFUNC, n->type, Z, l); 956 gpcdata(PCDATA_ArgSize, -1); 957 if(REGARG >= 0 && reg[REGARG]) 958 reg[REGARG]--; 959 if(nn != Z) { 960 regret(&nod, n); 961 gmove(&nod, nn); 962 regfree(&nod); 963 } 964 break; 965 966 case OIND: 967 if(nn == Z) { 968 nullwarn(l, Z); 969 break; 970 } 971 regialloc(&nod, n, nn); 972 r = l; 973 while(r->op == OADD) 974 r = r->right; 975 if(sconst(r)) { 976 v = r->vconst; 977 r->vconst = 0; 978 cgen(l, &nod); 979 nod.xoffset += v; 980 r->vconst = v; 981 } else 982 cgen(l, &nod); 983 regind(&nod, n); 984 gmove(&nod, nn); 985 regfree(&nod); 986 break; 987 988 case OEQ: 989 case ONE: 990 case OLE: 991 case OLT: 992 case OGE: 993 case OGT: 994 case OLO: 995 case OLS: 996 case OHI: 997 case OHS: 998 if(nn == Z) { 999 nullwarn(l, r); 1000 break; 1001 } 1002 boolgen(n, 1, nn); 1003 break; 1004 1005 case OANDAND: 1006 case OOROR: 1007 boolgen(n, 1, nn); 1008 if(nn == Z) 1009 patch(p, pc); 1010 break; 1011 1012 case ONOT: 1013 if(nn == Z) { 1014 nullwarn(l, Z); 1015 break; 1016 } 1017 boolgen(n, 1, nn); 1018 break; 1019 1020 case OCOMMA: 1021 cgen(l, Z); 1022 cgen(r, nn); 1023 break; 1024 1025 case OCAST: 1026 if(nn == Z) { 1027 nullwarn(l, Z); 1028 break; 1029 } 1030 /* 1031 * convert from types l->n->nn 1032 */ 1033 if(nocast(l->type, n->type) && nocast(n->type, nn->type)) { 1034 /* both null, gen l->nn */ 1035 cgen(l, nn); 1036 break; 1037 } 1038 if(ewidth[n->type->etype] < ewidth[l->type->etype]){ 1039 if(l->type->etype == TIND && typechlp[n->type->etype]) 1040 warn(n, "conversion of pointer to shorter integer"); 1041 }else if(0){ 1042 if(nocast(n->type, nn->type) || castup(n->type, nn->type)){ 1043 if(typefd[l->type->etype] != typefd[nn->type->etype]) 1044 regalloc(&nod, l, nn); 1045 else 1046 regalloc(&nod, nn, nn); 1047 cgen(l, &nod); 1048 gmove(&nod, nn); 1049 regfree(&nod); 1050 break; 1051 } 1052 } 1053 regalloc(&nod, l, nn); 1054 cgen(l, &nod); 1055 regalloc(&nod1, n, &nod); 1056 gmove(&nod, &nod1); 1057 gmove(&nod1, nn); 1058 regfree(&nod1); 1059 regfree(&nod); 1060 break; 1061 1062 case ODOT: 1063 sugen(l, nodrat, l->type->width); 1064 if(nn == Z) 1065 break; 1066 warn(n, "non-interruptable temporary"); 1067 nod = *nodrat; 1068 if(!r || r->op != OCONST) { 1069 diag(n, "DOT and no offset"); 1070 break; 1071 } 1072 nod.xoffset += (int32)r->vconst; 1073 nod.type = n->type; 1074 cgen(&nod, nn); 1075 break; 1076 1077 case OCOND: 1078 bcgen(l, 1); 1079 p1 = p; 1080 cgen(r->left, nn); 1081 gbranch(OGOTO); 1082 patch(p1, pc); 1083 p1 = p; 1084 cgen(r->right, nn); 1085 patch(p1, pc); 1086 break; 1087 1088 case OPOSTINC: 1089 case OPOSTDEC: 1090 v = 1; 1091 if(l->type->etype == TIND) 1092 v = l->type->link->width; 1093 if(o == OPOSTDEC) 1094 v = -v; 1095 if(l->op == OBIT) 1096 goto bitinc; 1097 if(nn == Z) 1098 goto pre; 1099 1100 if(hardleft) 1101 reglcgen(&nod, l, Z); 1102 else 1103 nod = *l; 1104 1105 gmove(&nod, nn); 1106 if(typefd[n->type->etype]) { 1107 regalloc(&nod1, l, Z); 1108 gmove(&nod, &nod1); 1109 if(v < 0) 1110 gopcode(OSUB, n->type, nodfconst(-v), &nod1); 1111 else 1112 gopcode(OADD, n->type, nodfconst(v), &nod1); 1113 gmove(&nod1, &nod); 1114 regfree(&nod1); 1115 } else 1116 gopcode(OADD, n->type, nodconst(v), &nod); 1117 if(hardleft) 1118 regfree(&nod); 1119 break; 1120 1121 case OPREINC: 1122 case OPREDEC: 1123 v = 1; 1124 if(l->type->etype == TIND) 1125 v = l->type->link->width; 1126 if(o == OPREDEC) 1127 v = -v; 1128 if(l->op == OBIT) 1129 goto bitinc; 1130 1131 pre: 1132 if(hardleft) 1133 reglcgen(&nod, l, Z); 1134 else 1135 nod = *l; 1136 if(typefd[n->type->etype]) { 1137 regalloc(&nod1, l, Z); 1138 gmove(&nod, &nod1); 1139 if(v < 0) 1140 gopcode(OSUB, n->type, nodfconst(-v), &nod1); 1141 else 1142 gopcode(OADD, n->type, nodfconst(v), &nod1); 1143 gmove(&nod1, &nod); 1144 regfree(&nod1); 1145 } else 1146 gopcode(OADD, n->type, nodconst(v), &nod); 1147 if(nn != Z) 1148 gmove(&nod, nn); 1149 if(hardleft) 1150 regfree(&nod); 1151 break; 1152 1153 bitinc: 1154 if(nn != Z && (o == OPOSTINC || o == OPOSTDEC)) { 1155 bitload(l, &nod, &nod1, &nod2, Z); 1156 gmove(&nod, nn); 1157 gopcode(OADD, tfield, nodconst(v), &nod); 1158 bitstore(l, &nod, &nod1, &nod2, Z); 1159 break; 1160 } 1161 bitload(l, &nod, &nod1, &nod2, nn); 1162 gopcode(OADD, tfield, nodconst(v), &nod); 1163 bitstore(l, &nod, &nod1, &nod2, nn); 1164 break; 1165 } 1166 done: 1167 cursafe = curs; 1168 } 1169 1170 void 1171 reglcgen(Node *t, Node *n, Node *nn) 1172 { 1173 Node *r; 1174 int32 v; 1175 1176 regialloc(t, n, nn); 1177 if(n->op == OIND) { 1178 r = n->left; 1179 while(r->op == OADD) 1180 r = r->right; 1181 if(sconst(r)) { 1182 v = r->vconst; 1183 r->vconst = 0; 1184 lcgen(n, t); 1185 t->xoffset += v; 1186 r->vconst = v; 1187 regind(t, n); 1188 return; 1189 } 1190 } 1191 lcgen(n, t); 1192 regind(t, n); 1193 } 1194 1195 void 1196 lcgen(Node *n, Node *nn) 1197 { 1198 Prog *p1; 1199 Node nod; 1200 1201 if(debug['g']) { 1202 prtree(nn, "lcgen lhs"); 1203 prtree(n, "lcgen"); 1204 } 1205 if(n == Z || n->type == T) 1206 return; 1207 if(nn == Z) { 1208 nn = &nod; 1209 regalloc(&nod, n, Z); 1210 } 1211 switch(n->op) { 1212 default: 1213 if(n->addable < INDEXED) { 1214 diag(n, "unknown op in lcgen: %O", n->op); 1215 break; 1216 } 1217 gopcode(OADDR, n->type, n, nn); 1218 break; 1219 1220 case OCOMMA: 1221 cgen(n->left, n->left); 1222 lcgen(n->right, nn); 1223 break; 1224 1225 case OIND: 1226 cgen(n->left, nn); 1227 break; 1228 1229 case OCOND: 1230 bcgen(n->left, 1); 1231 p1 = p; 1232 lcgen(n->right->left, nn); 1233 gbranch(OGOTO); 1234 patch(p1, pc); 1235 p1 = p; 1236 lcgen(n->right->right, nn); 1237 patch(p1, pc); 1238 break; 1239 } 1240 } 1241 1242 void 1243 bcgen(Node *n, int true) 1244 { 1245 1246 if(n->type == T) 1247 gbranch(OGOTO); 1248 else 1249 boolgen(n, true, Z); 1250 } 1251 1252 void 1253 boolgen(Node *n, int true, Node *nn) 1254 { 1255 int o; 1256 Prog *p1, *p2, *p3; 1257 Node *l, *r, nod, nod1; 1258 int32 curs; 1259 1260 if(debug['g']) { 1261 print("boolgen %d\n", true); 1262 prtree(nn, "boolgen lhs"); 1263 prtree(n, "boolgen"); 1264 } 1265 curs = cursafe; 1266 l = n->left; 1267 r = n->right; 1268 switch(n->op) { 1269 1270 default: 1271 o = ONE; 1272 if(true) 1273 o = OEQ; 1274 /* bad, 13 is address of external that becomes constant */ 1275 if(n->addable >= INDEXED && n->addable != 13) { 1276 if(typefd[n->type->etype]) { 1277 regalloc(&nod1, n, Z); 1278 gmove(nodfconst(0.0), &nod1); /* TO DO: FREGZERO */ 1279 gopcode(o, n->type, n, &nod1); 1280 regfree(&nod1); 1281 } else 1282 gopcode(o, n->type, n, nodconst(0)); 1283 goto com; 1284 } 1285 regalloc(&nod, n, nn); 1286 cgen(n, &nod); 1287 if(typefd[n->type->etype]) { 1288 regalloc(&nod1, n, Z); 1289 gmove(nodfconst(0.0), &nod1); /* TO DO: FREGZERO */ 1290 gopcode(o, n->type, &nod, &nod1); 1291 regfree(&nod1); 1292 } else 1293 gopcode(o, n->type, &nod, nodconst(0)); 1294 regfree(&nod); 1295 goto com; 1296 1297 case OCONST: 1298 o = vconst(n); 1299 if(!true) 1300 o = !o; 1301 gbranch(OGOTO); 1302 if(o) { 1303 p1 = p; 1304 gbranch(OGOTO); 1305 patch(p1, pc); 1306 } 1307 goto com; 1308 1309 case OCOMMA: 1310 cgen(l, Z); 1311 boolgen(r, true, nn); 1312 break; 1313 1314 case ONOT: 1315 boolgen(l, !true, nn); 1316 break; 1317 1318 case OCOND: 1319 bcgen(l, 1); 1320 p1 = p; 1321 bcgen(r->left, true); 1322 p2 = p; 1323 gbranch(OGOTO); 1324 patch(p1, pc); 1325 p1 = p; 1326 bcgen(r->right, !true); 1327 patch(p2, pc); 1328 p2 = p; 1329 gbranch(OGOTO); 1330 patch(p1, pc); 1331 patch(p2, pc); 1332 goto com; 1333 1334 case OANDAND: 1335 if(!true) 1336 goto caseor; 1337 1338 caseand: 1339 bcgen(l, true); 1340 p1 = p; 1341 bcgen(r, !true); 1342 p2 = p; 1343 patch(p1, pc); 1344 gbranch(OGOTO); 1345 patch(p2, pc); 1346 goto com; 1347 1348 case OOROR: 1349 if(!true) 1350 goto caseand; 1351 1352 caseor: 1353 bcgen(l, !true); 1354 p1 = p; 1355 bcgen(r, !true); 1356 p2 = p; 1357 gbranch(OGOTO); 1358 patch(p1, pc); 1359 patch(p2, pc); 1360 goto com; 1361 1362 case OEQ: 1363 case ONE: 1364 case OLE: 1365 case OLT: 1366 case OGE: 1367 case OGT: 1368 case OHI: 1369 case OHS: 1370 case OLO: 1371 case OLS: 1372 o = n->op; 1373 if(true && typefd[l->type->etype] && (o == OEQ || o == ONE)) { 1374 // Cannot rewrite !(l == r) into l != r with float64; it breaks NaNs. 1375 // Jump around instead. 1376 boolgen(n, 0, Z); 1377 p1 = p; 1378 gbranch(OGOTO); 1379 patch(p1, pc); 1380 goto com; 1381 } 1382 if(true) 1383 o = comrel[relindex(o)]; 1384 if(l->complex >= FNX && r->complex >= FNX) { 1385 regret(&nod, r); 1386 cgen(r, &nod); 1387 regsalloc(&nod1, r); 1388 gmove(&nod, &nod1); 1389 regfree(&nod); 1390 nod = *n; 1391 nod.right = &nod1; 1392 boolgen(&nod, true, nn); 1393 break; 1394 } 1395 if(immconst(l)) { 1396 // NOTE: Reversing the comparison here is wrong 1397 // for floating point ordering comparisons involving NaN, 1398 // but we don't have any of those yet so we don't 1399 // bother worrying about it. 1400 o = invrel[relindex(o)]; 1401 /* bad, 13 is address of external that becomes constant */ 1402 if(r->addable < INDEXED || r->addable == 13) { 1403 regalloc(&nod, r, nn); 1404 cgen(r, &nod); 1405 gopcode(o, l->type, &nod, l); 1406 regfree(&nod); 1407 } else 1408 gopcode(o, l->type, r, l); 1409 goto com; 1410 } 1411 if(typefd[l->type->etype]) 1412 o = invrel[relindex(logrel[relindex(o)])]; 1413 if(l->complex >= r->complex) { 1414 regalloc(&nod, l, nn); 1415 cgen(l, &nod); 1416 if(r->addable < INDEXED || hardconst(r) || typefd[l->type->etype]) { 1417 regalloc(&nod1, r, Z); 1418 cgen(r, &nod1); 1419 gopcode(o, l->type, &nod, &nod1); 1420 regfree(&nod1); 1421 } else { 1422 gopcode(o, l->type, &nod, r); 1423 } 1424 regfree(&nod); 1425 goto fixfloat; 1426 } 1427 regalloc(&nod, r, nn); 1428 cgen(r, &nod); 1429 if(l->addable < INDEXED || l->addable == 13 || hardconst(l)) { 1430 regalloc(&nod1, l, Z); 1431 cgen(l, &nod1); 1432 if(typechl[l->type->etype] && ewidth[l->type->etype] <= ewidth[TINT]) 1433 gopcode(o, types[TINT], &nod1, &nod); 1434 else 1435 gopcode(o, l->type, &nod1, &nod); 1436 regfree(&nod1); 1437 } else 1438 gopcode(o, l->type, l, &nod); 1439 regfree(&nod); 1440 fixfloat: 1441 if(typefd[l->type->etype]) { 1442 switch(o) { 1443 case OEQ: 1444 // Already emitted AJEQ; want AJEQ and AJPC. 1445 p1 = p; 1446 gbranch(OGOTO); 1447 p2 = p; 1448 patch(p1, pc); 1449 gins(AJPC, Z, Z); 1450 patch(p2, pc); 1451 break; 1452 1453 case ONE: 1454 // Already emitted AJNE; want AJNE or AJPS. 1455 p1 = p; 1456 gins(AJPS, Z, Z); 1457 p2 = p; 1458 gbranch(OGOTO); 1459 p3 = p; 1460 patch(p1, pc); 1461 patch(p2, pc); 1462 gbranch(OGOTO); 1463 patch(p3, pc); 1464 break; 1465 } 1466 } 1467 1468 com: 1469 if(nn != Z) { 1470 p1 = p; 1471 gmove(nodconst(1L), nn); 1472 gbranch(OGOTO); 1473 p2 = p; 1474 patch(p1, pc); 1475 gmove(nodconst(0L), nn); 1476 patch(p2, pc); 1477 } 1478 break; 1479 } 1480 cursafe = curs; 1481 } 1482 1483 void 1484 sugen(Node *n, Node *nn, int32 w) 1485 { 1486 Prog *p1; 1487 Node nod0, nod1, nod2, nod3, nod4, *l, *r; 1488 Type *t; 1489 int c, mt, mo; 1490 vlong o0, o1; 1491 1492 if(n == Z || n->type == T) 1493 return; 1494 if(debug['g']) { 1495 prtree(nn, "sugen lhs"); 1496 prtree(n, "sugen"); 1497 } 1498 if(nn == nodrat) 1499 if(w > nrathole) 1500 nrathole = w; 1501 switch(n->op) { 1502 case OIND: 1503 if(nn == Z) { 1504 nullwarn(n->left, Z); 1505 break; 1506 } 1507 1508 default: 1509 goto copy; 1510 1511 case OCONST: 1512 goto copy; 1513 1514 case ODOT: 1515 l = n->left; 1516 sugen(l, nodrat, l->type->width); 1517 if(nn == Z) 1518 break; 1519 warn(n, "non-interruptable temporary"); 1520 nod1 = *nodrat; 1521 r = n->right; 1522 if(!r || r->op != OCONST) { 1523 diag(n, "DOT and no offset"); 1524 break; 1525 } 1526 nod1.xoffset += (int32)r->vconst; 1527 nod1.type = n->type; 1528 sugen(&nod1, nn, w); 1529 break; 1530 1531 case OSTRUCT: 1532 /* 1533 * rewrite so lhs has no fn call 1534 */ 1535 if(nn != Z && side(nn)) { 1536 nod1 = *n; 1537 nod1.type = typ(TIND, n->type); 1538 regret(&nod2, &nod1); 1539 lcgen(nn, &nod2); 1540 regsalloc(&nod0, &nod1); 1541 cgen(&nod2, &nod0); 1542 regfree(&nod2); 1543 1544 nod1 = *n; 1545 nod1.op = OIND; 1546 nod1.left = &nod0; 1547 nod1.right = Z; 1548 nod1.complex = 1; 1549 1550 sugen(n, &nod1, w); 1551 return; 1552 } 1553 1554 r = n->left; 1555 for(t = n->type->link; t != T; t = t->down) { 1556 l = r; 1557 if(r->op == OLIST) { 1558 l = r->left; 1559 r = r->right; 1560 } 1561 if(nn == Z) { 1562 cgen(l, nn); 1563 continue; 1564 } 1565 /* 1566 * hand craft *(&nn + o) = l 1567 */ 1568 nod0 = znode; 1569 nod0.op = OAS; 1570 nod0.type = t; 1571 nod0.left = &nod1; 1572 nod0.right = nil; 1573 1574 nod1 = znode; 1575 nod1.op = OIND; 1576 nod1.type = t; 1577 nod1.left = &nod2; 1578 1579 nod2 = znode; 1580 nod2.op = OADD; 1581 nod2.type = typ(TIND, t); 1582 nod2.left = &nod3; 1583 nod2.right = &nod4; 1584 1585 nod3 = znode; 1586 nod3.op = OADDR; 1587 nod3.type = nod2.type; 1588 nod3.left = nn; 1589 1590 nod4 = znode; 1591 nod4.op = OCONST; 1592 nod4.type = nod2.type; 1593 nod4.vconst = t->offset; 1594 1595 ccom(&nod0); 1596 acom(&nod0); 1597 xcom(&nod0); 1598 nod0.addable = 0; 1599 nod0.right = l; 1600 1601 // prtree(&nod0, "hand craft"); 1602 cgen(&nod0, Z); 1603 } 1604 break; 1605 1606 case OAS: 1607 if(nn == Z) { 1608 if(n->addable < INDEXED) 1609 sugen(n->right, n->left, w); 1610 break; 1611 } 1612 1613 sugen(n->right, nodrat, w); 1614 warn(n, "non-interruptable temporary"); 1615 sugen(nodrat, n->left, w); 1616 sugen(nodrat, nn, w); 1617 break; 1618 1619 case OFUNC: 1620 if(nn == Z) { 1621 sugen(n, nodrat, w); 1622 break; 1623 } 1624 if(nn->op != OIND) { 1625 nn = new1(OADDR, nn, Z); 1626 nn->type = types[TIND]; 1627 nn->addable = 0; 1628 } else 1629 nn = nn->left; 1630 n = new(OFUNC, n->left, new(OLIST, nn, n->right)); 1631 n->type = types[TVOID]; 1632 n->left->type = types[TVOID]; 1633 cgen(n, Z); 1634 break; 1635 1636 case OCOND: 1637 bcgen(n->left, 1); 1638 p1 = p; 1639 sugen(n->right->left, nn, w); 1640 gbranch(OGOTO); 1641 patch(p1, pc); 1642 p1 = p; 1643 sugen(n->right->right, nn, w); 1644 patch(p1, pc); 1645 break; 1646 1647 case OCOMMA: 1648 cgen(n->left, Z); 1649 sugen(n->right, nn, w); 1650 break; 1651 } 1652 return; 1653 1654 copy: 1655 if(nn == Z) { 1656 switch(n->op) { 1657 case OASADD: 1658 case OASSUB: 1659 case OASAND: 1660 case OASOR: 1661 case OASXOR: 1662 1663 case OASMUL: 1664 case OASLMUL: 1665 1666 1667 case OASASHL: 1668 case OASASHR: 1669 case OASLSHR: 1670 break; 1671 1672 case OPOSTINC: 1673 case OPOSTDEC: 1674 case OPREINC: 1675 case OPREDEC: 1676 break; 1677 1678 default: 1679 return; 1680 } 1681 } 1682 1683 if(n->complex >= FNX && nn != nil && nn->complex >= FNX) { 1684 t = nn->type; 1685 nn->type = types[TIND]; 1686 regialloc(&nod1, nn, Z); 1687 lcgen(nn, &nod1); 1688 regsalloc(&nod2, nn); 1689 nn->type = t; 1690 1691 gins(AMOVQ, &nod1, &nod2); 1692 regfree(&nod1); 1693 1694 nod2.type = typ(TIND, t); 1695 1696 nod1 = nod2; 1697 nod1.op = OIND; 1698 nod1.left = &nod2; 1699 nod1.right = Z; 1700 nod1.complex = 1; 1701 nod1.type = t; 1702 1703 sugen(n, &nod1, w); 1704 return; 1705 } 1706 1707 if(w <= 32) { 1708 c = cursafe; 1709 if(n->left != Z && n->left->complex >= FNX 1710 && n->right != Z && n->right->complex >= FNX) { 1711 regsalloc(&nod1, n->right); 1712 cgen(n->right, &nod1); 1713 nod2 = *n; 1714 nod2.right = &nod1; 1715 cgen(&nod2, nn); 1716 cursafe = c; 1717 return; 1718 } 1719 if(w & 7) { 1720 mt = TLONG; 1721 mo = AMOVL; 1722 } else { 1723 mt = TVLONG; 1724 mo = AMOVQ; 1725 } 1726 if(n->complex > nn->complex) { 1727 t = n->type; 1728 n->type = types[mt]; 1729 regalloc(&nod0, n, Z); 1730 if(!vaddr(n, 0)) { 1731 reglcgen(&nod1, n, Z); 1732 n->type = t; 1733 n = &nod1; 1734 } 1735 else 1736 n->type = t; 1737 1738 t = nn->type; 1739 nn->type = types[mt]; 1740 if(!vaddr(nn, 0)) { 1741 reglcgen(&nod2, nn, Z); 1742 nn->type = t; 1743 nn = &nod2; 1744 } 1745 else 1746 nn->type = t; 1747 } else { 1748 t = nn->type; 1749 nn->type = types[mt]; 1750 regalloc(&nod0, nn, Z); 1751 if(!vaddr(nn, 0)) { 1752 reglcgen(&nod2, nn, Z); 1753 nn->type = t; 1754 nn = &nod2; 1755 } 1756 else 1757 nn->type = t; 1758 1759 t = n->type; 1760 n->type = types[mt]; 1761 if(!vaddr(n, 0)) { 1762 reglcgen(&nod1, n, Z); 1763 n->type = t; 1764 n = &nod1; 1765 } 1766 else 1767 n->type = t; 1768 } 1769 o0 = n->xoffset; 1770 o1 = nn->xoffset; 1771 w /= ewidth[mt]; 1772 while(--w >= 0) { 1773 gins(mo, n, &nod0); 1774 gins(mo, &nod0, nn); 1775 n->xoffset += ewidth[mt]; 1776 nn->xoffset += ewidth[mt]; 1777 } 1778 n->xoffset = o0; 1779 nn->xoffset = o1; 1780 if(nn == &nod2) 1781 regfree(&nod2); 1782 if(n == &nod1) 1783 regfree(&nod1); 1784 regfree(&nod0); 1785 return; 1786 } 1787 1788 /* botch, need to save in .safe */ 1789 c = 0; 1790 if(n->complex > nn->complex) { 1791 t = n->type; 1792 n->type = types[TIND]; 1793 nodreg(&nod1, n, D_SI); 1794 if(reg[D_SI]) { 1795 gins(APUSHQ, &nod1, Z); 1796 c |= 1; 1797 reg[D_SI]++; 1798 } 1799 lcgen(n, &nod1); 1800 n->type = t; 1801 1802 t = nn->type; 1803 nn->type = types[TIND]; 1804 nodreg(&nod2, nn, D_DI); 1805 if(reg[D_DI]) { 1806 warn(Z, "DI botch"); 1807 gins(APUSHQ, &nod2, Z); 1808 c |= 2; 1809 reg[D_DI]++; 1810 } 1811 lcgen(nn, &nod2); 1812 nn->type = t; 1813 } else { 1814 t = nn->type; 1815 nn->type = types[TIND]; 1816 nodreg(&nod2, nn, D_DI); 1817 if(reg[D_DI]) { 1818 warn(Z, "DI botch"); 1819 gins(APUSHQ, &nod2, Z); 1820 c |= 2; 1821 reg[D_DI]++; 1822 } 1823 lcgen(nn, &nod2); 1824 nn->type = t; 1825 1826 t = n->type; 1827 n->type = types[TIND]; 1828 nodreg(&nod1, n, D_SI); 1829 if(reg[D_SI]) { 1830 gins(APUSHQ, &nod1, Z); 1831 c |= 1; 1832 reg[D_SI]++; 1833 } 1834 lcgen(n, &nod1); 1835 n->type = t; 1836 } 1837 nodreg(&nod3, n, D_CX); 1838 if(reg[D_CX]) { 1839 gins(APUSHQ, &nod3, Z); 1840 c |= 4; 1841 reg[D_CX]++; 1842 } 1843 gins(AMOVL, nodconst(w/SZ_INT), &nod3); 1844 gins(ACLD, Z, Z); 1845 gins(AREP, Z, Z); 1846 gins(AMOVSL, Z, Z); 1847 if(c & 4) { 1848 gins(APOPQ, Z, &nod3); 1849 reg[D_CX]--; 1850 } 1851 if(c & 2) { 1852 gins(APOPQ, Z, &nod2); 1853 reg[nod2.reg]--; 1854 } 1855 if(c & 1) { 1856 gins(APOPQ, Z, &nod1); 1857 reg[nod1.reg]--; 1858 } 1859 } 1860 1861 /* 1862 * TO DO 1863 */ 1864 void 1865 layout(Node *f, Node *t, int c, int cv, Node *cn) 1866 { 1867 Node t1, t2; 1868 1869 while(c > 3) { 1870 layout(f, t, 2, 0, Z); 1871 c -= 2; 1872 } 1873 1874 regalloc(&t1, &lregnode, Z); 1875 regalloc(&t2, &lregnode, Z); 1876 if(c > 0) { 1877 gmove(f, &t1); 1878 f->xoffset += SZ_INT; 1879 } 1880 if(cn != Z) 1881 gmove(nodconst(cv), cn); 1882 if(c > 1) { 1883 gmove(f, &t2); 1884 f->xoffset += SZ_INT; 1885 } 1886 if(c > 0) { 1887 gmove(&t1, t); 1888 t->xoffset += SZ_INT; 1889 } 1890 if(c > 2) { 1891 gmove(f, &t1); 1892 f->xoffset += SZ_INT; 1893 } 1894 if(c > 1) { 1895 gmove(&t2, t); 1896 t->xoffset += SZ_INT; 1897 } 1898 if(c > 2) { 1899 gmove(&t1, t); 1900 t->xoffset += SZ_INT; 1901 } 1902 regfree(&t1); 1903 regfree(&t2); 1904 } 1905 1906 /* 1907 * constant is not vlong or fits as 32-bit signed immediate 1908 */ 1909 int 1910 immconst(Node *n) 1911 { 1912 int32 v; 1913 1914 if(n->op != OCONST || !typechlpv[n->type->etype]) 1915 return 0; 1916 if(typechl[n->type->etype]) 1917 return 1; 1918 v = n->vconst; 1919 return n->vconst == (vlong)v; 1920 } 1921 1922 /* 1923 * if a constant and vlong, doesn't fit as 32-bit signed immediate 1924 */ 1925 int 1926 hardconst(Node *n) 1927 { 1928 return n->op == OCONST && !immconst(n); 1929 } 1930 1931 /* 1932 * casting up to t2 covers an intermediate cast to t1 1933 */ 1934 int 1935 castup(Type *t1, Type *t2) 1936 { 1937 int ft; 1938 1939 if(!nilcast(t1, t2)) 1940 return 0; 1941 /* known to be small to large */ 1942 ft = t1->etype; 1943 switch(t2->etype){ 1944 case TINT: 1945 case TLONG: 1946 return ft == TLONG || ft == TINT || ft == TSHORT || ft == TCHAR; 1947 case TUINT: 1948 case TULONG: 1949 return ft == TULONG || ft == TUINT || ft == TUSHORT || ft == TUCHAR; 1950 case TVLONG: 1951 return ft == TLONG || ft == TINT || ft == TSHORT; 1952 case TUVLONG: 1953 return ft == TULONG || ft == TUINT || ft == TUSHORT; 1954 } 1955 return 0; 1956 } 1957 1958 void 1959 zeroregm(Node *n) 1960 { 1961 gins(AMOVL, nodconst(0), n); 1962 } 1963 1964 /* do we need to load the address of a vlong? */ 1965 int 1966 vaddr(Node *n, int a) 1967 { 1968 switch(n->op) { 1969 case ONAME: 1970 if(a) 1971 return 1; 1972 return !(n->class == CEXTERN || n->class == CGLOBL || n->class == CSTATIC); 1973 1974 case OCONST: 1975 case OREGISTER: 1976 case OINDREG: 1977 return 1; 1978 } 1979 return 0; 1980 } 1981 1982 int32 1983 hi64v(Node *n) 1984 { 1985 if(align(0, types[TCHAR], Aarg1, nil)) /* isbigendian */ 1986 return (int32)(n->vconst) & ~0L; 1987 else 1988 return (int32)((uvlong)n->vconst>>32) & ~0L; 1989 } 1990 1991 int32 1992 lo64v(Node *n) 1993 { 1994 if(align(0, types[TCHAR], Aarg1, nil)) /* isbigendian */ 1995 return (int32)((uvlong)n->vconst>>32) & ~0L; 1996 else 1997 return (int32)(n->vconst) & ~0L; 1998 } 1999 2000 Node * 2001 hi64(Node *n) 2002 { 2003 return nodconst(hi64v(n)); 2004 } 2005 2006 Node * 2007 lo64(Node *n) 2008 { 2009 return nodconst(lo64v(n)); 2010 } 2011 2012 int 2013 cond(int op) 2014 { 2015 switch(op) { 2016 case OANDAND: 2017 case OOROR: 2018 case ONOT: 2019 return 1; 2020 2021 case OEQ: 2022 case ONE: 2023 case OLE: 2024 case OLT: 2025 case OGE: 2026 case OGT: 2027 case OHI: 2028 case OHS: 2029 case OLO: 2030 case OLS: 2031 return 1; 2032 } 2033 return 0; 2034 }