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