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