home *** CD-ROM | disk | FTP | other *** search
/ minnie.tuhs.org / unixen.tar / unixen / PDP-11 / Trees / V7 / usr / src / cmd / mip / reader.c < prev    next >
Encoding:
C/C++ Source or Header  |  1979-01-10  |  23.0 KB  |  1,254 lines

  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.     }
  1253.  
  1254.