1 # ifndef lint 2 static char *sccsid ="@(#)local2.c 1.33 (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 #if defined(FORT) || defined(SPRECC) 489 m = r->in.type; 490 #else 491 m = r->in.type==FLOAT ? DOUBLE : r->in.type; 492 #endif 493 if (forarg) 494 l = makearg( m ); 495 else 496 l = resc; 497 l->in.type = m; 498 r = getlr(p, 'L'); 499 } 500 else { /* OPLTYPE */ 501 #if defined(FORT) || defined(SPRECC) 502 m = (r->in.type==FLOAT || r->in.type==DOUBLE ? r->in.type : INT); 503 #else 504 m = (r->in.type==FLOAT || r->in.type==DOUBLE ? DOUBLE : INT); 505 #endif 506 if (forarg) 507 l = makearg( m ); 508 else 509 l = resc; 510 l->in.type = m; 511 } 512 if (r->in.op == ICON) 513 if (r->in.name[0] == '\0') { 514 if (r->tn.lval == 0 && !forarg) { 515 putstr("clr"); 516 prtype(l); 517 putchar('\t'); 518 adrput(l); 519 goto cleanup; 520 } 521 if (r->tn.lval < 0 && r->tn.lval >= -63) { 522 putstr("mneg"); 523 prtype(l); 524 r->tn.lval = -r->tn.lval; 525 goto ops; 526 } 527 if (r->tn.lval < 0) 528 r->in.type = r->tn.lval >= -128 ? CHAR 529 : (r->tn.lval >= -32768 ? SHORT 530 : INT); 531 else if (l->in.type == FLOAT || 532 l->in.type == DOUBLE) 533 r->in.type = r->tn.lval <= 63 ? INT 534 : (r->tn.lval <= 127 ? CHAR 535 : (r->tn.lval <= 32767 ? SHORT 536 : INT)); 537 else 538 r->in.type = r->tn.lval <= 63 ? INT 539 : (r->tn.lval <= 127 ? CHAR 540 : (r->tn.lval <= 255 ? UCHAR 541 : (r->tn.lval <= 32767 ? SHORT 542 : (r->tn.lval <= 65535 ? USHORT 543 : INT)))); 544 if (forarg && r->in.type == INT) { 545 putstr("pushl\t"); 546 adrput(r); 547 goto cleanup; 548 } 549 } 550 else { 551 if (forarg && tlen(r) == SZINT/SZCHAR) { 552 putstr("pushl\t"); 553 adrput(r); 554 goto cleanup; 555 } 556 putstr("moval\t"); 557 acon(r); 558 putchar(','); 559 adrput(l); 560 goto cleanup; 561 } 562 563 if (p->in.op == SCONV && 564 !(l->in.type == FLOAT || l->in.type == DOUBLE) && 565 !mixtypes(l, r)) { 566 /* 567 * Because registers must always contain objects 568 * of the same width as INTs, we may have to 569 * perform two conversions to get an INT. Can 570 * the conversions be collapsed into one? 571 */ 572 if (m = collapsible(l, r)) 573 r->in.type = m; 574 else { 575 /* 576 * Two steps are required. 577 */ 578 NODE *x = &resc[1]; 579 580 *x = *l; 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 602 label1 = getlab(); 603 label2 = getlab(); 604 605 putstr("movl\t"); 606 adrput(r); 607 putchar(','); 608 adrput(l); 609 putstr("\n\tjbsc\t$31,"); 610 adrput(l); 611 printf(",L%d\n\tcvtl", label1); 612 prtype(l); 613 putchar('\t'); 614 adrput(l); 615 putchar(','); 616 adrput(l); 617 printf("\n\tjbr\tL%d\nL%d:\n\tcvtl", label2, label1); 618 prtype(l); 619 putchar('\t'); 620 adrput(l); 621 putchar(','); 622 adrput(l); 623 putstr("\n\tadd"); 624 prtype(l); 625 putstr("2\t$0"); 626 prtype(l); 627 putstr("2.147483648e9,"); 628 adrput(l); 629 printf("\nL%d:", label2); 630 631 goto cleanup; 632 } 633 634 if (!mixtypes(l,r)) { 635 if (tlen(l) == tlen(r)) { 636 if (forarg && tlen(l) == SZINT/SZCHAR) { 637 putstr("pushl\t"); 638 adrput(r); 639 goto cleanup; 640 } 641 putstr("mov"); 642 #ifdef FORT 643 if (Oflag) 644 prtype(l); 645 else { 646 if (l->in.type == DOUBLE) 647 putchar('q'); 648 else if(l->in.type == FLOAT) 649 putchar('l'); 650 else 651 prtype(l); 652 } 653 #else 654 prtype(l); 655 #endif FORT 656 goto ops; 657 } 658 else if (tlen(l) > tlen(r) && ISUNSIGNED(r->in.type)) 659 putstr("movz"); 660 else 661 putstr("cvt"); 662 } 663 else 664 putstr("cvt"); 665 prtype(r); 666 prtype(l); 667 ops: 668 putchar('\t'); 669 adrput(r); 670 putchar(','); 671 adrput(l); 672 673 cleanup: 674 if (forarg) 675 tfree(l); 676 } 677 678 /* 679 * collapsible(dest, src) -- if a conversion with a register destination 680 * can be accomplished in one instruction, return the type of src 681 * that will do the job correctly; otherwise return 0. Note that 682 * a register must always end up having type INT or UNSIGNED. 683 */ 684 int 685 collapsible(dest, src) 686 NODE *dest, *src; 687 { 688 int st = src->in.type; 689 int dt = dest->in.type; 690 int newt = 0; 691 692 /* 693 * Are there side effects of evaluating src? 694 * If the derived type will not be the same size as src, 695 * we may have to use two steps. 696 */ 697 if (tlen(src) > tlen(dest)) { 698 if (tshape(src, STARREG)) 699 return (0); 700 if (src->in.op == OREG && R2TEST(src->tn.rval)) 701 return (0); 702 } 703 704 /* 705 * Can we get an object of dest's type by punning src? 706 * Praises be to great Cthulhu for little-endian machines... 707 */ 708 if (st == CHAR && dt == USHORT) 709 /* 710 * Special case -- we must sign-extend to 16 bits. 711 */ 712 return (0); 713 714 if (tlen(src) < tlen(dest)) 715 newt = st; 716 else 717 newt = dt; 718 719 return (newt); 720 } 721 722 rmove( rt, rs, t ) TWORD t; { 723 printf( " %s %s,%s\n", 724 #ifdef FORT 725 !Oflag ? (t==DOUBLE ? "movq" : "movl") : 726 #endif 727 (t==FLOAT ? "movf" : (t==DOUBLE ? "movd" : "movl")), 728 rnames[rs], rnames[rt] ); 729 } 730 731 struct respref 732 respref[] = { 733 INTAREG|INTBREG, INTAREG|INTBREG, 734 INAREG|INBREG, INAREG|INBREG|SOREG|STARREG|STARNM|SNAME|SCON, 735 INTEMP, INTEMP, 736 FORARG, FORARG, 737 INTEMP, INTAREG|INAREG|INTBREG|INBREG|SOREG|STARREG|STARNM, 738 0, 0 }; 739 740 setregs(){ /* set up temporary registers */ 741 fregs = 6; /* tbl- 6 free regs on VAX (0-5) */ 742 } 743 744 /*ARGSUSED*/ 745 rewfld( p ) NODE *p; { 746 return(1); 747 } 748 749 /*ARGSUSED*/ 750 callreg(p) NODE *p; { 751 return( R0 ); 752 } 753 754 base( p ) register NODE *p; { 755 register int o = p->in.op; 756 757 if( o==ICON && p->tn.name[0] != '\0' ) return( 100 ); /* ie no base reg */ 758 if( o==REG ) return( p->tn.rval ); 759 if( (o==PLUS || o==MINUS) && p->in.left->in.op == REG && p->in.right->in.op==ICON) 760 return( p->in.left->tn.rval ); 761 if( o==OREG && !R2TEST(p->tn.rval) && (p->in.type==INT || p->in.type==UNSIGNED || ISPTR(p->in.type)) ) 762 return( p->tn.rval + 0200*1 ); 763 if( o==INCR && p->in.left->in.op==REG ) return( p->in.left->tn.rval + 0200*2 ); 764 if( o==ASG MINUS && p->in.left->in.op==REG) return( p->in.left->tn.rval + 0200*4 ); 765 if( o==UNARY MUL && p->in.left->in.op==INCR && p->in.left->in.left->in.op==REG 766 && (p->in.type==INT || p->in.type==UNSIGNED || ISPTR(p->in.type)) ) 767 return( p->in.left->in.left->tn.rval + 0200*(1+2) ); 768 if( o==NAME ) return( 100 + 0200*1 ); 769 return( -1 ); 770 } 771 772 offset( p, tyl ) register NODE *p; int tyl; { 773 774 if( tyl==1 && 775 p->in.op==REG && 776 (p->in.type==INT || p->in.type==UNSIGNED) ) 777 return( p->tn.rval ); 778 if( p->in.op==LS && 779 p->in.left->in.op==REG && 780 (p->in.left->in.type==INT || p->in.left->in.type==UNSIGNED) && 781 p->in.right->in.op==ICON && 782 p->in.right->in.name[0]=='\0' && 783 (1<<p->in.right->tn.lval)==tyl) 784 return( p->in.left->tn.rval ); 785 if( tyl==2 && 786 p->in.op==PLUS && 787 (p->in.left->in.type==INT || p->in.left->in.type==UNSIGNED) && 788 p->in.left->in.op==REG && 789 p->in.right->in.op==REG && 790 p->in.left->tn.rval==p->in.right->tn.rval ) 791 return( p->in.left->tn.rval ); 792 return( -1 ); 793 } 794 795 makeor2( p, q, b, o) register NODE *p, *q; register int b, o; { 796 register NODE *t; 797 NODE *f; 798 799 p->in.op = OREG; 800 f = p->in.left; /* have to free this subtree later */ 801 802 /* init base */ 803 switch (q->in.op) { 804 case ICON: 805 case REG: 806 case OREG: 807 case NAME: 808 t = q; 809 break; 810 811 case MINUS: 812 q->in.right->tn.lval = -q->in.right->tn.lval; 813 case PLUS: 814 t = q->in.right; 815 break; 816 817 case INCR: 818 case ASG MINUS: 819 t = q->in.left; 820 break; 821 822 case UNARY MUL: 823 t = q->in.left->in.left; 824 break; 825 826 default: 827 cerror("illegal makeor2"); 828 } 829 830 p->tn.lval = t->tn.lval; 831 #ifndef FLEXNAMES 832 { 833 register int i; 834 for(i=0; i<NCHNAM; ++i) 835 p->in.name[i] = t->in.name[i]; 836 } 837 #else 838 p->in.name = t->in.name; 839 #endif 840 841 /* init offset */ 842 p->tn.rval = R2PACK( (b & 0177), o, (b>>7) ); 843 844 tfree(f); 845 return; 846 } 847 848 canaddr( p ) NODE *p; { 849 register int o = p->in.op; 850 851 if( o==NAME || o==REG || o==ICON || o==OREG || (o==UNARY MUL && shumul(p->in.left)) ) return(1); 852 return(0); 853 } 854 855 flshape( p ) NODE *p; { 856 register int o = p->in.op; 857 858 return( o == REG || o == NAME || o == ICON || 859 (o == OREG && (!R2TEST(p->tn.rval) || tlen(p) == 1)) ); 860 } 861 862 /* INTEMP shapes must not contain any temporary registers */ 863 shtemp( p ) register NODE *p; { 864 int r; 865 866 if( p->in.op == STARG ) p = p->in.left; 867 868 switch (p->in.op) { 869 case REG: 870 return( !istreg(p->tn.rval) ); 871 case OREG: 872 r = p->tn.rval; 873 if( R2TEST(r) ) { 874 if( istreg(R2UPK1(r)) ) 875 return(0); 876 r = R2UPK2(r); 877 } 878 return( !istreg(r) ); 879 case UNARY MUL: 880 p = p->in.left; 881 return( p->in.op != UNARY MUL && shtemp(p) ); 882 } 883 884 if( optype( p->in.op ) != LTYPE ) return(0); 885 return(1); 886 } 887 888 shumul( p ) register NODE *p; { 889 register int o; 890 extern int xdebug; 891 892 if (xdebug) { 893 int val; 894 printf("shumul:\n"); 895 eprint(p, 0, &val, &val); 896 } 897 898 o = p->in.op; 899 if( o == NAME || (o == OREG && !R2TEST(p->tn.rval)) || o == ICON ) return( STARNM ); 900 901 if( ( o == INCR || o == ASG MINUS ) && 902 ( p->in.left->in.op == REG && p->in.right->in.op == ICON ) && 903 p->in.right->in.name[0] == '\0' ) 904 { 905 switch (p->in.type) 906 { 907 case CHAR|PTR: 908 case UCHAR|PTR: 909 o = 1; 910 break; 911 912 case SHORT|PTR: 913 case USHORT|PTR: 914 o = 2; 915 break; 916 917 case INT|PTR: 918 case UNSIGNED|PTR: 919 case LONG|PTR: 920 case ULONG|PTR: 921 case FLOAT|PTR: 922 o = 4; 923 break; 924 925 case DOUBLE|PTR: 926 o = 8; 927 break; 928 929 default: 930 if ( ISPTR(p->in.type) && 931 ISPTR(DECREF(p->in.type)) ) { 932 o = 4; 933 break; 934 } 935 else return(0); 936 } 937 return( p->in.right->tn.lval == o ? STARREG : 0); 938 } 939 940 return( 0 ); 941 } 942 943 adrcon( val ) CONSZ val; { 944 putchar( '$' ); 945 printf( CONFMT, val ); 946 } 947 948 conput( p ) register NODE *p; { 949 switch( p->in.op ){ 950 951 case ICON: 952 acon( p ); 953 return; 954 955 case REG: 956 putstr( rnames[p->tn.rval] ); 957 return; 958 959 default: 960 cerror( "illegal conput" ); 961 } 962 } 963 964 /*ARGSUSED*/ 965 insput( p ) NODE *p; { 966 cerror( "insput" ); 967 } 968 969 upput( p, size ) NODE *p; int size; { 970 if( size == SZLONG && p->in.op == REG ) { 971 putstr( rnames[p->tn.rval + 1] ); 972 return; 973 } 974 cerror( "upput" ); 975 } 976 977 adrput( p ) register NODE *p; { 978 register int r; 979 /* output an address, with offsets, from p */ 980 981 if( p->in.op == FLD ){ 982 p = p->in.left; 983 } 984 switch( p->in.op ){ 985 986 case NAME: 987 acon( p ); 988 return; 989 990 case ICON: 991 /* addressable value of the constant */ 992 putchar( '$' ); 993 acon( p ); 994 return; 995 996 case REG: 997 putstr( rnames[p->tn.rval] ); 998 return; 999 1000 case OREG: 1001 r = p->tn.rval; 1002 if( R2TEST(r) ){ /* double indexing */ 1003 register int flags; 1004 1005 flags = R2UPK3(r); 1006 if( flags & 1 ) putchar('*'); 1007 if( flags & 4 ) putchar('-'); 1008 if( p->tn.lval != 0 || p->in.name[0] != '\0' ) acon(p); 1009 if( R2UPK1(r) != 100) printf( "(%s)", rnames[R2UPK1(r)] ); 1010 if( flags & 2 ) putchar('+'); 1011 printf( "[%s]", rnames[R2UPK2(r)] ); 1012 return; 1013 } 1014 if( r == AP ){ /* in the argument region */ 1015 if( p->in.name[0] != '\0' ) werror( "bad arg temp" ); 1016 printf( CONFMT, p->tn.lval ); 1017 putstr( "(ap)" ); 1018 return; 1019 } 1020 if( p->tn.lval != 0 || p->in.name[0] != '\0') acon( p ); 1021 printf( "(%s)", rnames[p->tn.rval] ); 1022 return; 1023 1024 case UNARY MUL: 1025 /* STARNM or STARREG found */ 1026 if( tshape(p, STARNM) ) { 1027 putchar( '*' ); 1028 adrput( p->in.left); 1029 } 1030 else { /* STARREG - really auto inc or dec */ 1031 register NODE *q; 1032 1033 q = p->in.left; 1034 if( q->in.right->tn.lval != tlen(p) ) 1035 cerror("adrput: bad auto-increment/decrement"); 1036 printf("%s(%s)%s", (q->in.op==INCR ? "" : "-"), 1037 rnames[q->in.left->tn.rval], 1038 (q->in.op==INCR ? "+" : "") ); 1039 p->in.op = OREG; 1040 p->tn.rval = q->in.left->tn.rval; 1041 p->tn.lval = (q->in.op == INCR ? -q->in.right->tn.lval : 0); 1042 #ifndef FLEXNAMES 1043 p->in.name[0] = '\0'; 1044 #else 1045 p->in.name = ""; 1046 #endif 1047 tfree(q); 1048 } 1049 return; 1050 1051 default: 1052 cerror( "illegal address" ); 1053 return; 1054 1055 } 1056 1057 } 1058 1059 acon( p ) register NODE *p; { /* print out a constant */ 1060 1061 if( p->in.name[0] == '\0' ) 1062 printf( CONFMT, p->tn.lval); 1063 else { 1064 #ifndef FLEXNAMES 1065 printf( "%.8s", p->in.name ); 1066 #else 1067 putstr( p->in.name ); 1068 #endif 1069 if( p->tn.lval != 0 ) { 1070 putchar( '+' ); 1071 printf( CONFMT, p->tn.lval ); 1072 } 1073 } 1074 } 1075 1076 genscall( p, cookie ) register NODE *p; { 1077 /* structure valued call */ 1078 return( gencall( p, cookie ) ); 1079 } 1080 1081 /* tbl */ 1082 int gc_numbytes; 1083 /* tbl */ 1084 1085 /*ARGSUSED*/ 1086 gencall( p, cookie ) register NODE *p; { 1087 /* generate the call given by p */ 1088 register NODE *p1; 1089 register int temp, temp1; 1090 register int m; 1091 1092 if( p->in.right ) temp = argsize( p->in.right ); 1093 else temp = 0; 1094 1095 if( p->in.op == STCALL || p->in.op == UNARY STCALL ){ 1096 /* set aside room for structure return */ 1097 1098 if( p->stn.stsize > temp ) temp1 = p->stn.stsize; 1099 else temp1 = temp; 1100 } 1101 1102 if( temp > maxargs ) maxargs = temp; 1103 SETOFF(temp1,4); 1104 1105 if( p->in.right ){ /* make temp node, put offset in, and generate args */ 1106 genargs( p->in.right ); 1107 } 1108 1109 p1 = p->in.left; 1110 if( p1->in.op != ICON ){ 1111 if( p1->in.op != REG ){ 1112 if( p1->in.op != OREG || R2TEST(p1->tn.rval) ){ 1113 if( p1->in.op != NAME ){ 1114 order( p1, INAREG ); 1115 } 1116 } 1117 } 1118 } 1119 1120 /* tbl 1121 setup gc_numbytes so reference to ZC works */ 1122 1123 gc_numbytes = temp&(0x3ff); 1124 /* tbl */ 1125 1126 p->in.op = UNARY CALL; 1127 m = match( p, INTAREG|INTBREG ); 1128 1129 /* compensate for deficiency in 'ret' instruction ... wah,kre */ 1130 /* (plus in assignment to gc_numbytes above, for neatness only) */ 1131 if (temp >= 1024) 1132 printf(" addl2 $%d,sp\n", (temp&(~0x3ff))); 1133 1134 return(m != MDONE); 1135 } 1136 1137 /* tbl */ 1138 char * 1139 ccbranches[] = { 1140 "eql", 1141 "neq", 1142 "leq", 1143 "lss", 1144 "geq", 1145 "gtr", 1146 "lequ", 1147 "lssu", 1148 "gequ", 1149 "gtru", 1150 }; 1151 /* tbl */ 1152 1153 /*ARGSUSED*/ 1154 cbgen( o, lab, mode ) { /* printf conditional and unconditional branches */ 1155 1156 if( o != 0 && ( o < EQ || o > UGT ) ) 1157 cerror( "bad conditional branch: %s", opst[o] ); 1158 printf( " j%s L%d\n", o == 0 ? "br" : ccbranches[o-EQ], lab ); 1159 } 1160 1161 nextcook( p, cookie ) NODE *p; { 1162 /* we have failed to match p with cookie; try another */ 1163 if( cookie == FORREW ) return( 0 ); /* hopeless! */ 1164 if( !(cookie&(INTAREG|INTBREG)) ) return( INTAREG|INTBREG ); 1165 if( !(cookie&INTEMP) && asgop(p->in.op) ) return( INTEMP|INAREG|INTAREG|INTBREG|INBREG ); 1166 return( FORREW ); 1167 } 1168 1169 /*ARGSUSED*/ 1170 lastchance( p, cook ) NODE *p; { 1171 /* forget it! */ 1172 return(0); 1173 } 1174 1175 optim2( p ) register NODE *p; { 1176 /* do local tree transformations and optimizations */ 1177 1178 int o; 1179 int i, mask; 1180 register NODE *l, *r; 1181 1182 switch( o = p->in.op ) { 1183 1184 case AND: 1185 /* commute L and R to eliminate complements and constants */ 1186 if( (l = p->in.left)->in.op == ICON && l->in.name[0] == 0 || 1187 l->in.op == COMPL ) { 1188 p->in.left = p->in.right; 1189 p->in.right = l; 1190 } 1191 case ASG AND: 1192 /* change meaning of AND to ~R&L - bic on pdp11 */ 1193 r = p->in.right; 1194 if( r->in.op==ICON && r->in.name[0]==0 ) { 1195 /* check for degenerate operations */ 1196 l = p->in.left; 1197 mask = (1 << tlen(l) * SZCHAR) - 1; 1198 if( ISUNSIGNED(r->in.type) ) { 1199 i = (~r->tn.lval & mask); 1200 if( i == 0 ) { 1201 r->in.op = FREE; 1202 ncopy(p, l); 1203 l->in.op = FREE; 1204 break; 1205 } 1206 else if( i == mask ) 1207 goto zero; 1208 else 1209 r->tn.lval = i; 1210 break; 1211 } 1212 else if( r->tn.lval == mask && 1213 tlen(l) < SZINT/SZCHAR ) { 1214 r->in.op = SCONV; 1215 r->in.left = l; 1216 r->in.right = 0; 1217 r->in.type = ENUNSIGN(l->in.type); 1218 r->in.su = l->in.su > 1 ? l->in.su : 1; 1219 ncopy(p, r); 1220 p->in.left = r; 1221 p->in.type = INT; 1222 break; 1223 } 1224 /* complement constant */ 1225 r->tn.lval = ~r->tn.lval; 1226 } 1227 else if( r->in.op==COMPL ) { /* ~~A => A */ 1228 r->in.op = FREE; 1229 p->in.right = r->in.left; 1230 } 1231 else { /* insert complement node */ 1232 p->in.right = l = talloc(); 1233 l->in.op = COMPL; 1234 l->in.rall = NOPREF; 1235 l->in.type = r->in.type; 1236 l->in.left = r; 1237 l->in.right = NULL; 1238 } 1239 break; 1240 1241 case SCONV: 1242 l = p->in.left; 1243 if( (l->in.type == UCHAR || l->in.type == USHORT) && 1244 (p->in.type == DOUBLE || p->in.type == FLOAT) ) { 1245 /* we can convert to INT without loss of significance */ 1246 r = talloc(); 1247 *r = *p; 1248 r->in.type = INT; 1249 p->in.left = r; 1250 #if !defined(FORT) && !defined(SPRECC) 1251 /* nothing to be 'gained' by a FLOAT conversion */ 1252 p->in.type = DOUBLE; 1253 #endif 1254 return; 1255 } 1256 #if defined(FORT) || defined(SPRECC) 1257 if( p->in.type == FLOAT || p->in.type == DOUBLE || 1258 l->in.type == FLOAT || l->in.type == DOUBLE ) 1259 return; 1260 #else 1261 if( mixtypes(p, l) ) return; 1262 #endif 1263 if( l->in.op == PCONV ) 1264 return; 1265 if( (l->in.op == CALL || l->in.op == UNARY CALL) && 1266 l->in.type != INT && l->in.type != UNSIGNED ) 1267 return; 1268 1269 /* Only trust it to get it right if the size is the same */ 1270 if( tlen(p) != tlen(l) ) 1271 return; 1272 1273 /* clobber conversion */ 1274 if( l->in.op != FLD ) 1275 l->in.type = p->in.type; 1276 ncopy( p, l ); 1277 l->in.op = FREE; 1278 1279 break; 1280 1281 case ASSIGN: 1282 /* 1283 * Conversions are equivalent to assignments; 1284 * when the two operations are combined, 1285 * we can sometimes zap the conversion. 1286 */ 1287 r = p->in.right; 1288 l = p->in.left; 1289 if ( r->in.op == SCONV && 1290 !mixtypes(l, r) && 1291 l->in.op != FLD && 1292 tlen(l) == tlen(r) ) { 1293 p->in.right = r->in.left; 1294 r->in.op = FREE; 1295 } 1296 else if( (r->in.type == UCHAR || r->in.type == USHORT) && 1297 (p->in.type == DOUBLE || p->in.type == FLOAT) ) { 1298 /* we can convert to INT without loss of significance */ 1299 l = talloc(); 1300 l->in.op = SCONV; 1301 l->in.rall = NOPREF; 1302 l->in.left = r; 1303 l->in.right = NULL; 1304 l->in.type = INT; 1305 p->in.right = r; 1306 return; 1307 } 1308 break; 1309 1310 case ULE: 1311 case ULT: 1312 case UGE: 1313 case UGT: 1314 p->in.op -= (UGE-GE); 1315 if( degenerate(p) ) 1316 break; 1317 p->in.op += (UGE-GE); 1318 break; 1319 1320 case EQ: 1321 case NE: 1322 case LE: 1323 case LT: 1324 case GE: 1325 case GT: 1326 if( p->in.left->in.op == SCONV && 1327 p->in.right->in.op == SCONV ) { 1328 l = p->in.left; 1329 r = p->in.right; 1330 if( l->in.type == DOUBLE && 1331 l->in.left->in.type == FLOAT && 1332 r->in.left->in.type == FLOAT ) { 1333 /* nuke the conversions */ 1334 p->in.left = l->in.left; 1335 p->in.right = r->in.left; 1336 l->in.op = FREE; 1337 r->in.op = FREE; 1338 } 1339 /* more? */ 1340 } 1341 (void) degenerate(p); 1342 break; 1343 1344 case DIV: 1345 if( p->in.right->in.op == ICON && 1346 p->in.right->tn.name[0] == '\0' && 1347 ISUNSIGNED(p->in.right->in.type) && 1348 (unsigned) p->in.right->tn.lval >= 0x80000000 ) { 1349 /* easy to do here, harder to do in zzzcode() */ 1350 p->in.op = UGE; 1351 break; 1352 } 1353 case MOD: 1354 case ASG DIV: 1355 case ASG MOD: 1356 /* 1357 * optimize DIV and MOD 1358 * 1359 * basically we spot UCHAR and USHORT and try to do them 1360 * as signed ints... apparently div+mul+sub is always 1361 * faster than ediv for finding MOD on the VAX, when 1362 * full unsigned MOD isn't needed. 1363 * 1364 * a curious fact: for MOD, cmp+sub and cmp+sub+cmp+sub 1365 * are faster for unsigned dividend and a constant divisor 1366 * in the right range (.5 to 1 of dividend's range for the 1367 * first, .333+ to .5 for the second). full unsigned is 1368 * already done cmp+sub in the appropriate case; the 1369 * other cases are less common and require more ambition. 1370 */ 1371 if( degenerate(p) ) 1372 break; 1373 l = p->in.left; 1374 r = p->in.right; 1375 if( !ISUNSIGNED(r->in.type) || 1376 tlen(l) >= SZINT/SZCHAR || 1377 !(tlen(r) < SZINT/SZCHAR || 1378 (r->in.op == ICON && r->tn.name[0] == '\0')) ) 1379 break; 1380 if( r->in.op == ICON ) 1381 r->tn.type = INT; 1382 else { 1383 NODE *t = talloc(); 1384 t->in.left = r; 1385 r = t; 1386 r->in.op = SCONV; 1387 r->in.type = INT; 1388 r->in.right = 0; 1389 p->in.right = r; 1390 } 1391 if( o == DIV || o == MOD ) { 1392 NODE *t = talloc(); 1393 t->in.left = l; 1394 l = t; 1395 l->in.op = SCONV; 1396 l->in.type = INT; 1397 l->in.right = 0; 1398 p->in.left = l; 1399 } 1400 /* handle asgops in table */ 1401 break; 1402 1403 case RS: 1404 case ASG RS: 1405 case LS: 1406 case ASG LS: 1407 /* pick up degenerate shifts */ 1408 l = p->in.left; 1409 r = p->in.right; 1410 if( !(r->in.op == ICON && r->tn.name[0] == '\0') ) 1411 break; 1412 i = r->tn.lval; 1413 if( i < 0 ) 1414 /* front end 'fixes' this? */ 1415 if( o == LS || o == ASG LS ) 1416 o += (RS-LS); 1417 else 1418 o += (LS-RS); 1419 if( (o == RS || o == ASG RS) && 1420 !ISUNSIGNED(l->in.type) ) 1421 /* can't optimize signed right shifts */ 1422 break; 1423 if( o == LS ) { 1424 if( i < SZINT ) 1425 break; 1426 } 1427 else { 1428 if( i < tlen(l) * SZCHAR ) 1429 break; 1430 } 1431 zero: 1432 if( !asgop( o ) ) 1433 if( tshape(l, SAREG|SNAME|SCON|SOREG|STARNM) ) { 1434 /* no side effects */ 1435 tfree(l); 1436 ncopy(p, r); 1437 r->in.op = FREE; 1438 p->tn.lval = 0; 1439 } 1440 else { 1441 p->in.op = COMOP; 1442 r->tn.lval = 0; 1443 } 1444 else { 1445 p->in.op = ASSIGN; 1446 r->tn.lval = 0; 1447 } 1448 break; 1449 } 1450 } 1451 1452 degenerate(p) register NODE *p; { 1453 int o; 1454 int result, i; 1455 int lower, upper; 1456 register NODE *l, *r; 1457 1458 /* 1459 * try to keep degenerate comparisons with constants 1460 * out of the table. 1461 */ 1462 r = p->in.right; 1463 l = p->in.left; 1464 if( r->in.op != ICON || 1465 r->tn.name[0] != '\0' || 1466 tlen(l) >= tlen(r) ) 1467 return (0); 1468 switch( l->in.type ) { 1469 case CHAR: 1470 lower = -(1 << SZCHAR - 1); 1471 upper = (1 << SZCHAR - 1) - 1; 1472 break; 1473 case UCHAR: 1474 lower = 0; 1475 upper = (1 << SZCHAR) - 1; 1476 break; 1477 case SHORT: 1478 lower = -(1 << SZSHORT - 1); 1479 upper = (1 << SZSHORT - 1) - 1; 1480 break; 1481 case USHORT: 1482 lower = 0; 1483 upper = (1 << SZSHORT) - 1; 1484 break; 1485 default: 1486 cerror("unsupported type in degenerate()"); 1487 } 1488 i = r->tn.lval; 1489 switch( o = p->in.op ) { 1490 case DIV: 1491 case ASG DIV: 1492 case MOD: 1493 case ASG MOD: 1494 /* DIV and MOD work like EQ */ 1495 case EQ: 1496 case NE: 1497 if( lower == 0 && (unsigned) i > upper ) 1498 result = o == NE; 1499 else if( i < lower || i > upper ) 1500 result = o == NE; 1501 else 1502 return (0); 1503 break; 1504 case LT: 1505 case GE: 1506 if( lower == 0 && (unsigned) i > upper ) 1507 result = o == LT; 1508 else if( i <= lower ) 1509 result = o != LT; 1510 else if( i > upper ) 1511 result = o == LT; 1512 else 1513 return (0); 1514 break; 1515 case LE: 1516 case GT: 1517 if( lower == 0 && (unsigned) i >= upper ) 1518 result = o == LE; 1519 else if( i < lower ) 1520 result = o != LE; 1521 else if( i >= upper ) 1522 result = o == LE; 1523 else 1524 return (0); 1525 break; 1526 default: 1527 cerror("unknown op in degenerate()"); 1528 } 1529 1530 if( o == MOD || o == ASG MOD ) { 1531 r->in.op = FREE; 1532 ncopy(p, l); 1533 l->in.op = FREE; 1534 } 1535 else if( o != ASG DIV && tshape(l, SAREG|SNAME|SCON|SOREG|STARNM) ) { 1536 /* no side effects */ 1537 tfree(l); 1538 ncopy(p, r); 1539 r->in.op = FREE; 1540 p->tn.lval = result; 1541 } 1542 else { 1543 if( o == ASG DIV ) 1544 p->in.op = ASSIGN; 1545 else { 1546 p->in.op = COMOP; 1547 r->tn.type = INT; 1548 } 1549 r->tn.lval = result; 1550 } 1551 if( logop(o) ) 1552 p->in.type = INT; 1553 1554 return (1); 1555 } 1556 1557 /* added by jwf */ 1558 struct functbl { 1559 int fop; 1560 TWORD ftype; 1561 char *func; 1562 } opfunc[] = { 1563 DIV, TANY, "udiv", 1564 MOD, TANY, "urem", 1565 ASG DIV, TANY, "audiv", 1566 ASG MOD, TANY, "aurem", 1567 0, 0, 0 }; 1568 1569 hardops(p) register NODE *p; { 1570 /* change hard to do operators into function calls. */ 1571 register NODE *q; 1572 register struct functbl *f; 1573 register o; 1574 NODE *old,*temp; 1575 1576 o = p->in.op; 1577 if( ! (optype(o)==BITYPE && 1578 (ISUNSIGNED(p->in.left->in.type) || 1579 ISUNSIGNED(p->in.right->in.type))) ) 1580 return; 1581 1582 for( f=opfunc; f->fop; f++ ) { 1583 if( o==f->fop ) goto convert; 1584 } 1585 return; 1586 1587 convert: 1588 if( p->in.right->in.op == ICON && p->in.right->tn.name[0] == '\0' ) 1589 /* 'J', 'K' in zzzcode() -- assumes DIV or MOD operations */ 1590 /* save a subroutine call -- use at most 5 instructions */ 1591 return; 1592 if( tlen(p->in.left) < SZINT/SZCHAR && tlen(p->in.right) < SZINT/SZCHAR ) 1593 /* optim2() will modify the op into an ordinary int op */ 1594 return; 1595 if( asgop( o ) ) { 1596 old = NIL; 1597 switch( p->in.left->in.op ){ 1598 case FLD: 1599 q = p->in.left->in.left; 1600 /* 1601 * rewrite (lval.fld /= rval); as 1602 * ((*temp).fld = udiv((*(temp = &lval)).fld,rval)); 1603 * else the compiler will evaluate lval twice. 1604 */ 1605 if( q->in.op == UNARY MUL ){ 1606 /* first allocate a temp storage */ 1607 temp = talloc(); 1608 temp->in.op = OREG; 1609 temp->tn.rval = TMPREG; 1610 temp->tn.lval = BITOOR(freetemp(1)); 1611 temp->in.type = INCREF(p->in.type); 1612 #ifdef FLEXNAMES 1613 temp->in.name = ""; 1614 #else 1615 temp->in.name[0] = '\0'; 1616 #endif 1617 old = q->in.left; 1618 q->in.left = temp; 1619 } 1620 /* fall thru ... */ 1621 1622 case REG: 1623 case NAME: 1624 case OREG: 1625 /* change ASG OP to a simple OP */ 1626 q = talloc(); 1627 q->in.op = NOASG p->in.op; 1628 q->in.rall = NOPREF; 1629 q->in.type = p->in.type; 1630 q->in.left = tcopy(p->in.left); 1631 q->in.right = p->in.right; 1632 p->in.op = ASSIGN; 1633 p->in.right = q; 1634 p = q; 1635 f -= 2; /* Note: this depends on the table order */ 1636 /* on the right side only - replace *temp with 1637 *(temp = &lval), build the assignment node */ 1638 if( old ){ 1639 temp = q->in.left->in.left; /* the "*" node */ 1640 q = talloc(); 1641 q->in.op = ASSIGN; 1642 q->in.left = temp->in.left; 1643 q->in.right = old; 1644 q->in.type = old->in.type; 1645 #ifdef FLEXNAMES 1646 q->in.name = ""; 1647 #else 1648 q->in.name[0] = '\0'; 1649 #endif 1650 temp->in.left = q; 1651 } 1652 break; 1653 1654 case UNARY MUL: 1655 /* avoid doing side effects twice */ 1656 q = p->in.left; 1657 p->in.left = q->in.left; 1658 q->in.op = FREE; 1659 break; 1660 1661 default: 1662 cerror( "hardops: can't compute & LHS" ); 1663 } 1664 } 1665 1666 /* build comma op for args to function */ 1667 q = talloc(); 1668 q->in.op = CM; 1669 q->in.rall = NOPREF; 1670 q->in.type = INT; 1671 q->in.left = p->in.left; 1672 q->in.right = p->in.right; 1673 p->in.op = CALL; 1674 p->in.right = q; 1675 1676 /* put function name in left node of call */ 1677 p->in.left = q = talloc(); 1678 q->in.op = ICON; 1679 q->in.rall = NOPREF; 1680 q->in.type = INCREF( FTN + p->in.type ); 1681 #ifndef FLEXNAMES 1682 strcpy( q->in.name, f->func ); 1683 #else 1684 q->in.name = f->func; 1685 #endif 1686 q->tn.lval = 0; 1687 q->tn.rval = 0; 1688 1689 } 1690 1691 zappost(p) NODE *p; { 1692 /* look for ++ and -- operators and remove them */ 1693 1694 register int o, ty; 1695 register NODE *q; 1696 o = p->in.op; 1697 ty = optype( o ); 1698 1699 switch( o ){ 1700 1701 case INCR: 1702 case DECR: 1703 q = p->in.left; 1704 p->in.right->in.op = FREE; /* zap constant */ 1705 ncopy( p, q ); 1706 q->in.op = FREE; 1707 return; 1708 1709 } 1710 1711 if( ty == BITYPE ) zappost( p->in.right ); 1712 if( ty != LTYPE ) zappost( p->in.left ); 1713 } 1714 1715 fixpre(p) NODE *p; { 1716 1717 register int o, ty; 1718 o = p->in.op; 1719 ty = optype( o ); 1720 1721 switch( o ){ 1722 1723 case ASG PLUS: 1724 p->in.op = PLUS; 1725 break; 1726 case ASG MINUS: 1727 p->in.op = MINUS; 1728 break; 1729 } 1730 1731 if( ty == BITYPE ) fixpre( p->in.right ); 1732 if( ty != LTYPE ) fixpre( p->in.left ); 1733 } 1734 1735 /*ARGSUSED*/ 1736 NODE * addroreg(l) NODE *l; 1737 /* OREG was built in clocal() 1738 * for an auto or formal parameter 1739 * now its address is being taken 1740 * local code must unwind it 1741 * back to PLUS/MINUS REG ICON 1742 * according to local conventions 1743 */ 1744 { 1745 cerror("address of OREG taken"); 1746 /*NOTREACHED*/ 1747 } 1748 1749 1750 1751 # ifndef ONEPASS 1752 main( argc, argv ) char *argv[]; { 1753 return( mainp2( argc, argv ) ); 1754 } 1755 # endif 1756 1757 strip(p) register NODE *p; { 1758 NODE *q; 1759 1760 /* strip nodes off the top when no side effects occur */ 1761 for( ; ; ) { 1762 switch( p->in.op ) { 1763 case SCONV: /* remove lint tidbits */ 1764 q = p->in.left; 1765 ncopy( p, q ); 1766 q->in.op = FREE; 1767 break; 1768 /* could probably add a few more here */ 1769 default: 1770 return; 1771 } 1772 } 1773 } 1774 1775 myreader(p) register NODE *p; { 1776 strip( p ); /* strip off operations with no side effects */ 1777 canon( p ); /* expands r-vals for fields */ 1778 walkf( p, hardops ); /* convert ops to function calls */ 1779 walkf( p, optim2 ); 1780 } 1781