home *** CD-ROM | disk | FTP | other *** search
/ CD Shareware Magazine 1996 December / CD_shareware_12-96.iso / DOS / Programa / CCDL122.ZIP / SOURCE / OPTIMIZE.C < prev    next >
Encoding:
C/C++ Source or Header  |  1996-07-19  |  30.9 KB  |  879 lines

  1. /*
  2.  * 68K/386 32-bit C compiler.
  3.  *
  4.  * copyright (c) 1996, David Lindauer
  5.  * 
  6.  * This compiler is intended for educational use.  It may not be used
  7.  * for profit without the express written consent of the author.
  8.  *
  9.  * It may be freely redistributed, as long as this notice remains intact
  10.  * and sources are distributed along with any executables derived from them.
  11.  *
  12.  * The author is not responsible for damages, either direct or consequential,
  13.  * that may arise from use of this software.
  14.  *
  15.  * v1.5 August 1996
  16.  * David Lindauer, gclind01@starbase.spd.louisville.edu
  17.  *
  18.  * Credits to Mathew Brandt for original K&R C compiler
  19.  *
  20.  */
  21. #include        <stdio.h>
  22. #include        "expr.h"
  23. #include        "c.h"
  24. #include        "gen.h"
  25. #include        "cglbdec.h"
  26.  
  27. int getmode(ENODE *ep1,ENODE *ep2)
  28. /*
  29.  * get the constant mode of a pair of nodes
  30.  * 0 = Neither node is a constant
  31.  * 1 = icon,icon
  32.  * 2 = icon,rcon
  33.  * 3 = rcon,icon
  34.  * 4 = rcon,rcon
  35.  * 5 = icon,nothing
  36.  * 6 = rcon,nothing
  37.  * 7 = nothing,icon
  38.  * 8 = nothing,rcon
  39.  */
  40. {
  41.                 int mode = 0;
  42.                 if (ep1->nodetype == en_icon) 
  43.                     if (ep2)  {
  44.                         if (ep2->nodetype == en_icon)
  45.                             mode = 1;
  46.                         else  if (ep2->nodetype == en_icon)
  47.                             mode = 2;
  48.                         else mode = 5;
  49.                     }
  50.                     else
  51.                         mode = 5;
  52.                 else if (ep1->nodetype == en_rcon)
  53.                     if (ep2)  {
  54.                         if (ep2->nodetype == en_icon)
  55.                             mode = 3;
  56.                         else  if (ep2->nodetype == en_rcon)
  57.                             mode = 4;
  58.                         else mode = 6;
  59.                     }
  60.                     else
  61.                         mode = 6;
  62.                 else if (ep2)
  63.                     if (ep2->nodetype == en_icon)
  64.                         mode = 7;
  65.                     else if (ep2->nodetype == en_rcon)
  66.                         mode = 8;
  67.     return(mode);
  68. }
  69.     
  70. void dooper(ENODE ** node, int mode)
  71. /*
  72.  *      dooper will execute a constant operation in a node and
  73.  *      modify the node to be the result of the operation.
  74.  *            It will also cast integers to floating point values when
  75.  *            necessary
  76.  */                             
  77. {     ENODE    *ep,*ep1,*ep2;
  78.       ep = *node;
  79.             ep1 = ep->v.p[0];
  80.             ep2 = ep->v.p[1];
  81.             if (mode ==5) {
  82.                     if (floatrecurse(ep2)) {
  83.                     ep1->v.f = ep1->v.i;
  84.                     ep1->nodetype = en_rcon;
  85.                 }
  86.                 return;
  87.             }
  88.             else if (mode == 7) {
  89.                 if (floatrecurse(ep1)) {
  90.                     ep2->v.f = ep2->v.i;
  91.                     ep2->nodetype = en_rcon;
  92.                 }
  93.                 return;
  94.             }
  95.             else if (mode == 6 || mode == 8)
  96.                 return;
  97.             else
  98.         switch( ep->nodetype ) {
  99.                 case en_add:
  100.                                                  switch (mode) {
  101.                                                     case 1:    
  102.                                 ep->nodetype = en_icon;
  103.                                 ep->v.i = ep1->v.i + ep2->v.i;
  104.                                                         break;
  105.                                                     case 2:    
  106.                                 ep->nodetype = en_rcon;
  107.                                 ep->v.f = ep1->v.i + ep2->v.f;
  108.                                                         break;
  109.                                                     case 3:    
  110.                                 ep->nodetype = en_rcon;
  111.                                 ep->v.f = ep1->v.f + ep2->v.i;
  112.                                                         break;
  113.                                                     case 4:    
  114.                                 ep->nodetype = en_rcon;
  115.                                 ep->v.f = ep1->v.f + ep2->v.f;
  116.                                                         break;
  117.                         }
  118.                                                 break;
  119.                 case en_sub:
  120.                                                  switch (mode) {
  121.                                                     case 1:    
  122.                                 ep->nodetype = en_icon;
  123.                                 ep->v.i = ep1->v.i - ep2->v.i;
  124.                                                         break;
  125.                                                     case 2:    
  126.                                 ep->nodetype = en_rcon;
  127.                                 ep->v.f = ep1->v.i - ep2->v.f;
  128.                                                         break;
  129.                                                     case 3:    
  130.                                 ep->nodetype = en_rcon;
  131.                                 ep->v.f = ep1->v.f - ep2->v.i;
  132.                                                         break;
  133.                                                     case 4:    
  134.                                 ep->nodetype = en_rcon;
  135.                                 ep->v.f = ep1->v.f - ep2->v.f;
  136.                                                         break;
  137.                                                 }
  138.                         break;
  139.                                 case en_pmul:
  140.                                 case en_umul:
  141.                 case en_mul:
  142.                                                  switch (mode) {
  143.                                                     case 1:    
  144.                                 ep->nodetype = en_icon;
  145.                                 ep->v.i = ep1->v.i * ep2->v.i;
  146.                                                         break;
  147.                                                     case 2:    
  148.                                 ep->nodetype = en_rcon;
  149.                                 ep->v.f = ep1->v.i * ep2->v.f;
  150.                                                         break;
  151.                                                     case 3:    
  152.                                 ep->nodetype = en_rcon;
  153.                                 ep->v.f = ep1->v.f * ep2->v.i;
  154.                                                         break;
  155.                                                     case 4:    
  156.                                 ep->nodetype = en_rcon;
  157.                                 ep->v.f = ep1->v.f * ep2->v.f;
  158.                                                         break;
  159.                                                 }
  160.                         break;
  161.                                 case en_pdiv:
  162.                 case en_div:
  163.                 case en_udiv:
  164.                                                  switch (mode) {
  165.                                                     case 1:    
  166.                                 ep->nodetype = en_icon;
  167.                                 ep->v.i = ep1->v.i / ep2->v.i;
  168.                                                         break;
  169.                                                     case 2:    
  170.                                 ep->nodetype = en_rcon;
  171.                                 ep->v.f = ep1->v.i / ep2->v.f;
  172.                                                         break;
  173.                                                     case 3:    
  174.                                 ep->nodetype = en_rcon;
  175.                                 ep->v.f = ep1->v.f / ep2->v.i;
  176.                                                         break;
  177.                                                     case 4:    
  178.                                 ep->nodetype = en_rcon;
  179.                                 ep->v.f = ep1->v.f / ep2->v.f;
  180.                                                         break;
  181.                                                 }
  182.                         break;
  183.                                 case en_mod:
  184.                                                 ep->nodetype = en_icon;
  185.                                                 ep->v.i = ep1->v.i % ep2->v.i;
  186.                                                 break;
  187.                 case en_lsh:
  188.                                 case en_alsh:
  189.                         ep->nodetype = en_icon;
  190.                         ep->v.i = ep1->v.i << ep2->v.i;
  191.                         break;
  192.                 case en_rsh:
  193.                                 case en_arsh:
  194.                         ep->nodetype = en_icon;
  195.                         ep->v.i = ep1->v.i >> ep2->v.i;
  196.                         break;
  197.                 case en_and:
  198.                         ep->nodetype = en_icon;
  199.                         ep->v.i = ep1->v.i & ep2->v.i;
  200.                         break;
  201.                 case en_or:
  202.                         ep->nodetype = en_icon;
  203.                         ep->v.i = ep1->v.i | ep2->v.i;
  204.                         break;
  205.                 case en_xor:
  206.                         ep->nodetype = en_icon;
  207.                         ep->v.i = ep1->v.i ^ ep2->v.i;
  208.                         break;
  209.                 }
  210. }
  211.  
  212. long     pwrof2(int i)
  213. /*
  214.  *      return which power of two i is or -1.
  215.  */
  216. {       long     p, q;
  217.         q = 2;
  218.         p = 1;
  219.         while( q > 0 )
  220.                 {
  221.                 if( q == i )
  222.                         return p;
  223.                 q <<= 1;
  224.                 ++p;
  225.                 }
  226.         return -1;
  227. }
  228.  
  229. long     mod_mask(int i)
  230. /*
  231.  *      make a mod mask for a power of two.
  232.  */
  233. {       long     m;
  234.         m = 0;
  235.         while( i-- )
  236.                 m = (m << 1) | 1;
  237.         return m;
  238. }
  239.  
  240. void opt0(ENODE ** node)
  241. /*
  242.  *      opt0 - delete useless expressions and combine constants.
  243.  *
  244.  *      opt0 will delete expressions such as x + 0, x - 0, x * 0,
  245.  *      x * 1, 0 / x, x / 1, x mod 0, etc from the tree pointed to
  246.  *      by node and combine obvious constant operations. It cannot
  247.  *      combine name and label constants but will combine icon type
  248.  *      nodes.
  249.  */
  250. {       ENODE    *ep;
  251.         int             sc,mode,val;
  252.                 double dval;
  253.         ep = *node;
  254.         if( ep == 0 )
  255.                 return;
  256.         switch( (*node)->nodetype ) {
  257.                 case en_b_ref:
  258.                 case en_w_ref:          /* optimize unary node */
  259.                 case en_ub_ref:
  260.                 case en_uw_ref:          /* optimize unary node */
  261.                 case en_l_ref:
  262.                                 case en_ul_ref:
  263.                                 case en_floatref: case en_doubleref: case en_longdoubleref:
  264.                                 case en_cb: case en_cub:
  265.                                 case en_cw: case en_cuw:
  266.                                 case en_cl: case en_cul:
  267.                                 case en_cf: case en_cd: case en_cp: case en_bits: case en_cld:
  268.                 case en_ainc:
  269.                 case en_adec:
  270.                 case en_not:
  271.                 case en_compl:
  272.                         opt0( &((*node)->v.p[0]));
  273.                         return;
  274.                 case en_uminus:
  275.                         opt0( &(ep->v.p[0]));
  276.                         if( ep->v.p[0]->nodetype == en_icon )
  277.                                 {
  278.                                 ep->nodetype = en_icon;
  279.                                 ep->v.i = -ep->v.p[0]->v.i;
  280.                                 }
  281.                         else if( ep->v.p[0]->nodetype == en_rcon )
  282.                                 {
  283.                                 ep->nodetype = en_rcon;
  284.                                 ep->v.i = -ep->v.p[0]->v.f;
  285.                                 }
  286.                         return;
  287.                 case en_add:
  288.                 case en_sub:
  289.                         opt0(&(ep->v.p[0]));
  290.                         opt0(&(ep->v.p[1]));
  291.                                                 mode = getmode(ep->v.p[0],ep->v.p[1]);
  292.                                                 switch (mode) {
  293.                                                     case 1: case 2: case 3: case 4:
  294.                                                         dooper(node,mode);
  295.                                                         break;
  296.                                                     case 5:
  297.                                                         if (ep->v.p[0]->v.i == 0) {
  298.                                                             if (ep->nodetype == en_sub) {
  299.                                                                 *node = ep->v.p[1];
  300.                                                                 ep->v.p[1]->v.i = - ep->v.p[1]->v.i;
  301.  
  302.                                                             }
  303.                                                             else *node = ep->v.p[1];
  304.                                                         }
  305.                                                         else dooper(node,mode);
  306.                                                         break;
  307.                                                     case 6:
  308.                                                         if (ep->v.p[0]->v.f == 0) {
  309.                                                             if (ep->nodetype == en_sub) {
  310.                                                                 *node = ep->v.p[1];
  311.                                                                 ep->v.p[1]->v.f = - ep->v.p[1]->v.f;
  312.  
  313.                                                             }
  314.                                                             else *node = ep->v.p[1];
  315.                                                         }
  316.                                                         else dooper(node,mode);
  317.                                                         break;
  318.                                                   case 7:
  319.                                                         if (ep->v.p[1]->v.i == 0) {
  320.                                                             *node = ep->v.p[0];
  321.                                                         }
  322.                                                         else dooper(node,mode);
  323.                                                         break;
  324.                                                     case 8:
  325.                                                         if (ep->v.p[1]->v.f == 0) {
  326.                                                             *node = ep->v.p[0];
  327.                                                         }
  328.                                                         else dooper(node,mode);
  329.                                                         break;
  330.                                                 }
  331.                         return;
  332.                 case en_mul:
  333.                                 case en_umul:
  334.                                 case en_pmul:
  335.                                 case en_asmul: case en_asumul:
  336.                         opt0(&(ep->v.p[0]));
  337.                         opt0(&(ep->v.p[1]));
  338.                                                 mode = getmode(ep->v.p[0],ep->v.p[1]);
  339.                                                 switch(mode) {
  340.                                                     case 1: case 2: case 3: case 4:
  341.                                                         dooper(node,mode);
  342.                                                         break;
  343.                                                     case 5:
  344.                                                         if (!floatrecurse(ep->v.p[1])) {
  345.                                 sc = pwrof2(ep->v.p[0]->v.i);
  346.                                 if( sc != -1 )
  347.                                         {
  348.                                                                                 ENODE *temp = ep->v.p[0];
  349.                                                                                 ep->v.p[0 ] = ep->v.p[1];
  350.                                                                                 ep->v.p[1] = temp;
  351.                                         ep->v.p[1]->v.i = sc;
  352.                                                                                 switch(ep->nodetype) {
  353.                                                                                     case en_mul:
  354.                                                                                         ep->nodetype = en_alsh;
  355.                                                                                         break;
  356.                                                                                     case en_asmul:
  357.                                                                                         ep->nodetype = en_asalsh;
  358.                                                                                         break;
  359.                                                                                     case en_umul:
  360.                                                                                     case en_pmul:
  361.                                                                                         ep->nodetype = en_lsh;
  362.                                                                                         break;
  363.                                                                                     case en_asumul:
  364.                                                                                         ep->nodetype = en_aslsh;
  365.                                                                                         break;
  366.                                                                                 }
  367.                                                                                 break;
  368.                                         }
  369.                             }
  370.                                                         val = ep->v.p[0]->v.i;
  371.                                                         if (val == 0)
  372.                                                             *node = ep->v.p[0];
  373.                                                         else if (val == 1)
  374.                                                             *node = ep->v.p[1];
  375.                                                         else if (val == -1)
  376.                                                             *node = makenode(en_uminus,(char *)ep->v.p[1],0);
  377.                                                         else dooper(node,mode);
  378.                                                         break;
  379.                                                     case 6:
  380.                                                         dval = ep->v.p[0]->v.f;
  381.                                                         if (dval == 0)
  382.                                                             *node = ep->v.p[0];
  383.                                                         else if (dval == 1)
  384.                                                             *node = ep->v.p[1];
  385.                                                         else if (dval == -1)
  386.                                                             *node = makenode(en_uminus,(char *)ep->v.p[1],0);
  387.                                                         else dooper(node,mode);
  388.                                                         break;
  389.                                                     case 7:
  390.                                                         if (!floatrecurse(ep->v.p[0])) {
  391.                                 sc = pwrof2(ep->v.p[1]->v.i);
  392.                                 if( sc != -1 )
  393.                                         {
  394.                                         ep->v.p[1]->v.i = sc;
  395.                                                                                 switch(ep->nodetype) {
  396.                                                                                     case en_mul:
  397.                                                                                         ep->nodetype = en_alsh;
  398.                                                                                         break;
  399.                                                                                     case en_asmul:
  400.                                                                                         ep->nodetype = en_asalsh;
  401.                                                                                         break;
  402.                                                                                     case en_umul:
  403.                                                                                     case en_pmul:
  404.                                                                                         ep->nodetype = en_lsh;
  405.                                                                                         break;
  406.                                                                                     case en_asumul:
  407.                                                                                         ep->nodetype = en_aslsh;
  408.                                                                                         break;
  409.                                                                                 }
  410.                                                                                 break;
  411.                                         }
  412.                             }
  413.                                                         val = ep->v.p[1]->v.i;
  414.                                                         if (val == 0)
  415.                                                             *node = ep->v.p[1];
  416.                                                         else if (val == 1)
  417.                                                             *node = ep->v.p[0];
  418.                                                         else if (val == -1)
  419.                                                             *node = makenode(en_uminus,(char *)ep->v.p[0],0);
  420.                                                         else dooper(node,mode);
  421.                                                         break;
  422.                                                     case 8:
  423.                                                         dval = ep->v.p[1]->v.f;
  424.                                                         if (dval == 0)
  425.                                                             *node = ep->v.p[1];
  426.                                                         else if (dval == 1)
  427.                                                             *node = ep->v.p[0];
  428.                                                         else if (dval == -1)
  429.                                                             *node = makenode(en_uminus,(char *)ep->v.p[0],0);
  430.                                                         else dooper(node,mode);
  431.                                                         break;
  432.                                                 }
  433.                         break;
  434.                                 case en_pdiv:
  435.                 case en_div:
  436.                                 case en_udiv:
  437.                                 case en_asdiv:
  438.                                 case en_asudiv:
  439.                         opt0(&(ep->v.p[0]));
  440.                         opt0(&(ep->v.p[1]));
  441.                                                 mode = getmode(ep->v.p[0],ep->v.p[1]);
  442.                                                 switch(mode) {
  443.                                                     case 1:
  444.                                                     case 2:
  445.                                                     case 3:
  446.                                                     case 4: 
  447.                                                         dooper(node,mode);
  448.                                                         break;
  449.                                                     case 5:
  450.                                                         if (ep->v.p[0]->v.i == 0)
  451.                                                             *node = ep->v.p[0];
  452.                                                         else
  453.                                                             dooper(node,mode);
  454.                                                         break;
  455.                                                     case 6:
  456.                                                         if (ep->v.p[0]->v.f == 0)
  457.                                                             *node = ep->v.p[0];
  458.                                                         else
  459.                                                             dooper(node,mode);
  460.                                                         break;
  461.                                                     case 7:
  462.                                                         if (!floatrecurse(ep->v.p[0])) {
  463.                                 sc = pwrof2(ep->v.p[1]->v.i);
  464.                                 if( sc != -1 )
  465.                                         {
  466.                                         ep->v.p[1]->v.i = sc;
  467.                                                                                 switch(ep->nodetype) {
  468.                                                                                     case en_div:
  469.                                                                                         ep->nodetype = en_arsh;
  470.                                                                                         break;
  471.                                                                                     case en_asdiv:
  472.                                                                                         ep->nodetype = en_asarsh;
  473.                                                                                         break;
  474.                                                                                     case en_udiv:
  475.                                                                                     case en_pdiv:
  476.                                                                                         ep->nodetype = en_rsh;
  477.                                                                                         break;
  478.                                                                                     case en_asudiv:
  479.                                                                                         ep->nodetype = en_asrsh;
  480.                                                                                         break;
  481.                                                                                 }
  482.                                                                                 break;
  483.                                         }
  484.                             }
  485.                                                         val = ep->v.p[1]->v.i;
  486.                                                         if (val == 1)
  487.                                                             *node = ep->v.p[0];
  488.                                                         else if (val == -1)
  489.                                                             *node = makenode(en_uminus,(char *)ep->v.p[0],0);
  490.                                                         else dooper(node,mode);
  491.                                                         break;
  492.                                                     case 8:
  493.                                                         dval = ep->v.p[1]->v.f;
  494.                                                         if (dval == 1)
  495.                                                             *node = ep->v.p[0];
  496.                                                         else if (dval == -1)
  497.                                                             *node = makenode(en_uminus,(char *)ep->v.p[0],0);
  498.                                                         else dooper(node,mode);
  499.                                                         break;
  500.                                                 }
  501.                         break;
  502.                 case en_mod:
  503.                                 case en_umod:
  504.                                 case en_asmod: case en_asumod:
  505.                         opt0(&(ep->v.p[0]));
  506.                         opt0(&(ep->v.p[1]));
  507.                                                 mode = getmode(ep->v.p[0],ep->v.p[1]);
  508.                                                 switch(mode) {
  509.                                                     case 7:
  510.                                                         if (!floatrecurse(ep->v.p[0])) {
  511.                                 sc = pwrof2(ep->v.p[1]->v.i);
  512.                                 if( sc != -1 )
  513.                                         {
  514.                                         ep->v.p[1]->v.i = mod_mask(sc);
  515.                                                                                 if (ep->nodetype == en_asmod || ep->nodetype == en_asumod)
  516.                                             ep->nodetype = en_asand;
  517.                                                                                 else
  518.                                             ep->nodetype = en_and;
  519.                                                                                 break;
  520.                                         }
  521.                                 }
  522.                                                     case 1:
  523.                                                     case 2:
  524.                                                     case 3:
  525.                                                     case 4: 
  526.                                                     case 5: case 6: case 8:
  527.                                                         dooper(node,mode);
  528.                                                 }
  529.                         break;
  530.                 case en_and:    case en_or:
  531.                 case en_xor:    case en_rsh:
  532.                 case en_lsh:    case en_arsh: case en_alsh:
  533.                         opt0(&(ep->v.p[0]));
  534.                         opt0(&(ep->v.p[1]));
  535.                         if( ep->v.p[0]->nodetype == en_icon &&
  536.                                 ep->v.p[1]->nodetype == en_icon )
  537.                                 dooper(node,getmode(ep->v.p[1],ep->v.p[2]));
  538.                         break;
  539.                 case en_land:   case en_lor:
  540.                 case en_lt:        case en_le:
  541.                 case en_ugt:    case en_uge: case en_ult: case en_ule:
  542.                 case en_gt:        case en_ge:
  543.                 case en_eq:        case en_ne:
  544.                                 case en_asalsh: case en_asarsh:
  545.                 case en_asand:  case en_asor:
  546.                 case en_asadd:  case en_assub:
  547.                 case en_asrsh:
  548.                 case en_aslsh:  case en_cond:
  549.                 case en_fcall:  case en_void: case en_trapcall: case en_intcall:
  550.                 case en_assign: case en_moveblock: en_stackblock: en_callblock:
  551.                                 case en_fcallb: case en_refassign:
  552.                         opt0(&(ep->v.p[0]));
  553.                         opt0(&(ep->v.p[1]));
  554.                         break;
  555.                 }
  556. }
  557. #ifdef DOUBLEFOLD
  558. double     xfold(ENODE * node)
  559. /*
  560.  *      xfold will remove constant nodes and return the values to
  561.  *      the calling routines.
  562.  */
  563. {       double     i;
  564.         if( node == 0 )
  565.                 return 0;
  566.         switch( node->nodetype )
  567.                 {
  568.                 case en_icon:
  569.                         i = node->v.i;
  570.                         node->v.i = 0;
  571.                         return i;
  572.                 case en_rcon:
  573.                         i = node->v.f;
  574.                         node->v.f = 0;
  575.                         return i;
  576.                 case en_add:
  577.                         return xfold(node->v.p[0]) + xfold(node->v.p[1]);
  578.                 case en_sub:
  579.                         return xfold(node->v.p[0]) - xfold(node->v.p[1]);
  580.                 case en_mul:
  581.                                 case en_pmul:
  582.                                 case en_umul:
  583.                         if( node->v.p[0]->nodetype == en_icon)
  584.                                 return xfold(node->v.p[1]) * node->v.p[0]->v.i;
  585.                                                     else if (node->v.p[0]->nodetype == en_rcon)
  586.                                 return xfold(node->v.p[1]) * node->v.p[0]->v.f;
  587.                         else if( node->v.p[1]->nodetype == en_icon)
  588.                                 return xfold(node->v.p[0]) * node->v.p[1]->v.i;
  589.                                                     else if (node->v.p[1]->nodetype == en_rcon)
  590.                                 return xfold(node->v.p[0]) * node->v.p[1]->v.f;
  591.                         else return 0;
  592.                 case en_lsh:
  593.                                 case en_alsh:
  594.                         if( node->v.p[0]->nodetype == en_icon )
  595.                                 return (double)(((int)xfold(node->v.p[1])) << node->v.p[0]->v.i);
  596.                         else if( node->v.p[1]->nodetype == en_icon )
  597.                                 return (double)(((int)xfold(node->v.p[0])) << node->v.p[1]->v.i);
  598.                         else return 0;
  599.                 case en_uminus:
  600.                         return - xfold(node->v.p[0]);
  601.                                 case en_asalsh: case en_asarsh: case en_arsh:
  602.                 case en_rsh:    case en_div:  case en_pdiv:
  603.                 case en_mod:    case en_asadd:
  604.                 case en_assub:  case en_asmul:
  605.                 case en_asdiv:  case en_asmod:
  606.                 case en_and:    case en_land:
  607.                 case en_or:     case en_lor:
  608.                 case en_xor:    case en_asand:
  609.                 case en_asor:   case en_void:
  610.                 case en_fcall:  case en_assign: case en_moveblock: case en_trapcall:
  611.                                 case en_stackblock: case en_intcall: en_callblock: case en_fcallb:
  612.                                 case en_asumul: case en_asudiv: case en_asumod: case en_refassign:
  613.                                 case en_udiv:
  614.                         fold_const(&node->v.p[0]);
  615.                         fold_const(&node->v.p[1]);
  616.                         return 0;
  617.                 case en_b_ref:  case en_w_ref:
  618.                 case en_ub_ref:  case en_uw_ref:
  619.                 case en_l_ref:  case en_compl: case en_ul_ref:
  620.                                 case en_floatref: case en_doubleref: case en_longdoubleref:
  621.                 case en_not: case en_bits:
  622.                         fold_const(&node->v.p[0]);
  623.                         return 0;
  624.                 }
  625.         return 0;
  626. }
  627.  
  628. void fold_const(ENODE ** node)
  629. /*
  630.  *      reorganize an expression for optimal constant grouping.
  631.  */
  632. {       ENODE    *ep;
  633.         double   i;
  634.         ep = *node;
  635.         if( ep == 0 )
  636.                 return;
  637.         if( ep->nodetype == en_add || ep->nodetype == en_sub)
  638.                 {
  639.                                 if (ep->v.p[0]->nodetype == en_cp && ep->v.p[0]->v.p[0]->nodetype == en_icon) {
  640.                                                 ep->v.p[0]->v.p[0]->v.i += xfold(ep->v.p[1]);
  641.                                                 return;
  642.                                                 }
  643.                                 else if (ep->v.p[1]->nodetype == en_cp && ep->v.p[1]->v.p[0]->nodetype == en_icon) {
  644.                                                 ep->v.p[1]->v.p[0]->v.i += xfold(ep->v.p[0]);
  645.                                                 return;
  646.                                                 }
  647.                 else if( ep->v.p[0]->nodetype == en_icon )
  648.                         {
  649.                         ep->v.p[0]->v.i += xfold(ep->v.p[1]);
  650.                         return;
  651.                         }
  652.                 else if( ep->v.p[0]->nodetype == en_rcon )
  653.                         {
  654.                         ep->v.p[0]->v.f += xfold(ep->v.p[1]);
  655.                         return;
  656.                         }
  657.  
  658.                 else if( ep->v.p[1]->nodetype == en_icon )
  659.                         {
  660.                         ep->v.p[1]->v.i += xfold(ep->v.p[0]);
  661.                         return;
  662.                         }
  663.                 else if( ep->v.p[0]->nodetype == en_rcon )
  664.                         {
  665.                         ep->v.p[1]->v.f += xfold(ep->v.p[0]);
  666.                         return;
  667.                         }
  668.  
  669.                 }
  670.         else if( ep->nodetype == en_sub )
  671.                 {
  672.                                 if (ep->v.p[0]->nodetype == en_cp && ep->v.p[0]->v.p[0]->nodetype == en_icon) {
  673.                                                 ep->v.p[0]->v.p[0]->v.i -= xfold(ep->v.p[1]);
  674.                                                 return;
  675.                                                 }
  676.                                 else if (ep->v.p[1]->nodetype == en_cp && ep->v.p[1]->v.p[0]->nodetype == en_icon) {
  677.                                                 ep->v.p[1]->v.p[0]->v.i = xfold(ep->v.p[0]) - ep->v.p[1]->v.p[0]->v.i;
  678.                                                 return;
  679.                                                 }
  680.                 else if( ep->v.p[0]->nodetype == en_icon )
  681.                         {
  682.                         ep->v.p[0]->v.i -= xfold(ep->v.p[1]);
  683.                         return;
  684.                         }
  685.                 else if( ep->v.p[0]->nodetype == en_rcon )
  686.                         {
  687.                         ep->v.p[0]->v.f -= xfold(ep->v.p[1]);
  688.                         return;
  689.                         }
  690.                 else if( ep->v.p[1]->nodetype == en_icon )
  691.                         {
  692.                         ep->v.p[1]->v.i = xfold(ep->v.p[0]) - ep->v.p[1]->v.i;
  693.                         return;
  694.                         }
  695.                 else if( ep->v.p[1]->nodetype == en_rcon )
  696.                         {
  697.                         ep->v.p[1]->v.f = xfold(ep->v.p[0]) - ep->v.p[1]->v.f;
  698.                         return;
  699.                         }
  700.  
  701.                 }
  702.         i = xfold(ep);
  703.         if( i != 0 ) {
  704.                                 if ((int)i != i) {
  705.                                     ep = xalloc(sizeof(ENODE));
  706.                                     ep->nodetype = en_rcon;
  707.                                     ep->v.f = i;
  708.                     ep = makenode(en_add,ep,*node);
  709.                                 }
  710.                                 else {
  711.                       ep = makenode(en_icon,(char *)(int)i,0);
  712.                     ep = makenode(en_add,ep,*node);
  713.                                 }
  714.                 *node = ep;
  715.         }
  716. }
  717. #endif
  718. void fold_const2(ENODE **node);
  719. long     xfold2(ENODE * node)
  720. /*
  721.  *      xfold2 will remove constant nodes and return the values to
  722.  *      the calling routines.
  723.  */
  724. {       long     i;
  725.         if( node == 0 )
  726.                 return 0;
  727.         switch( node->nodetype )
  728.                 {
  729.                 case en_icon:
  730.                         i = node->v.i;
  731.                         node->v.i = 0;
  732.                         return i;
  733.                 case en_add:
  734.                         return xfold2(node->v.p[0]) + xfold2(node->v.p[1]);
  735.                 case en_sub:
  736.                         return xfold2(node->v.p[0]) - xfold2(node->v.p[1]);
  737.                                 case en_or:
  738.                         return xfold2(node->v.p[0]) | xfold2(node->v.p[1]);
  739.                                 case en_xor:
  740.                         return xfold2(node->v.p[0]) ^ xfold2(node->v.p[1]);
  741.                 case en_mul:
  742.                                 case en_pmul:
  743.                                 case en_umul:
  744.                         if( node->v.p[0]->nodetype == en_icon)
  745.                                 return xfold2(node->v.p[1]) * node->v.p[0]->v.i;
  746.                         else if( node->v.p[1]->nodetype == en_icon)
  747.                                 return xfold2(node->v.p[0]) * node->v.p[1]->v.i;
  748.                         else return 0;
  749.                 case en_lsh:
  750.                                 case en_alsh:
  751.                         if( node->v.p[0]->nodetype == en_icon )
  752.                                 return (double)(((int)xfold2(node->v.p[1])) << node->v.p[0]->v.i);
  753.                         else if( node->v.p[1]->nodetype == en_icon )
  754.                                 return (double)(((int)xfold2(node->v.p[0])) << node->v.p[1]->v.i);
  755.                         else return 0;
  756.                 case en_uminus:
  757.                         return - xfold2(node->v.p[0]);
  758.                                 case en_asalsh: case en_asarsh: case en_arsh:
  759.                 case en_rsh:    case en_div:  case en_pdiv:
  760.                 case en_mod:    case en_asadd:
  761.                 case en_assub:  case en_asmul:
  762.                 case en_asdiv:  case en_asmod:
  763.                 case en_land: case en_lor:
  764.                 case en_asand:    case en_and:
  765.                 case en_asor:   case en_void:
  766.                 case en_fcall:  case en_assign: case en_moveblock: case en_trapcall:
  767.                                 case en_stackblock: case en_intcall: en_callblock: case en_fcallb:
  768.                                 case en_asumul: case en_asudiv: case en_asumod: case en_refassign:
  769.                                 case en_udiv:
  770.                         fold_const2(&node->v.p[0]);
  771.                         fold_const2(&node->v.p[1]);
  772.                         return 0;
  773.                 case en_b_ref:  case en_w_ref:
  774.                 case en_ub_ref:  case en_uw_ref:
  775.                 case en_l_ref:  case en_compl: case en_ul_ref:
  776.                                 case en_floatref: case en_doubleref: case en_longdoubleref:
  777.                 case en_not: case en_bits:
  778.                         fold_const2(&node->v.p[0]);
  779.                         return 0;
  780.                 }
  781.         return 0;
  782. }
  783.  
  784. void fold_const2(ENODE ** node)
  785. /*
  786.  *      reorganize an expression for optimal constant grouping.
  787.  */
  788. {       ENODE    *ep;
  789.         long   i;
  790.         ep = *node;
  791.         if( ep == 0 )
  792.                 return;
  793.                 switch (ep->nodetype) {
  794.                         case en_add:
  795.                                 if (ep->v.p[0]->nodetype == en_cp && ep->v.p[0]->v.p[0]->nodetype == en_icon) {
  796.                                                 ep->v.p[0]->v.p[0]->v.i += xfold2(ep->v.p[1]);
  797.                                                 return;
  798.                                                 }
  799.                                 else if (ep->v.p[1]->nodetype == en_cp && ep->v.p[1]->v.p[0]->nodetype == en_icon) {
  800.                                                 ep->v.p[1]->v.p[0]->v.i += xfold2(ep->v.p[0]);
  801.                                                 return;
  802.                                                 }
  803.                 else if( ep->v.p[0]->nodetype == en_icon )
  804.                         {
  805.                         ep->v.p[0]->v.i += xfold2(ep->v.p[1]);
  806.                         return;
  807.                         }
  808.  
  809.                 else if( ep->v.p[1]->nodetype == en_icon )
  810.                         {
  811.                         ep->v.p[1]->v.i += xfold2(ep->v.p[0]);
  812.                         return;
  813.                         }
  814.  
  815.                                 break;
  816.                         case en_sub:
  817.                                 if (ep->v.p[0]->nodetype == en_cp && ep->v.p[0]->v.p[0]->nodetype == en_icon) {
  818.                                                 ep->v.p[0]->v.p[0]->v.i -= xfold2(ep->v.p[1]);
  819.                                                 return;
  820.                                                 }
  821.                                 else if (ep->v.p[1]->nodetype == en_cp && ep->v.p[1]->v.p[0]->nodetype == en_icon) {
  822.                                                 ep->v.p[1]->v.p[0]->v.i -= xfold2(ep->v.p[0]);
  823.                                                 return;
  824.                                                 }
  825.                 else if( ep->v.p[0]->nodetype == en_icon )
  826.                         {
  827.                         ep->v.p[0]->v.i -= xfold2(ep->v.p[1]);
  828.                         return;
  829.                         }
  830.                 else if( ep->v.p[1]->nodetype == en_icon )
  831.                         {
  832.                         ep->v.p[1]->v.i -= xfold2(ep->v.p[0]);
  833.                         return;
  834.                         }
  835.  
  836.                                 break;
  837.                         case en_or:
  838.                 if( ep->v.p[0]->nodetype == en_icon )
  839.                         {
  840.                         ep->v.p[0]->v.i |= xfold2(ep->v.p[1]);
  841.                         return;
  842.                         }
  843.                 else if( ep->v.p[1]->nodetype == en_icon )
  844.                         {
  845.                         ep->v.p[1]->v.i |= xfold2(ep->v.p[0]);
  846.                         return;
  847.                         }
  848.                                 break;
  849.                         case en_xor:
  850.                 if( ep->v.p[0]->nodetype == en_icon )
  851.                         {
  852.                         ep->v.p[0]->v.i ^= xfold2(ep->v.p[1]);
  853.                         return;
  854.                         }
  855.                 else if( ep->v.p[1]->nodetype == en_icon )
  856.                         {
  857.                         ep->v.p[1]->v.i ^= xfold2(ep->v.p[0]);
  858.                         return;
  859.                         }
  860.                                 break;
  861.                 }
  862.         i = xfold2(ep);
  863.         if( i != 0 ) {
  864.                                     ep = xalloc(sizeof(ENODE));
  865.                                     ep->nodetype = en_icon;
  866.                                     ep->v.i = i;
  867.                     ep = makenode(en_add,ep,*node);
  868.                 *node = ep;
  869.         }
  870. }
  871. void opt4(ENODE ** node)
  872. /*
  873.  *      apply all constant optimizations.
  874.  */
  875. {
  876.         opt0(node);
  877.         fold_const2(node);
  878.         opt0(node);
  879. }