1 # ifndef lint 2 static char *sccsid ="@(#)local2.c 1.27 (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 int val; 829 printf("shumul:\n"); 830 eprint(p, 0, &val, &val); 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, mask; 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 mask = (1 << tlen(l) * SZCHAR) - 1; 1203 if( ISUNSIGNED(r->in.type) ) { 1204 i = (r->tn.lval & mask); 1205 if( i == mask ) { 1206 r->in.op = FREE; 1207 ncopy(p, l); 1208 l->in.op = FREE; 1209 break; 1210 } 1211 else if( i == 0 ) 1212 goto zero; 1213 else 1214 r->tn.lval = i; 1215 } 1216 else if( r->tn.lval == mask && 1217 tlen(l) < SZINT/SZCHAR ) { 1218 r->in.op = SCONV; 1219 r->in.left = l; 1220 r->in.right = 0; 1221 r->in.type = ENUNSIGN(l->in.type); 1222 r->in.su = l->in.su > 1 ? l->in.su : 1; 1223 ncopy(p, r); 1224 p->in.left = r; 1225 p->in.type = INT; 1226 break; 1227 } 1228 /* complement constant */ 1229 r->tn.lval = ~r->tn.lval; 1230 } 1231 else if( r->in.op==COMPL ) { /* ~~A => A */ 1232 r->in.op = FREE; 1233 p->in.right = r->in.left; 1234 } 1235 else { /* insert complement node */ 1236 p->in.right = l = talloc(); 1237 l->in.op = COMPL; 1238 l->in.rall = NOPREF; 1239 l->in.type = r->in.type; 1240 l->in.left = r; 1241 l->in.right = NULL; 1242 } 1243 break; 1244 1245 case SCONV: 1246 l = p->in.left; 1247 #if defined(FORT) || defined(SPRECC) 1248 if( p->in.type == FLOAT || p->in.type == DOUBLE || 1249 l->in.type == FLOAT || l->in.type == DOUBLE ) 1250 return; 1251 #else 1252 if( mixtypes(p, l) ) return; 1253 #endif 1254 if( l->in.op == PCONV || l->in.op == CALL || l->in.op == UNARY CALL ) 1255 return; 1256 1257 /* Only trust it to get it right if the size is the same */ 1258 if( tlen(p) != tlen(l) ) 1259 return; 1260 1261 /* clobber conversion */ 1262 if( l->in.op != FLD ) 1263 l->in.type = p->in.type; 1264 ncopy( p, l ); 1265 l->in.op = FREE; 1266 1267 break; 1268 1269 case ASSIGN: 1270 /* 1271 * Conversions are equivalent to assignments; 1272 * when the two operations are combined, 1273 * we can sometimes zap the conversion. 1274 */ 1275 r = p->in.right; 1276 l = p->in.left; 1277 if ( r->in.op == SCONV && 1278 !mixtypes(l, r) && 1279 l->in.op != FLD && 1280 tlen(l) == tlen(r) ) { 1281 p->in.right = r->in.left; 1282 r->in.op = FREE; 1283 } 1284 break; 1285 1286 case ULE: 1287 case ULT: 1288 case UGE: 1289 case UGT: 1290 p->in.op -= (UGE-GE); 1291 if( degenerate(p) ) 1292 break; 1293 p->in.op += (UGE-GE); 1294 break; 1295 1296 case EQ: 1297 case NE: 1298 case LE: 1299 case LT: 1300 case GE: 1301 case GT: 1302 (void) degenerate(p); 1303 break; 1304 1305 case DIV: 1306 if( p->in.right->in.op == ICON && 1307 p->in.right->tn.name[0] == '\0' && 1308 ISUNSIGNED(p->in.right->in.type) && 1309 (unsigned) p->in.right->tn.lval >= 0x80000000 ) { 1310 /* easy to do here, harder to do in zzzcode() */ 1311 p->in.op = UGE; 1312 break; 1313 } 1314 case MOD: 1315 case ASG DIV: 1316 case ASG MOD: 1317 /* 1318 * optimize DIV and MOD 1319 * 1320 * basically we spot UCHAR and USHORT and try to do them 1321 * as signed ints... apparently div+mul+sub is always 1322 * faster than ediv for finding MOD on the VAX, when 1323 * full unsigned MOD isn't needed. 1324 * 1325 * a curious fact: for MOD, cmp+sub and cmp+sub+cmp+sub 1326 * are faster for unsigned dividend and a constant divisor 1327 * in the right range (.5 to 1 of dividend's range for the 1328 * first, .333+ to .5 for the second). full unsigned is 1329 * already done cmp+sub in the appropriate case; the 1330 * other cases are less common and require more ambition. 1331 */ 1332 if( degenerate(p) ) 1333 break; 1334 l = p->in.left; 1335 r = p->in.right; 1336 if( !ISUNSIGNED(r->in.type) || 1337 tlen(l) >= SZINT/SZCHAR || 1338 !(tlen(r) < SZINT/SZCHAR || 1339 (r->in.op == ICON && r->tn.name[0] == '\0')) ) 1340 break; 1341 if( r->in.op == ICON ) 1342 r->tn.type = INT; 1343 else { 1344 NODE *t = talloc(); 1345 t->in.left = r; 1346 r = t; 1347 r->in.op = SCONV; 1348 r->in.type = INT; 1349 r->in.right = 0; 1350 p->in.right = r; 1351 } 1352 if( o == DIV || o == MOD ) { 1353 NODE *t = talloc(); 1354 t->in.left = l; 1355 l = t; 1356 l->in.op = SCONV; 1357 l->in.type = INT; 1358 l->in.right = 0; 1359 p->in.left = l; 1360 } 1361 /* handle asgops in table */ 1362 break; 1363 1364 case RS: 1365 case ASG RS: 1366 case LS: 1367 case ASG LS: 1368 /* pick up degenerate shifts */ 1369 l = p->in.left; 1370 r = p->in.right; 1371 if( !(r->in.op == ICON && r->tn.name[0] == '\0') ) 1372 break; 1373 i = r->tn.lval; 1374 if( i < 0 ) 1375 /* front end 'fixes' this? */ 1376 if( o == LS || o == ASG LS ) 1377 o += (RS-LS); 1378 else 1379 o += (LS-RS); 1380 if( (o == RS || o == ASG RS) && 1381 !ISUNSIGNED(l->in.type) ) 1382 /* can't optimize signed right shifts */ 1383 break; 1384 if( i < tlen(l) * SZCHAR ) 1385 break; 1386 zero: 1387 if( !asgop( o ) ) 1388 if( tshape(l, SAREG|SNAME|SCON|SOREG|STARNM) ) { 1389 /* no side effects */ 1390 tfree(l); 1391 ncopy(p, r); 1392 r->in.op = FREE; 1393 p->tn.lval = 0; 1394 } 1395 else { 1396 p->in.op = COMOP; 1397 r->tn.lval = 0; 1398 } 1399 else { 1400 p->in.op = ASSIGN; 1401 r->tn.lval = 0; 1402 } 1403 break; 1404 } 1405 } 1406 1407 degenerate(p) register NODE *p; { 1408 int o; 1409 int result, i; 1410 int lower, upper; 1411 register NODE *l, *r; 1412 1413 /* 1414 * try to keep degenerate comparisons with constants 1415 * out of the table. 1416 */ 1417 r = p->in.right; 1418 l = p->in.left; 1419 if( r->in.op != ICON || 1420 r->tn.name[0] != '\0' || 1421 tlen(l) >= tlen(r) ) 1422 return (0); 1423 switch( l->in.type ) { 1424 case CHAR: 1425 lower = -(1 << SZCHAR - 1); 1426 upper = (1 << SZCHAR - 1) - 1; 1427 break; 1428 case UCHAR: 1429 lower = 0; 1430 upper = (1 << SZCHAR) - 1; 1431 break; 1432 case SHORT: 1433 lower = -(1 << SZSHORT - 1); 1434 upper = (1 << SZSHORT - 1) - 1; 1435 break; 1436 case USHORT: 1437 lower = 0; 1438 upper = (1 << SZSHORT) - 1; 1439 break; 1440 default: 1441 cerror("unsupported type in degenerate()"); 1442 } 1443 i = r->tn.lval; 1444 switch( o = p->in.op ) { 1445 case DIV: 1446 case ASG DIV: 1447 case MOD: 1448 case ASG MOD: 1449 /* DIV and MOD work like EQ */ 1450 case EQ: 1451 case NE: 1452 if( lower == 0 && (unsigned) i > upper ) 1453 result = o == NE; 1454 else if( i < lower || i > upper ) 1455 result = o == NE; 1456 else 1457 return (0); 1458 break; 1459 case LT: 1460 case GE: 1461 if( lower == 0 && (unsigned) i > upper ) 1462 result = o == LT; 1463 else if( i <= lower ) 1464 result = o != LT; 1465 else if( i > upper ) 1466 result = o == LT; 1467 else 1468 return (0); 1469 break; 1470 case LE: 1471 case GT: 1472 if( lower == 0 && (unsigned) i >= upper ) 1473 result = o == LE; 1474 else if( i < lower ) 1475 result = o != LE; 1476 else if( i >= upper ) 1477 result = o == LE; 1478 else 1479 return (0); 1480 break; 1481 default: 1482 cerror("unknown op in degenerate()"); 1483 } 1484 1485 if( o == MOD || o == ASG MOD ) { 1486 r->in.op = FREE; 1487 ncopy(p, l); 1488 l->in.op = FREE; 1489 } 1490 else if( o != ASG DIV && tshape(l, SAREG|SNAME|SCON|SOREG|STARNM) ) { 1491 /* no side effects */ 1492 tfree(l); 1493 ncopy(p, r); 1494 r->in.op = FREE; 1495 p->tn.lval = result; 1496 } 1497 else { 1498 if( o == ASG DIV ) 1499 p->in.op = ASSIGN; 1500 else { 1501 p->in.op = COMOP; 1502 r->tn.type = INT; 1503 } 1504 r->tn.lval = result; 1505 } 1506 if( logop(o) ) 1507 p->in.type = INT; 1508 1509 return (1); 1510 } 1511 1512 /*ARGSUSED*/ 1513 NODE * addroreg(l) NODE *l; 1514 /* OREG was built in clocal() 1515 * for an auto or formal parameter 1516 * now its address is being taken 1517 * local code must unwind it 1518 * back to PLUS/MINUS REG ICON 1519 * according to local conventions 1520 */ 1521 { 1522 cerror("address of OREG taken"); 1523 /*NOTREACHED*/ 1524 } 1525 1526 1527 1528 # ifndef ONEPASS 1529 main( argc, argv ) char *argv[]; { 1530 return( mainp2( argc, argv ) ); 1531 } 1532 # endif 1533 1534 1535 /* added by jwf */ 1536 struct functbl { 1537 int fop; 1538 TWORD ftype; 1539 char *func; 1540 } opfunc[] = { 1541 DIV, TANY, "udiv", 1542 MOD, TANY, "urem", 1543 ASG DIV, TANY, "audiv", 1544 ASG MOD, TANY, "aurem", 1545 0, 0, 0 }; 1546 1547 hardops(p) register NODE *p; { 1548 /* change hard to do operators into function calls. */ 1549 register NODE *q; 1550 register struct functbl *f; 1551 register o; 1552 NODE *old,*temp; 1553 1554 o = p->in.op; 1555 if( ! (optype(o)==BITYPE && 1556 (ISUNSIGNED(p->in.left->in.type) || 1557 ISUNSIGNED(p->in.right->in.type))) ) 1558 return; 1559 1560 for( f=opfunc; f->fop; f++ ) { 1561 if( o==f->fop ) goto convert; 1562 } 1563 return; 1564 1565 convert: 1566 if( p->in.right->in.op == ICON && p->in.right->tn.name[0] == '\0' ) 1567 /* 'J', 'K' in zzzcode() -- assumes DIV or MOD operations */ 1568 /* save a subroutine call -- use at most 5 instructions */ 1569 return; 1570 if( tlen(p->in.left) < SZINT/SZCHAR && tlen(p->in.right) < SZINT/SZCHAR ) 1571 /* optim2() will modify the op into an ordinary int op */ 1572 return; 1573 if( asgop( o ) ) { 1574 old = NIL; 1575 switch( p->in.left->in.op ){ 1576 case FLD: 1577 q = p->in.left->in.left; 1578 /* 1579 * rewrite (lval.fld /= rval); as 1580 * ((*temp).fld = udiv((*(temp = &lval)).fld,rval)); 1581 * else the compiler will evaluate lval twice. 1582 */ 1583 if( q->in.op == UNARY MUL ){ 1584 /* first allocate a temp storage */ 1585 temp = talloc(); 1586 temp->in.op = OREG; 1587 temp->tn.rval = TMPREG; 1588 temp->tn.lval = BITOOR(freetemp(1)); 1589 temp->in.type = INCREF(p->in.type); 1590 #ifdef FLEXNAMES 1591 temp->in.name = ""; 1592 #else 1593 temp->in.name[0] = '\0'; 1594 #endif 1595 old = q->in.left; 1596 q->in.left = temp; 1597 } 1598 /* fall thru ... */ 1599 1600 case REG: 1601 case NAME: 1602 case OREG: 1603 /* change ASG OP to a simple OP */ 1604 q = talloc(); 1605 q->in.op = NOASG p->in.op; 1606 q->in.rall = NOPREF; 1607 q->in.type = p->in.type; 1608 q->in.left = tcopy(p->in.left); 1609 q->in.right = p->in.right; 1610 p->in.op = ASSIGN; 1611 p->in.right = q; 1612 p = q; 1613 f -= 2; /* Note: this depends on the table order */ 1614 /* on the right side only - replace *temp with 1615 *(temp = &lval), build the assignment node */ 1616 if( old ){ 1617 temp = q->in.left->in.left; /* the "*" node */ 1618 q = talloc(); 1619 q->in.op = ASSIGN; 1620 q->in.left = temp->in.left; 1621 q->in.right = old; 1622 q->in.type = old->in.type; 1623 #ifdef FLEXNAMES 1624 q->in.name = ""; 1625 #else 1626 q->in.name[0] = '\0'; 1627 #endif 1628 temp->in.left = q; 1629 } 1630 break; 1631 1632 case UNARY MUL: 1633 /* avoid doing side effects twice */ 1634 q = p->in.left; 1635 p->in.left = q->in.left; 1636 q->in.op = FREE; 1637 break; 1638 1639 default: 1640 cerror( "hardops: can't compute & LHS" ); 1641 } 1642 } 1643 1644 /* build comma op for args to function */ 1645 q = talloc(); 1646 q->in.op = CM; 1647 q->in.rall = NOPREF; 1648 q->in.type = INT; 1649 q->in.left = p->in.left; 1650 q->in.right = p->in.right; 1651 p->in.op = CALL; 1652 p->in.right = q; 1653 1654 /* put function name in left node of call */ 1655 p->in.left = q = talloc(); 1656 q->in.op = ICON; 1657 q->in.rall = NOPREF; 1658 q->in.type = INCREF( FTN + p->in.type ); 1659 #ifndef FLEXNAMES 1660 strcpy( q->in.name, f->func ); 1661 #else 1662 q->in.name = f->func; 1663 #endif 1664 q->tn.lval = 0; 1665 q->tn.rval = 0; 1666 1667 } 1668 1669 zappost(p) NODE *p; { 1670 /* look for ++ and -- operators and remove them */ 1671 1672 register o, ty; 1673 register NODE *q; 1674 o = p->in.op; 1675 ty = optype( o ); 1676 1677 switch( o ){ 1678 1679 case INCR: 1680 case DECR: 1681 q = p->in.left; 1682 p->in.right->in.op = FREE; /* zap constant */ 1683 ncopy( p, q ); 1684 q->in.op = FREE; 1685 return; 1686 1687 } 1688 1689 if( ty == BITYPE ) zappost( p->in.right ); 1690 if( ty != LTYPE ) zappost( p->in.left ); 1691 } 1692 1693 fixpre(p) NODE *p; { 1694 1695 register o, ty; 1696 o = p->in.op; 1697 ty = optype( o ); 1698 1699 switch( o ){ 1700 1701 case ASG PLUS: 1702 p->in.op = PLUS; 1703 break; 1704 case ASG MINUS: 1705 p->in.op = MINUS; 1706 break; 1707 } 1708 1709 if( ty == BITYPE ) fixpre( p->in.right ); 1710 if( ty != LTYPE ) fixpre( p->in.left ); 1711 } 1712 1713 strip(p) register NODE *p; { 1714 NODE *q; 1715 1716 /* strip nodes off the top when no side effects occur */ 1717 for( ; ; ) { 1718 switch( p->in.op ) { 1719 case SCONV: /* remove lint tidbits */ 1720 q = p->in.left; 1721 ncopy( p, q ); 1722 q->in.op = FREE; 1723 break; 1724 /* could probably add a few more here */ 1725 default: 1726 return; 1727 } 1728 } 1729 } 1730 1731 myreader(p) register NODE *p; { 1732 strip( p ); /* strip off operations with no side effects */ 1733 canon( p ); /* expands r-vals for fields */ 1734 walkf( p, hardops ); /* convert ops to function calls */ 1735 walkf( p, optim2 ); 1736 /* jwf toff = 0; /* stack offset swindle */ 1737 } 1738