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

Defined functions

canon defined in line 1319; used 4 times
cbranch defined in line 904; used 12 times
codgen defined in line 376; used 13 times
constore defined in line 825; used 2 times
delay defined in line 277; used 4 times
delay1 defined in line 295; used 5 times
delay2 defined in line 325; used 3 times
eprint defined in line 1043; never used
eread defined in line 1091; used 4 times
ffld defined in line 1184; used 2 times
mainp2 defined in line 129; never used
markcall defined in line 846; used 4 times
order defined in line 462; used 8 times
oreg2 defined in line 1250; used 2 times
p2bbeg defined in line 250; never used
p2bend defined in line 267; never used
p2compile defined in line 230; never used
p2init defined in line 39; used 3 times
prcook defined in line 431; used 5 times
rcount defined in line 1035; used 3 times
rdin defined in line 1147; used 11 times
stoarg defined in line 876; used 2 times
store defined in line 760; used 9 times

Defined variables

CONSZ defined in line 1147; used 2 times
Oflag defined in line 21; used 2 times
callflag defined in line 757; used 10 times
cnames defined in line 404; used 2 times
deli defined in line 275; used 8 times
deltrees defined in line 274; used 4 times
edebug defined in line 24; never used
filename defined in line 11; never used
fregs defined in line 758; used 6 times
ftnno defined in line 12; used 9 times
lflag defined in line 19; used 6 times
lineno defined in line 13; used 19 times
maxtreg defined in line 31; used 4 times
negrel defined in line 902; used 1 times
node defined in line 10; used 2 times
nrecur defined in line 18; used 6 times
odebug defined in line 460; used 8 times
offsz defined in line 128; used 3 times
sccsid defined in line 2; never used
stocook defined in line 34; used 3 times
stotree defined in line 33; used 7 times
udebug defined in line 26; used 2 times
vdebug defined in line 27; used 1 times
  • in line 80
xdebug defined in line 25; never used

Defined macros

NOMAIN defined in line 15; used 2 times
Last modified: 1985-08-25
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3237
Valid CSS Valid XHTML 1.0 Strict