1 # ifndef lint 2 static char *sccsid ="@(#)local2.c 1.34 (Berkeley) 12/11/87"; 3 # endif 4 5 # include "pass2.h" 6 # include <ctype.h> 7 8 # define putstr(s) fputs((s), stdout) 9 10 # ifdef FORT 11 int ftlab1, ftlab2; 12 # endif 13 /* a lot of the machine dependent parts of the second pass */ 14 15 # define BITMASK(n) ((1L<<n)-1) 16 17 /*ARGSUSED*/ 18 where(c){ 19 fprintf( stderr, "%s, line %d: ", filename, lineno ); 20 } 21 22 lineid( l, fn ) char *fn; { 23 /* identify line l and file fn */ 24 printf( "# line %d, file %s\n", l, fn ); 25 } 26 27 28 eobl2(){ 29 register OFFSZ spoff; /* offset from stack pointer */ 30 #ifndef FORT 31 extern int ftlab1, ftlab2; 32 #endif 33 34 spoff = maxoff; 35 if( spoff >= AUTOINIT ) spoff -= AUTOINIT; 36 spoff /= SZCHAR; 37 SETOFF(spoff,4); 38 #ifdef FORT 39 #ifndef FLEXNAMES 40 printf( " .set .F%d,%ld\n", ftnno, spoff ); 41 #else 42 /* SHOULD BE L%d ... ftnno but must change pc/f77 */ 43 printf( " .set LF%d,%ld\n", ftnno, spoff ); 44 #endif 45 #else 46 printf( "L%d:\n", ftlab1); 47 if( spoff!=0 ) 48 if( spoff < 64 ) 49 printf( " subl2 $%ld,sp\n", spoff); 50 else 51 printf( " movab -%ld(sp),sp\n", spoff); 52 printf( " jbr L%d\n", ftlab2); 53 #endif 54 maxargs = -1; 55 } 56 57 struct hoptab { int opmask; char * opstring; } ioptab[] = { 58 59 PLUS, "add", 60 MINUS, "sub", 61 MUL, "mul", 62 DIV, "div", 63 OR, "bis", 64 ER, "xor", 65 AND, "bic", 66 -1, "" }; 67 68 hopcode( f, o ){ 69 /* output the appropriate string from the above table */ 70 71 register struct hoptab *q; 72 73 if(asgop(o)) 74 o = NOASG o; 75 for( q = ioptab; q->opmask>=0; ++q ){ 76 if( q->opmask == o ){ 77 printf( "%s%c", q->opstring, tolower(f)); 78 return; 79 } 80 } 81 cerror( "no hoptab for %s", opst[o] ); 82 } 83 84 char * 85 rnames[] = { /* keyed to register number tokens */ 86 87 "r0", "r1", 88 "r2", "r3", "r4", "r5", 89 "r6", "r7", "r8", "r9", "r10", "r11", 90 "ap", "fp", "sp", "pc", 91 }; 92 93 int rstatus[] = { 94 SAREG|STAREG, SAREG|STAREG, 95 SAREG|STAREG, SAREG|STAREG, SAREG|STAREG, SAREG|STAREG, 96 SAREG, SAREG, SAREG, SAREG, SAREG, SAREG, 97 SAREG, SAREG, SAREG, SAREG, 98 }; 99 100 tlen(p) NODE *p; 101 { 102 switch(p->in.type) { 103 case CHAR: 104 case UCHAR: 105 return(1); 106 107 case SHORT: 108 case USHORT: 109 return(SZSHORT/SZCHAR); 110 111 case DOUBLE: 112 return(SZDOUBLE/SZCHAR); 113 114 default: 115 return(SZINT/SZCHAR); 116 } 117 } 118 119 mixtypes(p, q) NODE *p, *q; 120 { 121 register TWORD tp, tq; 122 123 tp = p->in.type; 124 tq = q->in.type; 125 126 return( (tp==FLOAT || tp==DOUBLE) != 127 (tq==FLOAT || tq==DOUBLE) ); 128 } 129 130 prtype(n) NODE *n; 131 { 132 switch (n->in.type) 133 { 134 135 case DOUBLE: 136 putchar('d'); 137 return; 138 139 case FLOAT: 140 putchar('f'); 141 return; 142 143 case LONG: 144 case ULONG: 145 case INT: 146 case UNSIGNED: 147 putchar('l'); 148 return; 149 150 case SHORT: 151 case USHORT: 152 putchar('w'); 153 return; 154 155 case CHAR: 156 case UCHAR: 157 putchar('b'); 158 return; 159 160 default: 161 if ( !ISPTR( n->in.type ) ) cerror("zzzcode- bad type"); 162 else { 163 putchar('l'); 164 return; 165 } 166 } 167 } 168 169 zzzcode( p, c ) register NODE *p; { 170 register int m; 171 int val; 172 switch( c ){ 173 174 case 'N': /* logical ops, turned into 0-1 */ 175 /* use register given by register 1 */ 176 cbgen( 0, m=getlab(), 'I' ); 177 deflab( p->bn.label ); 178 printf( " clrl %s\n", rnames[getlr( p, '1' )->tn.rval] ); 179 deflab( m ); 180 return; 181 182 case 'P': 183 cbgen( p->in.op, p->bn.label, c ); 184 return; 185 186 case 'A': 187 case 'V': 188 sconv( p, c == 'V' ); 189 return; 190 191 case 'G': /* i *= f; asgops with int lhs and float rhs */ 192 { 193 register NODE *l, *r, *s; 194 int rt; 195 196 l = p->in.left; 197 r = p->in.right; 198 s = talloc(); 199 rt = r->in.type; 200 201 s->in.op = SCONV; 202 s->in.left = l; 203 s->in.type = rt; 204 zzzcode(s, 'A'); 205 putstr("\n\t"); 206 207 hopcode(rt == FLOAT ? 'F' : 'D', p->in.op); 208 putstr("2\t"); 209 adrput(r); 210 putchar(','); 211 adrput(resc); 212 putstr("\n\t"); 213 214 s->in.op = ASSIGN; 215 s->in.left = l; 216 s->in.right = resc; 217 s->in.type = l->in.type; 218 zzzcode(s, 'A'); 219 220 s->in.op = FREE; 221 return; 222 } 223 224 case 'J': /* unsigned DIV/MOD with constant divisors */ 225 { 226 register int ck = INAREG; 227 int label1, label2; 228 229 /* case constant <= 1 is handled by optim() in pass 1 */ 230 /* case constant < 0x80000000 is handled in table */ 231 switch( p->in.op ) { 232 /* case DIV: handled in optim2() */ 233 case MOD: 234 if( p->in.left->in.op == REG && 235 p->in.left->tn.rval == resc->tn.rval ) 236 goto asgmod; 237 label1 = getlab(); 238 expand(p, ck, "movl\tAL,A1\n\tcmpl\tA1,AR\n"); 239 printf("\tjlssu\tL%d\n", label1); 240 expand(p, ck, "\tsubl2\tAR,A1\n"); 241 printf("L%d:", label1); 242 break; 243 case ASG DIV: 244 label1 = getlab(); 245 label2 = getlab(); 246 expand(p, ck, "cmpl\tAL,AR\n"); 247 printf("\tjgequ\tL%d\n", label1); 248 expand(p, ck, "\tmovl\t$1,AL\n"); 249 printf("\tjbr\tL%d\nL%d:\n", label2, label1); 250 expand(p, ck, "\tclrl\tAL\n"); 251 printf("L%d:", label2); 252 break; 253 case ASG MOD: 254 asgmod: 255 label1 = getlab(); 256 expand(p, ck, "cmpl\tAL,AR\n"); 257 printf("\tjlssu\tL%d\n", label1); 258 expand(p, ck, "\tsubl2\tAR,AL\n"); 259 printf("L%d:", label1); 260 break; 261 } 262 return; 263 } 264 265 case 'B': /* get oreg value in temp register for left shift */ 266 { 267 register NODE *r; 268 if (xdebug) eprint(p, 0, &val, &val); 269 r = p->in.right; 270 if( tlen(r) == SZINT/SZCHAR && r->in.type != FLOAT ) 271 putstr("movl"); 272 else { 273 putstr(ISUNSIGNED(r->in.type) ? "movz" : "cvt"); 274 prtype(r); 275 putchar('l'); 276 } 277 return; 278 } 279 280 case 'C': /* num words pushed on arg stack */ 281 { 282 extern int gc_numbytes; 283 extern int xdebug; 284 285 if (xdebug) printf("->%d<-",gc_numbytes); 286 287 printf("$%d", gc_numbytes/(SZLONG/SZCHAR) ); 288 return; 289 } 290 291 case 'D': /* INCR and DECR */ 292 zzzcode(p->in.left, 'A'); 293 putchar('\n'); 294 putchar('\t'); 295 296 case 'E': /* INCR and DECR, FOREFF */ 297 if (p->in.right->in.op == ICON && p->in.right->tn.lval == 1) 298 { 299 putstr(p->in.op == INCR ? "inc" : "dec"); 300 prtype(p->in.left); 301 putchar('\t'); 302 adrput(p->in.left); 303 return; 304 } 305 putstr(p->in.op == INCR ? "add" : "sub"); 306 prtype(p->in.left); 307 putchar('2'); 308 putchar('\t'); 309 adrput(p->in.right); 310 putchar(','); 311 adrput(p->in.left); 312 return; 313 314 case 'F': /* register type of right operand */ 315 { 316 register NODE *n; 317 extern int xdebug; 318 register int ty; 319 320 n = getlr( p, 'R' ); 321 ty = n->in.type; 322 323 if (xdebug) printf("->%d<-", ty); 324 325 if ( ty==DOUBLE) putchar('d'); 326 else if ( ty==FLOAT ) putchar('f'); 327 else putchar('l'); 328 return; 329 } 330 331 case 'L': /* type of left operand */ 332 case 'R': /* type of right operand */ 333 { 334 register NODE *n; 335 extern int xdebug; 336 337 n = getlr( p, c ); 338 if (xdebug) printf("->%d<-", n->in.type); 339 340 prtype(n); 341 return; 342 } 343 344 case 'Z': /* AND for CC with ICON -- lval is complemented */ 345 { 346 register NODE *l, *r; 347 348 l = getlr( p, 'L' ); 349 r = getlr( p, 'R' ); 350 m = (1 << tlen(l) * SZCHAR) - 1; 351 r->tn.lval = ~r->tn.lval; 352 if( (l->in.type == CHAR || l->in.type == SHORT) && 353 (r->tn.lval & ~m) ) { 354 putstr("cvt"); 355 prtype(l); 356 putstr("l\t"); 357 adrput(l); 358 putchar(','); 359 adrput(resc); 360 putstr("\n\t"); 361 resc->tn.type = INT; 362 l = resc; 363 } 364 else if( l->in.type == UCHAR || l->in.type == USHORT ) 365 /* remove trash left over from complementing */ 366 r->tn.lval &= m; 367 putstr("bit"); 368 prtype(l); 369 printf("\t$%ld", r->tn.lval); 370 putchar(','); 371 adrput(l); 372 return; 373 } 374 375 case 'U': /* 32 - n, for unsigned right shifts */ 376 printf("$%d", 32 - p->in.right->tn.lval ); 377 return; 378 379 case 'T': /* rounded structure length for arguments */ 380 { 381 int size; 382 383 size = p->stn.stsize; 384 SETOFF( size, 4); 385 printf("$%d", size); 386 return; 387 } 388 389 case 'S': /* structure assignment */ 390 stasg(p); 391 break; 392 393 default: 394 cerror( "illegal zzzcode" ); 395 } 396 } 397 398 stasg(p) 399 register NODE *p; 400 { 401 register NODE *l, *r; 402 register size; 403 404 if( p->in.op == STASG ){ 405 l = p->in.left; 406 r = p->in.right; 407 408 } 409 else if( p->in.op == STARG ){ /* store an arg into a temporary */ 410 r = p->in.left; 411 } 412 else cerror( "STASG bad" ); 413 414 if( r->in.op == ICON ) r->in.op = NAME; 415 else if( r->in.op == REG ) r->in.op = OREG; 416 else if( r->in.op != OREG ) cerror( "STASG-r" ); 417 418 size = p->stn.stsize; 419 420 if( size <= 0 || size > 65535 ) 421 cerror("structure size <0=0 or >65535"); 422 423 switch(size) { 424 case 1: 425 putstr(" movb "); 426 break; 427 case 2: 428 putstr(" movw "); 429 break; 430 case 4: 431 putstr(" movl "); 432 break; 433 case 8: 434 putstr(" movq "); 435 break; 436 default: 437 printf(" movc3 $%d,", size); 438 break; 439 } 440 adrput(r); 441 if( p->in.op == STASG ){ 442 putchar(','); 443 adrput(l); 444 putchar('\n'); 445 } 446 else 447 putstr(",(sp)\n"); 448 449 if( r->in.op == NAME ) r->in.op = ICON; 450 else if( r->in.op == OREG ) r->in.op = REG; 451 } 452 453 NODE *makearg( ty ) int ty; { 454 register NODE *p, *q; 455 456 /* build a -(sp) operand */ 457 p = talloc(); 458 p->in.op = REG; 459 /* the type needn't be right, just consistent */ 460 p->in.type = INCREF(ty); 461 p->tn.rval = SP; 462 p->tn.lval = 0; 463 q = talloc(); 464 q->in.op = ASG MINUS; 465 q->in.type = INCREF(ty); 466 q->in.left = p; 467 p = talloc(); 468 p->in.op = ICON; 469 p->in.type = INT; 470 p->tn.name = ""; 471 p->tn.lval = szty(ty) * (SZINT/SZCHAR); 472 q->in.right = p; 473 p = talloc(); 474 p->in.op = UNARY MUL; 475 p->in.left = q; 476 return( p ); 477 } 478 479 sconv( p, forarg ) register NODE *p; { 480 register NODE *l, *r; 481 int m, val; 482 483 if (xdebug) eprint(p, 0, &val, &val); 484 r = getlr(p, 'R'); 485 if (p->in.op == ASSIGN) 486 l = getlr(p, 'L'); 487 else if (p->in.op == SCONV) { 488 m = r->in.type; 489 if (forarg) 490 l = makearg( m ); 491 else 492 l = resc; 493 l->in.type = m; 494 r = getlr(p, 'L'); 495 } 496 else { /* OPLTYPE */ 497 m = (r->in.type==FLOAT || r->in.type==DOUBLE ? r->in.type : INT); 498 if (forarg) 499 l = makearg( m ); 500 else 501 l = resc; 502 l->in.type = m; 503 } 504 if (r->in.op == ICON) 505 if (r->in.name[0] == '\0') { 506 if (r->tn.lval == 0 && !forarg) { 507 putstr("clr"); 508 prtype(l); 509 putchar('\t'); 510 adrput(l); 511 goto cleanup; 512 } 513 if (r->tn.lval < 0 && r->tn.lval >= -63) { 514 putstr("mneg"); 515 prtype(l); 516 r->tn.lval = -r->tn.lval; 517 goto ops; 518 } 519 if (r->tn.lval < 0) 520 r->in.type = r->tn.lval >= -128 ? CHAR 521 : (r->tn.lval >= -32768 ? SHORT 522 : INT); 523 else if (l->in.type == FLOAT || 524 l->in.type == DOUBLE) 525 r->in.type = r->tn.lval <= 63 ? INT 526 : (r->tn.lval <= 127 ? CHAR 527 : (r->tn.lval <= 32767 ? SHORT 528 : INT)); 529 else 530 r->in.type = r->tn.lval <= 63 ? INT 531 : (r->tn.lval <= 127 ? CHAR 532 : (r->tn.lval <= 255 ? UCHAR 533 : (r->tn.lval <= 32767 ? SHORT 534 : (r->tn.lval <= 65535 ? USHORT 535 : INT)))); 536 if (forarg && r->in.type == INT) { 537 putstr("pushl\t"); 538 adrput(r); 539 goto cleanup; 540 } 541 } 542 else { 543 if (forarg && tlen(r) == SZINT/SZCHAR) { 544 putstr("pushl\t"); 545 adrput(r); 546 goto cleanup; 547 } 548 putstr("moval\t"); 549 acon(r); 550 putchar(','); 551 adrput(l); 552 goto cleanup; 553 } 554 555 if (p->in.op == SCONV && 556 !(l->in.type == FLOAT || l->in.type == DOUBLE) && 557 !mixtypes(l, r)) { 558 /* 559 * Because registers must always contain objects 560 * of the same width as INTs, we may have to 561 * perform two conversions to get an INT. Can 562 * the conversions be collapsed into one? 563 */ 564 if (m = collapsible(l, r)) 565 r->in.type = m; 566 else { 567 /* 568 * Two steps are required. 569 */ 570 NODE *x; 571 572 if (forarg) { 573 x = resc; 574 x->in.type = l->in.type; 575 } 576 else { 577 x = &resc[1]; 578 *x = *l; 579 } 580 581 if (tlen(x) > tlen(r) && ISUNSIGNED(r->in.type)) 582 putstr("movz"); 583 else 584 putstr("cvt"); 585 prtype(r); 586 prtype(x); 587 putchar('\t'); 588 adrput(r); 589 putchar(','); 590 adrput(x); 591 putchar('\n'); 592 putchar('\t'); 593 r = x; 594 } 595 l->in.type = (ISUNSIGNED(l->in.type) ? UNSIGNED : INT); 596 } 597 598 if ((r->in.type == UNSIGNED || r->in.type == ULONG) && 599 mixtypes(l, r)) { 600 int label1, label2; 601 NODE *x = NULL; 602 603 #if defined(FORT) || defined(SPRECC) 604 if (forarg) 605 #else 606 if (forarg || l == resc) 607 #endif 608 { 609 /* compute in register, convert to double when done */ 610 x = l; 611 l = resc; 612 l->in.type = x->in.type; 613 } 614 615 label1 = getlab(); 616 label2 = getlab(); 617 618 putstr("movl\t"); 619 adrput(r); 620 putchar(','); 621 adrput(l); 622 putstr("\n\tjbsc\t$31,"); 623 adrput(l); 624 printf(",L%d\n\tcvtl", label1); 625 prtype(l); 626 putchar('\t'); 627 adrput(l); 628 putchar(','); 629 adrput(l); 630 printf("\n\tjbr\tL%d\nL%d:\n\tcvtl", label2, label1); 631 prtype(l); 632 putchar('\t'); 633 adrput(l); 634 putchar(','); 635 adrput(l); 636 putstr("\n\tadd"); 637 prtype(l); 638 putstr("2\t$0"); 639 prtype(l); 640 putstr("2.147483648e9,"); 641 adrput(l); 642 printf("\nL%d:", label2); 643 644 if (!forarg && (l->in.type == DOUBLE || l != resc)) 645 goto cleanup; 646 if (x != NULL) { 647 if (l == x) { 648 r = &resc[1]; 649 *r = *l; 650 } 651 else { 652 r = l; 653 l = x; 654 } 655 l->in.type = DOUBLE; 656 } 657 putstr("\n\t"); 658 } 659 660 if( (l->in.type == FLOAT || l->in.type == DOUBLE) && 661 (r->in.type == UCHAR || r->in.type == USHORT) ) { 662 /* skip unnecessary unsigned to floating conversion */ 663 #if defined(FORT) || defined(SPRECC) 664 if (forarg) 665 #else 666 if (forarg || l == resc) 667 #endif 668 l->in.type = DOUBLE; 669 putstr("movz"); 670 prtype(r); 671 putstr("l\t"); 672 adrput(r); 673 putchar(','); 674 adrput(resc); 675 putstr("\n\t"); 676 if (l == resc) { 677 r = &resc[1]; 678 *r = *l; 679 } 680 else 681 r = resc; 682 r->in.type = INT; 683 } 684 685 #if defined(FORT) || defined(SPRECC) 686 if (forarg && l->in.type == FLOAT) 687 #else 688 if ((forarg || l == resc) && l->in.type == FLOAT) 689 #endif 690 { 691 /* perform an implicit conversion to double */ 692 l->in.type = DOUBLE; 693 if (r->in.type != FLOAT && 694 r->in.type != CHAR && 695 r->in.type != SHORT) { 696 /* trim bits from the mantissa */ 697 putstr("cvt"); 698 prtype(r); 699 putstr("f\t"); 700 adrput(r); 701 putchar(','); 702 adrput(resc); 703 putstr("\n\t"); 704 if (l == resc) { 705 r = &resc[1]; 706 *r = *l; 707 } 708 else 709 r = resc; 710 r->in.type = FLOAT; 711 } 712 } 713 714 if (!mixtypes(l,r)) { 715 if (tlen(l) == tlen(r)) { 716 if (forarg && tlen(l) == SZINT/SZCHAR) { 717 putstr("pushl\t"); 718 adrput(r); 719 goto cleanup; 720 } 721 putstr("mov"); 722 #ifdef FORT 723 if (Oflag) 724 prtype(l); 725 else { 726 if (l->in.type == DOUBLE) 727 putchar('q'); 728 else if(l->in.type == FLOAT) 729 putchar('l'); 730 else 731 prtype(l); 732 } 733 #else 734 prtype(l); 735 #endif FORT 736 goto ops; 737 } 738 else if (tlen(l) > tlen(r) && ISUNSIGNED(r->in.type)) 739 putstr("movz"); 740 else 741 putstr("cvt"); 742 } 743 else 744 putstr("cvt"); 745 prtype(r); 746 prtype(l); 747 ops: 748 putchar('\t'); 749 adrput(r); 750 putchar(','); 751 adrput(l); 752 753 cleanup: 754 if (forarg) 755 tfree(l); 756 } 757 758 /* 759 * collapsible(dest, src) -- if a conversion with a register destination 760 * can be accomplished in one instruction, return the type of src 761 * that will do the job correctly; otherwise return 0. Note that 762 * a register must always end up having type INT or UNSIGNED. 763 */ 764 int 765 collapsible(dest, src) 766 NODE *dest, *src; 767 { 768 int st = src->in.type; 769 int dt = dest->in.type; 770 int newt = 0; 771 772 /* 773 * Are there side effects of evaluating src? 774 * If the derived type will not be the same size as src, 775 * we may have to use two steps. 776 */ 777 if (tlen(src) > tlen(dest)) { 778 if (tshape(src, STARREG)) 779 return (0); 780 if (src->in.op == OREG && R2TEST(src->tn.rval)) 781 return (0); 782 } 783 784 /* 785 * Can we get an object of dest's type by punning src? 786 * Praises be to great Cthulhu for little-endian machines... 787 */ 788 if (st == CHAR && dt == USHORT) 789 /* 790 * Special case -- we must sign-extend to 16 bits. 791 */ 792 return (0); 793 794 if (tlen(src) < tlen(dest)) 795 newt = st; 796 else 797 newt = dt; 798 799 return (newt); 800 } 801 802 rmove( rt, rs, t ) TWORD t; { 803 printf( " %s %s,%s\n", 804 #ifdef FORT 805 !Oflag ? (t==DOUBLE ? "movq" : "movl") : 806 #endif 807 (t==FLOAT ? "movf" : (t==DOUBLE ? "movd" : "movl")), 808 rnames[rs], rnames[rt] ); 809 } 810 811 struct respref 812 respref[] = { 813 INTAREG|INTBREG, INTAREG|INTBREG, 814 INAREG|INBREG, INAREG|INBREG|SOREG|STARREG|STARNM|SNAME|SCON, 815 INTEMP, INTEMP, 816 FORARG, FORARG, 817 INTEMP, INTAREG|INAREG|INTBREG|INBREG|SOREG|STARREG|STARNM, 818 0, 0 }; 819 820 setregs(){ /* set up temporary registers */ 821 fregs = 6; /* tbl- 6 free regs on VAX (0-5) */ 822 } 823 824 /*ARGSUSED*/ 825 rewfld( p ) NODE *p; { 826 return(1); 827 } 828 829 /*ARGSUSED*/ 830 callreg(p) NODE *p; { 831 return( R0 ); 832 } 833 834 base( p ) register NODE *p; { 835 register int o = p->in.op; 836 837 if( o==ICON && p->tn.name[0] != '\0' ) return( 100 ); /* ie no base reg */ 838 if( o==REG ) return( p->tn.rval ); 839 if( (o==PLUS || o==MINUS) && p->in.left->in.op == REG && p->in.right->in.op==ICON) 840 return( p->in.left->tn.rval ); 841 if( o==OREG && !R2TEST(p->tn.rval) && (p->in.type==INT || p->in.type==UNSIGNED || ISPTR(p->in.type)) ) 842 return( p->tn.rval + 0200*1 ); 843 if( o==INCR && p->in.left->in.op==REG ) return( p->in.left->tn.rval + 0200*2 ); 844 if( o==ASG MINUS && p->in.left->in.op==REG) return( p->in.left->tn.rval + 0200*4 ); 845 if( o==UNARY MUL && p->in.left->in.op==INCR && p->in.left->in.left->in.op==REG 846 && (p->in.type==INT || p->in.type==UNSIGNED || ISPTR(p->in.type)) ) 847 return( p->in.left->in.left->tn.rval + 0200*(1+2) ); 848 if( o==NAME ) return( 100 + 0200*1 ); 849 return( -1 ); 850 } 851 852 offset( p, tyl ) register NODE *p; int tyl; { 853 854 if( tyl==1 && 855 p->in.op==REG && 856 (p->in.type==INT || p->in.type==UNSIGNED) ) 857 return( p->tn.rval ); 858 if( p->in.op==LS && 859 p->in.left->in.op==REG && 860 (p->in.left->in.type==INT || p->in.left->in.type==UNSIGNED) && 861 p->in.right->in.op==ICON && 862 p->in.right->in.name[0]=='\0' && 863 (1<<p->in.right->tn.lval)==tyl) 864 return( p->in.left->tn.rval ); 865 if( tyl==2 && 866 p->in.op==PLUS && 867 (p->in.left->in.type==INT || p->in.left->in.type==UNSIGNED) && 868 p->in.left->in.op==REG && 869 p->in.right->in.op==REG && 870 p->in.left->tn.rval==p->in.right->tn.rval ) 871 return( p->in.left->tn.rval ); 872 return( -1 ); 873 } 874 875 makeor2( p, q, b, o) register NODE *p, *q; register int b, o; { 876 register NODE *t; 877 NODE *f; 878 879 p->in.op = OREG; 880 f = p->in.left; /* have to free this subtree later */ 881 882 /* init base */ 883 switch (q->in.op) { 884 case ICON: 885 case REG: 886 case OREG: 887 case NAME: 888 t = q; 889 break; 890 891 case MINUS: 892 q->in.right->tn.lval = -q->in.right->tn.lval; 893 case PLUS: 894 t = q->in.right; 895 break; 896 897 case INCR: 898 case ASG MINUS: 899 t = q->in.left; 900 break; 901 902 case UNARY MUL: 903 t = q->in.left->in.left; 904 break; 905 906 default: 907 cerror("illegal makeor2"); 908 } 909 910 p->tn.lval = t->tn.lval; 911 #ifndef FLEXNAMES 912 { 913 register int i; 914 for(i=0; i<NCHNAM; ++i) 915 p->in.name[i] = t->in.name[i]; 916 } 917 #else 918 p->in.name = t->in.name; 919 #endif 920 921 /* init offset */ 922 p->tn.rval = R2PACK( (b & 0177), o, (b>>7) ); 923 924 tfree(f); 925 return; 926 } 927 928 canaddr( p ) NODE *p; { 929 register int o = p->in.op; 930 931 if( o==NAME || o==REG || o==ICON || o==OREG || (o==UNARY MUL && shumul(p->in.left)) ) return(1); 932 return(0); 933 } 934 935 flshape( p ) NODE *p; { 936 register int o = p->in.op; 937 938 return( o == REG || o == NAME || o == ICON || 939 (o == OREG && (!R2TEST(p->tn.rval) || tlen(p) == 1)) ); 940 } 941 942 /* INTEMP shapes must not contain any temporary registers */ 943 shtemp( p ) register NODE *p; { 944 int r; 945 946 if( p->in.op == STARG ) p = p->in.left; 947 948 switch (p->in.op) { 949 case REG: 950 return( !istreg(p->tn.rval) ); 951 case OREG: 952 r = p->tn.rval; 953 if( R2TEST(r) ) { 954 if( istreg(R2UPK1(r)) ) 955 return(0); 956 r = R2UPK2(r); 957 } 958 return( !istreg(r) ); 959 case UNARY MUL: 960 p = p->in.left; 961 return( p->in.op != UNARY MUL && shtemp(p) ); 962 } 963 964 if( optype( p->in.op ) != LTYPE ) return(0); 965 return(1); 966 } 967 968 shumul( p ) register NODE *p; { 969 register int o; 970 extern int xdebug; 971 972 if (xdebug) { 973 int val; 974 printf("shumul:\n"); 975 eprint(p, 0, &val, &val); 976 } 977 978 o = p->in.op; 979 if( o == NAME || (o == OREG && !R2TEST(p->tn.rval)) || o == ICON ) return( STARNM ); 980 981 if( ( o == INCR || o == ASG MINUS ) && 982 ( p->in.left->in.op == REG && p->in.right->in.op == ICON ) && 983 p->in.right->in.name[0] == '\0' ) 984 { 985 switch (p->in.type) 986 { 987 case CHAR|PTR: 988 case UCHAR|PTR: 989 o = 1; 990 break; 991 992 case SHORT|PTR: 993 case USHORT|PTR: 994 o = 2; 995 break; 996 997 case INT|PTR: 998 case UNSIGNED|PTR: 999 case LONG|PTR: 1000 case ULONG|PTR: 1001 case FLOAT|PTR: 1002 o = 4; 1003 break; 1004 1005 case DOUBLE|PTR: 1006 o = 8; 1007 break; 1008 1009 default: 1010 if ( ISPTR(p->in.type) && 1011 ISPTR(DECREF(p->in.type)) ) { 1012 o = 4; 1013 break; 1014 } 1015 else return(0); 1016 } 1017 return( p->in.right->tn.lval == o ? STARREG : 0); 1018 } 1019 1020 return( 0 ); 1021 } 1022 1023 adrcon( val ) CONSZ val; { 1024 putchar( '$' ); 1025 printf( CONFMT, val ); 1026 } 1027 1028 conput( p ) register NODE *p; { 1029 switch( p->in.op ){ 1030 1031 case ICON: 1032 acon( p ); 1033 return; 1034 1035 case REG: 1036 putstr( rnames[p->tn.rval] ); 1037 return; 1038 1039 default: 1040 cerror( "illegal conput" ); 1041 } 1042 } 1043 1044 /*ARGSUSED*/ 1045 insput( p ) NODE *p; { 1046 cerror( "insput" ); 1047 } 1048 1049 upput( p, size ) NODE *p; int size; { 1050 if( size == SZLONG && p->in.op == REG ) { 1051 putstr( rnames[p->tn.rval + 1] ); 1052 return; 1053 } 1054 cerror( "upput" ); 1055 } 1056 1057 adrput( p ) register NODE *p; { 1058 register int r; 1059 /* output an address, with offsets, from p */ 1060 1061 if( p->in.op == FLD ){ 1062 p = p->in.left; 1063 } 1064 switch( p->in.op ){ 1065 1066 case NAME: 1067 acon( p ); 1068 return; 1069 1070 case ICON: 1071 /* addressable value of the constant */ 1072 putchar( '$' ); 1073 acon( p ); 1074 return; 1075 1076 case REG: 1077 putstr( rnames[p->tn.rval] ); 1078 return; 1079 1080 case OREG: 1081 r = p->tn.rval; 1082 if( R2TEST(r) ){ /* double indexing */ 1083 register int flags; 1084 1085 flags = R2UPK3(r); 1086 if( flags & 1 ) putchar('*'); 1087 if( flags & 4 ) putchar('-'); 1088 if( p->tn.lval != 0 || p->in.name[0] != '\0' ) acon(p); 1089 if( R2UPK1(r) != 100) printf( "(%s)", rnames[R2UPK1(r)] ); 1090 if( flags & 2 ) putchar('+'); 1091 printf( "[%s]", rnames[R2UPK2(r)] ); 1092 return; 1093 } 1094 if( r == AP ){ /* in the argument region */ 1095 if( p->in.name[0] != '\0' ) werror( "bad arg temp" ); 1096 printf( CONFMT, p->tn.lval ); 1097 putstr( "(ap)" ); 1098 return; 1099 } 1100 if( p->tn.lval != 0 || p->in.name[0] != '\0') acon( p ); 1101 printf( "(%s)", rnames[p->tn.rval] ); 1102 return; 1103 1104 case UNARY MUL: 1105 /* STARNM or STARREG found */ 1106 if( tshape(p, STARNM) ) { 1107 putchar( '*' ); 1108 adrput( p->in.left); 1109 } 1110 else { /* STARREG - really auto inc or dec */ 1111 register NODE *q; 1112 1113 q = p->in.left; 1114 if( q->in.right->tn.lval != tlen(p) ) 1115 cerror("adrput: bad auto-increment/decrement"); 1116 printf("%s(%s)%s", (q->in.op==INCR ? "" : "-"), 1117 rnames[q->in.left->tn.rval], 1118 (q->in.op==INCR ? "+" : "") ); 1119 p->in.op = OREG; 1120 p->tn.rval = q->in.left->tn.rval; 1121 p->tn.lval = (q->in.op == INCR ? -q->in.right->tn.lval : 0); 1122 #ifndef FLEXNAMES 1123 p->in.name[0] = '\0'; 1124 #else 1125 p->in.name = ""; 1126 #endif 1127 tfree(q); 1128 } 1129 return; 1130 1131 default: 1132 cerror( "illegal address" ); 1133 return; 1134 1135 } 1136 1137 } 1138 1139 acon( p ) register NODE *p; { /* print out a constant */ 1140 1141 if( p->in.name[0] == '\0' ) 1142 printf( CONFMT, p->tn.lval); 1143 else { 1144 #ifndef FLEXNAMES 1145 printf( "%.8s", p->in.name ); 1146 #else 1147 putstr( p->in.name ); 1148 #endif 1149 if( p->tn.lval != 0 ) { 1150 putchar( '+' ); 1151 printf( CONFMT, p->tn.lval ); 1152 } 1153 } 1154 } 1155 1156 genscall( p, cookie ) register NODE *p; { 1157 /* structure valued call */ 1158 return( gencall( p, cookie ) ); 1159 } 1160 1161 /* tbl */ 1162 int gc_numbytes; 1163 /* tbl */ 1164 1165 /*ARGSUSED*/ 1166 gencall( p, cookie ) register NODE *p; { 1167 /* generate the call given by p */ 1168 register NODE *p1; 1169 register int temp, temp1; 1170 register int m; 1171 1172 if( p->in.right ) temp = argsize( p->in.right ); 1173 else temp = 0; 1174 1175 if( p->in.op == STCALL || p->in.op == UNARY STCALL ){ 1176 /* set aside room for structure return */ 1177 1178 if( p->stn.stsize > temp ) temp1 = p->stn.stsize; 1179 else temp1 = temp; 1180 } 1181 1182 if( temp > maxargs ) maxargs = temp; 1183 SETOFF(temp1,4); 1184 1185 if( p->in.right ){ /* make temp node, put offset in, and generate args */ 1186 genargs( p->in.right ); 1187 } 1188 1189 p1 = p->in.left; 1190 if( p1->in.op != ICON ){ 1191 if( p1->in.op != REG ){ 1192 if( p1->in.op != OREG || R2TEST(p1->tn.rval) ){ 1193 if( p1->in.op != NAME ){ 1194 order( p1, INAREG ); 1195 } 1196 } 1197 } 1198 } 1199 1200 /* tbl 1201 setup gc_numbytes so reference to ZC works */ 1202 1203 gc_numbytes = temp&(0x3ff); 1204 /* tbl */ 1205 1206 p->in.op = UNARY CALL; 1207 m = match( p, INTAREG|INTBREG ); 1208 1209 /* compensate for deficiency in 'ret' instruction ... wah,kre */ 1210 /* (plus in assignment to gc_numbytes above, for neatness only) */ 1211 if (temp >= 1024) 1212 printf(" addl2 $%d,sp\n", (temp&(~0x3ff))); 1213 1214 return(m != MDONE); 1215 } 1216 1217 /* tbl */ 1218 char * 1219 ccbranches[] = { 1220 "eql", 1221 "neq", 1222 "leq", 1223 "lss", 1224 "geq", 1225 "gtr", 1226 "lequ", 1227 "lssu", 1228 "gequ", 1229 "gtru", 1230 }; 1231 /* tbl */ 1232 1233 /*ARGSUSED*/ 1234 cbgen( o, lab, mode ) { /* printf conditional and unconditional branches */ 1235 1236 if( o != 0 && ( o < EQ || o > UGT ) ) 1237 cerror( "bad conditional branch: %s", opst[o] ); 1238 printf( " j%s L%d\n", o == 0 ? "br" : ccbranches[o-EQ], lab ); 1239 } 1240 1241 nextcook( p, cookie ) NODE *p; { 1242 /* we have failed to match p with cookie; try another */ 1243 if( cookie == FORREW ) return( 0 ); /* hopeless! */ 1244 if( !(cookie&(INTAREG|INTBREG)) ) return( INTAREG|INTBREG ); 1245 if( !(cookie&INTEMP) && asgop(p->in.op) ) return( INTEMP|INAREG|INTAREG|INTBREG|INBREG ); 1246 return( FORREW ); 1247 } 1248 1249 /*ARGSUSED*/ 1250 lastchance( p, cook ) NODE *p; { 1251 /* forget it! */ 1252 return(0); 1253 } 1254 1255 optim2( p ) register NODE *p; { 1256 /* do local tree transformations and optimizations */ 1257 1258 int o; 1259 int i, mask; 1260 register NODE *l, *r; 1261 1262 switch( o = p->in.op ) { 1263 1264 case AND: 1265 /* commute L and R to eliminate complements and constants */ 1266 if( (l = p->in.left)->in.op == ICON && l->in.name[0] == 0 || 1267 l->in.op == COMPL ) { 1268 p->in.left = p->in.right; 1269 p->in.right = l; 1270 } 1271 case ASG AND: 1272 /* change meaning of AND to ~R&L - bic on pdp11 */ 1273 r = p->in.right; 1274 if( r->in.op==ICON && r->in.name[0]==0 ) { 1275 /* check for degenerate operations */ 1276 l = p->in.left; 1277 mask = (1 << tlen(l) * SZCHAR) - 1; 1278 if( ISUNSIGNED(r->in.type) ) { 1279 i = (~r->tn.lval & mask); 1280 if( i == 0 ) { 1281 r->in.op = FREE; 1282 ncopy(p, l); 1283 l->in.op = FREE; 1284 break; 1285 } 1286 else if( i == mask ) 1287 goto zero; 1288 else 1289 r->tn.lval = i; 1290 break; 1291 } 1292 else if( r->tn.lval == mask && 1293 tlen(l) < SZINT/SZCHAR ) { 1294 r->in.op = SCONV; 1295 r->in.left = l; 1296 r->in.right = 0; 1297 r->in.type = ENUNSIGN(l->in.type); 1298 r->in.su = l->in.su > 1 ? l->in.su : 1; 1299 ncopy(p, r); 1300 p->in.left = r; 1301 p->in.type = INT; 1302 break; 1303 } 1304 /* complement constant */ 1305 r->tn.lval = ~r->tn.lval; 1306 } 1307 else if( r->in.op==COMPL ) { /* ~~A => A */ 1308 r->in.op = FREE; 1309 p->in.right = r->in.left; 1310 } 1311 else { /* insert complement node */ 1312 p->in.right = l = talloc(); 1313 l->in.op = COMPL; 1314 l->in.rall = NOPREF; 1315 l->in.type = r->in.type; 1316 l->in.left = r; 1317 l->in.right = NULL; 1318 } 1319 break; 1320 1321 case SCONV: 1322 l = p->in.left; 1323 #if defined(FORT) || defined(SPRECC) 1324 if( p->in.type == FLOAT || p->in.type == DOUBLE || 1325 l->in.type == FLOAT || l->in.type == DOUBLE ) 1326 return; 1327 #else 1328 if( mixtypes(p, l) ) return; 1329 #endif 1330 if( l->in.op == PCONV ) 1331 return; 1332 if( (l->in.op == CALL || l->in.op == UNARY CALL) && 1333 l->in.type != INT && l->in.type != UNSIGNED ) 1334 return; 1335 1336 /* Only trust it to get it right if the size is the same */ 1337 if( tlen(p) != tlen(l) ) 1338 return; 1339 1340 /* clobber conversion */ 1341 if( l->in.op != FLD ) 1342 l->in.type = p->in.type; 1343 ncopy( p, l ); 1344 l->in.op = FREE; 1345 1346 break; 1347 1348 case ASSIGN: 1349 /* 1350 * Conversions are equivalent to assignments; 1351 * when the two operations are combined, 1352 * we can sometimes zap the conversion. 1353 */ 1354 r = p->in.right; 1355 l = p->in.left; 1356 if ( r->in.op == SCONV && 1357 !mixtypes(l, r) && 1358 l->in.op != FLD && 1359 tlen(l) == tlen(r) ) { 1360 p->in.right = r->in.left; 1361 r->in.op = FREE; 1362 } 1363 break; 1364 1365 case ULE: 1366 case ULT: 1367 case UGE: 1368 case UGT: 1369 p->in.op -= (UGE-GE); 1370 if( degenerate(p) ) 1371 break; 1372 p->in.op += (UGE-GE); 1373 break; 1374 1375 case EQ: 1376 case NE: 1377 case LE: 1378 case LT: 1379 case GE: 1380 case GT: 1381 if( p->in.left->in.op == SCONV && 1382 p->in.right->in.op == SCONV ) { 1383 l = p->in.left; 1384 r = p->in.right; 1385 if( l->in.type == DOUBLE && 1386 l->in.left->in.type == FLOAT && 1387 r->in.left->in.type == FLOAT ) { 1388 /* nuke the conversions */ 1389 p->in.left = l->in.left; 1390 p->in.right = r->in.left; 1391 l->in.op = FREE; 1392 r->in.op = FREE; 1393 } 1394 /* more? */ 1395 } 1396 (void) degenerate(p); 1397 break; 1398 1399 case DIV: 1400 if( p->in.right->in.op == ICON && 1401 p->in.right->tn.name[0] == '\0' && 1402 ISUNSIGNED(p->in.right->in.type) && 1403 (unsigned) p->in.right->tn.lval >= 0x80000000 ) { 1404 /* easy to do here, harder to do in zzzcode() */ 1405 p->in.op = UGE; 1406 break; 1407 } 1408 case MOD: 1409 case ASG DIV: 1410 case ASG MOD: 1411 /* 1412 * optimize DIV and MOD 1413 * 1414 * basically we spot UCHAR and USHORT and try to do them 1415 * as signed ints... apparently div+mul+sub is always 1416 * faster than ediv for finding MOD on the VAX, when 1417 * full unsigned MOD isn't needed. 1418 * 1419 * a curious fact: for MOD, cmp+sub and cmp+sub+cmp+sub 1420 * are faster for unsigned dividend and a constant divisor 1421 * in the right range (.5 to 1 of dividend's range for the 1422 * first, .333+ to .5 for the second). full unsigned is 1423 * already done cmp+sub in the appropriate case; the 1424 * other cases are less common and require more ambition. 1425 */ 1426 if( degenerate(p) ) 1427 break; 1428 l = p->in.left; 1429 r = p->in.right; 1430 if( !ISUNSIGNED(r->in.type) || 1431 tlen(l) >= SZINT/SZCHAR || 1432 !(tlen(r) < SZINT/SZCHAR || 1433 (r->in.op == ICON && r->tn.name[0] == '\0')) ) 1434 break; 1435 if( r->in.op == ICON ) 1436 r->tn.type = INT; 1437 else { 1438 NODE *t = talloc(); 1439 t->in.left = r; 1440 r = t; 1441 r->in.op = SCONV; 1442 r->in.type = INT; 1443 r->in.right = 0; 1444 p->in.right = r; 1445 } 1446 if( o == DIV || o == MOD ) { 1447 NODE *t = talloc(); 1448 t->in.left = l; 1449 l = t; 1450 l->in.op = SCONV; 1451 l->in.type = INT; 1452 l->in.right = 0; 1453 p->in.left = l; 1454 } 1455 /* handle asgops in table */ 1456 break; 1457 1458 case RS: 1459 case ASG RS: 1460 case LS: 1461 case ASG LS: 1462 /* pick up degenerate shifts */ 1463 l = p->in.left; 1464 r = p->in.right; 1465 if( !(r->in.op == ICON && r->tn.name[0] == '\0') ) 1466 break; 1467 i = r->tn.lval; 1468 if( i < 0 ) 1469 /* front end 'fixes' this? */ 1470 if( o == LS || o == ASG LS ) 1471 o += (RS-LS); 1472 else 1473 o += (LS-RS); 1474 if( (o == RS || o == ASG RS) && 1475 !ISUNSIGNED(l->in.type) ) 1476 /* can't optimize signed right shifts */ 1477 break; 1478 if( o == LS ) { 1479 if( i < SZINT ) 1480 break; 1481 } 1482 else { 1483 if( i < tlen(l) * SZCHAR ) 1484 break; 1485 } 1486 zero: 1487 if( !asgop( o ) ) 1488 if( tshape(l, SAREG|SNAME|SCON|SOREG|STARNM) ) { 1489 /* no side effects */ 1490 tfree(l); 1491 ncopy(p, r); 1492 r->in.op = FREE; 1493 p->tn.lval = 0; 1494 } 1495 else { 1496 p->in.op = COMOP; 1497 r->tn.lval = 0; 1498 } 1499 else { 1500 p->in.op = ASSIGN; 1501 r->tn.lval = 0; 1502 } 1503 break; 1504 } 1505 } 1506 1507 degenerate(p) register NODE *p; { 1508 int o; 1509 int result, i; 1510 int lower, upper; 1511 register NODE *l, *r; 1512 1513 /* 1514 * try to keep degenerate comparisons with constants 1515 * out of the table. 1516 */ 1517 r = p->in.right; 1518 l = p->in.left; 1519 if( r->in.op != ICON || 1520 r->tn.name[0] != '\0' || 1521 tlen(l) >= tlen(r) ) 1522 return (0); 1523 switch( l->in.type ) { 1524 case CHAR: 1525 lower = -(1 << SZCHAR - 1); 1526 upper = (1 << SZCHAR - 1) - 1; 1527 break; 1528 case UCHAR: 1529 lower = 0; 1530 upper = (1 << SZCHAR) - 1; 1531 break; 1532 case SHORT: 1533 lower = -(1 << SZSHORT - 1); 1534 upper = (1 << SZSHORT - 1) - 1; 1535 break; 1536 case USHORT: 1537 lower = 0; 1538 upper = (1 << SZSHORT) - 1; 1539 break; 1540 default: 1541 cerror("unsupported type in degenerate()"); 1542 } 1543 i = r->tn.lval; 1544 switch( o = p->in.op ) { 1545 case DIV: 1546 case ASG DIV: 1547 case MOD: 1548 case ASG MOD: 1549 /* DIV and MOD work like EQ */ 1550 case EQ: 1551 case NE: 1552 if( lower == 0 && (unsigned) i > upper ) 1553 result = o == NE; 1554 else if( i < lower || i > upper ) 1555 result = o == NE; 1556 else 1557 return (0); 1558 break; 1559 case LT: 1560 case GE: 1561 if( lower == 0 && (unsigned) i > upper ) 1562 result = o == LT; 1563 else if( i <= lower ) 1564 result = o != LT; 1565 else if( i > upper ) 1566 result = o == LT; 1567 else 1568 return (0); 1569 break; 1570 case LE: 1571 case GT: 1572 if( lower == 0 && (unsigned) i >= upper ) 1573 result = o == LE; 1574 else if( i < lower ) 1575 result = o != LE; 1576 else if( i >= upper ) 1577 result = o == LE; 1578 else 1579 return (0); 1580 break; 1581 default: 1582 cerror("unknown op in degenerate()"); 1583 } 1584 1585 if( o == MOD || o == ASG MOD ) { 1586 r->in.op = FREE; 1587 ncopy(p, l); 1588 l->in.op = FREE; 1589 } 1590 else if( o != ASG DIV && tshape(l, SAREG|SNAME|SCON|SOREG|STARNM) ) { 1591 /* no side effects */ 1592 tfree(l); 1593 ncopy(p, r); 1594 r->in.op = FREE; 1595 p->tn.lval = result; 1596 } 1597 else { 1598 if( o == ASG DIV ) 1599 p->in.op = ASSIGN; 1600 else { 1601 p->in.op = COMOP; 1602 r->tn.type = INT; 1603 } 1604 r->tn.lval = result; 1605 } 1606 if( logop(o) ) 1607 p->in.type = INT; 1608 1609 return (1); 1610 } 1611 1612 /* added by jwf */ 1613 struct functbl { 1614 int fop; 1615 TWORD ftype; 1616 char *func; 1617 } opfunc[] = { 1618 DIV, TANY, "udiv", 1619 MOD, TANY, "urem", 1620 ASG DIV, TANY, "audiv", 1621 ASG MOD, TANY, "aurem", 1622 0, 0, 0 }; 1623 1624 hardops(p) register NODE *p; { 1625 /* change hard to do operators into function calls. */ 1626 register NODE *q; 1627 register struct functbl *f; 1628 register o; 1629 NODE *old,*temp; 1630 1631 o = p->in.op; 1632 if( ! (optype(o)==BITYPE && 1633 (ISUNSIGNED(p->in.left->in.type) || 1634 ISUNSIGNED(p->in.right->in.type))) ) 1635 return; 1636 1637 for( f=opfunc; f->fop; f++ ) { 1638 if( o==f->fop ) goto convert; 1639 } 1640 return; 1641 1642 convert: 1643 if( p->in.right->in.op == ICON && p->in.right->tn.name[0] == '\0' ) 1644 /* 'J', 'K' in zzzcode() -- assumes DIV or MOD operations */ 1645 /* save a subroutine call -- use at most 5 instructions */ 1646 return; 1647 if( tlen(p->in.left) < SZINT/SZCHAR && tlen(p->in.right) < SZINT/SZCHAR ) 1648 /* optim2() will modify the op into an ordinary int op */ 1649 return; 1650 if( asgop( o ) ) { 1651 old = NIL; 1652 switch( p->in.left->in.op ){ 1653 case FLD: 1654 q = p->in.left->in.left; 1655 /* 1656 * rewrite (lval.fld /= rval); as 1657 * ((*temp).fld = udiv((*(temp = &lval)).fld,rval)); 1658 * else the compiler will evaluate lval twice. 1659 */ 1660 if( q->in.op == UNARY MUL ){ 1661 /* first allocate a temp storage */ 1662 temp = talloc(); 1663 temp->in.op = OREG; 1664 temp->tn.rval = TMPREG; 1665 temp->tn.lval = BITOOR(freetemp(1)); 1666 temp->in.type = INCREF(p->in.type); 1667 #ifdef FLEXNAMES 1668 temp->in.name = ""; 1669 #else 1670 temp->in.name[0] = '\0'; 1671 #endif 1672 old = q->in.left; 1673 q->in.left = temp; 1674 } 1675 /* fall thru ... */ 1676 1677 case REG: 1678 case NAME: 1679 case OREG: 1680 /* change ASG OP to a simple OP */ 1681 q = talloc(); 1682 q->in.op = NOASG p->in.op; 1683 q->in.rall = NOPREF; 1684 q->in.type = p->in.type; 1685 q->in.left = tcopy(p->in.left); 1686 q->in.right = p->in.right; 1687 p->in.op = ASSIGN; 1688 p->in.right = q; 1689 p = q; 1690 f -= 2; /* Note: this depends on the table order */ 1691 /* on the right side only - replace *temp with 1692 *(temp = &lval), build the assignment node */ 1693 if( old ){ 1694 temp = q->in.left->in.left; /* the "*" node */ 1695 q = talloc(); 1696 q->in.op = ASSIGN; 1697 q->in.left = temp->in.left; 1698 q->in.right = old; 1699 q->in.type = old->in.type; 1700 #ifdef FLEXNAMES 1701 q->in.name = ""; 1702 #else 1703 q->in.name[0] = '\0'; 1704 #endif 1705 temp->in.left = q; 1706 } 1707 break; 1708 1709 case UNARY MUL: 1710 /* avoid doing side effects twice */ 1711 q = p->in.left; 1712 p->in.left = q->in.left; 1713 q->in.op = FREE; 1714 break; 1715 1716 default: 1717 cerror( "hardops: can't compute & LHS" ); 1718 } 1719 } 1720 1721 /* build comma op for args to function */ 1722 q = talloc(); 1723 q->in.op = CM; 1724 q->in.rall = NOPREF; 1725 q->in.type = INT; 1726 q->in.left = p->in.left; 1727 q->in.right = p->in.right; 1728 p->in.op = CALL; 1729 p->in.right = q; 1730 1731 /* put function name in left node of call */ 1732 p->in.left = q = talloc(); 1733 q->in.op = ICON; 1734 q->in.rall = NOPREF; 1735 q->in.type = INCREF( FTN + p->in.type ); 1736 #ifndef FLEXNAMES 1737 strcpy( q->in.name, f->func ); 1738 #else 1739 q->in.name = f->func; 1740 #endif 1741 q->tn.lval = 0; 1742 q->tn.rval = 0; 1743 1744 } 1745 1746 zappost(p) NODE *p; { 1747 /* look for ++ and -- operators and remove them */ 1748 1749 register int o, ty; 1750 register NODE *q; 1751 o = p->in.op; 1752 ty = optype( o ); 1753 1754 switch( o ){ 1755 1756 case INCR: 1757 case DECR: 1758 q = p->in.left; 1759 p->in.right->in.op = FREE; /* zap constant */ 1760 ncopy( p, q ); 1761 q->in.op = FREE; 1762 return; 1763 1764 } 1765 1766 if( ty == BITYPE ) zappost( p->in.right ); 1767 if( ty != LTYPE ) zappost( p->in.left ); 1768 } 1769 1770 fixpre(p) NODE *p; { 1771 1772 register int o, ty; 1773 o = p->in.op; 1774 ty = optype( o ); 1775 1776 switch( o ){ 1777 1778 case ASG PLUS: 1779 p->in.op = PLUS; 1780 break; 1781 case ASG MINUS: 1782 p->in.op = MINUS; 1783 break; 1784 } 1785 1786 if( ty == BITYPE ) fixpre( p->in.right ); 1787 if( ty != LTYPE ) fixpre( p->in.left ); 1788 } 1789 1790 /*ARGSUSED*/ 1791 NODE * addroreg(l) NODE *l; 1792 /* OREG was built in clocal() 1793 * for an auto or formal parameter 1794 * now its address is being taken 1795 * local code must unwind it 1796 * back to PLUS/MINUS REG ICON 1797 * according to local conventions 1798 */ 1799 { 1800 cerror("address of OREG taken"); 1801 /*NOTREACHED*/ 1802 } 1803 1804 1805 1806 # ifndef ONEPASS 1807 main( argc, argv ) char *argv[]; { 1808 return( mainp2( argc, argv ) ); 1809 } 1810 # endif 1811 1812 strip(p) register NODE *p; { 1813 NODE *q; 1814 1815 /* strip nodes off the top when no side effects occur */ 1816 for( ; ; ) { 1817 switch( p->in.op ) { 1818 case SCONV: /* remove lint tidbits */ 1819 q = p->in.left; 1820 ncopy( p, q ); 1821 q->in.op = FREE; 1822 break; 1823 /* could probably add a few more here */ 1824 default: 1825 return; 1826 } 1827 } 1828 } 1829 1830 myreader(p) register NODE *p; { 1831 strip( p ); /* strip off operations with no side effects */ 1832 canon( p ); /* expands r-vals for fields */ 1833 walkf( p, hardops ); /* convert ops to function calls */ 1834 walkf( p, optim2 ); 1835 } 1836