github.com/ader1990/go@v0.0.0-20140630135419-8c24447fa791/src/cmd/5g/cgen.c (about) 1 // Copyright 2009 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 #include <u.h> 6 #include <libc.h> 7 #include "gg.h" 8 9 /* 10 * generate: 11 * res = n; 12 * simplifies and calls gmove. 13 */ 14 void 15 cgen(Node *n, Node *res) 16 { 17 Node *nl, *nr, *r; 18 Node n1, n2, f0, f1; 19 int a, w, rg; 20 Prog *p1, *p2, *p3; 21 Addr addr; 22 23 if(debug['g']) { 24 dump("\ncgen-n", n); 25 dump("cgen-res", res); 26 } 27 if(n == N || n->type == T) 28 goto ret; 29 30 if(res == N || res->type == T) 31 fatal("cgen: res nil"); 32 33 switch(n->op) { 34 case OSLICE: 35 case OSLICEARR: 36 case OSLICESTR: 37 case OSLICE3: 38 case OSLICE3ARR: 39 if (res->op != ONAME || !res->addable) { 40 tempname(&n1, n->type); 41 cgen_slice(n, &n1); 42 cgen(&n1, res); 43 } else 44 cgen_slice(n, res); 45 return; 46 case OEFACE: 47 if (res->op != ONAME || !res->addable) { 48 tempname(&n1, n->type); 49 cgen_eface(n, &n1); 50 cgen(&n1, res); 51 } else 52 cgen_eface(n, res); 53 return; 54 } 55 56 while(n->op == OCONVNOP) 57 n = n->left; 58 59 if(n->ullman >= UINF) { 60 if(n->op == OINDREG) 61 fatal("cgen: this is going to misscompile"); 62 if(res->ullman >= UINF) { 63 tempname(&n1, n->type); 64 cgen(n, &n1); 65 cgen(&n1, res); 66 goto ret; 67 } 68 } 69 70 if(isfat(n->type)) { 71 if(n->type->width < 0) 72 fatal("forgot to compute width for %T", n->type); 73 sgen(n, res, n->type->width); 74 goto ret; 75 } 76 77 78 // update addressability for string, slice 79 // can't do in walk because n->left->addable 80 // changes if n->left is an escaping local variable. 81 switch(n->op) { 82 case OSPTR: 83 case OLEN: 84 if(isslice(n->left->type) || istype(n->left->type, TSTRING)) 85 n->addable = n->left->addable; 86 break; 87 case OCAP: 88 if(isslice(n->left->type)) 89 n->addable = n->left->addable; 90 break; 91 case OITAB: 92 n->addable = n->left->addable; 93 break; 94 } 95 96 // if both are addressable, move 97 if(n->addable && res->addable) { 98 if(is64(n->type) || is64(res->type) || 99 n->op == OREGISTER || res->op == OREGISTER || 100 iscomplex[n->type->etype] || iscomplex[res->type->etype]) { 101 gmove(n, res); 102 } else { 103 regalloc(&n1, n->type, N); 104 gmove(n, &n1); 105 cgen(&n1, res); 106 regfree(&n1); 107 } 108 goto ret; 109 } 110 111 // if both are not addressable, use a temporary. 112 if(!n->addable && !res->addable) { 113 // could use regalloc here sometimes, 114 // but have to check for ullman >= UINF. 115 tempname(&n1, n->type); 116 cgen(n, &n1); 117 cgen(&n1, res); 118 return; 119 } 120 121 // if result is not addressable directly but n is, 122 // compute its address and then store via the address. 123 if(!res->addable) { 124 igen(res, &n1, N); 125 cgen(n, &n1); 126 regfree(&n1); 127 return; 128 } 129 130 if(complexop(n, res)) { 131 complexgen(n, res); 132 return; 133 } 134 135 // if n is sudoaddable generate addr and move 136 if (!is64(n->type) && !is64(res->type) && !iscomplex[n->type->etype] && !iscomplex[res->type->etype]) { 137 a = optoas(OAS, n->type); 138 if(sudoaddable(a, n, &addr, &w)) { 139 if (res->op != OREGISTER) { 140 regalloc(&n2, res->type, N); 141 p1 = gins(a, N, &n2); 142 p1->from = addr; 143 if(debug['g']) 144 print("%P [ignore previous line]\n", p1); 145 gmove(&n2, res); 146 regfree(&n2); 147 } else { 148 p1 = gins(a, N, res); 149 p1->from = addr; 150 if(debug['g']) 151 print("%P [ignore previous line]\n", p1); 152 } 153 sudoclean(); 154 goto ret; 155 } 156 } 157 158 // otherwise, the result is addressable but n is not. 159 // let's do some computation. 160 161 nl = n->left; 162 nr = n->right; 163 164 if(nl != N && nl->ullman >= UINF) 165 if(nr != N && nr->ullman >= UINF) { 166 tempname(&n1, nl->type); 167 cgen(nl, &n1); 168 n2 = *n; 169 n2.left = &n1; 170 cgen(&n2, res); 171 goto ret; 172 } 173 174 // 64-bit ops are hard on 32-bit machine. 175 if(is64(n->type) || is64(res->type) || n->left != N && is64(n->left->type)) { 176 switch(n->op) { 177 // math goes to cgen64. 178 case OMINUS: 179 case OCOM: 180 case OADD: 181 case OSUB: 182 case OMUL: 183 case OLROT: 184 case OLSH: 185 case ORSH: 186 case OAND: 187 case OOR: 188 case OXOR: 189 cgen64(n, res); 190 return; 191 } 192 } 193 194 if(nl != N && isfloat[n->type->etype] && isfloat[nl->type->etype]) 195 goto flt; 196 switch(n->op) { 197 default: 198 dump("cgen", n); 199 fatal("cgen: unknown op %+hN", n); 200 break; 201 202 case OREAL: 203 case OIMAG: 204 case OCOMPLEX: 205 fatal("unexpected complex"); 206 break; 207 208 // these call bgen to get a bool value 209 case OOROR: 210 case OANDAND: 211 case OEQ: 212 case ONE: 213 case OLT: 214 case OLE: 215 case OGE: 216 case OGT: 217 case ONOT: 218 p1 = gbranch(AB, T, 0); 219 p2 = pc; 220 gmove(nodbool(1), res); 221 p3 = gbranch(AB, T, 0); 222 patch(p1, pc); 223 bgen(n, 1, 0, p2); 224 gmove(nodbool(0), res); 225 patch(p3, pc); 226 goto ret; 227 228 case OPLUS: 229 cgen(nl, res); 230 goto ret; 231 232 // unary 233 case OCOM: 234 a = optoas(OXOR, nl->type); 235 regalloc(&n1, nl->type, N); 236 cgen(nl, &n1); 237 nodconst(&n2, nl->type, -1); 238 gins(a, &n2, &n1); 239 gmove(&n1, res); 240 regfree(&n1); 241 goto ret; 242 243 case OMINUS: 244 regalloc(&n1, nl->type, N); 245 cgen(nl, &n1); 246 nodconst(&n2, nl->type, 0); 247 gins(optoas(OMINUS, nl->type), &n2, &n1); 248 gmove(&n1, res); 249 regfree(&n1); 250 goto ret; 251 252 // symmetric binary 253 case OAND: 254 case OOR: 255 case OXOR: 256 case OADD: 257 case OADDPTR: 258 case OMUL: 259 a = optoas(n->op, nl->type); 260 goto sbop; 261 262 // asymmetric binary 263 case OSUB: 264 a = optoas(n->op, nl->type); 265 goto abop; 266 267 case OHMUL: 268 cgen_hmul(nl, nr, res); 269 break; 270 271 case OLROT: 272 case OLSH: 273 case ORSH: 274 cgen_shift(n->op, n->bounded, nl, nr, res); 275 break; 276 277 case OCONV: 278 if(eqtype(n->type, nl->type) || noconv(n->type, nl->type)) { 279 cgen(nl, res); 280 break; 281 } 282 if(nl->addable && !is64(nl->type)) { 283 regalloc(&n1, nl->type, res); 284 gmove(nl, &n1); 285 } else { 286 if(n->type->width > widthptr || is64(nl->type) || isfloat[nl->type->etype]) 287 tempname(&n1, nl->type); 288 else 289 regalloc(&n1, nl->type, res); 290 cgen(nl, &n1); 291 } 292 if(n->type->width > widthptr || is64(n->type) || isfloat[n->type->etype]) 293 tempname(&n2, n->type); 294 else 295 regalloc(&n2, n->type, N); 296 gmove(&n1, &n2); 297 gmove(&n2, res); 298 if(n1.op == OREGISTER) 299 regfree(&n1); 300 if(n2.op == OREGISTER) 301 regfree(&n2); 302 break; 303 304 case ODOT: 305 case ODOTPTR: 306 case OINDEX: 307 case OIND: 308 case ONAME: // PHEAP or PPARAMREF var 309 igen(n, &n1, res); 310 gmove(&n1, res); 311 regfree(&n1); 312 break; 313 314 case OITAB: 315 // interface table is first word of interface value 316 igen(nl, &n1, res); 317 n1.type = n->type; 318 gmove(&n1, res); 319 regfree(&n1); 320 break; 321 322 case OSPTR: 323 // pointer is the first word of string or slice. 324 if(isconst(nl, CTSTR)) { 325 regalloc(&n1, types[tptr], res); 326 p1 = gins(AMOVW, N, &n1); 327 datastring(nl->val.u.sval->s, nl->val.u.sval->len, &p1->from); 328 gmove(&n1, res); 329 regfree(&n1); 330 break; 331 } 332 igen(nl, &n1, res); 333 n1.type = n->type; 334 gmove(&n1, res); 335 regfree(&n1); 336 break; 337 338 case OLEN: 339 if(istype(nl->type, TMAP) || istype(nl->type, TCHAN)) { 340 // map has len in the first 32-bit word. 341 // a zero pointer means zero length 342 regalloc(&n1, types[tptr], res); 343 cgen(nl, &n1); 344 345 nodconst(&n2, types[tptr], 0); 346 gcmp(optoas(OCMP, types[tptr]), &n1, &n2); 347 p1 = gbranch(optoas(OEQ, types[tptr]), T, -1); 348 349 n2 = n1; 350 n2.op = OINDREG; 351 n2.type = types[TINT32]; 352 gmove(&n2, &n1); 353 354 patch(p1, pc); 355 356 gmove(&n1, res); 357 regfree(&n1); 358 break; 359 } 360 if(istype(nl->type, TSTRING) || isslice(nl->type)) { 361 // both slice and string have len one pointer into the struct. 362 igen(nl, &n1, res); 363 n1.type = types[TUINT32]; 364 n1.xoffset += Array_nel; 365 gmove(&n1, res); 366 regfree(&n1); 367 break; 368 } 369 fatal("cgen: OLEN: unknown type %lT", nl->type); 370 break; 371 372 case OCAP: 373 if(istype(nl->type, TCHAN)) { 374 // chan has cap in the second 32-bit word. 375 // a zero pointer means zero length 376 regalloc(&n1, types[tptr], res); 377 cgen(nl, &n1); 378 379 nodconst(&n2, types[tptr], 0); 380 gcmp(optoas(OCMP, types[tptr]), &n1, &n2); 381 p1 = gbranch(optoas(OEQ, types[tptr]), T, -1); 382 383 n2 = n1; 384 n2.op = OINDREG; 385 n2.xoffset = 4; 386 n2.type = types[TINT32]; 387 gmove(&n2, &n1); 388 389 patch(p1, pc); 390 391 gmove(&n1, res); 392 regfree(&n1); 393 break; 394 } 395 if(isslice(nl->type)) { 396 igen(nl, &n1, res); 397 n1.type = types[TUINT32]; 398 n1.xoffset += Array_cap; 399 gmove(&n1, res); 400 regfree(&n1); 401 break; 402 } 403 fatal("cgen: OCAP: unknown type %lT", nl->type); 404 break; 405 406 case OADDR: 407 agen(nl, res); 408 break; 409 410 case OCALLMETH: 411 case OCALLFUNC: 412 // Release res so that it is available for cgen_call. 413 // Pick it up again after the call. 414 rg = -1; 415 if(n->ullman >= UINF) { 416 if(res != N && (res->op == OREGISTER || res->op == OINDREG)) { 417 rg = res->val.u.reg; 418 reg[rg]--; 419 } 420 } 421 if(n->op == OCALLMETH) 422 cgen_callmeth(n, 0); 423 else 424 cgen_call(n, 0); 425 if(rg >= 0) 426 reg[rg]++; 427 cgen_callret(n, res); 428 break; 429 430 case OCALLINTER: 431 cgen_callinter(n, res, 0); 432 cgen_callret(n, res); 433 break; 434 435 case OMOD: 436 case ODIV: 437 a = optoas(n->op, nl->type); 438 goto abop; 439 } 440 goto ret; 441 442 sbop: // symmetric binary 443 if(nl->ullman < nr->ullman) { 444 r = nl; 445 nl = nr; 446 nr = r; 447 } 448 449 abop: // asymmetric binary 450 // TODO(kaib): use fewer registers here. 451 if(nl->ullman >= nr->ullman) { 452 regalloc(&n1, nl->type, res); 453 cgen(nl, &n1); 454 switch(n->op) { 455 case OADD: 456 case OSUB: 457 case OAND: 458 case OOR: 459 case OXOR: 460 if(smallintconst(nr)) { 461 n2 = *nr; 462 break; 463 } 464 default: 465 regalloc(&n2, nr->type, N); 466 cgen(nr, &n2); 467 } 468 } else { 469 switch(n->op) { 470 case OADD: 471 case OSUB: 472 case OAND: 473 case OOR: 474 case OXOR: 475 if(smallintconst(nr)) { 476 n2 = *nr; 477 break; 478 } 479 default: 480 regalloc(&n2, nr->type, res); 481 cgen(nr, &n2); 482 } 483 regalloc(&n1, nl->type, N); 484 cgen(nl, &n1); 485 } 486 gins(a, &n2, &n1); 487 // Normalize result for types smaller than word. 488 if(n->type->width < widthptr) { 489 switch(n->op) { 490 case OADD: 491 case OSUB: 492 case OMUL: 493 gins(optoas(OAS, n->type), &n1, &n1); 494 break; 495 } 496 } 497 gmove(&n1, res); 498 regfree(&n1); 499 if(n2.op != OLITERAL) 500 regfree(&n2); 501 goto ret; 502 503 flt: // floating-point. 504 regalloc(&f0, nl->type, res); 505 if(nr != N) 506 goto flt2; 507 508 if(n->op == OMINUS) { 509 nr = nodintconst(-1); 510 convlit(&nr, n->type); 511 n->op = OMUL; 512 goto flt2; 513 } 514 515 // unary 516 cgen(nl, &f0); 517 if(n->op != OCONV && n->op != OPLUS) 518 gins(optoas(n->op, n->type), &f0, &f0); 519 gmove(&f0, res); 520 regfree(&f0); 521 goto ret; 522 523 flt2: // binary 524 if(nl->ullman >= nr->ullman) { 525 cgen(nl, &f0); 526 regalloc(&f1, n->type, N); 527 gmove(&f0, &f1); 528 cgen(nr, &f0); 529 gins(optoas(n->op, n->type), &f0, &f1); 530 } else { 531 cgen(nr, &f0); 532 regalloc(&f1, n->type, N); 533 cgen(nl, &f1); 534 gins(optoas(n->op, n->type), &f0, &f1); 535 } 536 gmove(&f1, res); 537 regfree(&f0); 538 regfree(&f1); 539 goto ret; 540 541 ret: 542 ; 543 } 544 545 /* 546 * generate array index into res. 547 * n might be any size; res is 32-bit. 548 * returns Prog* to patch to panic call. 549 */ 550 Prog* 551 cgenindex(Node *n, Node *res, int bounded) 552 { 553 Node tmp, lo, hi, zero, n1, n2; 554 555 if(!is64(n->type)) { 556 cgen(n, res); 557 return nil; 558 } 559 560 tempname(&tmp, types[TINT64]); 561 cgen(n, &tmp); 562 split64(&tmp, &lo, &hi); 563 gmove(&lo, res); 564 if(bounded) { 565 splitclean(); 566 return nil; 567 } 568 regalloc(&n1, types[TINT32], N); 569 regalloc(&n2, types[TINT32], N); 570 nodconst(&zero, types[TINT32], 0); 571 gmove(&hi, &n1); 572 gmove(&zero, &n2); 573 gcmp(ACMP, &n1, &n2); 574 regfree(&n2); 575 regfree(&n1); 576 splitclean(); 577 return gbranch(ABNE, T, -1); 578 } 579 580 /* 581 * generate: 582 * res = &n; 583 * The generated code checks that the result is not nil. 584 */ 585 void 586 agen(Node *n, Node *res) 587 { 588 Node *nl; 589 Node n1, n2, n3; 590 int r; 591 592 if(debug['g']) { 593 dump("\nagen-res", res); 594 dump("agen-r", n); 595 } 596 if(n == N || n->type == T || res == N || res->type == T) 597 fatal("agen"); 598 599 while(n->op == OCONVNOP) 600 n = n->left; 601 602 if(isconst(n, CTNIL) && n->type->width > widthptr) { 603 // Use of a nil interface or nil slice. 604 // Create a temporary we can take the address of and read. 605 // The generated code is just going to panic, so it need not 606 // be terribly efficient. See issue 3670. 607 tempname(&n1, n->type); 608 gvardef(&n1); 609 clearfat(&n1); 610 regalloc(&n2, types[tptr], res); 611 gins(AMOVW, &n1, &n2); 612 gmove(&n2, res); 613 regfree(&n2); 614 goto ret; 615 } 616 617 618 if(n->addable) { 619 memset(&n1, 0, sizeof n1); 620 n1.op = OADDR; 621 n1.left = n; 622 regalloc(&n2, types[tptr], res); 623 gins(AMOVW, &n1, &n2); 624 gmove(&n2, res); 625 regfree(&n2); 626 goto ret; 627 } 628 629 nl = n->left; 630 631 switch(n->op) { 632 default: 633 fatal("agen: unknown op %+hN", n); 634 break; 635 636 case OCALLMETH: 637 case OCALLFUNC: 638 // Release res so that it is available for cgen_call. 639 // Pick it up again after the call. 640 r = -1; 641 if(n->ullman >= UINF) { 642 if(res->op == OREGISTER || res->op == OINDREG) { 643 r = res->val.u.reg; 644 reg[r]--; 645 } 646 } 647 if(n->op == OCALLMETH) 648 cgen_callmeth(n, 0); 649 else 650 cgen_call(n, 0); 651 if(r >= 0) 652 reg[r]++; 653 cgen_aret(n, res); 654 break; 655 656 case OCALLINTER: 657 cgen_callinter(n, res, 0); 658 cgen_aret(n, res); 659 break; 660 661 case OSLICE: 662 case OSLICEARR: 663 case OSLICESTR: 664 case OSLICE3: 665 case OSLICE3ARR: 666 tempname(&n1, n->type); 667 cgen_slice(n, &n1); 668 agen(&n1, res); 669 break; 670 671 case OEFACE: 672 tempname(&n1, n->type); 673 cgen_eface(n, &n1); 674 agen(&n1, res); 675 break; 676 677 case OINDEX: 678 agenr(n, &n1, res); 679 gmove(&n1, res); 680 regfree(&n1); 681 break; 682 683 case ONAME: 684 // should only get here with names in this func. 685 if(n->funcdepth > 0 && n->funcdepth != funcdepth) { 686 dump("bad agen", n); 687 fatal("agen: bad ONAME funcdepth %d != %d", 688 n->funcdepth, funcdepth); 689 } 690 691 // should only get here for heap vars or paramref 692 if(!(n->class & PHEAP) && n->class != PPARAMREF) { 693 dump("bad agen", n); 694 fatal("agen: bad ONAME class %#x", n->class); 695 } 696 cgen(n->heapaddr, res); 697 if(n->xoffset != 0) { 698 nodconst(&n1, types[TINT32], n->xoffset); 699 regalloc(&n2, n1.type, N); 700 regalloc(&n3, types[TINT32], N); 701 gmove(&n1, &n2); 702 gmove(res, &n3); 703 gins(optoas(OADD, types[tptr]), &n2, &n3); 704 gmove(&n3, res); 705 regfree(&n2); 706 regfree(&n3); 707 } 708 break; 709 710 case OIND: 711 cgen(nl, res); 712 cgen_checknil(res); 713 break; 714 715 case ODOT: 716 agen(nl, res); 717 if(n->xoffset != 0) { 718 nodconst(&n1, types[TINT32], n->xoffset); 719 regalloc(&n2, n1.type, N); 720 regalloc(&n3, types[TINT32], N); 721 gmove(&n1, &n2); 722 gmove(res, &n3); 723 gins(optoas(OADD, types[tptr]), &n2, &n3); 724 gmove(&n3, res); 725 regfree(&n2); 726 regfree(&n3); 727 } 728 break; 729 730 case ODOTPTR: 731 cgen(nl, res); 732 cgen_checknil(res); 733 if(n->xoffset != 0) { 734 nodconst(&n1, types[TINT32], n->xoffset); 735 regalloc(&n2, n1.type, N); 736 regalloc(&n3, types[tptr], N); 737 gmove(&n1, &n2); 738 gmove(res, &n3); 739 gins(optoas(OADD, types[tptr]), &n2, &n3); 740 gmove(&n3, res); 741 regfree(&n2); 742 regfree(&n3); 743 } 744 break; 745 } 746 747 ret: 748 ; 749 } 750 751 /* 752 * generate: 753 * newreg = &n; 754 * res = newreg 755 * 756 * on exit, a has been changed to be *newreg. 757 * caller must regfree(a). 758 * The generated code checks that the result is not *nil. 759 */ 760 void 761 igen(Node *n, Node *a, Node *res) 762 { 763 Node n1; 764 int r; 765 766 if(debug['g']) { 767 dump("\nigen-n", n); 768 } 769 switch(n->op) { 770 case ONAME: 771 if((n->class&PHEAP) || n->class == PPARAMREF) 772 break; 773 *a = *n; 774 return; 775 776 case OINDREG: 777 // Increase the refcount of the register so that igen's caller 778 // has to call regfree. 779 if(n->val.u.reg != REGSP) 780 reg[n->val.u.reg]++; 781 *a = *n; 782 return; 783 784 case ODOT: 785 igen(n->left, a, res); 786 a->xoffset += n->xoffset; 787 a->type = n->type; 788 return; 789 790 case ODOTPTR: 791 if(n->left->addable 792 || n->left->op == OCALLFUNC 793 || n->left->op == OCALLMETH 794 || n->left->op == OCALLINTER) { 795 // igen-able nodes. 796 igen(n->left, &n1, res); 797 regalloc(a, types[tptr], &n1); 798 gmove(&n1, a); 799 regfree(&n1); 800 } else { 801 regalloc(a, types[tptr], res); 802 cgen(n->left, a); 803 } 804 cgen_checknil(a); 805 a->op = OINDREG; 806 a->xoffset = n->xoffset; 807 a->type = n->type; 808 return; 809 810 case OCALLMETH: 811 case OCALLFUNC: 812 case OCALLINTER: 813 // Release res so that it is available for cgen_call. 814 // Pick it up again after the call. 815 r = -1; 816 if(n->ullman >= UINF) { 817 if(res != N && (res->op == OREGISTER || res->op == OINDREG)) { 818 r = res->val.u.reg; 819 reg[r]--; 820 } 821 } 822 switch(n->op) { 823 case OCALLMETH: 824 cgen_callmeth(n, 0); 825 break; 826 case OCALLFUNC: 827 cgen_call(n, 0); 828 break; 829 case OCALLINTER: 830 cgen_callinter(n, N, 0); 831 break; 832 } 833 if(r >= 0) 834 reg[r]++; 835 regalloc(a, types[tptr], res); 836 cgen_aret(n, a); 837 a->op = OINDREG; 838 a->type = n->type; 839 return; 840 } 841 842 agenr(n, a, res); 843 a->op = OINDREG; 844 a->type = n->type; 845 } 846 847 /* 848 * allocate a register in res and generate 849 * newreg = &n 850 * The caller must call regfree(a). 851 */ 852 void 853 cgenr(Node *n, Node *a, Node *res) 854 { 855 Node n1; 856 857 if(debug['g']) 858 dump("cgenr-n", n); 859 860 if(isfat(n->type)) 861 fatal("cgenr on fat node"); 862 863 if(n->addable) { 864 regalloc(a, types[tptr], res); 865 gmove(n, a); 866 return; 867 } 868 869 switch(n->op) { 870 case ONAME: 871 case ODOT: 872 case ODOTPTR: 873 case OINDEX: 874 case OCALLFUNC: 875 case OCALLMETH: 876 case OCALLINTER: 877 igen(n, &n1, res); 878 regalloc(a, types[tptr], &n1); 879 gmove(&n1, a); 880 regfree(&n1); 881 break; 882 default: 883 regalloc(a, n->type, res); 884 cgen(n, a); 885 break; 886 } 887 } 888 889 /* 890 * generate: 891 * newreg = &n; 892 * 893 * caller must regfree(a). 894 * The generated code checks that the result is not nil. 895 */ 896 void 897 agenr(Node *n, Node *a, Node *res) 898 { 899 Node *nl, *nr; 900 Node n1, n2, n3, n4, tmp; 901 Prog *p1, *p2; 902 uint32 w; 903 uint64 v; 904 int bounded; 905 906 if(debug['g']) 907 dump("agenr-n", n); 908 909 nl = n->left; 910 nr = n->right; 911 912 switch(n->op) { 913 case ODOT: 914 case ODOTPTR: 915 case OCALLFUNC: 916 case OCALLMETH: 917 case OCALLINTER: 918 igen(n, &n1, res); 919 regalloc(a, types[tptr], &n1); 920 agen(&n1, a); 921 regfree(&n1); 922 break; 923 924 case OIND: 925 cgenr(n->left, a, res); 926 cgen_checknil(a); 927 break; 928 929 case OINDEX: 930 p2 = nil; // to be patched to panicindex. 931 w = n->type->width; 932 bounded = debug['B'] || n->bounded; 933 if(nr->addable) { 934 if(!isconst(nr, CTINT)) 935 tempname(&tmp, types[TINT32]); 936 if(!isconst(nl, CTSTR)) 937 agenr(nl, &n3, res); 938 if(!isconst(nr, CTINT)) { 939 p2 = cgenindex(nr, &tmp, bounded); 940 regalloc(&n1, tmp.type, N); 941 gmove(&tmp, &n1); 942 } 943 } else 944 if(nl->addable) { 945 if(!isconst(nr, CTINT)) { 946 tempname(&tmp, types[TINT32]); 947 p2 = cgenindex(nr, &tmp, bounded); 948 regalloc(&n1, tmp.type, N); 949 gmove(&tmp, &n1); 950 } 951 if(!isconst(nl, CTSTR)) { 952 agenr(nl, &n3, res); 953 } 954 } else { 955 tempname(&tmp, types[TINT32]); 956 p2 = cgenindex(nr, &tmp, bounded); 957 nr = &tmp; 958 if(!isconst(nl, CTSTR)) 959 agenr(nl, &n3, res); 960 regalloc(&n1, tmp.type, N); 961 gins(optoas(OAS, tmp.type), &tmp, &n1); 962 } 963 964 // &a is in &n3 (allocated in res) 965 // i is in &n1 (if not constant) 966 // w is width 967 968 // constant index 969 if(isconst(nr, CTINT)) { 970 if(isconst(nl, CTSTR)) 971 fatal("constant string constant index"); 972 v = mpgetfix(nr->val.u.xval); 973 if(isslice(nl->type) || nl->type->etype == TSTRING) { 974 if(!debug['B'] && !n->bounded) { 975 n1 = n3; 976 n1.op = OINDREG; 977 n1.type = types[tptr]; 978 n1.xoffset = Array_nel; 979 regalloc(&n4, n1.type, N); 980 gmove(&n1, &n4); 981 nodconst(&n2, types[TUINT32], v); 982 gcmp(optoas(OCMP, types[TUINT32]), &n4, &n2); 983 regfree(&n4); 984 p1 = gbranch(optoas(OGT, types[TUINT32]), T, +1); 985 ginscall(panicindex, 0); 986 patch(p1, pc); 987 } 988 989 n1 = n3; 990 n1.op = OINDREG; 991 n1.type = types[tptr]; 992 n1.xoffset = Array_array; 993 gmove(&n1, &n3); 994 } 995 996 nodconst(&n2, types[tptr], v*w); 997 gins(optoas(OADD, types[tptr]), &n2, &n3); 998 *a = n3; 999 break; 1000 } 1001 1002 regalloc(&n2, types[TINT32], &n1); // i 1003 gmove(&n1, &n2); 1004 regfree(&n1); 1005 1006 if(!debug['B'] && !n->bounded) { 1007 // check bounds 1008 if(isconst(nl, CTSTR)) { 1009 nodconst(&n4, types[TUINT32], nl->val.u.sval->len); 1010 } else if(isslice(nl->type) || nl->type->etype == TSTRING) { 1011 n1 = n3; 1012 n1.op = OINDREG; 1013 n1.type = types[tptr]; 1014 n1.xoffset = Array_nel; 1015 regalloc(&n4, types[TUINT32], N); 1016 gmove(&n1, &n4); 1017 } else { 1018 nodconst(&n4, types[TUINT32], nl->type->bound); 1019 } 1020 gcmp(optoas(OCMP, types[TUINT32]), &n2, &n4); 1021 if(n4.op == OREGISTER) 1022 regfree(&n4); 1023 p1 = gbranch(optoas(OLT, types[TUINT32]), T, +1); 1024 if(p2) 1025 patch(p2, pc); 1026 ginscall(panicindex, 0); 1027 patch(p1, pc); 1028 } 1029 1030 if(isconst(nl, CTSTR)) { 1031 regalloc(&n3, types[tptr], res); 1032 p1 = gins(AMOVW, N, &n3); 1033 datastring(nl->val.u.sval->s, nl->val.u.sval->len, &p1->from); 1034 p1->from.type = D_CONST; 1035 } else 1036 if(isslice(nl->type) || nl->type->etype == TSTRING) { 1037 n1 = n3; 1038 n1.op = OINDREG; 1039 n1.type = types[tptr]; 1040 n1.xoffset = Array_array; 1041 gmove(&n1, &n3); 1042 } 1043 1044 if(w == 0) { 1045 // nothing to do 1046 } else if(w == 1 || w == 2 || w == 4 || w == 8) { 1047 memset(&n4, 0, sizeof n4); 1048 n4.op = OADDR; 1049 n4.left = &n2; 1050 cgen(&n4, &n3); 1051 if (w == 1) 1052 gins(AADD, &n2, &n3); 1053 else if(w == 2) 1054 gshift(AADD, &n2, SHIFT_LL, 1, &n3); 1055 else if(w == 4) 1056 gshift(AADD, &n2, SHIFT_LL, 2, &n3); 1057 else if(w == 8) 1058 gshift(AADD, &n2, SHIFT_LL, 3, &n3); 1059 } else { 1060 regalloc(&n4, types[TUINT32], N); 1061 nodconst(&n1, types[TUINT32], w); 1062 gmove(&n1, &n4); 1063 gins(optoas(OMUL, types[TUINT32]), &n4, &n2); 1064 gins(optoas(OADD, types[tptr]), &n2, &n3); 1065 regfree(&n4); 1066 } 1067 1068 *a = n3; 1069 regfree(&n2); 1070 break; 1071 1072 default: 1073 regalloc(a, types[tptr], res); 1074 agen(n, a); 1075 break; 1076 } 1077 } 1078 1079 void 1080 gencmp0(Node *n, Type *t, int o, int likely, Prog *to) 1081 { 1082 Node n1, n2, n3; 1083 int a; 1084 1085 regalloc(&n1, t, N); 1086 cgen(n, &n1); 1087 a = optoas(OCMP, t); 1088 if(a != ACMP) { 1089 nodconst(&n2, t, 0); 1090 regalloc(&n3, t, N); 1091 gmove(&n2, &n3); 1092 gcmp(a, &n1, &n3); 1093 regfree(&n3); 1094 } else 1095 gins(ATST, &n1, N); 1096 a = optoas(o, t); 1097 patch(gbranch(a, t, likely), to); 1098 regfree(&n1); 1099 } 1100 1101 /* 1102 * generate: 1103 * if(n == true) goto to; 1104 */ 1105 void 1106 bgen(Node *n, int true, int likely, Prog *to) 1107 { 1108 int et, a; 1109 Node *nl, *nr, *r; 1110 Node n1, n2, n3, n4, tmp; 1111 NodeList *ll; 1112 Prog *p1, *p2; 1113 1114 USED(n4); // in unreachable code below 1115 if(debug['g']) { 1116 dump("\nbgen", n); 1117 } 1118 1119 if(n == N) 1120 n = nodbool(1); 1121 1122 if(n->ninit != nil) 1123 genlist(n->ninit); 1124 1125 if(n->type == T) { 1126 convlit(&n, types[TBOOL]); 1127 if(n->type == T) 1128 goto ret; 1129 } 1130 1131 et = n->type->etype; 1132 if(et != TBOOL) { 1133 yyerror("cgen: bad type %T for %O", n->type, n->op); 1134 patch(gins(AEND, N, N), to); 1135 goto ret; 1136 } 1137 nr = N; 1138 1139 switch(n->op) { 1140 default: 1141 a = ONE; 1142 if(!true) 1143 a = OEQ; 1144 gencmp0(n, n->type, a, likely, to); 1145 goto ret; 1146 1147 case OLITERAL: 1148 // need to ask if it is bool? 1149 if(!true == !n->val.u.bval) 1150 patch(gbranch(AB, T, 0), to); 1151 goto ret; 1152 1153 case OANDAND: 1154 if(!true) 1155 goto caseor; 1156 1157 caseand: 1158 p1 = gbranch(AB, T, 0); 1159 p2 = gbranch(AB, T, 0); 1160 patch(p1, pc); 1161 bgen(n->left, !true, -likely, p2); 1162 bgen(n->right, !true, -likely, p2); 1163 p1 = gbranch(AB, T, 0); 1164 patch(p1, to); 1165 patch(p2, pc); 1166 goto ret; 1167 1168 case OOROR: 1169 if(!true) 1170 goto caseand; 1171 1172 caseor: 1173 bgen(n->left, true, likely, to); 1174 bgen(n->right, true, likely, to); 1175 goto ret; 1176 1177 case OEQ: 1178 case ONE: 1179 case OLT: 1180 case OGT: 1181 case OLE: 1182 case OGE: 1183 nr = n->right; 1184 if(nr == N || nr->type == T) 1185 goto ret; 1186 1187 case ONOT: // unary 1188 nl = n->left; 1189 if(nl == N || nl->type == T) 1190 goto ret; 1191 } 1192 1193 switch(n->op) { 1194 1195 case ONOT: 1196 bgen(nl, !true, likely, to); 1197 goto ret; 1198 1199 case OEQ: 1200 case ONE: 1201 case OLT: 1202 case OGT: 1203 case OLE: 1204 case OGE: 1205 a = n->op; 1206 if(!true) { 1207 if(isfloat[nl->type->etype]) { 1208 // brcom is not valid on floats when NaN is involved. 1209 p1 = gbranch(AB, T, 0); 1210 p2 = gbranch(AB, T, 0); 1211 patch(p1, pc); 1212 ll = n->ninit; 1213 n->ninit = nil; 1214 bgen(n, 1, -likely, p2); 1215 n->ninit = ll; 1216 patch(gbranch(AB, T, 0), to); 1217 patch(p2, pc); 1218 goto ret; 1219 } 1220 a = brcom(a); 1221 true = !true; 1222 } 1223 1224 // make simplest on right 1225 if(nl->op == OLITERAL || (nl->ullman < UINF && nl->ullman < nr->ullman)) { 1226 a = brrev(a); 1227 r = nl; 1228 nl = nr; 1229 nr = r; 1230 } 1231 1232 if(isslice(nl->type)) { 1233 // only valid to cmp darray to literal nil 1234 if((a != OEQ && a != ONE) || nr->op != OLITERAL) { 1235 yyerror("illegal array comparison"); 1236 break; 1237 } 1238 1239 igen(nl, &n1, N); 1240 n1.xoffset += Array_array; 1241 n1.type = types[tptr]; 1242 gencmp0(&n1, types[tptr], a, likely, to); 1243 regfree(&n1); 1244 break; 1245 } 1246 1247 if(isinter(nl->type)) { 1248 // front end shold only leave cmp to literal nil 1249 if((a != OEQ && a != ONE) || nr->op != OLITERAL) { 1250 yyerror("illegal interface comparison"); 1251 break; 1252 } 1253 1254 igen(nl, &n1, N); 1255 n1.type = types[tptr]; 1256 n1.xoffset += 0; 1257 gencmp0(&n1, types[tptr], a, likely, to); 1258 regfree(&n1); 1259 break; 1260 } 1261 1262 if(iscomplex[nl->type->etype]) { 1263 complexbool(a, nl, nr, true, likely, to); 1264 break; 1265 } 1266 1267 if(is64(nr->type)) { 1268 if(!nl->addable) { 1269 tempname(&n1, nl->type); 1270 cgen(nl, &n1); 1271 nl = &n1; 1272 } 1273 if(!nr->addable) { 1274 tempname(&n2, nr->type); 1275 cgen(nr, &n2); 1276 nr = &n2; 1277 } 1278 cmp64(nl, nr, a, likely, to); 1279 break; 1280 } 1281 1282 if(nr->op == OLITERAL) { 1283 if(isconst(nr, CTINT) && mpgetfix(nr->val.u.xval) == 0) { 1284 gencmp0(nl, nl->type, a, likely, to); 1285 break; 1286 } 1287 if(nr->val.ctype == CTNIL) { 1288 gencmp0(nl, nl->type, a, likely, to); 1289 break; 1290 } 1291 } 1292 1293 a = optoas(a, nr->type); 1294 1295 if(nr->ullman >= UINF) { 1296 regalloc(&n1, nl->type, N); 1297 cgen(nl, &n1); 1298 1299 tempname(&tmp, nl->type); 1300 gmove(&n1, &tmp); 1301 regfree(&n1); 1302 1303 regalloc(&n2, nr->type, N); 1304 cgen(nr, &n2); 1305 1306 regalloc(&n1, nl->type, N); 1307 cgen(&tmp, &n1); 1308 1309 gcmp(optoas(OCMP, nr->type), &n1, &n2); 1310 patch(gbranch(a, nr->type, likely), to); 1311 1312 regfree(&n1); 1313 regfree(&n2); 1314 break; 1315 } 1316 1317 tempname(&n3, nl->type); 1318 cgen(nl, &n3); 1319 1320 tempname(&tmp, nr->type); 1321 cgen(nr, &tmp); 1322 1323 regalloc(&n1, nl->type, N); 1324 gmove(&n3, &n1); 1325 1326 regalloc(&n2, nr->type, N); 1327 gmove(&tmp, &n2); 1328 1329 gcmp(optoas(OCMP, nr->type), &n1, &n2); 1330 if(isfloat[nl->type->etype]) { 1331 if(n->op == ONE) { 1332 p1 = gbranch(ABVS, nr->type, likely); 1333 patch(gbranch(a, nr->type, likely), to); 1334 patch(p1, to); 1335 } else { 1336 p1 = gbranch(ABVS, nr->type, -likely); 1337 patch(gbranch(a, nr->type, likely), to); 1338 patch(p1, pc); 1339 } 1340 } else { 1341 patch(gbranch(a, nr->type, likely), to); 1342 } 1343 regfree(&n1); 1344 regfree(&n2); 1345 break; 1346 } 1347 goto ret; 1348 1349 ret: 1350 ; 1351 } 1352 1353 /* 1354 * n is on stack, either local variable 1355 * or return value from function call. 1356 * return n's offset from SP. 1357 */ 1358 int32 1359 stkof(Node *n) 1360 { 1361 Type *t; 1362 Iter flist; 1363 int32 off; 1364 1365 switch(n->op) { 1366 case OINDREG: 1367 return n->xoffset; 1368 1369 case ODOT: 1370 t = n->left->type; 1371 if(isptr[t->etype]) 1372 break; 1373 off = stkof(n->left); 1374 if(off == -1000 || off == 1000) 1375 return off; 1376 return off + n->xoffset; 1377 1378 case OINDEX: 1379 t = n->left->type; 1380 if(!isfixedarray(t)) 1381 break; 1382 off = stkof(n->left); 1383 if(off == -1000 || off == 1000) 1384 return off; 1385 if(isconst(n->right, CTINT)) 1386 return off + t->type->width * mpgetfix(n->right->val.u.xval); 1387 return 1000; 1388 1389 case OCALLMETH: 1390 case OCALLINTER: 1391 case OCALLFUNC: 1392 t = n->left->type; 1393 if(isptr[t->etype]) 1394 t = t->type; 1395 1396 t = structfirst(&flist, getoutarg(t)); 1397 if(t != T) 1398 return t->width + 4; // correct for LR 1399 break; 1400 } 1401 1402 // botch - probably failing to recognize address 1403 // arithmetic on the above. eg INDEX and DOT 1404 return -1000; 1405 } 1406 1407 /* 1408 * block copy: 1409 * memmove(&res, &n, w); 1410 * NB: character copy assumed little endian architecture 1411 */ 1412 void 1413 sgen(Node *n, Node *res, int64 w) 1414 { 1415 Node dst, src, tmp, nend, r0, r1, r2, *f; 1416 int32 c, odst, osrc; 1417 int dir, align, op; 1418 Prog *p, *ploop; 1419 NodeList *l; 1420 1421 if(debug['g']) { 1422 print("\nsgen w=%lld\n", w); 1423 dump("r", n); 1424 dump("res", res); 1425 } 1426 1427 if(n->ullman >= UINF && res->ullman >= UINF) 1428 fatal("sgen UINF"); 1429 1430 if(w < 0 || (int32)w != w) 1431 fatal("sgen copy %lld", w); 1432 1433 if(n->type == T) 1434 fatal("sgen: missing type"); 1435 1436 if(w == 0) { 1437 // evaluate side effects only. 1438 regalloc(&dst, types[tptr], N); 1439 agen(res, &dst); 1440 agen(n, &dst); 1441 regfree(&dst); 1442 return; 1443 } 1444 1445 // If copying .args, that's all the results, so record definition sites 1446 // for them for the liveness analysis. 1447 if(res->op == ONAME && strcmp(res->sym->name, ".args") == 0) 1448 for(l = curfn->dcl; l != nil; l = l->next) 1449 if(l->n->class == PPARAMOUT) 1450 gvardef(l->n); 1451 1452 // Avoid taking the address for simple enough types. 1453 if(componentgen(n, res)) 1454 return; 1455 1456 // determine alignment. 1457 // want to avoid unaligned access, so have to use 1458 // smaller operations for less aligned types. 1459 // for example moving [4]byte must use 4 MOVB not 1 MOVW. 1460 align = n->type->align; 1461 switch(align) { 1462 default: 1463 fatal("sgen: invalid alignment %d for %T", align, n->type); 1464 case 1: 1465 op = AMOVB; 1466 break; 1467 case 2: 1468 op = AMOVH; 1469 break; 1470 case 4: 1471 op = AMOVW; 1472 break; 1473 } 1474 if(w%align) 1475 fatal("sgen: unaligned size %lld (align=%d) for %T", w, align, n->type); 1476 c = w / align; 1477 1478 // offset on the stack 1479 osrc = stkof(n); 1480 odst = stkof(res); 1481 if(osrc != -1000 && odst != -1000 && (osrc == 1000 || odst == 1000)) { 1482 // osrc and odst both on stack, and at least one is in 1483 // an unknown position. Could generate code to test 1484 // for forward/backward copy, but instead just copy 1485 // to a temporary location first. 1486 tempname(&tmp, n->type); 1487 sgen(n, &tmp, w); 1488 sgen(&tmp, res, w); 1489 return; 1490 } 1491 if(osrc%align != 0 || odst%align != 0) 1492 fatal("sgen: unaligned offset src %d or dst %d (align %d)", osrc, odst, align); 1493 1494 // if we are copying forward on the stack and 1495 // the src and dst overlap, then reverse direction 1496 dir = align; 1497 if(osrc < odst && odst < osrc+w) 1498 dir = -dir; 1499 1500 if(op == AMOVW && dir > 0 && c >= 4 && c <= 128) { 1501 r0.op = OREGISTER; 1502 r0.val.u.reg = REGALLOC_R0; 1503 r1.op = OREGISTER; 1504 r1.val.u.reg = REGALLOC_R0 + 1; 1505 r2.op = OREGISTER; 1506 r2.val.u.reg = REGALLOC_R0 + 2; 1507 1508 regalloc(&src, types[tptr], &r1); 1509 regalloc(&dst, types[tptr], &r2); 1510 if(n->ullman >= res->ullman) { 1511 // eval n first 1512 agen(n, &src); 1513 if(res->op == ONAME) 1514 gvardef(res); 1515 agen(res, &dst); 1516 } else { 1517 // eval res first 1518 if(res->op == ONAME) 1519 gvardef(res); 1520 agen(res, &dst); 1521 agen(n, &src); 1522 } 1523 regalloc(&tmp, types[tptr], &r0); 1524 f = sysfunc("duffcopy"); 1525 p = gins(ADUFFCOPY, N, f); 1526 afunclit(&p->to, f); 1527 // 8 and 128 = magic constants: see ../../pkg/runtime/asm_arm.s 1528 p->to.offset = 8*(128-c); 1529 1530 regfree(&tmp); 1531 regfree(&src); 1532 regfree(&dst); 1533 return; 1534 } 1535 1536 if(n->ullman >= res->ullman) { 1537 agenr(n, &dst, res); // temporarily use dst 1538 regalloc(&src, types[tptr], N); 1539 gins(AMOVW, &dst, &src); 1540 if(res->op == ONAME) 1541 gvardef(res); 1542 agen(res, &dst); 1543 } else { 1544 if(res->op == ONAME) 1545 gvardef(res); 1546 agenr(res, &dst, res); 1547 agenr(n, &src, N); 1548 } 1549 1550 regalloc(&tmp, types[TUINT32], N); 1551 1552 // set up end marker 1553 memset(&nend, 0, sizeof nend); 1554 if(c >= 4) { 1555 regalloc(&nend, types[TUINT32], N); 1556 1557 p = gins(AMOVW, &src, &nend); 1558 p->from.type = D_CONST; 1559 if(dir < 0) 1560 p->from.offset = dir; 1561 else 1562 p->from.offset = w; 1563 } 1564 1565 // move src and dest to the end of block if necessary 1566 if(dir < 0) { 1567 p = gins(AMOVW, &src, &src); 1568 p->from.type = D_CONST; 1569 p->from.offset = w + dir; 1570 1571 p = gins(AMOVW, &dst, &dst); 1572 p->from.type = D_CONST; 1573 p->from.offset = w + dir; 1574 } 1575 1576 // move 1577 if(c >= 4) { 1578 p = gins(op, &src, &tmp); 1579 p->from.type = D_OREG; 1580 p->from.offset = dir; 1581 p->scond |= C_PBIT; 1582 ploop = p; 1583 1584 p = gins(op, &tmp, &dst); 1585 p->to.type = D_OREG; 1586 p->to.offset = dir; 1587 p->scond |= C_PBIT; 1588 1589 p = gins(ACMP, &src, N); 1590 raddr(&nend, p); 1591 1592 patch(gbranch(ABNE, T, 0), ploop); 1593 regfree(&nend); 1594 } else { 1595 while(c-- > 0) { 1596 p = gins(op, &src, &tmp); 1597 p->from.type = D_OREG; 1598 p->from.offset = dir; 1599 p->scond |= C_PBIT; 1600 1601 p = gins(op, &tmp, &dst); 1602 p->to.type = D_OREG; 1603 p->to.offset = dir; 1604 p->scond |= C_PBIT; 1605 } 1606 } 1607 1608 regfree(&dst); 1609 regfree(&src); 1610 regfree(&tmp); 1611 } 1612 1613 static int 1614 cadable(Node *n) 1615 { 1616 if(!n->addable) { 1617 // dont know how it happens, 1618 // but it does 1619 return 0; 1620 } 1621 1622 switch(n->op) { 1623 case ONAME: 1624 return 1; 1625 } 1626 return 0; 1627 } 1628 1629 /* 1630 * copy a composite value by moving its individual components. 1631 * Slices, strings and interfaces are supported. 1632 * nr is N when assigning a zero value. 1633 * return 1 if can do, 0 if cant. 1634 */ 1635 int 1636 componentgen(Node *nr, Node *nl) 1637 { 1638 Node nodl, nodr, tmp; 1639 int freel, freer; 1640 1641 freel = 0; 1642 freer = 0; 1643 1644 switch(nl->type->etype) { 1645 default: 1646 goto no; 1647 1648 case TARRAY: 1649 if(!isslice(nl->type)) 1650 goto no; 1651 case TSTRING: 1652 case TINTER: 1653 break; 1654 } 1655 1656 nodl = *nl; 1657 if(!cadable(nl)) { 1658 if(nr == N || !cadable(nr)) 1659 goto no; 1660 igen(nl, &nodl, N); 1661 freel = 1; 1662 } 1663 1664 if(nr != N) { 1665 nodr = *nr; 1666 if(!cadable(nr)) { 1667 igen(nr, &nodr, N); 1668 freer = 1; 1669 } 1670 } else { 1671 // When zeroing, prepare a register containing zero. 1672 nodconst(&tmp, nl->type, 0); 1673 regalloc(&nodr, types[TUINT], N); 1674 gmove(&tmp, &nodr); 1675 freer = 1; 1676 } 1677 1678 // nl and nr are 'cadable' which basically means they are names (variables) now. 1679 // If they are the same variable, don't generate any code, because the 1680 // VARDEF we generate will mark the old value as dead incorrectly. 1681 // (And also the assignments are useless.) 1682 if(nr != N && nl->op == ONAME && nr->op == ONAME && nl == nr) 1683 goto yes; 1684 1685 switch(nl->type->etype) { 1686 case TARRAY: 1687 if(nl->op == ONAME) 1688 gvardef(nl); 1689 nodl.xoffset += Array_array; 1690 nodl.type = ptrto(nl->type->type); 1691 1692 if(nr != N) { 1693 nodr.xoffset += Array_array; 1694 nodr.type = nodl.type; 1695 } 1696 gmove(&nodr, &nodl); 1697 1698 nodl.xoffset += Array_nel-Array_array; 1699 nodl.type = types[simtype[TUINT]]; 1700 1701 if(nr != N) { 1702 nodr.xoffset += Array_nel-Array_array; 1703 nodr.type = nodl.type; 1704 } 1705 gmove(&nodr, &nodl); 1706 1707 nodl.xoffset += Array_cap-Array_nel; 1708 nodl.type = types[simtype[TUINT]]; 1709 1710 if(nr != N) { 1711 nodr.xoffset += Array_cap-Array_nel; 1712 nodr.type = nodl.type; 1713 } 1714 gmove(&nodr, &nodl); 1715 1716 goto yes; 1717 1718 case TSTRING: 1719 if(nl->op == ONAME) 1720 gvardef(nl); 1721 nodl.xoffset += Array_array; 1722 nodl.type = ptrto(types[TUINT8]); 1723 1724 if(nr != N) { 1725 nodr.xoffset += Array_array; 1726 nodr.type = nodl.type; 1727 } 1728 gmove(&nodr, &nodl); 1729 1730 nodl.xoffset += Array_nel-Array_array; 1731 nodl.type = types[simtype[TUINT]]; 1732 1733 if(nr != N) { 1734 nodr.xoffset += Array_nel-Array_array; 1735 nodr.type = nodl.type; 1736 } 1737 gmove(&nodr, &nodl); 1738 1739 goto yes; 1740 1741 case TINTER: 1742 if(nl->op == ONAME) 1743 gvardef(nl); 1744 nodl.xoffset += Array_array; 1745 nodl.type = ptrto(types[TUINT8]); 1746 1747 if(nr != N) { 1748 nodr.xoffset += Array_array; 1749 nodr.type = nodl.type; 1750 } 1751 gmove(&nodr, &nodl); 1752 1753 nodl.xoffset += Array_nel-Array_array; 1754 nodl.type = ptrto(types[TUINT8]); 1755 1756 if(nr != N) { 1757 nodr.xoffset += Array_nel-Array_array; 1758 nodr.type = nodl.type; 1759 } 1760 gmove(&nodr, &nodl); 1761 1762 goto yes; 1763 } 1764 1765 no: 1766 if(freer) 1767 regfree(&nodr); 1768 if(freel) 1769 regfree(&nodl); 1770 return 0; 1771 1772 yes: 1773 if(freer) 1774 regfree(&nodr); 1775 if(freel) 1776 regfree(&nodl); 1777 return 1; 1778 }