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