|
|
1.1 ! root 1: #ifndef lint ! 2: static char *sccsid ="@(#)reader.c 4.4 (Berkeley) 8/22/85"; ! 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: order( p1, INBREG|INAREG ); ! 621: goto again; ! 622: ! 623: case NAME: ! 624: /* all leaves end up here ... */ ! 625: if( o == REG ) goto nomat; ! 626: order( p, INTAREG|INTBREG ); ! 627: goto again; ! 628: ! 629: case INIT: ! 630: uerror( "illegal initialization" ); ! 631: return; ! 632: ! 633: case UNARY FORTCALL: ! 634: p->in.right = NIL; ! 635: case FORTCALL: ! 636: o = p->in.op = UNARY FORTCALL; ! 637: if( genfcall( p, cookie ) ) goto nomat; ! 638: goto cleanup; ! 639: ! 640: case UNARY CALL: ! 641: p->in.right = NIL; ! 642: case CALL: ! 643: o = p->in.op = UNARY CALL; ! 644: if( gencall( p, cookie ) ) goto nomat; ! 645: goto cleanup; ! 646: ! 647: case UNARY STCALL: ! 648: p->in.right = NIL; ! 649: case STCALL: ! 650: o = p->in.op = UNARY STCALL; ! 651: if( genscall( p, cookie ) ) goto nomat; ! 652: goto cleanup; ! 653: ! 654: /* if arguments are passed in register, care must be taken that reclaim ! 655: /* not throw away the register which now has the result... */ ! 656: ! 657: case UNARY MUL: ! 658: if( cook == FOREFF ){ ! 659: /* do nothing */ ! 660: order( p->in.left, FOREFF ); ! 661: p->in.op = FREE; ! 662: return; ! 663: } ! 664: offstar( p->in.left ); ! 665: goto again; ! 666: ! 667: case INCR: /* INCR and DECR */ ! 668: if( setincr(p) ) goto again; ! 669: ! 670: /* x++ becomes (x += 1) -1; */ ! 671: ! 672: if( cook & FOREFF ){ /* result not needed so inc or dec and be done with it */ ! 673: /* x++ => x += 1 */ ! 674: p->in.op = (p->in.op==INCR)?ASG PLUS:ASG MINUS; ! 675: goto again; ! 676: } ! 677: ! 678: p1 = tcopy(p); ! 679: reclaim( p->in.left, RNULL, 0 ); ! 680: p->in.left = p1; ! 681: p1->in.op = (p->in.op==INCR)?ASG PLUS:ASG MINUS; ! 682: p->in.op = (p->in.op==INCR)?MINUS:PLUS; ! 683: goto again; ! 684: ! 685: case STASG: ! 686: if( setstr( p ) ) goto again; ! 687: goto nomat; ! 688: ! 689: case ASG PLUS: /* and other assignment ops */ ! 690: if( setasop(p) ) goto again; ! 691: ! 692: /* there are assumed to be no side effects in LHS */ ! 693: ! 694: p2 = tcopy(p); ! 695: p->in.op = ASSIGN; ! 696: reclaim( p->in.right, RNULL, 0 ); ! 697: p->in.right = p2; ! 698: canon(p); ! 699: rallo( p, p->in.rall ); ! 700: ! 701: # ifndef BUG4 ! 702: if( odebug ) fwalk( p, eprint, 0 ); ! 703: # endif ! 704: ! 705: order( p2->in.left, INTBREG|INTAREG ); ! 706: order( p2, INTBREG|INTAREG ); ! 707: goto again; ! 708: ! 709: case ASSIGN: ! 710: if( setasg( p ) ) goto again; ! 711: goto nomat; ! 712: ! 713: ! 714: case BITYPE: ! 715: if( setbin( p ) ) goto again; ! 716: /* try to replace binary ops by =ops */ ! 717: switch(o){ ! 718: ! 719: case PLUS: ! 720: case MINUS: ! 721: case MUL: ! 722: case DIV: ! 723: case MOD: ! 724: case AND: ! 725: case OR: ! 726: case ER: ! 727: case LS: ! 728: case RS: ! 729: p->in.op = ASG o; ! 730: goto again; ! 731: } ! 732: goto nomat; ! 733: ! 734: } ! 735: ! 736: cleanup: ! 737: ! 738: /* if it is not yet in the right state, put it there */ ! 739: ! 740: if( cook & FOREFF ){ ! 741: reclaim( p, RNULL, 0 ); ! 742: return; ! 743: } ! 744: ! 745: if( p->in.op==FREE ) return; ! 746: ! 747: if( tshape( p, cook ) ) return; ! 748: ! 749: if( (m=match(p,cook) ) == MDONE ) return; ! 750: ! 751: /* we are in bad shape, try one last chance */ ! 752: if( lastchance( p, cook ) ) goto again; ! 753: ! 754: goto nomat; ! 755: } ! 756: ! 757: int callflag; ! 758: int fregs; ! 759: ! 760: store( p ) register NODE *p; { ! 761: ! 762: /* find a subtree of p which should be stored */ ! 763: ! 764: register o, ty; ! 765: ! 766: o = p->in.op; ! 767: ty = optype(o); ! 768: ! 769: if( ty == LTYPE ) return; ! 770: ! 771: switch( o ){ ! 772: ! 773: case UNARY CALL: ! 774: case UNARY FORTCALL: ! 775: case UNARY STCALL: ! 776: ++callflag; ! 777: break; ! 778: ! 779: case UNARY MUL: ! 780: if( asgop(p->in.left->in.op) ) stoasg( p->in.left, UNARY MUL ); ! 781: break; ! 782: ! 783: case CALL: ! 784: case FORTCALL: ! 785: case STCALL: ! 786: store( p->in.left ); ! 787: stoarg( p->in.right, o ); ! 788: ++callflag; ! 789: return; ! 790: ! 791: case COMOP: ! 792: markcall( p->in.right ); ! 793: if( p->in.right->in.su > fregs ) SETSTO( p, INTEMP ); ! 794: store( p->in.left ); ! 795: return; ! 796: ! 797: case ANDAND: ! 798: case OROR: ! 799: case QUEST: ! 800: markcall( p->in.right ); ! 801: if( p->in.right->in.su > fregs ) SETSTO( p, INTEMP ); ! 802: case CBRANCH: /* to prevent complicated expressions on the LHS from being stored */ ! 803: case NOT: ! 804: constore( p->in.left ); ! 805: return; ! 806: ! 807: } ! 808: ! 809: if( ty == UTYPE ){ ! 810: store( p->in.left ); ! 811: return; ! 812: } ! 813: ! 814: if( asgop( p->in.right->in.op ) ) stoasg( p->in.right, o ); ! 815: ! 816: if( p->in.su>fregs ){ /* must store */ ! 817: mkadrs( p ); /* set up stotree and stocook to subtree ! 818: that must be stored */ ! 819: } ! 820: ! 821: store( p->in.right ); ! 822: store( p->in.left ); ! 823: } ! 824: ! 825: constore( p ) register NODE *p; { ! 826: ! 827: /* store conditional expressions */ ! 828: /* the point is, avoid storing expressions in conditional ! 829: conditional context, since the evaluation order is predetermined */ ! 830: ! 831: switch( p->in.op ) { ! 832: ! 833: case ANDAND: ! 834: case OROR: ! 835: case QUEST: ! 836: markcall( p->in.right ); ! 837: case NOT: ! 838: constore( p->in.left ); ! 839: return; ! 840: ! 841: } ! 842: ! 843: store( p ); ! 844: } ! 845: ! 846: markcall( p ) register NODE *p; { /* mark off calls below the current node */ ! 847: ! 848: again: ! 849: switch( p->in.op ){ ! 850: ! 851: case UNARY CALL: ! 852: case UNARY STCALL: ! 853: case UNARY FORTCALL: ! 854: case CALL: ! 855: case STCALL: ! 856: case FORTCALL: ! 857: ++callflag; ! 858: return; ! 859: ! 860: } ! 861: ! 862: switch( optype( p->in.op ) ){ ! 863: ! 864: case BITYPE: ! 865: markcall( p->in.right ); ! 866: case UTYPE: ! 867: p = p->in.left; ! 868: /* eliminate recursion (aren't I clever...) */ ! 869: goto again; ! 870: case LTYPE: ! 871: return; ! 872: } ! 873: ! 874: } ! 875: ! 876: stoarg( p, calltype ) register NODE *p; { ! 877: /* arrange to store the args */ ! 878: ! 879: if( p->in.op == CM ){ ! 880: stoarg( p->in.left, calltype ); ! 881: p = p->in.right ; ! 882: } ! 883: if( calltype == CALL ){ ! 884: STOARG(p); ! 885: } ! 886: else if( calltype == STCALL ){ ! 887: STOSTARG(p); ! 888: } ! 889: else { ! 890: STOFARG(p); ! 891: } ! 892: callflag = 0; ! 893: store(p); ! 894: # ifndef NESTCALLS ! 895: if( callflag ){ /* prevent two calls from being active at once */ ! 896: SETSTO(p,INTEMP); ! 897: store(p); /* do again to preserve bottom up nature.... */ ! 898: } ! 899: #endif ! 900: } ! 901: ! 902: int negrel[] = { NE, EQ, GT, GE, LT, LE, UGT, UGE, ULT, ULE } ; /* negatives of relationals */ ! 903: ! 904: cbranch( p, true, false ) NODE *p; { ! 905: /* evaluate p for truth value, and branch to true or false ! 906: /* accordingly: label <0 means fall through */ ! 907: ! 908: register o, lab, flab, tlab; ! 909: ! 910: lab = -1; ! 911: ! 912: switch( o=p->in.op ){ ! 913: ! 914: case ULE: ! 915: case ULT: ! 916: case UGE: ! 917: case UGT: ! 918: case EQ: ! 919: case NE: ! 920: case LE: ! 921: case LT: ! 922: case GE: ! 923: case GT: ! 924: if( true < 0 ){ ! 925: o = p->in.op = negrel[ o-EQ ]; ! 926: true = false; ! 927: false = -1; ! 928: } ! 929: #ifndef NOOPT ! 930: if( p->in.right->in.op == ICON && p->in.right->tn.lval == 0 && p->in.right->in.name[0] == '\0' ){ ! 931: switch( o ){ ! 932: ! 933: case UGT: ! 934: case ULE: ! 935: o = p->in.op = (o==UGT)?NE:EQ; ! 936: case EQ: ! 937: case NE: ! 938: case LE: ! 939: case LT: ! 940: case GE: ! 941: case GT: ! 942: if( logop(p->in.left->in.op) ){ ! 943: /* strange situation: e.g., (a!=0) == 0 */ ! 944: /* must prevent reference to p->in.left->lable, so get 0/1 */ ! 945: /* we could optimize, but why bother */ ! 946: codgen( p->in.left, INAREG|INBREG ); ! 947: } ! 948: codgen( p->in.left, FORCC ); ! 949: cbgen( o, true, 'I' ); ! 950: break; ! 951: ! 952: case UGE: ! 953: codgen(p->in.left, FORCC); ! 954: cbgen( 0, true, 'I' ); /* unconditional branch */ ! 955: break; ! 956: case ULT: ! 957: codgen(p->in.left, FORCC); ! 958: } ! 959: } ! 960: else ! 961: #endif ! 962: { ! 963: p->bn.label = true; ! 964: codgen( p, FORCC ); ! 965: } ! 966: if( false>=0 ) cbgen( 0, false, 'I' ); ! 967: reclaim( p, RNULL, 0 ); ! 968: return; ! 969: ! 970: case ANDAND: ! 971: lab = false<0 ? getlab() : false ; ! 972: cbranch( p->in.left, -1, lab ); ! 973: cbranch( p->in.right, true, false ); ! 974: if( false < 0 ) deflab( lab ); ! 975: p->in.op = FREE; ! 976: return; ! 977: ! 978: case OROR: ! 979: lab = true<0 ? getlab() : true; ! 980: cbranch( p->in.left, lab, -1 ); ! 981: cbranch( p->in.right, true, false ); ! 982: if( true < 0 ) deflab( lab ); ! 983: p->in.op = FREE; ! 984: return; ! 985: ! 986: case NOT: ! 987: cbranch( p->in.left, false, true ); ! 988: p->in.op = FREE; ! 989: break; ! 990: ! 991: case COMOP: ! 992: codgen( p->in.left, FOREFF ); ! 993: p->in.op = FREE; ! 994: cbranch( p->in.right, true, false ); ! 995: return; ! 996: ! 997: case QUEST: ! 998: flab = false<0 ? getlab() : false; ! 999: tlab = true<0 ? getlab() : true; ! 1000: cbranch( p->in.left, -1, lab = getlab() ); ! 1001: cbranch( p->in.right->in.left, tlab, flab ); ! 1002: deflab( lab ); ! 1003: cbranch( p->in.right->in.right, true, false ); ! 1004: if( true < 0 ) deflab( tlab); ! 1005: if( false < 0 ) deflab( flab ); ! 1006: p->in.right->in.op = FREE; ! 1007: p->in.op = FREE; ! 1008: return; ! 1009: ! 1010: case ICON: ! 1011: if( p->in.type != FLOAT && p->in.type != DOUBLE ){ ! 1012: ! 1013: if( p->tn.lval || p->in.name[0] ){ ! 1014: /* addresses of C objects are never 0 */ ! 1015: if( true>=0 ) cbgen( 0, true, 'I' ); ! 1016: } ! 1017: else if( false>=0 ) cbgen( 0, false, 'I' ); ! 1018: p->in.op = FREE; ! 1019: return; ! 1020: } ! 1021: /* fall through to default with other strange constants */ ! 1022: ! 1023: default: ! 1024: /* get condition codes */ ! 1025: codgen( p, FORCC ); ! 1026: if( true >= 0 ) cbgen( NE, true, 'I' ); ! 1027: if( false >= 0 ) cbgen( true >= 0 ? 0 : EQ, false, 'I' ); ! 1028: reclaim( p, RNULL, 0 ); ! 1029: return; ! 1030: ! 1031: } ! 1032: ! 1033: } ! 1034: ! 1035: rcount(){ /* count recursions */ ! 1036: if( ++nrecur > NRECUR ){ ! 1037: cerror( "expression causes compiler loop: try simplifying" ); ! 1038: } ! 1039: ! 1040: } ! 1041: ! 1042: # ifndef BUG4 ! 1043: eprint( p, down, a, b ) NODE *p; int *a, *b; { ! 1044: ! 1045: *a = *b = down+1; ! 1046: while( down >= 2 ){ ! 1047: printf( "\t" ); ! 1048: down -= 2; ! 1049: } ! 1050: if( down-- ) printf( " " ); ! 1051: ! 1052: ! 1053: printf( "%o) %s", p, opst[p->in.op] ); ! 1054: switch( p->in.op ) { /* special cases */ ! 1055: ! 1056: case REG: ! 1057: printf( " %s", rnames[p->tn.rval] ); ! 1058: break; ! 1059: ! 1060: case ICON: ! 1061: case NAME: ! 1062: case OREG: ! 1063: printf( " " ); ! 1064: adrput( p ); ! 1065: break; ! 1066: ! 1067: case STCALL: ! 1068: case UNARY STCALL: ! 1069: case STARG: ! 1070: case STASG: ! 1071: printf( " size=%d", p->stn.stsize ); ! 1072: printf( " align=%d", p->stn.stalign ); ! 1073: break; ! 1074: } ! 1075: ! 1076: printf( ", " ); ! 1077: tprint( p->in.type ); ! 1078: printf( ", " ); ! 1079: if( p->in.rall == NOPREF ) printf( "NOPREF" ); ! 1080: else { ! 1081: if( p->in.rall & MUSTDO ) printf( "MUSTDO " ); ! 1082: else printf( "PREF " ); ! 1083: printf( "%s", rnames[p->in.rall&~MUSTDO]); ! 1084: } ! 1085: printf( ", SU= %d\n", p->in.su ); ! 1086: ! 1087: } ! 1088: # endif ! 1089: ! 1090: # ifndef NOMAIN ! 1091: NODE * ! 1092: eread(){ ! 1093: ! 1094: /* call eread recursively to get subtrees, if any */ ! 1095: ! 1096: register NODE *p; ! 1097: register i, c; ! 1098: register char *pc; ! 1099: register j; ! 1100: ! 1101: i = rdin( 10 ); ! 1102: ! 1103: p = talloc(); ! 1104: ! 1105: p->in.op = i; ! 1106: ! 1107: i = optype(i); ! 1108: ! 1109: if( i == LTYPE ) p->tn.lval = rdin( 10 ); ! 1110: if( i != BITYPE ) p->tn.rval = rdin( 10 ); ! 1111: ! 1112: p->in.type = rdin(8 ); ! 1113: p->in.rall = NOPREF; /* register allocation information */ ! 1114: ! 1115: if( p->in.op == STASG || p->in.op == STARG || p->in.op == STCALL || p->in.op == UNARY STCALL ){ ! 1116: p->stn.stsize = (rdin( 10 ) + (SZCHAR-1) )/SZCHAR; ! 1117: p->stn.stalign = rdin(10) / SZCHAR; ! 1118: if( getchar() != '\n' ) cerror( "illegal \n" ); ! 1119: } ! 1120: else { /* usual case */ ! 1121: if( p->in.op == REG ) rbusy( p->tn.rval, p->in.type ); /* non usually, but sometimes justified */ ! 1122: #ifndef FLEXNAMES ! 1123: for( pc=p->in.name,j=0; ( c = getchar() ) != '\n'; ++j ){ ! 1124: if( j < NCHNAM ) *pc++ = c; ! 1125: } ! 1126: if( j < NCHNAM ) *pc = '\0'; ! 1127: #else ! 1128: { char buf[BUFSIZ]; ! 1129: for( pc=buf,j=0; ( c = getchar() ) != '\n'; ++j ){ ! 1130: if( j < BUFSIZ ) *pc++ = c; ! 1131: } ! 1132: if( j < BUFSIZ ) *pc = '\0'; ! 1133: p->in.name = tstr(buf); ! 1134: } ! 1135: #endif ! 1136: } ! 1137: ! 1138: /* now, recursively read descendents, if any */ ! 1139: ! 1140: if( i != LTYPE ) p->in.left = eread(); ! 1141: if( i == BITYPE ) p->in.right = eread(); ! 1142: ! 1143: return( p ); ! 1144: ! 1145: } ! 1146: ! 1147: CONSZ ! 1148: rdin( base ){ ! 1149: register sign, c; ! 1150: CONSZ val; ! 1151: ! 1152: sign = 1; ! 1153: val = 0; ! 1154: ! 1155: while( (c=getchar()) > 0 ) { ! 1156: if( c == '-' ){ ! 1157: if( val != 0 ) cerror( "illegal -"); ! 1158: sign = -sign; ! 1159: continue; ! 1160: } ! 1161: if( c == '\t' ) break; ! 1162: if( c>='0' && c<='9' ) { ! 1163: val *= base; ! 1164: if( sign > 0 ) ! 1165: val += c-'0'; ! 1166: else ! 1167: val -= c-'0'; ! 1168: continue; ! 1169: } ! 1170: cerror( "illegal character `%c' on intermediate file", c ); ! 1171: break; ! 1172: } ! 1173: ! 1174: if( c <= 0 ) { ! 1175: cerror( "unexpected EOF"); ! 1176: } ! 1177: return( val ); ! 1178: } ! 1179: # endif ! 1180: ! 1181: #ifndef FIELDOPS ! 1182: /* do this if there is no special hardware support for fields */ ! 1183: ! 1184: ffld( p, down, down1, down2 ) NODE *p; int *down1, *down2; { ! 1185: /* look for fields that are not in an lvalue context, and rewrite them... */ ! 1186: register NODE *shp; ! 1187: register s, o, v, ty; ! 1188: ! 1189: *down1 = asgop( p->in.op ); ! 1190: *down2 = 0; ! 1191: ! 1192: if( !down && p->in.op == FLD ){ /* rewrite the node */ ! 1193: ! 1194: if( !rewfld(p) ) return; ! 1195: ! 1196: ty = (szty(p->in.type) == 2)? LONG: INT; ! 1197: v = p->tn.rval; ! 1198: s = UPKFSZ(v); ! 1199: # ifdef RTOLBYTES ! 1200: o = UPKFOFF(v); /* amount to shift */ ! 1201: # else ! 1202: o = szty(p->in.type)*SZINT - s - UPKFOFF(v); /* amount to shift */ ! 1203: #endif ! 1204: ! 1205: /* make & mask part */ ! 1206: ! 1207: p->in.left->in.type = ty; ! 1208: ! 1209: p->in.op = AND; ! 1210: p->in.right = talloc(); ! 1211: p->in.right->in.op = ICON; ! 1212: p->in.right->in.rall = NOPREF; ! 1213: p->in.right->in.type = ty; ! 1214: p->in.right->tn.lval = 1; ! 1215: p->in.right->tn.rval = 0; ! 1216: #ifndef FLEXNAMES ! 1217: p->in.right->in.name[0] = '\0'; ! 1218: #else ! 1219: p->in.right->in.name = ""; ! 1220: #endif ! 1221: p->in.right->tn.lval <<= s; ! 1222: p->in.right->tn.lval--; ! 1223: ! 1224: /* now, if a shift is needed, do it */ ! 1225: ! 1226: if( o != 0 ){ ! 1227: shp = talloc(); ! 1228: shp->in.op = RS; ! 1229: shp->in.rall = NOPREF; ! 1230: shp->in.type = ty; ! 1231: shp->in.left = p->in.left; ! 1232: shp->in.right = talloc(); ! 1233: shp->in.right->in.op = ICON; ! 1234: shp->in.right->in.rall = NOPREF; ! 1235: shp->in.right->in.type = ty; ! 1236: shp->in.right->tn.rval = 0; ! 1237: shp->in.right->tn.lval = o; /* amount to shift */ ! 1238: #ifndef FLEXNAMES ! 1239: shp->in.right->in.name[0] = '\0'; ! 1240: #else ! 1241: shp->in.right->in.name = ""; ! 1242: #endif ! 1243: p->in.left = shp; ! 1244: /* whew! */ ! 1245: } ! 1246: } ! 1247: } ! 1248: #endif ! 1249: ! 1250: oreg2( p ) register NODE *p; { ! 1251: ! 1252: /* look for situations where we can turn * into OREG */ ! 1253: ! 1254: NODE *q; ! 1255: register i; ! 1256: register r; ! 1257: register char *cp; ! 1258: register NODE *ql, *qr; ! 1259: CONSZ temp; ! 1260: ! 1261: if( p->in.op == UNARY MUL ){ ! 1262: q = p->in.left; ! 1263: if( q->in.op == REG ){ ! 1264: temp = q->tn.lval; ! 1265: r = q->tn.rval; ! 1266: cp = q->in.name; ! 1267: goto ormake; ! 1268: } ! 1269: ! 1270: if( q->in.op != PLUS && q->in.op != MINUS ) return; ! 1271: ql = q->in.left; ! 1272: qr = q->in.right; ! 1273: ! 1274: #ifdef R2REGS ! 1275: ! 1276: /* look for doubly indexed expressions */ ! 1277: ! 1278: if( q->in.op == PLUS) { ! 1279: if( (r=base(ql))>=0 && (i=offset(qr, tlen(p)))>=0) { ! 1280: makeor2(p, ql, r, i); ! 1281: return; ! 1282: } else if( (r=base(qr))>=0 && (i=offset(ql, tlen(p)))>=0) { ! 1283: makeor2(p, qr, r, i); ! 1284: return; ! 1285: } ! 1286: } ! 1287: ! 1288: ! 1289: #endif ! 1290: ! 1291: if( (q->in.op==PLUS || q->in.op==MINUS) && qr->in.op == ICON && ! 1292: ql->in.op==REG && szty(qr->in.type)==1) { ! 1293: temp = qr->tn.lval; ! 1294: if( q->in.op == MINUS ) temp = -temp; ! 1295: r = ql->tn.rval; ! 1296: temp += ql->tn.lval; ! 1297: cp = qr->in.name; ! 1298: if( *cp && ( q->in.op == MINUS || *ql->in.name ) ) return; ! 1299: if( !*cp ) cp = ql->in.name; ! 1300: ! 1301: ormake: ! 1302: if( notoff( p->in.type, r, temp, cp ) ) return; ! 1303: p->in.op = OREG; ! 1304: p->tn.rval = r; ! 1305: p->tn.lval = temp; ! 1306: #ifndef FLEXNAMES ! 1307: for( i=0; i<NCHNAM; ++i ) ! 1308: p->in.name[i] = *cp++; ! 1309: #else ! 1310: p->in.name = cp; ! 1311: #endif ! 1312: tfree(q); ! 1313: return; ! 1314: } ! 1315: } ! 1316: ! 1317: } ! 1318: ! 1319: canon(p) NODE *p; { ! 1320: /* put p in canonical form */ ! 1321: int oreg2(), sucomp(); ! 1322: ! 1323: #ifndef FIELDOPS ! 1324: int ffld(); ! 1325: fwalk( p, ffld, 0 ); /* look for field operators */ ! 1326: # endif ! 1327: walkf( p, oreg2 ); /* look for and create OREG nodes */ ! 1328: #ifdef MYCANON ! 1329: MYCANON(p); /* your own canonicalization routine(s) */ ! 1330: #endif ! 1331: walkf( p, sucomp ); /* do the Sethi-Ullman computation */ ! 1332: ! 1333: } ! 1334:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.