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