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