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