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