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