|
|
1.1 ! root 1: #ifndef lint ! 2: static char *sccsid ="@(#)reader.c 4.5 (Berkeley) 10/15/86"; ! 3: #endif lint ! 4: ! 5: # include "pass2.h" ! 6: ! 7: /* some storage declarations */ ! 8: ! 9: # ifndef ONEPASS ! 10: NODE node[TREESZ]; ! 11: char filename[100] = ""; /* the name of the file */ ! 12: int ftnno; /* number of current function */ ! 13: int lineno; ! 14: # else ! 15: # define NOMAIN ! 16: #endif ! 17: ! 18: int nrecur; ! 19: int lflag; ! 20: #ifdef FORT ! 21: int Oflag = 0; ! 22: #endif ! 23: extern int Wflag; ! 24: int edebug = 0; ! 25: int xdebug = 0; ! 26: int udebug = 0; ! 27: int vdebug = 0; ! 28: ! 29: OFFSZ tmpoff; /* offset for first temporary, in bits for current block */ ! 30: OFFSZ maxoff; /* maximum temporary offset over all blocks in current ftn, in bits */ ! 31: int maxtreg; ! 32: ! 33: NODE *stotree; ! 34: int stocook; ! 35: ! 36: OFFSZ baseoff = 0; ! 37: OFFSZ maxtemp = 0; ! 38: ! 39: p2init( argc, argv ) char *argv[];{ ! 40: /* set the values of the pass 2 arguments */ ! 41: ! 42: register int c; ! 43: register char *cp; ! 44: register files; ! 45: ! 46: allo0(); /* free all regs */ ! 47: files = 0; ! 48: ! 49: for( c=1; c<argc; ++c ){ ! 50: if( *(cp=argv[c]) == '-' ){ ! 51: while( *++cp ){ ! 52: switch( *cp ){ ! 53: ! 54: case 'X': /* pass1 flags */ ! 55: while( *++cp ) { /* VOID */ } ! 56: --cp; ! 57: break; ! 58: ! 59: case 'l': /* linenos */ ! 60: ++lflag; ! 61: break; ! 62: ! 63: case 'e': /* expressions */ ! 64: ++edebug; ! 65: break; ! 66: ! 67: case 'o': /* orders */ ! 68: ++odebug; ! 69: break; ! 70: ! 71: case 'r': /* register allocation */ ! 72: ++rdebug; ! 73: break; ! 74: ! 75: case 'a': /* rallo */ ! 76: ++radebug; ! 77: break; ! 78: ! 79: case 'v': ! 80: ++vdebug; ! 81: break; ! 82: ! 83: case 't': /* ttype calls */ ! 84: ++tdebug; ! 85: break; ! 86: ! 87: case 's': /* shapes */ ! 88: ++sdebug; ! 89: break; ! 90: ! 91: case 'u': /* Sethi-Ullman testing (machine dependent) */ ! 92: ++udebug; ! 93: break; ! 94: ! 95: case 'x': /* general machine-dependent debugging flag */ ! 96: ++xdebug; ! 97: break; ! 98: ! 99: case 'w': ! 100: case 'W': /* shut up warnings */ ! 101: ! 102: ++Wflag; ! 103: break; ! 104: ! 105: #ifdef FORT ! 106: case 'O': /* optimizing */ ! 107: ++Oflag; ! 108: break; ! 109: #endif ! 110: ! 111: default: ! 112: cerror( "bad option: %c", *cp ); ! 113: } ! 114: } ! 115: } ! 116: else files = 1; /* assumed to be a filename */ ! 117: } ! 118: ! 119: mkdope(); ! 120: setrew(); ! 121: return( files ); ! 122: ! 123: } ! 124: ! 125: # ifndef NOMAIN ! 126: ! 127: unsigned int caloff(); ! 128: unsigned int offsz; ! 129: mainp2( argc, argv ) char *argv[]; { ! 130: register files; ! 131: register temp; ! 132: register c; ! 133: register char *cp; ! 134: register NODE *p; ! 135: ! 136: offsz = caloff(); ! 137: files = p2init( argc, argv ); ! 138: tinit(); ! 139: ! 140: reread: ! 141: ! 142: if( files ){ ! 143: while( files < argc && argv[files][0] == '-' ) { ! 144: ++files; ! 145: } ! 146: if( files > argc ) return( nerrors ); ! 147: freopen( argv[files], "r", stdin ); ! 148: } ! 149: while( (c=getchar()) > 0 ) switch( c ){ ! 150: case ')': ! 151: default: ! 152: /* copy line unchanged */ ! 153: if ( c != ')' ) ! 154: PUTCHAR( c ); /* initial tab */ ! 155: while( (c=getchar()) > 0 ){ ! 156: PUTCHAR(c); ! 157: if( c == '\n' ) break; ! 158: } ! 159: continue; ! 160: ! 161: case BBEG: ! 162: /* beginning of a block */ ! 163: temp = rdin(10); /* ftnno */ ! 164: tmpoff = baseoff = (unsigned int) rdin(10); /* autooff for block gives max offset of autos in block */ ! 165: maxtreg = rdin(10); ! 166: if( getchar() != '\n' ) cerror( "intermediate file format error"); ! 167: ! 168: if( temp != ftnno ){ /* beginning of function */ ! 169: maxoff = baseoff; ! 170: ftnno = temp; ! 171: maxtemp = 0; ! 172: } ! 173: else { ! 174: if( baseoff > maxoff ) maxoff = baseoff; ! 175: /* maxoff at end of ftn is max of autos and temps ! 176: over all blocks in the function */ ! 177: } ! 178: setregs(); ! 179: continue; ! 180: ! 181: case BEND: /* end of block */ ! 182: SETOFF( maxoff, ALSTACK ); ! 183: eobl2(); ! 184: while( (c=getchar()) != '\n' ){ ! 185: if( c <= 0 ) cerror( "intermediate file format eof" ); ! 186: } ! 187: continue; ! 188: ! 189: case EXPR: ! 190: /* compile code for an expression */ ! 191: lineno = rdin( 10 ); ! 192: for( cp=filename; (*cp=getchar()) != '\n'; ++cp ) ; /* VOID, reads filename */ ! 193: *cp = '\0'; ! 194: if( lflag ) lineid( lineno, filename ); ! 195: ! 196: tmpoff = baseoff; /* expression at top level reuses temps */ ! 197: p = eread(); ! 198: ! 199: # ifndef BUG4 ! 200: if( edebug ) fwalk( p, eprint, 0 ); ! 201: # endif ! 202: ! 203: # ifdef MYREADER ! 204: MYREADER(p); /* do your own laundering of the input */ ! 205: # endif ! 206: ! 207: nrecur = 0; ! 208: delay( p ); /* expression statement throws out results */ ! 209: reclaim( p, RNULL, 0 ); ! 210: ! 211: allchk(); ! 212: tcheck(); ! 213: continue; ! 214: ! 215: default: ! 216: cerror( "intermediate file format error" ); ! 217: ! 218: } ! 219: ! 220: /* EOF */ ! 221: if( files ) goto reread; ! 222: return(nerrors); ! 223: ! 224: } ! 225: ! 226: # endif ! 227: ! 228: # ifdef ONEPASS ! 229: ! 230: p2compile( p ) NODE *p; { ! 231: ! 232: if( lflag ) lineid( lineno, filename ); ! 233: tmpoff = baseoff; /* expression at top level reuses temps */ ! 234: /* generate code for the tree p */ ! 235: # ifndef BUG4 ! 236: if( edebug ) fwalk( p, eprint, 0 ); ! 237: # endif ! 238: ! 239: # ifdef MYREADER ! 240: MYREADER(p); /* do your own laundering of the input */ ! 241: # endif ! 242: nrecur = 0; ! 243: delay( p ); /* do the code generation */ ! 244: reclaim( p, RNULL, 0 ); ! 245: allchk(); ! 246: /* can't do tcheck here; some stuff (e.g., attributes) may be around from first pass */ ! 247: /* first pass will do it... */ ! 248: } ! 249: ! 250: p2bbeg( aoff, myreg ) { ! 251: static int myftn = -1; ! 252: ! 253: tmpoff = baseoff = (unsigned int) aoff; ! 254: maxtreg = myreg; ! 255: if( myftn != ftnno ){ /* beginning of function */ ! 256: maxoff = baseoff; ! 257: myftn = ftnno; ! 258: maxtemp = 0; ! 259: } ! 260: else { ! 261: if( baseoff > maxoff ) maxoff = baseoff; ! 262: /* maxoff at end of ftn is max of autos and temps over all blocks */ ! 263: } ! 264: setregs(); ! 265: } ! 266: ! 267: p2bend(){ ! 268: SETOFF( maxoff, ALSTACK ); ! 269: eobl2(); ! 270: } ! 271: ! 272: # endif ! 273: ! 274: NODE *deltrees[DELAYS]; ! 275: int deli; ! 276: ! 277: delay( p ) register NODE *p; { ! 278: /* look in all legal places for COMOP's and ++ and -- ops to delay */ ! 279: /* note; don't delay ++ and -- within calls or things like ! 280: /* getchar (in their macro forms) will start behaving strangely */ ! 281: register i; ! 282: ! 283: /* look for visible COMOPS, and rewrite repeatedly */ ! 284: ! 285: while( delay1( p ) ) { /* VOID */ } ! 286: ! 287: /* look for visible, delayable ++ and -- */ ! 288: ! 289: deli = 0; ! 290: delay2( p ); ! 291: codgen( p, FOREFF ); /* do what is left */ ! 292: for( i = 0; i<deli; ++i ) codgen( deltrees[i], FOREFF ); /* do the rest */ ! 293: } ! 294: ! 295: delay1( p ) register NODE *p; { /* look for COMOPS */ ! 296: register o, ty; ! 297: ! 298: o = p->in.op; ! 299: ty = optype( o ); ! 300: if( ty == LTYPE ) return( 0 ); ! 301: else if( ty == UTYPE ) return( delay1( p->in.left ) ); ! 302: ! 303: switch( o ){ ! 304: ! 305: case QUEST: ! 306: case ANDAND: ! 307: case OROR: ! 308: /* don't look on RHS */ ! 309: return( delay1(p->in.left ) ); ! 310: ! 311: case COMOP: /* the meat of the routine */ ! 312: delay( p->in.left ); /* completely evaluate the LHS */ ! 313: /* rewrite the COMOP */ ! 314: { register NODE *q; ! 315: q = p->in.right; ! 316: ncopy( p, p->in.right ); ! 317: q->in.op = FREE; ! 318: } ! 319: return( 1 ); ! 320: } ! 321: ! 322: return( delay1(p->in.left) || delay1(p->in.right ) ); ! 323: } ! 324: ! 325: delay2( p ) register NODE *p; { ! 326: ! 327: /* look for delayable ++ and -- operators */ ! 328: ! 329: register o, ty; ! 330: o = p->in.op; ! 331: ty = optype( o ); ! 332: ! 333: switch( o ){ ! 334: ! 335: case NOT: ! 336: case QUEST: ! 337: case ANDAND: ! 338: case OROR: ! 339: case CALL: ! 340: case UNARY CALL: ! 341: case STCALL: ! 342: case UNARY STCALL: ! 343: case FORTCALL: ! 344: case UNARY FORTCALL: ! 345: case COMOP: ! 346: case CBRANCH: ! 347: /* for the moment, don't delay past a conditional context, or ! 348: /* inside of a call */ ! 349: return; ! 350: ! 351: case UNARY MUL: ! 352: /* if *p++, do not rewrite */ ! 353: if( autoincr( p ) ) return; ! 354: break; ! 355: ! 356: case INCR: ! 357: case DECR: ! 358: if( deltest( p ) ){ ! 359: if( deli < DELAYS ){ ! 360: register NODE *q; ! 361: deltrees[deli++] = tcopy(p); ! 362: q = p->in.left; ! 363: p->in.right->in.op = FREE; /* zap constant */ ! 364: ncopy( p, q ); ! 365: q->in.op = FREE; ! 366: return; ! 367: } ! 368: } ! 369: ! 370: } ! 371: ! 372: if( ty == BITYPE ) delay2( p->in.right ); ! 373: if( ty != LTYPE ) delay2( p->in.left ); ! 374: } ! 375: ! 376: codgen( p, cookie ) NODE *p; { ! 377: ! 378: /* generate the code for p; ! 379: order may call codgen recursively */ ! 380: /* cookie is used to describe the context */ ! 381: ! 382: for(;;){ ! 383: canon(p); /* creats OREG from * if possible and does sucomp */ ! 384: stotree = NIL; ! 385: # ifndef BUG4 ! 386: if( edebug ){ ! 387: printf( "store called on:\n" ); ! 388: fwalk( p, eprint, 0 ); ! 389: } ! 390: # endif ! 391: store(p); ! 392: if( stotree==NIL ) break; ! 393: ! 394: /* because it's minimal, can do w.o. stores */ ! 395: ! 396: order( stotree, stocook ); ! 397: } ! 398: ! 399: order( p, cookie ); ! 400: ! 401: } ! 402: ! 403: # ifndef BUG4 ! 404: char *cnames[] = { ! 405: "SANY", ! 406: "SAREG", ! 407: "STAREG", ! 408: "SBREG", ! 409: "STBREG", ! 410: "SCC", ! 411: "SNAME", ! 412: "SCON", ! 413: "SFLD", ! 414: "SOREG", ! 415: # ifdef WCARD1 ! 416: "WCARD1", ! 417: # else ! 418: "STARNM", ! 419: # endif ! 420: # ifdef WCARD2 ! 421: "WCARD2", ! 422: # else ! 423: "STARREG", ! 424: # endif ! 425: "INTEMP", ! 426: "FORARG", ! 427: "SWADD", ! 428: 0, ! 429: }; ! 430: ! 431: prcook( cookie ){ ! 432: ! 433: /* print a nice-looking description of cookie */ ! 434: ! 435: int i, flag; ! 436: ! 437: if( cookie & SPECIAL ){ ! 438: if( cookie == SZERO ) printf( "SZERO" ); ! 439: else if( cookie == SONE ) printf( "SONE" ); ! 440: else if( cookie == SMONE ) printf( "SMONE" ); ! 441: else if( cookie == SCCON ) printf( "SCCON" ); ! 442: else if( cookie == SSCON ) printf( "SSCON" ); ! 443: else if( cookie == SSOREG ) printf( "SSOREG" ); ! 444: else printf( "SPECIAL+%d", cookie & ~SPECIAL ); ! 445: return; ! 446: } ! 447: ! 448: flag = 0; ! 449: for( i=0; cnames[i]; ++i ){ ! 450: if( cookie & (1<<i) ){ ! 451: if( flag ) printf( "|" ); ! 452: ++flag; ! 453: printf( cnames[i] ); ! 454: } ! 455: } ! 456: ! 457: } ! 458: # endif ! 459: ! 460: int odebug = 0; ! 461: ! 462: order(p,cook) NODE *p; { ! 463: ! 464: register o, ty, m; ! 465: int m1; ! 466: int cookie; ! 467: NODE *p1, *p2; ! 468: ! 469: cookie = cook; ! 470: rcount(); ! 471: canon(p); ! 472: rallo( p, p->in.rall ); ! 473: goto first; ! 474: /* by this time, p should be able to be generated without stores; ! 475: the only question is how */ ! 476: ! 477: again: ! 478: ! 479: if ( p->in.op == FREE ) ! 480: return; /* whole tree was done */ ! 481: cookie = cook; ! 482: rcount(); ! 483: canon(p); ! 484: rallo( p, p->in.rall ); ! 485: /* if any rewriting and canonicalization has put ! 486: * the tree (p) into a shape that cook is happy ! 487: * with (exclusive of FOREFF, FORREW, and INTEMP) ! 488: * then we are done. ! 489: * this allows us to call order with shapes in ! 490: * addition to cookies and stop short if possible. ! 491: */ ! 492: if( tshape(p, cook &(~(FOREFF|FORREW|INTEMP))) )return; ! 493: ! 494: first: ! 495: # ifndef BUG4 ! 496: if( odebug ){ ! 497: printf( "order( %o, ", p ); ! 498: prcook( cookie ); ! 499: printf( " )\n" ); ! 500: fwalk( p, eprint, 0 ); ! 501: } ! 502: # endif ! 503: ! 504: o = p->in.op; ! 505: ty = optype(o); ! 506: ! 507: /* first of all, for most ops, see if it is in the table */ ! 508: ! 509: /* look for ops */ ! 510: ! 511: switch( m = p->in.op ){ ! 512: ! 513: default: ! 514: /* look for op in table */ ! 515: for(;;){ ! 516: if( (m = match( p, cookie ) ) == MDONE ) goto cleanup; ! 517: else if( m == MNOPE ){ ! 518: if( !(cookie = nextcook( p, cookie ) ) ) goto nomat; ! 519: continue; ! 520: } ! 521: else break; ! 522: } ! 523: break; ! 524: ! 525: case COMOP: ! 526: case FORCE: ! 527: case CBRANCH: ! 528: case QUEST: ! 529: case ANDAND: ! 530: case OROR: ! 531: case NOT: ! 532: case UNARY CALL: ! 533: case CALL: ! 534: case UNARY STCALL: ! 535: case STCALL: ! 536: case UNARY FORTCALL: ! 537: case FORTCALL: ! 538: /* don't even go near the table... */ ! 539: ; ! 540: ! 541: } ! 542: /* get here to do rewriting if no match or ! 543: fall through from above for hard ops */ ! 544: ! 545: p1 = p->in.left; ! 546: if( ty == BITYPE ) p2 = p->in.right; ! 547: else p2 = NIL; ! 548: ! 549: # ifndef BUG4 ! 550: if( odebug ){ ! 551: printf( "order( %o, ", p ); ! 552: prcook( cook ); ! 553: printf( " ), cookie " ); ! 554: prcook( cookie ); ! 555: printf( ", rewrite %s\n", opst[m] ); ! 556: } ! 557: # endif ! 558: switch( m ){ ! 559: default: ! 560: nomat: ! 561: cerror( "no table entry for op %s", opst[p->in.op] ); ! 562: ! 563: case COMOP: ! 564: codgen( p1, FOREFF ); ! 565: p2->in.rall = p->in.rall; ! 566: codgen( p2, cookie ); ! 567: ncopy( p, p2 ); ! 568: p2->in.op = FREE; ! 569: goto cleanup; ! 570: ! 571: case FORCE: ! 572: /* recurse, letting the work be done by rallo */ ! 573: p = p->in.left; ! 574: cook = INTAREG|INTBREG; ! 575: goto again; ! 576: ! 577: case CBRANCH: ! 578: o = p2->tn.lval; ! 579: cbranch( p1, -1, o ); ! 580: p2->in.op = FREE; ! 581: p->in.op = FREE; ! 582: return; ! 583: ! 584: case QUEST: ! 585: cbranch( p1, -1, m=getlab() ); ! 586: p2->in.left->in.rall = p->in.rall; ! 587: codgen( p2->in.left, INTAREG|INTBREG ); ! 588: /* force right to compute result into same reg used by left */ ! 589: p2->in.right->in.rall = p2->in.left->tn.rval|MUSTDO; ! 590: reclaim( p2->in.left, RNULL, 0 ); ! 591: cbgen( 0, m1 = getlab(), 'I' ); ! 592: deflab( m ); ! 593: codgen( p2->in.right, INTAREG|INTBREG ); ! 594: deflab( m1 ); ! 595: p->in.op = REG; /* set up node describing result */ ! 596: p->tn.lval = 0; ! 597: p->tn.rval = p2->in.right->tn.rval; ! 598: p->in.type = p2->in.right->in.type; ! 599: tfree( p2->in.right ); ! 600: p2->in.op = FREE; ! 601: goto cleanup; ! 602: ! 603: case ANDAND: ! 604: case OROR: ! 605: case NOT: /* logical operators */ ! 606: /* if here, must be a logical operator for 0-1 value */ ! 607: cbranch( p, -1, m=getlab() ); ! 608: p->in.op = CCODES; ! 609: p->bn.label = m; ! 610: order( p, INTAREG ); ! 611: goto cleanup; ! 612: ! 613: case FLD: /* fields of funny type */ ! 614: if ( p1->in.op == UNARY MUL ){ ! 615: offstar( p1->in.left ); ! 616: goto again; ! 617: } ! 618: ! 619: case UNARY MINUS: ! 620: #if defined(tahoe) ! 621: order( p1, INBREG|INAREG|SOREG ); ! 622: #else ! 623: order( p1, INBREG|INAREG ); ! 624: #endif ! 625: goto again; ! 626: ! 627: case NAME: ! 628: /* all leaves end up here ... */ ! 629: if( o == REG ) goto nomat; ! 630: order( p, INTAREG|INTBREG ); ! 631: goto again; ! 632: ! 633: case INIT: ! 634: uerror( "illegal initialization" ); ! 635: return; ! 636: ! 637: case UNARY FORTCALL: ! 638: p->in.right = NIL; ! 639: case FORTCALL: ! 640: o = p->in.op = UNARY FORTCALL; ! 641: if( genfcall( p, cookie ) ) goto nomat; ! 642: goto cleanup; ! 643: ! 644: case UNARY CALL: ! 645: p->in.right = NIL; ! 646: case CALL: ! 647: o = p->in.op = UNARY CALL; ! 648: if( gencall( p, cookie ) ) goto nomat; ! 649: goto cleanup; ! 650: ! 651: case UNARY STCALL: ! 652: p->in.right = NIL; ! 653: case STCALL: ! 654: o = p->in.op = UNARY STCALL; ! 655: if( genscall( p, cookie ) ) goto nomat; ! 656: goto cleanup; ! 657: ! 658: /* if arguments are passed in register, care must be taken that reclaim ! 659: /* not throw away the register which now has the result... */ ! 660: ! 661: case UNARY MUL: ! 662: if( cook == FOREFF ){ ! 663: /* do nothing */ ! 664: order( p->in.left, FOREFF ); ! 665: p->in.op = FREE; ! 666: return; ! 667: } ! 668: offstar( p->in.left ); ! 669: goto again; ! 670: ! 671: case INCR: /* INCR and DECR */ ! 672: if( setincr(p) ) goto again; ! 673: ! 674: /* x++ becomes (x += 1) -1; */ ! 675: ! 676: if( cook & FOREFF ){ /* result not needed so inc or dec and be done with it */ ! 677: /* x++ => x += 1 */ ! 678: p->in.op = (p->in.op==INCR)?ASG PLUS:ASG MINUS; ! 679: goto again; ! 680: } ! 681: ! 682: p1 = tcopy(p); ! 683: reclaim( p->in.left, RNULL, 0 ); ! 684: p->in.left = p1; ! 685: p1->in.op = (p->in.op==INCR)?ASG PLUS:ASG MINUS; ! 686: p->in.op = (p->in.op==INCR)?MINUS:PLUS; ! 687: goto again; ! 688: ! 689: case STASG: ! 690: if( setstr( p ) ) goto again; ! 691: goto nomat; ! 692: ! 693: case ASG PLUS: /* and other assignment ops */ ! 694: if( setasop(p) ) goto again; ! 695: ! 696: /* there are assumed to be no side effects in LHS */ ! 697: ! 698: p2 = tcopy(p); ! 699: p->in.op = ASSIGN; ! 700: reclaim( p->in.right, RNULL, 0 ); ! 701: p->in.right = p2; ! 702: canon(p); ! 703: rallo( p, p->in.rall ); ! 704: ! 705: # ifndef BUG4 ! 706: if( odebug ) fwalk( p, eprint, 0 ); ! 707: # endif ! 708: ! 709: order( p2->in.left, INTBREG|INTAREG ); ! 710: order( p2, INTBREG|INTAREG ); ! 711: goto again; ! 712: ! 713: case ASSIGN: ! 714: if( setasg( p ) ) goto again; ! 715: goto nomat; ! 716: ! 717: ! 718: case BITYPE: ! 719: if( setbin( p ) ) goto again; ! 720: /* try to replace binary ops by =ops */ ! 721: switch(o){ ! 722: ! 723: case PLUS: ! 724: case MINUS: ! 725: case MUL: ! 726: case DIV: ! 727: case MOD: ! 728: case AND: ! 729: case OR: ! 730: case ER: ! 731: case LS: ! 732: case RS: ! 733: p->in.op = ASG o; ! 734: goto again; ! 735: } ! 736: goto nomat; ! 737: ! 738: } ! 739: ! 740: cleanup: ! 741: ! 742: /* if it is not yet in the right state, put it there */ ! 743: ! 744: if( cook & FOREFF ){ ! 745: reclaim( p, RNULL, 0 ); ! 746: return; ! 747: } ! 748: ! 749: if( p->in.op==FREE ) return; ! 750: ! 751: if( tshape( p, cook ) ) return; ! 752: ! 753: if( (m=match(p,cook) ) == MDONE ) return; ! 754: ! 755: /* we are in bad shape, try one last chance */ ! 756: if( lastchance( p, cook ) ) goto again; ! 757: ! 758: goto nomat; ! 759: } ! 760: ! 761: int callflag; ! 762: int fregs; ! 763: ! 764: store( p ) register NODE *p; { ! 765: ! 766: /* find a subtree of p which should be stored */ ! 767: ! 768: register o, ty; ! 769: ! 770: o = p->in.op; ! 771: ty = optype(o); ! 772: ! 773: if( ty == LTYPE ) return; ! 774: ! 775: switch( o ){ ! 776: ! 777: case UNARY CALL: ! 778: case UNARY FORTCALL: ! 779: case UNARY STCALL: ! 780: ++callflag; ! 781: break; ! 782: ! 783: case UNARY MUL: ! 784: if( asgop(p->in.left->in.op) ) stoasg( p->in.left, UNARY MUL ); ! 785: break; ! 786: ! 787: case CALL: ! 788: case FORTCALL: ! 789: case STCALL: ! 790: store( p->in.left ); ! 791: stoarg( p->in.right, o ); ! 792: ++callflag; ! 793: return; ! 794: ! 795: case COMOP: ! 796: markcall( p->in.right ); ! 797: if( p->in.right->in.su > fregs ) SETSTO( p, INTEMP ); ! 798: store( p->in.left ); ! 799: return; ! 800: ! 801: case ANDAND: ! 802: case OROR: ! 803: case QUEST: ! 804: markcall( p->in.right ); ! 805: if( p->in.right->in.su > fregs ) SETSTO( p, INTEMP ); ! 806: case CBRANCH: /* to prevent complicated expressions on the LHS from being stored */ ! 807: case NOT: ! 808: constore( p->in.left ); ! 809: return; ! 810: ! 811: } ! 812: ! 813: if( ty == UTYPE ){ ! 814: store( p->in.left ); ! 815: return; ! 816: } ! 817: ! 818: if( asgop( p->in.right->in.op ) ) stoasg( p->in.right, o ); ! 819: ! 820: if( p->in.su>fregs ){ /* must store */ ! 821: mkadrs( p ); /* set up stotree and stocook to subtree ! 822: that must be stored */ ! 823: } ! 824: ! 825: store( p->in.right ); ! 826: store( p->in.left ); ! 827: } ! 828: ! 829: constore( p ) register NODE *p; { ! 830: ! 831: /* store conditional expressions */ ! 832: /* the point is, avoid storing expressions in conditional ! 833: conditional context, since the evaluation order is predetermined */ ! 834: ! 835: switch( p->in.op ) { ! 836: ! 837: case ANDAND: ! 838: case OROR: ! 839: case QUEST: ! 840: markcall( p->in.right ); ! 841: case NOT: ! 842: constore( p->in.left ); ! 843: return; ! 844: ! 845: } ! 846: ! 847: store( p ); ! 848: } ! 849: ! 850: markcall( p ) register NODE *p; { /* mark off calls below the current node */ ! 851: ! 852: again: ! 853: switch( p->in.op ){ ! 854: ! 855: case UNARY CALL: ! 856: case UNARY STCALL: ! 857: case UNARY FORTCALL: ! 858: case CALL: ! 859: case STCALL: ! 860: case FORTCALL: ! 861: ++callflag; ! 862: return; ! 863: ! 864: } ! 865: ! 866: switch( optype( p->in.op ) ){ ! 867: ! 868: case BITYPE: ! 869: markcall( p->in.right ); ! 870: case UTYPE: ! 871: p = p->in.left; ! 872: /* eliminate recursion (aren't I clever...) */ ! 873: goto again; ! 874: case LTYPE: ! 875: return; ! 876: } ! 877: ! 878: } ! 879: ! 880: stoarg( p, calltype ) register NODE *p; { ! 881: /* arrange to store the args */ ! 882: ! 883: if( p->in.op == CM ){ ! 884: stoarg( p->in.left, calltype ); ! 885: p = p->in.right ; ! 886: } ! 887: if( calltype == CALL ){ ! 888: STOARG(p); ! 889: } ! 890: else if( calltype == STCALL ){ ! 891: STOSTARG(p); ! 892: } ! 893: else { ! 894: STOFARG(p); ! 895: } ! 896: callflag = 0; ! 897: store(p); ! 898: # ifndef NESTCALLS ! 899: if( callflag ){ /* prevent two calls from being active at once */ ! 900: SETSTO(p,INTEMP); ! 901: store(p); /* do again to preserve bottom up nature.... */ ! 902: } ! 903: #endif ! 904: } ! 905: ! 906: int negrel[] = { NE, EQ, GT, GE, LT, LE, UGT, UGE, ULT, ULE } ; /* negatives of relationals */ ! 907: ! 908: cbranch( p, true, false ) NODE *p; { ! 909: /* evaluate p for truth value, and branch to true or false ! 910: /* accordingly: label <0 means fall through */ ! 911: ! 912: register o, lab, flab, tlab; ! 913: ! 914: lab = -1; ! 915: ! 916: switch( o=p->in.op ){ ! 917: ! 918: case ULE: ! 919: case ULT: ! 920: case UGE: ! 921: case UGT: ! 922: case EQ: ! 923: case NE: ! 924: case LE: ! 925: case LT: ! 926: case GE: ! 927: case GT: ! 928: if( true < 0 ){ ! 929: o = p->in.op = negrel[ o-EQ ]; ! 930: true = false; ! 931: false = -1; ! 932: } ! 933: #ifndef NOOPT ! 934: if( p->in.right->in.op == ICON && p->in.right->tn.lval == 0 && p->in.right->in.name[0] == '\0' ){ ! 935: switch( o ){ ! 936: ! 937: case UGT: ! 938: case ULE: ! 939: o = p->in.op = (o==UGT)?NE:EQ; ! 940: case EQ: ! 941: case NE: ! 942: case LE: ! 943: case LT: ! 944: case GE: ! 945: case GT: ! 946: if( logop(p->in.left->in.op) ){ ! 947: /* strange situation: e.g., (a!=0) == 0 */ ! 948: /* must prevent reference to p->in.left->lable, so get 0/1 */ ! 949: /* we could optimize, but why bother */ ! 950: codgen( p->in.left, INAREG|INBREG ); ! 951: } ! 952: codgen( p->in.left, FORCC ); ! 953: cbgen( o, true, 'I' ); ! 954: break; ! 955: ! 956: case UGE: ! 957: codgen(p->in.left, FORCC); ! 958: cbgen( 0, true, 'I' ); /* unconditional branch */ ! 959: break; ! 960: case ULT: ! 961: codgen(p->in.left, FORCC); ! 962: } ! 963: } ! 964: else ! 965: #endif ! 966: { ! 967: p->bn.label = true; ! 968: codgen( p, FORCC ); ! 969: } ! 970: if( false>=0 ) cbgen( 0, false, 'I' ); ! 971: reclaim( p, RNULL, 0 ); ! 972: return; ! 973: ! 974: case ANDAND: ! 975: lab = false<0 ? getlab() : false ; ! 976: cbranch( p->in.left, -1, lab ); ! 977: cbranch( p->in.right, true, false ); ! 978: if( false < 0 ) deflab( lab ); ! 979: p->in.op = FREE; ! 980: return; ! 981: ! 982: case OROR: ! 983: lab = true<0 ? getlab() : true; ! 984: cbranch( p->in.left, lab, -1 ); ! 985: cbranch( p->in.right, true, false ); ! 986: if( true < 0 ) deflab( lab ); ! 987: p->in.op = FREE; ! 988: return; ! 989: ! 990: case NOT: ! 991: cbranch( p->in.left, false, true ); ! 992: p->in.op = FREE; ! 993: break; ! 994: ! 995: case COMOP: ! 996: codgen( p->in.left, FOREFF ); ! 997: p->in.op = FREE; ! 998: cbranch( p->in.right, true, false ); ! 999: return; ! 1000: ! 1001: case QUEST: ! 1002: flab = false<0 ? getlab() : false; ! 1003: tlab = true<0 ? getlab() : true; ! 1004: cbranch( p->in.left, -1, lab = getlab() ); ! 1005: cbranch( p->in.right->in.left, tlab, flab ); ! 1006: deflab( lab ); ! 1007: cbranch( p->in.right->in.right, true, false ); ! 1008: if( true < 0 ) deflab( tlab); ! 1009: if( false < 0 ) deflab( flab ); ! 1010: p->in.right->in.op = FREE; ! 1011: p->in.op = FREE; ! 1012: return; ! 1013: ! 1014: case ICON: ! 1015: if( p->in.type != FLOAT && p->in.type != DOUBLE ){ ! 1016: ! 1017: if( p->tn.lval || p->in.name[0] ){ ! 1018: /* addresses of C objects are never 0 */ ! 1019: if( true>=0 ) cbgen( 0, true, 'I' ); ! 1020: } ! 1021: else if( false>=0 ) cbgen( 0, false, 'I' ); ! 1022: p->in.op = FREE; ! 1023: return; ! 1024: } ! 1025: /* fall through to default with other strange constants */ ! 1026: ! 1027: default: ! 1028: /* get condition codes */ ! 1029: codgen( p, FORCC ); ! 1030: if( true >= 0 ) cbgen( NE, true, 'I' ); ! 1031: if( false >= 0 ) cbgen( true >= 0 ? 0 : EQ, false, 'I' ); ! 1032: reclaim( p, RNULL, 0 ); ! 1033: return; ! 1034: ! 1035: } ! 1036: ! 1037: } ! 1038: ! 1039: rcount(){ /* count recursions */ ! 1040: if( ++nrecur > NRECUR ){ ! 1041: cerror( "expression causes compiler loop: try simplifying" ); ! 1042: } ! 1043: ! 1044: } ! 1045: ! 1046: # ifndef BUG4 ! 1047: eprint( p, down, a, b ) NODE *p; int *a, *b; { ! 1048: ! 1049: *a = *b = down+1; ! 1050: while( down >= 2 ){ ! 1051: printf( "\t" ); ! 1052: down -= 2; ! 1053: } ! 1054: if( down-- ) printf( " " ); ! 1055: ! 1056: ! 1057: printf( "%o) %s", p, opst[p->in.op] ); ! 1058: switch( p->in.op ) { /* special cases */ ! 1059: ! 1060: case REG: ! 1061: printf( " %s", rnames[p->tn.rval] ); ! 1062: break; ! 1063: ! 1064: case ICON: ! 1065: case NAME: ! 1066: case OREG: ! 1067: printf( " " ); ! 1068: adrput( p ); ! 1069: break; ! 1070: ! 1071: case STCALL: ! 1072: case UNARY STCALL: ! 1073: case STARG: ! 1074: case STASG: ! 1075: printf( " size=%d", p->stn.stsize ); ! 1076: printf( " align=%d", p->stn.stalign ); ! 1077: break; ! 1078: } ! 1079: ! 1080: printf( ", " ); ! 1081: tprint( p->in.type ); ! 1082: printf( ", " ); ! 1083: if( p->in.rall == NOPREF ) printf( "NOPREF" ); ! 1084: else { ! 1085: if( p->in.rall & MUSTDO ) printf( "MUSTDO " ); ! 1086: else printf( "PREF " ); ! 1087: printf( "%s", rnames[p->in.rall&~MUSTDO]); ! 1088: } ! 1089: printf( ", SU= %d\n", p->in.su ); ! 1090: ! 1091: } ! 1092: # endif ! 1093: ! 1094: # ifndef NOMAIN ! 1095: NODE * ! 1096: eread(){ ! 1097: ! 1098: /* call eread recursively to get subtrees, if any */ ! 1099: ! 1100: register NODE *p; ! 1101: register i, c; ! 1102: register char *pc; ! 1103: register j; ! 1104: ! 1105: i = rdin( 10 ); ! 1106: ! 1107: p = talloc(); ! 1108: ! 1109: p->in.op = i; ! 1110: ! 1111: i = optype(i); ! 1112: ! 1113: if( i == LTYPE ) p->tn.lval = rdin( 10 ); ! 1114: if( i != BITYPE ) p->tn.rval = rdin( 10 ); ! 1115: ! 1116: p->in.type = rdin(8 ); ! 1117: p->in.rall = NOPREF; /* register allocation information */ ! 1118: ! 1119: if( p->in.op == STASG || p->in.op == STARG || p->in.op == STCALL || p->in.op == UNARY STCALL ){ ! 1120: p->stn.stsize = (rdin( 10 ) + (SZCHAR-1) )/SZCHAR; ! 1121: p->stn.stalign = rdin(10) / SZCHAR; ! 1122: if( getchar() != '\n' ) cerror( "illegal \n" ); ! 1123: } ! 1124: else { /* usual case */ ! 1125: if( p->in.op == REG ) rbusy( p->tn.rval, p->in.type ); /* non usually, but sometimes justified */ ! 1126: #ifndef FLEXNAMES ! 1127: for( pc=p->in.name,j=0; ( c = getchar() ) != '\n'; ++j ){ ! 1128: if( j < NCHNAM ) *pc++ = c; ! 1129: } ! 1130: if( j < NCHNAM ) *pc = '\0'; ! 1131: #else ! 1132: { char buf[BUFSIZ]; ! 1133: for( pc=buf,j=0; ( c = getchar() ) != '\n'; ++j ){ ! 1134: if( j < BUFSIZ ) *pc++ = c; ! 1135: } ! 1136: if( j < BUFSIZ ) *pc = '\0'; ! 1137: p->in.name = tstr(buf); ! 1138: } ! 1139: #endif ! 1140: } ! 1141: ! 1142: /* now, recursively read descendents, if any */ ! 1143: ! 1144: if( i != LTYPE ) p->in.left = eread(); ! 1145: if( i == BITYPE ) p->in.right = eread(); ! 1146: ! 1147: return( p ); ! 1148: ! 1149: } ! 1150: ! 1151: CONSZ ! 1152: rdin( base ){ ! 1153: register sign, c; ! 1154: CONSZ val; ! 1155: ! 1156: sign = 1; ! 1157: val = 0; ! 1158: ! 1159: while( (c=getchar()) > 0 ) { ! 1160: if( c == '-' ){ ! 1161: if( val != 0 ) cerror( "illegal -"); ! 1162: sign = -sign; ! 1163: continue; ! 1164: } ! 1165: if( c == '\t' ) break; ! 1166: if( c>='0' && c<='9' ) { ! 1167: val *= base; ! 1168: if( sign > 0 ) ! 1169: val += c-'0'; ! 1170: else ! 1171: val -= c-'0'; ! 1172: continue; ! 1173: } ! 1174: cerror( "illegal character `%c' on intermediate file", c ); ! 1175: break; ! 1176: } ! 1177: ! 1178: if( c <= 0 ) { ! 1179: cerror( "unexpected EOF"); ! 1180: } ! 1181: return( val ); ! 1182: } ! 1183: # endif ! 1184: ! 1185: #ifndef FIELDOPS ! 1186: /* do this if there is no special hardware support for fields */ ! 1187: ! 1188: ffld( p, down, down1, down2 ) NODE *p; int *down1, *down2; { ! 1189: /* look for fields that are not in an lvalue context, and rewrite them... */ ! 1190: register NODE *shp; ! 1191: register s, o, v, ty; ! 1192: ! 1193: *down1 = asgop( p->in.op ); ! 1194: *down2 = 0; ! 1195: ! 1196: if( !down && p->in.op == FLD ){ /* rewrite the node */ ! 1197: ! 1198: if( !rewfld(p) ) return; ! 1199: ! 1200: ty = (szty(p->in.type) == 2)? LONG: INT; ! 1201: v = p->tn.rval; ! 1202: s = UPKFSZ(v); ! 1203: # ifdef RTOLBYTES ! 1204: o = UPKFOFF(v); /* amount to shift */ ! 1205: # else ! 1206: o = szty(p->in.type)*SZINT - s - UPKFOFF(v); /* amount to shift */ ! 1207: #endif ! 1208: ! 1209: /* make & mask part */ ! 1210: ! 1211: p->in.left->in.type = ty; ! 1212: ! 1213: p->in.op = AND; ! 1214: p->in.right = talloc(); ! 1215: p->in.right->in.op = ICON; ! 1216: p->in.right->in.rall = NOPREF; ! 1217: p->in.right->in.type = ty; ! 1218: p->in.right->tn.lval = 1; ! 1219: p->in.right->tn.rval = 0; ! 1220: #ifndef FLEXNAMES ! 1221: p->in.right->in.name[0] = '\0'; ! 1222: #else ! 1223: p->in.right->in.name = ""; ! 1224: #endif ! 1225: p->in.right->tn.lval <<= s; ! 1226: p->in.right->tn.lval--; ! 1227: ! 1228: /* now, if a shift is needed, do it */ ! 1229: ! 1230: if( o != 0 ){ ! 1231: shp = talloc(); ! 1232: shp->in.op = RS; ! 1233: shp->in.rall = NOPREF; ! 1234: shp->in.type = ty; ! 1235: shp->in.left = p->in.left; ! 1236: shp->in.right = talloc(); ! 1237: shp->in.right->in.op = ICON; ! 1238: shp->in.right->in.rall = NOPREF; ! 1239: shp->in.right->in.type = ty; ! 1240: shp->in.right->tn.rval = 0; ! 1241: shp->in.right->tn.lval = o; /* amount to shift */ ! 1242: #ifndef FLEXNAMES ! 1243: shp->in.right->in.name[0] = '\0'; ! 1244: #else ! 1245: shp->in.right->in.name = ""; ! 1246: #endif ! 1247: p->in.left = shp; ! 1248: /* whew! */ ! 1249: } ! 1250: } ! 1251: } ! 1252: #endif ! 1253: ! 1254: oreg2( p ) register NODE *p; { ! 1255: ! 1256: /* look for situations where we can turn * into OREG */ ! 1257: ! 1258: NODE *q; ! 1259: register i; ! 1260: register r; ! 1261: register char *cp; ! 1262: register NODE *ql, *qr; ! 1263: CONSZ temp; ! 1264: ! 1265: if( p->in.op == UNARY MUL ){ ! 1266: q = p->in.left; ! 1267: if( q->in.op == REG ){ ! 1268: temp = q->tn.lval; ! 1269: r = q->tn.rval; ! 1270: cp = q->in.name; ! 1271: goto ormake; ! 1272: } ! 1273: ! 1274: if( q->in.op != PLUS && q->in.op != MINUS ) return; ! 1275: ql = q->in.left; ! 1276: qr = q->in.right; ! 1277: ! 1278: #ifdef R2REGS ! 1279: ! 1280: /* look for doubly indexed expressions */ ! 1281: ! 1282: if( q->in.op == PLUS) { ! 1283: if( (r=base(ql))>=0 && (i=offset(qr, tlen(p)))>=0) { ! 1284: makeor2(p, ql, r, i); ! 1285: return; ! 1286: } else if( (r=base(qr))>=0 && (i=offset(ql, tlen(p)))>=0) { ! 1287: makeor2(p, qr, r, i); ! 1288: return; ! 1289: } ! 1290: } ! 1291: ! 1292: ! 1293: #endif ! 1294: ! 1295: if( (q->in.op==PLUS || q->in.op==MINUS) && qr->in.op == ICON && ! 1296: ql->in.op==REG && szty(qr->in.type)==1) { ! 1297: temp = qr->tn.lval; ! 1298: if( q->in.op == MINUS ) temp = -temp; ! 1299: r = ql->tn.rval; ! 1300: temp += ql->tn.lval; ! 1301: cp = qr->in.name; ! 1302: if( *cp && ( q->in.op == MINUS || *ql->in.name ) ) return; ! 1303: if( !*cp ) cp = ql->in.name; ! 1304: ! 1305: ormake: ! 1306: if( notoff( p->in.type, r, temp, cp ) ) return; ! 1307: p->in.op = OREG; ! 1308: p->tn.rval = r; ! 1309: p->tn.lval = temp; ! 1310: #ifndef FLEXNAMES ! 1311: for( i=0; i<NCHNAM; ++i ) ! 1312: p->in.name[i] = *cp++; ! 1313: #else ! 1314: p->in.name = cp; ! 1315: #endif ! 1316: tfree(q); ! 1317: return; ! 1318: } ! 1319: } ! 1320: ! 1321: } ! 1322: ! 1323: canon(p) NODE *p; { ! 1324: /* put p in canonical form */ ! 1325: int oreg2(), sucomp(); ! 1326: ! 1327: #ifndef FIELDOPS ! 1328: int ffld(); ! 1329: fwalk( p, ffld, 0 ); /* look for field operators */ ! 1330: # endif ! 1331: walkf( p, oreg2 ); /* look for and create OREG nodes */ ! 1332: #ifdef MYCANON ! 1333: MYCANON(p); /* your own canonicalization routine(s) */ ! 1334: #endif ! 1335: walkf( p, sucomp ); /* do the Sethi-Ullman computation */ ! 1336: ! 1337: } ! 1338:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.