home *** CD-ROM | disk | FTP | other *** search
/ io Programmo 40 / IOPROG_40.ISO / SOFT / NETFrameworkSDK.exe / comsdk.cab / samples1.exe / smc / foldexpr.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2000-06-23  |  23.1 KB  |  908 lines

  1. /*****************************************************************************/
  2.  
  3. #include "smcPCH.h"
  4. #pragma hdrstop
  5.  
  6. #include <float.h>
  7.  
  8. /*****************************************************************************/
  9.  
  10. static
  11. double              toDouble(unsigned __int64 val)
  12. {
  13.     __int64         iv = (__int64)val;
  14.     double          dv = (double )iv;
  15.  
  16.     if  (iv < 0)
  17.         dv += 4294967296.0 * 4294967296.0;  // this is 2**64
  18.  
  19.     return  dv;
  20. }
  21.  
  22. /*****************************************************************************
  23.  *
  24.  *  Try to fold a binary operator with two string literal operands.
  25.  */
  26.  
  27. Tree                compiler::cmpFoldStrBinop(Tree expr)
  28. {
  29.     Tree            op1 = expr->tnOp.tnOp1;
  30.     Tree            op2 = expr->tnOp.tnOp2;
  31.  
  32.     assert(op1->tnOper == TN_CNS_STR);
  33.     assert(op2->tnOper == TN_CNS_STR);
  34.  
  35.     const   char *  sv1 = op1->tnStrCon.tnSconVal;
  36. //  size_t          sl1 = op1->tnStrCon.tnSconLen;
  37.  
  38.     const   char *  sv2 = op2->tnStrCon.tnSconVal;
  39. //  size_t          sl2 = op2->tnStrCon.tnSconLen;
  40.  
  41.     __int32         rel;
  42.  
  43.     switch (expr->tnOper)
  44.     {
  45.     case TN_EQ : rel = (strcmp(sv1, sv2) == 0); break;
  46.     case TN_NE : rel = (strcmp(sv1, sv2) != 0); break;
  47.     case TN_LT : rel = (strcmp(sv1, sv2) <  0); break;
  48.     case TN_LE : rel = (strcmp(sv1, sv2) <= 0); break;
  49.     case TN_GE : rel = (strcmp(sv1, sv2) >= 0); break;
  50.     case TN_GT : rel = (strcmp(sv1, sv2) >  0); break;
  51.  
  52.     default:
  53. #ifdef DEBUG
  54.         cmpParser->parseDispTree(expr);
  55. #endif
  56.         NO_WAY(!"unexpected operator");
  57.     }
  58.  
  59.     assert(expr->tnVtyp <= TYP_INT);
  60.  
  61.     expr->tnOper             = TN_CNS_INT;
  62.     expr->tnIntCon.tnIconVal = rel;
  63.  
  64.     return expr;
  65. }
  66.  
  67. /*****************************************************************************
  68.  *
  69.  *  Try to fold a unary operator with a 32-bit integer constant operand.
  70.  */
  71.  
  72. Tree                compiler::cmpFoldIntUnop(Tree expr)
  73. {
  74.     Tree            op1 = expr->tnOp.tnOp1;
  75.  
  76.     assert(op1->tnOper == TN_CNS_INT);
  77.  
  78.     // ISSUE: Does the following work for enum types and small integers?
  79.  
  80.     __int32         iv1 = op1->tnIntCon.tnIconVal;
  81.  
  82.     bool            uns = varTypeIsUnsigned(cmpActualVtyp(expr->tnType));
  83.  
  84.     /* Special case: cast of 'null' or 'int -> ptr' */
  85.  
  86.     if  (op1->tnVtyp == TYP_REF || op1->tnVtyp == TYP_PTR)
  87.     {
  88.         assert(expr->tnOper == TN_CAST);
  89.  
  90.         assert(expr->tnVtyp == TYP_REF  ||
  91.                expr->tnVtyp == TYP_PTR  ||
  92.                expr->tnVtyp == TYP_INT  ||
  93.                expr->tnVtyp == TYP_UINT ||
  94.                expr->tnVtyp == TYP_ARRAY);
  95.  
  96.         goto BASH_TYPE;
  97.     }
  98.  
  99.     assert(op1->tnVtyp <= TYP_UINT || op1->tnVtyp == TYP_ENUM);
  100.  
  101.     switch (expr->tnOper)
  102.     {
  103.         var_types       dstVtp;
  104.  
  105.     case TN_CAST:
  106.  
  107.         dstVtp = expr->tnVtypGet();
  108.  
  109.     CAST_REP:
  110.  
  111.         switch (dstVtp)
  112.         {
  113.         case TYP_PTR:
  114.         case TYP_REF:
  115.  
  116.             // The only address that can be cast is 'null'
  117.  
  118.             break;
  119.  
  120.         case TYP_CHAR  : iv1 = (  signed char )iv1; break;
  121.         case TYP_UCHAR : iv1 = (unsigned char )iv1; break;
  122.         case TYP_SHORT : iv1 = (  signed short)iv1; break;
  123.         case TYP_USHORT:
  124.         case TYP_WCHAR : iv1 = (unsigned short)iv1; break;
  125.  
  126.         case TYP_INT   :
  127.         case TYP_UINT  : break;
  128.  
  129.         case TYP_LONG:
  130.  
  131.             /* Bash the node operator (in addition to the type) */
  132.  
  133.             op1->tnOper             = TN_CNS_LNG;
  134.             op1->tnLngCon.tnLconVal = (__int64)(uns ? (unsigned)iv1
  135.                                                     :           iv1);
  136.             goto BASH_TYPE;
  137.  
  138.         case TYP_FLOAT:
  139.  
  140.             /* Bash the node operator (in addition to the type) */
  141.  
  142.             op1->tnOper             = TN_CNS_FLT;
  143.             op1->tnFltCon.tnFconVal = (float  )(uns ? (unsigned)iv1
  144.                                                     :           iv1);
  145.             goto BASH_TYPE;
  146.  
  147.         case TYP_DOUBLE:
  148.  
  149.             /* Bash the node operator (in addition to the type) */
  150.  
  151.             op1->tnOper             = TN_CNS_DBL;
  152.             op1->tnDblCon.tnDconVal = (double )(uns ? (unsigned)iv1
  153.                                                     :           iv1);
  154.             goto BASH_TYPE;
  155.  
  156.         case TYP_CLASS:
  157.             // ISSUE: Should we fold this ?
  158.             return  expr;
  159.  
  160.         case TYP_ENUM:
  161.             dstVtp = expr->tnType->tdEnum.tdeIntType->tdTypeKindGet();
  162.             goto CAST_REP;
  163.  
  164.         default:
  165.  
  166.             // UNDONE: need to handle more cases
  167.  
  168. #ifdef DEBUG
  169.             cmpParser->parseDispTree(expr);
  170. #endif
  171.             NO_WAY(!"unhandled cast type");
  172.             return expr;
  173.         }
  174.  
  175.         op1->tnIntCon.tnIconVal = iv1;
  176.  
  177.         /* Bash the type of the operand and return it */
  178.  
  179.     BASH_TYPE:
  180.  
  181.         op1->tnVtyp   = expr->tnVtyp;
  182.         op1->tnType   = expr->tnType;
  183.         op1->tnFlags |= TNF_BEEN_CAST;
  184.  
  185.         return op1;
  186.  
  187.     case TN_NEG:
  188.         iv1 = -iv1;
  189.         break;
  190.  
  191.     case TN_NOT:
  192.         iv1 = ~iv1;
  193.         break;
  194.  
  195.     case TN_LOG_NOT:
  196.         iv1 = !iv1;
  197.         break;
  198.  
  199.     case TN_NOP:
  200.         break;
  201.  
  202.     default:
  203. #ifdef DEBUG
  204.         cmpParser->parseDispTree(expr);
  205. #endif
  206.         NO_WAY(!"unexpected operator");
  207.     }
  208.  
  209.     assert(expr->tnVtyp <= TYP_UINT || expr->tnVtyp == TYP_ENUM);
  210.  
  211.     expr->tnOper             = TN_CNS_INT;
  212.     expr->tnIntCon.tnIconVal = iv1;
  213.  
  214.     return expr;
  215. }
  216.  
  217. /*****************************************************************************
  218.  *
  219.  *  Try to fold a binary operator with 32-bit integer constant operands.
  220.  */
  221.  
  222. Tree                compiler::cmpFoldIntBinop(Tree expr)
  223. {
  224.     Tree            op1 = expr->tnOp.tnOp1;
  225.     Tree            op2 = expr->tnOp.tnOp2;
  226.  
  227.     assert(op1->tnOper == TN_CNS_INT && (op1->tnVtyp <= TYP_UINT || op1->tnVtyp == TYP_ENUM));
  228.     assert(op2->tnOper == TN_CNS_INT && (op2->tnVtyp <= TYP_UINT || op2->tnVtyp == TYP_ENUM));
  229.  
  230.     __int32         iv1 = op1->tnIntCon.tnIconVal;
  231.     __int32         iv2 = op2->tnIntCon.tnIconVal;
  232.  
  233.     bool            uns = varTypeIsUnsigned(cmpActualVtyp(expr->tnType));
  234.  
  235.     switch (expr->tnOper)
  236.     {
  237.     case TN_ADD: iv1  += iv2; break;
  238.     case TN_SUB: iv1  -= iv2; break;
  239.     case TN_MUL: iv1  *= iv2; break;
  240.  
  241.     case TN_DIV: if (iv2 == 0) goto INT_DIV_ZERO;
  242.                  if (uns)
  243.                      iv1  = (unsigned)iv1 / (unsigned)iv2;
  244.                  else
  245.                      iv1 /= iv2;
  246.                  break;
  247.  
  248.     case TN_MOD: if (iv2 == 0) goto INT_DIV_ZERO;
  249.                  if (uns)
  250.                      iv1  = (unsigned)iv1 % (unsigned)iv2;
  251.                  else
  252.                      iv1 %= iv2;
  253.                  break;
  254.  
  255.     case TN_OR : iv1  |= iv2; break;
  256.     case TN_XOR: iv1  ^= iv2; break;
  257.     case TN_AND: iv1  &= iv2; break;
  258.  
  259.     // ISSUE: Need to check for signed/unsigned shift count!
  260.  
  261.     case TN_LSH: iv1 <<= iv2; break;
  262.     case TN_RSH: if (uns)
  263.                      iv1   = (unsigned)iv1 >> iv2;
  264.                  else
  265.                      iv1 >>= iv2;
  266.                  break;
  267.  
  268.     case TN_EQ : iv1 = (iv1 == iv2); break;
  269.     case TN_NE : iv1 = (iv1 != iv2); break;
  270.  
  271.     case TN_LT : if (uns)
  272.                      iv1 = ((unsigned)iv1 <  (unsigned)iv2);
  273.                  else
  274.                      iv1 = (iv1 <  iv2);
  275.                  break;
  276.     case TN_LE : if (uns)
  277.                      iv1 = ((unsigned)iv1 <= (unsigned)iv2);
  278.                  else
  279.                      iv1 = (iv1 <  iv2);
  280.                  break;
  281.     case TN_GE : if (uns)
  282.                      iv1 = ((unsigned)iv1 >= (unsigned)iv2);
  283.                  else
  284.                      iv1 = (iv1 <  iv2);
  285.                  break;
  286.     case TN_GT : if (uns)
  287.                      iv1 = ((unsigned)iv1 >  (unsigned)iv2);
  288.                  else
  289.                      iv1 = (iv1 <  iv2);
  290.                  break;
  291.  
  292.     case TN_LOG_OR : iv1 = iv1 || iv2; break;
  293.     case TN_LOG_AND: iv1 = iv1 && iv2; break;
  294.  
  295.     default:
  296. #ifdef DEBUG
  297.         cmpParser->parseDispTree(expr);
  298. #endif
  299.         NO_WAY(!"unexpected operator");
  300.     }
  301.  
  302.     assert(expr->tnVtyp <= TYP_UINT || expr->tnVtyp == TYP_ENUM);
  303.  
  304.     expr->tnOper             = TN_CNS_INT;
  305.     expr->tnIntCon.tnIconVal = iv1;
  306.  
  307.     return expr;
  308.  
  309. INT_DIV_ZERO:
  310.  
  311.     cmpError(ERRdivZero);
  312.  
  313.     expr->tnOper             = TN_ERROR;
  314.     expr->tnIntCon.tnIconVal = 0;
  315.  
  316.     return expr;
  317. }
  318.  
  319. /*****************************************************************************
  320.  *
  321.  *  Try to fold a unary operator with a 64-bit integer constant operand.
  322.  */
  323.  
  324. Tree                compiler::cmpFoldLngUnop(Tree expr)
  325. {
  326.     Tree            op1 = expr->tnOp.tnOp1;
  327.  
  328.     assert(op1->tnOper == TN_CNS_LNG);
  329.  
  330.     // ISSUE: Does the following work for enum types and small integers?
  331.  
  332.     __int64         lv1 = op1->tnLngCon.tnLconVal;
  333.  
  334.     bool            uns = varTypeIsUnsigned(cmpActualVtyp(expr->tnType));
  335.  
  336.     /* Special case: cast of 'null' */
  337.  
  338.     if  (op1->tnVtyp == TYP_REF)
  339.     {
  340.         assert(lv1 == 0);
  341.         assert(expr->tnVtyp == TYP_REF ||
  342.                expr->tnVtyp == TYP_PTR ||
  343.                expr->tnVtyp == TYP_ARRAY);
  344.  
  345.         goto BASH_TYPE;
  346.     }
  347.  
  348.     assert(op1->tnVtyp == TYP_LONG  ||
  349.            op1->tnVtyp == TYP_ULONG ||
  350.            op1->tnVtyp == TYP_ENUM);
  351.  
  352.     switch (expr->tnOper)
  353.     {
  354.     case TN_CAST:
  355.  
  356.         switch (expr->tnVtyp)
  357.         {
  358.         case TYP_REF:
  359.  
  360.             // The only address that can be cast is 'null'
  361.  
  362.             break;
  363.  
  364.         case TYP_CHAR  : lv1 = (  signed char )lv1; break;
  365.         case TYP_UCHAR : lv1 = (unsigned char )lv1; break;
  366.         case TYP_SHORT : lv1 = (  signed short)lv1; break;
  367.         case TYP_USHORT:
  368.         case TYP_WCHAR : lv1 = (unsigned short)lv1; break;
  369.  
  370.         case TYP_LONG  :
  371.         case TYP_ULONG : break;
  372.  
  373.         case TYP_INT:
  374.         case TYP_UINT:
  375.  
  376.             /* Bash the node operator (in addition to the type) */
  377.  
  378.             op1->tnOper             = TN_CNS_INT;
  379.             op1->tnIntCon.tnIconVal = (__int32)lv1;
  380.             goto BASH_TYPE;
  381.  
  382.         case TYP_FLOAT:
  383.  
  384.             /* Bash the node operator (in addition to the type) */
  385.  
  386.             uns = varTypeIsUnsigned(cmpActualVtyp(op1->tnType));
  387.  
  388.             op1->tnOper             = TN_CNS_FLT;
  389.             op1->tnFltCon.tnFconVal = (float  )(uns ? toDouble(lv1)
  390.                                                     :          lv1);
  391.             goto BASH_TYPE;
  392.  
  393.         case TYP_DOUBLE:
  394.  
  395.             /* Bash the node operator (in addition to the type) */
  396.  
  397.             uns = varTypeIsUnsigned(cmpActualVtyp(op1->tnType));
  398.  
  399.             op1->tnOper             = TN_CNS_DBL;
  400.             op1->tnDblCon.tnDconVal = uns ? toDouble(lv1)
  401.                                           :  (double)lv1;
  402.             goto BASH_TYPE;
  403.  
  404.         default:
  405.  
  406.             // UNDONE: need to handle more cases
  407.  
  408. #ifdef DEBUG
  409.             cmpParser->parseDispTree(expr);
  410. #endif
  411.             NO_WAY(!"unhandled cast type");
  412.             return expr;
  413.         }
  414.  
  415.         op1->tnLngCon.tnLconVal = lv1;
  416.  
  417.         /* Bash the type of the operand and return it */
  418.  
  419.     BASH_TYPE:
  420.  
  421.         op1->tnVtyp = expr->tnVtyp;
  422.         op1->tnType = expr->tnType;
  423.  
  424.         return op1;
  425.  
  426.     case TN_NEG:
  427.         lv1 = -lv1;
  428.         break;
  429.  
  430.     case TN_NOT:
  431.         lv1 = ~lv1;
  432.         break;
  433.  
  434.     case TN_LOG_NOT:
  435.         lv1 = !lv1;
  436.         break;
  437.  
  438.     case TN_NOP:
  439.         break;
  440.  
  441.     default:
  442. #ifdef DEBUG
  443.         cmpParser->parseDispTree(expr);
  444. #endif
  445.         NO_WAY(!"unexpected operator");
  446.     }
  447.  
  448.     assert(expr->tnVtyp == TYP_LONG  ||
  449.            expr->tnVtyp == TYP_ULONG ||
  450.            expr->tnVtyp == TYP_ENUM);
  451.  
  452.     expr->tnOper             = TN_CNS_LNG;
  453.     expr->tnLngCon.tnLconVal = lv1;
  454.  
  455.     return expr;
  456. }
  457.  
  458. /*****************************************************************************
  459.  *
  460.  *  Try to fold a binary operator with __int64 constant operands.
  461.  */
  462.  
  463. Tree                compiler::cmpFoldLngBinop(Tree expr)
  464. {
  465.     Tree            op1 = expr->tnOp.tnOp1;
  466.     Tree            op2 = expr->tnOp.tnOp2;
  467.  
  468.     bool            rel;
  469.  
  470.     bool            uns = varTypeIsUnsigned(expr->tnVtypGet());
  471.  
  472.     assert(op1->tnOper == TN_CNS_LNG && (op1->tnVtyp == TYP_LONG || op1->tnVtyp == TYP_ULONG || op1->tnVtyp == TYP_ENUM));
  473.  
  474.     __int64         lv1 = op1->tnLngCon.tnLconVal;
  475.     __int64         lv2;
  476.  
  477.     if  (op2->tnOper == TN_CNS_INT)
  478.     {
  479.         __int32         iv2 = op2->tnIntCon.tnIconVal;
  480.  
  481.         /* This must be a shift */
  482.  
  483.         switch (expr->tnOper)
  484.         {
  485.             // ISSUE: Need to check for signed/unsigned shift count, right ?
  486.  
  487.         case TN_LSH:
  488.             lv1 <<= iv2;
  489.             goto DONE;
  490.  
  491.         case TN_RSH:
  492.             if (uns)
  493.                 lv1   = (unsigned)lv1 >> iv2;
  494.             else
  495.                 lv1 >>= iv2;
  496.             goto DONE;
  497.  
  498.         case TN_RSZ:
  499.             lv1   = (unsigned)lv1 >> iv2;
  500.             goto DONE;
  501.         }
  502.     }
  503.  
  504.     assert(op2->tnOper == TN_CNS_LNG && (op2->tnVtyp == TYP_LONG || op2->tnVtyp == TYP_ULONG || op2->tnVtyp == TYP_ENUM));
  505.  
  506.     lv2 = op2->tnLngCon.tnLconVal;
  507.  
  508.     switch (expr->tnOper)
  509.     {
  510.     case TN_ADD: lv1  += lv2; break;
  511.     case TN_SUB: lv1  -= lv2; break;
  512.     case TN_MUL: lv1  *= lv2; break;
  513.  
  514.     case TN_DIV: if (lv2 == 0) goto LNG_DIV_ZERO;
  515.                  if (uns)
  516.                      lv1  = (unsigned)lv1 / (unsigned)lv2;
  517.                  else
  518.                      lv1 /= lv2;
  519.                  break;
  520.  
  521.     case TN_MOD: if (lv2 == 0) goto LNG_DIV_ZERO;
  522.                  if (uns)
  523.                      lv1  = (unsigned)lv1 % (unsigned)lv2;
  524.                  else
  525.                      lv1 %= lv2;
  526.                  break;
  527.  
  528.     case TN_OR : lv1  |= lv2; break;
  529.     case TN_XOR: lv1  ^= lv2; break;
  530.     case TN_AND: lv1  &= lv2; break;
  531.  
  532.     case TN_EQ : rel = (lv1 == lv2); goto RELOP;
  533.     case TN_NE : rel = (lv1 != lv2); goto RELOP;
  534.  
  535.     case TN_LT : if (uns)
  536.                      rel = ((unsigned)lv1 <  (unsigned)lv2);
  537.                  else
  538.                      rel = (lv1 <  lv2);
  539.                  goto RELOP;
  540.     case TN_LE : if (uns)
  541.                      rel = ((unsigned)lv1 <= (unsigned)lv2);
  542.                  else
  543.                      rel = (lv1 <  lv2);
  544.                  goto RELOP;
  545.     case TN_GE : if (uns)
  546.                      rel = ((unsigned)lv1 >= (unsigned)lv2);
  547.                  else
  548.                      rel = (lv1 <  lv2);
  549.                  goto RELOP;
  550.     case TN_GT : if (uns)
  551.                      rel = ((unsigned)lv1 >  (unsigned)lv2);
  552.                  else
  553.                      rel = (lv1 <  lv2);
  554.                  goto RELOP;
  555.  
  556.     default:
  557. #ifdef DEBUG
  558.         cmpParser->parseDispTree(expr);
  559. #endif
  560.         NO_WAY(!"unexpected operator");
  561.     }
  562.  
  563. DONE:
  564.  
  565.     assert(expr->tnVtyp == TYP_LONG  ||
  566.            expr->tnVtyp == TYP_ULONG ||
  567.            expr->tnVtyp == TYP_ENUM);
  568.  
  569.     expr->tnOper             = TN_CNS_LNG;
  570.     expr->tnLngCon.tnLconVal = lv1;
  571.  
  572.     return expr;
  573.  
  574. RELOP:
  575.  
  576.     assert(expr->tnVtyp <= TYP_INT);
  577.  
  578.     expr->tnOper             = TN_CNS_INT;
  579.     expr->tnIntCon.tnIconVal = rel;
  580.  
  581.     return expr;
  582.  
  583. LNG_DIV_ZERO:
  584.  
  585.     cmpError(ERRdivZero);
  586.  
  587.     expr->tnOper             = TN_ERROR;
  588.     expr->tnLngCon.tnLconVal = 0;
  589.  
  590.     return expr;
  591. }
  592.  
  593. /*****************************************************************************
  594.  *
  595.  *  Try to fold a unary operator with a float constant operand.
  596.  */
  597.  
  598. Tree                compiler::cmpFoldFltUnop(Tree expr)
  599. {
  600.     Tree            op1 = expr->tnOp.tnOp1;
  601.  
  602.     assert(op1->tnOper == TN_CNS_FLT && op1->tnVtyp == TYP_FLOAT);
  603.  
  604.     float           fv1 = op1->tnFltCon.tnFconVal;
  605.  
  606.     if  (_isnan(fv1))
  607.         return  expr;
  608.  
  609.     switch (expr->tnOper)
  610.     {
  611.     case TN_NEG:
  612.         fv1 = -fv1;
  613.         break;
  614.  
  615.     case TN_NOP:
  616.         break;
  617.  
  618.     case TN_CAST:
  619.  
  620.         switch (expr->tnVtyp)
  621.         {
  622.             __int32         i;
  623.             __int64         l;
  624.  
  625.         case TYP_CHAR:   i = (  signed char   )fv1; goto FLT2INT;
  626.         case TYP_UCHAR:  i = (unsigned char   )fv1; goto FLT2INT;
  627.         case TYP_SHORT:  i = (  signed short  )fv1; goto FLT2INT;
  628.         case TYP_USHORT: i = (unsigned short  )fv1; goto FLT2INT;
  629.         case TYP_WCHAR:  i = (int)      (wchar)fv1; goto FLT2INT;
  630.         case TYP_INT:    i = (  signed int    )fv1; goto FLT2INT;
  631.         case TYP_UINT:   i = (unsigned int    )fv1; goto FLT2INT;
  632.  
  633.         FLT2INT:
  634.  
  635.             expr->tnOper             = TN_CNS_INT;
  636.             expr->tnIntCon.tnIconVal = i;
  637.             break;
  638.  
  639.         case TYP_LONG:   l = (  signed __int64)fv1; goto FLT2LNG;
  640.         case TYP_ULONG:  l = (unsigned __int64)fv1; goto FLT2LNG;
  641.  
  642.         FLT2LNG:
  643.  
  644.             expr->tnOper             = TN_CNS_LNG;
  645.             expr->tnLngCon.tnLconVal = l;
  646.             break;
  647.  
  648.         case TYP_DOUBLE:
  649.  
  650.             expr->tnOper             = TN_CNS_DBL;
  651.             expr->tnDblCon.tnDconVal = (double)fv1;
  652.             return expr;
  653.  
  654.         default:
  655.             NO_WAY(!"unexpect type of cast");
  656.         }
  657.  
  658.         return  expr;
  659.  
  660.     default:
  661. #ifdef DEBUG
  662.         cmpParser->parseDispTree(expr);
  663. #endif
  664.         NO_WAY(!"unexpected operator");
  665.     }
  666.  
  667.     assert(expr->tnVtyp == TYP_FLOAT);
  668.  
  669.     expr->tnOper             = TN_CNS_FLT;
  670.     expr->tnFltCon.tnFconVal = fv1;
  671.  
  672.     return expr;
  673. }
  674.  
  675. /*****************************************************************************
  676.  *
  677.  *  Try to fold a binary operator with float constant operands.
  678.  */
  679.  
  680. Tree                compiler::cmpFoldFltBinop(Tree expr)
  681. {
  682.     Tree            op1 = expr->tnOp.tnOp1;
  683.     Tree            op2 = expr->tnOp.tnOp2;
  684.  
  685.     assert(op1->tnOper == TN_CNS_FLT && op1->tnVtyp == TYP_FLOAT);
  686.     assert(op2->tnOper == TN_CNS_FLT && op2->tnVtyp == TYP_FLOAT);
  687.  
  688.     float           fv1 = op1->tnFltCon.tnFconVal;
  689.     float           fv2 = op2->tnFltCon.tnFconVal;
  690.  
  691.     __int32         rel;
  692.  
  693.     if  (_isnan(fv1) || _isnan(fv2))
  694.     {
  695.         if  (expr->tnOperKind() & TNK_RELOP)
  696.         {
  697.             rel = (expr->tnOper == TN_NE);
  698.             goto RELOP;
  699.         }
  700.         else
  701.         {
  702.             goto DONE;
  703.         }
  704.     }
  705.  
  706.     switch (expr->tnOper)
  707.     {
  708.     case TN_ADD: fv1 += fv2; break;
  709.     case TN_SUB: fv1 -= fv2; break;
  710.     case TN_MUL: fv1 *= fv2; break;
  711.     case TN_DIV: fv1 /= fv2; break;
  712.  
  713.     case TN_MOD: return expr;
  714.  
  715.     case TN_EQ : rel = (fv1 == fv2); goto RELOP;
  716.     case TN_NE : rel = (fv1 != fv2); goto RELOP;
  717.     case TN_LT : rel = (fv1 <  fv2); goto RELOP;
  718.     case TN_LE : rel = (fv1 <= fv2); goto RELOP;
  719.     case TN_GE : rel = (fv1 >= fv2); goto RELOP;
  720.     case TN_GT : rel = (fv1 >  fv2); goto RELOP;
  721.  
  722.     default:
  723. #ifdef DEBUG
  724.         cmpParser->parseDispTree(expr);
  725. #endif
  726.         NO_WAY(!"unexpected operator");
  727.     }
  728.  
  729. DONE:
  730.  
  731.     assert(expr->tnVtyp == TYP_FLOAT);
  732.  
  733.     expr->tnOper             = TN_CNS_FLT;
  734.     expr->tnFltCon.tnFconVal = fv1;
  735.  
  736.     return expr;
  737.  
  738. RELOP:
  739.  
  740.     assert(expr->tnVtyp <= TYP_INT);
  741.  
  742.     expr->tnOper             = TN_CNS_INT;
  743.     expr->tnIntCon.tnIconVal = rel;
  744.  
  745.     return expr;
  746. }
  747.  
  748. /*****************************************************************************
  749.  *
  750.  *  Try to fold a unary operator with a double constant operand.
  751.  */
  752.  
  753. Tree                compiler::cmpFoldDblUnop(Tree expr)
  754. {
  755.     Tree            op1 = expr->tnOp.tnOp1;
  756.  
  757.     assert(op1->tnOper == TN_CNS_DBL && op1->tnVtyp == TYP_DOUBLE);
  758.  
  759.     double          dv1 = op1->tnDblCon.tnDconVal;
  760.  
  761.     if  (_isnan(dv1))
  762.         return  expr;
  763.  
  764.     switch (expr->tnOper)
  765.     {
  766.     case TN_NEG:
  767.         dv1 = -dv1;
  768.         break;
  769.  
  770.     case TN_NOP:
  771.         break;
  772.  
  773.     case TN_CAST:
  774.  
  775.         switch (expr->tnVtyp)
  776.         {
  777.             __int32         i;
  778.             __int64         l;
  779.  
  780.         case TYP_CHAR:   i = (  signed char   )dv1; goto DBL2INT;
  781.         case TYP_UCHAR:  i = (unsigned char   )dv1; goto DBL2INT;
  782.         case TYP_SHORT:  i = (  signed short  )dv1; goto DBL2INT;
  783.         case TYP_USHORT: i = (unsigned short  )dv1; goto DBL2INT;
  784.         case TYP_WCHAR:  i = (int)      (wchar)dv1; goto DBL2INT;
  785.         case TYP_INT:    i = (  signed int    )dv1; goto DBL2INT;
  786.         case TYP_UINT:   i = (unsigned int    )dv1; goto DBL2INT;
  787.  
  788.         DBL2INT:
  789.  
  790.             expr->tnOper             = TN_CNS_INT;
  791.             expr->tnIntCon.tnIconVal = i;
  792.             break;
  793.  
  794.         case TYP_LONG:   l = (  signed __int64)dv1; goto DBL2LNG;
  795. #ifdef  __SMC__
  796.         case TYP_ULONG:  l = (  signed __int64)dv1; goto DBL2LNG;   // HACK
  797. #else
  798.         case TYP_ULONG:  l = (unsigned __int64)dv1; goto DBL2LNG;
  799. #endif
  800.  
  801.         DBL2LNG:
  802.  
  803.             expr->tnOper             = TN_CNS_LNG;
  804.             expr->tnLngCon.tnLconVal = l;
  805.             break;
  806.  
  807.         case TYP_FLOAT:
  808.  
  809.             expr->tnOper             = TN_CNS_FLT;
  810.             expr->tnFltCon.tnFconVal = (float)dv1;
  811.             break;
  812.  
  813.         default:
  814.             NO_WAY(!"unexpect type of cast");
  815.         }
  816.  
  817.         return expr;
  818.  
  819.     default:
  820. #ifdef DEBUG
  821.         cmpParser->parseDispTree(expr);
  822. #endif
  823.         NO_WAY(!"unexpected operator");
  824.     }
  825.  
  826.     assert(expr->tnVtyp == TYP_DOUBLE);
  827.  
  828.     expr->tnOper             = TN_CNS_DBL;
  829.     expr->tnDblCon.tnDconVal = dv1;
  830.  
  831.     return expr;
  832. }
  833.  
  834. /*****************************************************************************
  835.  *
  836.  *  Try to fold a binary operator with double constant operands.
  837.  */
  838.  
  839. Tree                compiler::cmpFoldDblBinop(Tree expr)
  840. {
  841.     Tree            op1 = expr->tnOp.tnOp1;
  842.     Tree            op2 = expr->tnOp.tnOp2;
  843.  
  844.     assert(op1->tnOper == TN_CNS_DBL && op1->tnVtyp == TYP_DOUBLE);
  845.     assert(op2->tnOper == TN_CNS_DBL && op2->tnVtyp == TYP_DOUBLE);
  846.  
  847.     double          dv1 = op1->tnDblCon.tnDconVal;
  848.     double          dv2 = op2->tnDblCon.tnDconVal;
  849.  
  850.     __int32         rel;
  851.  
  852.     if  (_isnan(dv1) || _isnan(dv2))
  853.     {
  854.         if  (expr->tnOperKind() & TNK_RELOP)
  855.         {
  856.             rel = (expr->tnOper == TN_NE);
  857.             goto RELOP;
  858.         }
  859.         else
  860.         {
  861.             goto DONE;
  862.         }
  863.     }
  864.  
  865.     switch (expr->tnOper)
  866.     {
  867.     case TN_ADD: dv1 += dv2; break;
  868.     case TN_SUB: dv1 -= dv2; break;
  869.     case TN_MUL: dv1 *= dv2; break;
  870.     case TN_DIV: dv1 /= dv2; break;
  871.  
  872.     case TN_MOD: return expr;
  873.  
  874.     case TN_EQ : rel = (dv1 == dv2); goto RELOP;
  875.     case TN_NE : rel = (dv1 != dv2); goto RELOP;
  876.     case TN_LT : rel = (dv1 <  dv2); goto RELOP;
  877.     case TN_LE : rel = (dv1 <= dv2); goto RELOP;
  878.     case TN_GE : rel = (dv1 >= dv2); goto RELOP;
  879.     case TN_GT : rel = (dv1 >  dv2); goto RELOP;
  880.  
  881.     default:
  882. #ifdef DEBUG
  883.         cmpParser->parseDispTree(expr);
  884. #endif
  885.         NO_WAY(!"unexpected operator");
  886.     }
  887.  
  888. DONE:
  889.  
  890.     assert(expr->tnVtyp == TYP_DOUBLE);
  891.  
  892.     expr->tnOper             = TN_CNS_DBL;
  893.     expr->tnDblCon.tnDconVal = dv1;
  894.  
  895.     return expr;
  896.  
  897. RELOP:
  898.  
  899.     assert(expr->tnVtyp <= TYP_INT);
  900.  
  901.     expr->tnOper             = TN_CNS_INT;
  902.     expr->tnIntCon.tnIconVal = rel;
  903.  
  904.     return expr;
  905. }
  906.  
  907. /*****************************************************************************/
  908.