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