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