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