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:     }

Defined functions

canon defined in line 1238; used 3 times
cbranch defined in line 826; used 12 times
codgen defined in line 335; used 11 times
constore defined in line 747; used 2 times
delay defined in line 241; used 4 times
delay1 defined in line 259; used 5 times
delay2 defined in line 289; used 3 times
eprint defined in line 962; used 9 times
eread defined in line 1009; used 3 times
ffld defined in line 1092; used 2 times
mainp2 defined in line 102; never used
markcall defined in line 768; used 4 times
order defined in line 406; used 8 times
oreg2 defined in line 1150; used 2 times
p2bbeg defined in line 215; never used
p2bend defined in line 231; never used
p2compile defined in line 197; never used
p2init defined in line 30; used 3 times
prcook defined in line 379; used 4 times
rcount defined in line 955; used 2 times
rdin defined in line 1055; used 10 times
stoarg defined in line 798; used 2 times
store defined in line 682; used 9 times

Defined variables

callflag defined in line 679; used 5 times
cnames defined in line 360; used 2 times
deli defined in line 239; used 4 times
edebug defined in line 16; used 4 times
filename defined in line 7; used 3 times
fregs defined in line 680; used 3 times
ftnno defined in line 8; used 4 times
lflag defined in line 15; used 3 times
lineno defined in line 9; used 3 times
maxtreg defined in line 22; used 2 times
negrel defined in line 824; used 1 times
nrecur defined in line 14; used 3 times
odebug defined in line 404; used 4 times
stocook defined in line 25; used 1 times
udebug defined in line 18; used 1 times
  • in line 79
xdebug defined in line 17; used 1 times
  • in line 83

Defined macros

NOMAIN defined in line 11; used 2 times

Usage of this include

reader.c used 1 times
Last modified: 1982-08-28
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1816
Valid CSS Valid XHTML 1.0 Strict