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

Defined functions

canon defined in line 1318; used 4 times
cbranch defined in line 903; used 12 times
codgen defined in line 375; used 13 times
constore defined in line 824; used 2 times
delay defined in line 276; used 4 times
delay1 defined in line 294; used 5 times
delay2 defined in line 324; used 3 times
eprint defined in line 1042; never used
eread defined in line 1090; used 4 times
ffld defined in line 1183; used 2 times
mainp2 defined in line 129; never used
markcall defined in line 845; used 4 times
order defined in line 461; used 8 times
oreg2 defined in line 1249; used 2 times
p2bbeg defined in line 249; never used
p2bend defined in line 266; never used
p2compile defined in line 229; never used
p2init defined in line 39; used 3 times
prcook defined in line 430; used 5 times
rcount defined in line 1034; used 3 times
rdin defined in line 1146; used 11 times
stoarg defined in line 875; used 2 times
store defined in line 759; used 9 times

Defined variables

CONSZ defined in line 1146; used 2 times
Oflag defined in line 21; used 2 times
callflag defined in line 756; used 10 times
cnames defined in line 403; used 2 times
deli defined in line 274; used 8 times
deltrees defined in line 273; used 4 times
edebug defined in line 24; never used
filename defined in line 11; never used
fregs defined in line 757; 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 901; used 1 times
node defined in line 10; used 2 times
nrecur defined in line 18; used 6 times
odebug defined in line 459; used 8 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: 1995-01-18
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 5548
Valid CSS Valid XHTML 1.0 Strict