The Labs \ Source Viewer \ SSCLI \ Microsoft.JScript \ BitwiseBinary

  1. // ==++==
  2. //
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. //
  14. // ==--==
  15. namespace Microsoft.JScript
  16. {
  17.    
  18.     using System;
  19.     using System.Reflection;
  20.     using System.Reflection.Emit;
  21.     using System.Diagnostics;
  22.    
  23.     public sealed class BitwiseBinary : BinaryOp
  24.     {
  25.         private object metaData = null;
  26.        
  27.         internal BitwiseBinary(Context context, AST operand1, AST operand2, JSToken operatorTok) : base(context, operand1, operand2, operatorTok)
  28.         {
  29.         }
  30.        
  31.         public BitwiseBinary(int operatorTok) : base(null, null, null, (JSToken)operatorTok)
  32.         {
  33.         }
  34.        
  35.         internal override object Evaluate()
  36.         {
  37.             return this.EvaluateBitwiseBinary(this.operand1.Evaluate(), this.operand2.Evaluate());
  38.         }
  39.        
  40.         #if !DEBUG
  41.         [DebuggerStepThroughAttribute()]
  42.         [DebuggerHiddenAttribute()]
  43.         #endif
  44.         public object EvaluateBitwiseBinary(object v1, object v2)
  45.         {
  46.             if (v1 is Int32 && v2 is Int32)
  47.                 return DoOp((Int32)v1, (Int32)v2, this.operatorTok);
  48.             else
  49.                 return EvaluateBitwiseBinary(v1, v2, this.operatorTok);
  50.         }
  51.        
  52.         #if !DEBUG
  53.         [DebuggerStepThroughAttribute()]
  54.         [DebuggerHiddenAttribute()]
  55.         #endif
  56.         private object EvaluateBitwiseBinary(object v1, object v2, JSToken operatorTok)
  57.         {
  58.             IConvertible ic1 = Convert.GetIConvertible(v1);
  59.             IConvertible ic2 = Convert.GetIConvertible(v2);
  60.             TypeCode t1 = Convert.GetTypeCode(v1, ic1);
  61.             TypeCode t2 = Convert.GetTypeCode(v2, ic2);
  62.             switch (t1) {
  63.                 case TypeCode.Empty:
  64.                 case TypeCode.DBNull:
  65.                     return EvaluateBitwiseBinary(0, v2, operatorTok);
  66.                 case TypeCode.Boolean:
  67.                 case TypeCode.Char:
  68.                 case TypeCode.SByte:
  69.                 case TypeCode.Byte:
  70.                 case TypeCode.Int16:
  71.                 case TypeCode.UInt16:
  72.                 case TypeCode.Int32:
  73.                    
  74.                     int i = ic1.ToInt32(null);
  75.                     switch (t2) {
  76.                         case TypeCode.Empty:
  77.                         case TypeCode.DBNull:
  78.                             return DoOp(i, 0, operatorTok);
  79.                         case TypeCode.Boolean:
  80.                         case TypeCode.Char:
  81.                         case TypeCode.SByte:
  82.                         case TypeCode.Byte:
  83.                         case TypeCode.Int16:
  84.                         case TypeCode.UInt16:
  85.                         case TypeCode.Int32:
  86.                             return DoOp(i, ic2.ToInt32(null), operatorTok);
  87.                         case TypeCode.UInt32:
  88.                         case TypeCode.Int64:
  89.                         case TypeCode.UInt64:
  90.                         case TypeCode.Single:
  91.                         case TypeCode.Double:
  92.                             return DoOp(i, (int)Runtime.DoubleToInt64(ic2.ToDouble(null)), operatorTok);
  93.                         case TypeCode.Object:
  94.                         case TypeCode.Decimal:
  95.                         case TypeCode.DateTime:
  96.                         case TypeCode.String:
  97.                             break;
  98.                     }
  99.                     break;
  100.                 case TypeCode.UInt32:
  101.                 case TypeCode.Int64:
  102.                 case TypeCode.UInt64:
  103.                 case TypeCode.Single:
  104.                 case TypeCode.Double:
  105.                    
  106.                     i = (int)Runtime.DoubleToInt64(ic1.ToDouble(null));
  107.                     switch (t2) {
  108.                         case TypeCode.Empty:
  109.                         case TypeCode.DBNull:
  110.                             return DoOp(i, 0, operatorTok);
  111.                         case TypeCode.Boolean:
  112.                         case TypeCode.Char:
  113.                         case TypeCode.SByte:
  114.                         case TypeCode.Byte:
  115.                         case TypeCode.Int16:
  116.                         case TypeCode.UInt16:
  117.                         case TypeCode.Int32:
  118.                             return DoOp(i, ic2.ToInt32(null), operatorTok);
  119.                         case TypeCode.UInt32:
  120.                         case TypeCode.Int64:
  121.                         case TypeCode.UInt64:
  122.                         case TypeCode.Single:
  123.                         case TypeCode.Double:
  124.                             return DoOp(i, (int)Runtime.DoubleToInt64(ic2.ToDouble(null)), operatorTok);
  125.                         case TypeCode.Object:
  126.                         case TypeCode.Decimal:
  127.                         case TypeCode.DateTime:
  128.                         case TypeCode.String:
  129.                             break;
  130.                     }
  131.                     break;
  132.                 case TypeCode.Object:
  133.                 case TypeCode.Decimal:
  134.                 case TypeCode.DateTime:
  135.                 case TypeCode.String:
  136.                    
  137.                     break;
  138.             }
  139.             if (v2 == null)
  140.                 return DoOp(Convert.ToInt32(v1), 0, this.operatorTok);
  141.             MethodInfo oper = this.GetOperator(v1.GetType(), v2.GetType());
  142.             if (oper != null)
  143.                 return oper.Invoke(null, (BindingFlags)0, JSBinder.ob, new object[] {v1, v2}, null);
  144.             else
  145.                 return DoOp(Convert.ToInt32(v1), Convert.ToInt32(v2), this.operatorTok);
  146.         }
  147.        
  148.         static internal object DoOp(int i, int j, JSToken operatorTok)
  149.         {
  150.             switch (operatorTok) {
  151.                 case JSToken.BitwiseAnd:
  152.                     return i & j;
  153.                 case JSToken.BitwiseOr:
  154.                     return i | j;
  155.                 case JSToken.BitwiseXor:
  156.                     return i ^ j;
  157.                 case JSToken.LeftShift:
  158.                     return i << j;
  159.                 case JSToken.RightShift:
  160.                     return i >> j;
  161.                 case JSToken.UnsignedRightShift:
  162.                     return ((uint)i) >> j;
  163.                 default:
  164.                     throw new JScriptException(JSError.InternalError);
  165.                     break;
  166.             }
  167.         }
  168.        
  169.         internal override IReflect InferType(JSField inference_target)
  170.         {
  171.             MethodInfo oper;
  172.             if (this.type1 == null || inference_target != null) {
  173.                 oper = this.GetOperator(this.operand1.InferType(inference_target), this.operand2.InferType(inference_target));
  174.             }
  175.             else
  176.                 oper = this.GetOperator(this.type1, this.type2);
  177.             if (oper != null) {
  178.                 this.metaData = oper;
  179.                 return oper.ReturnType;
  180.             }
  181.             return BitwiseBinary.ResultType(this.type1, this.type2, this.operatorTok);
  182.         }
  183.        
  184.         static internal Type Operand2Type(JSToken operatorTok, Type bbrType)
  185.         {
  186.             switch (operatorTok) {
  187.                 case JSToken.LeftShift:
  188.                 case JSToken.RightShift:
  189.                 case JSToken.UnsignedRightShift:
  190.                     return Typeob.Int32;
  191.             }
  192.             return bbrType;
  193.         }
  194.        
  195.         static internal Type ResultType(Type type1, Type type2, JSToken operatorTok)
  196.         {
  197.             switch (operatorTok) {
  198.                 case JSToken.LeftShift:
  199.                 case JSToken.RightShift:
  200.                     if (Convert.IsPrimitiveIntegerType(type1))
  201.                         return type1;
  202.                     else if (Typeob.JSObject.IsAssignableFrom(type1))
  203.                         return Typeob.Int32;
  204.                     else
  205.                         return Typeob.Object;
  206.                     break;
  207.                 case JSToken.UnsignedRightShift:
  208.                     switch (Type.GetTypeCode(type1)) {
  209.                         case TypeCode.Byte:
  210.                         case TypeCode.SByte:
  211.                             return Typeob.Byte;
  212.                         case TypeCode.UInt16:
  213.                         case TypeCode.Int16:
  214.                             return Typeob.UInt16;
  215.                         case TypeCode.Int32:
  216.                         case TypeCode.UInt32:
  217.                             return Typeob.UInt32;
  218.                         case TypeCode.Int64:
  219.                         case TypeCode.UInt64:
  220.                             return Typeob.UInt64;
  221.                         default:
  222.                             if (Typeob.JSObject.IsAssignableFrom(type1))
  223.                                 return Typeob.Int32;
  224.                             else
  225.                                 return Typeob.Object;
  226.                             break;
  227.                     }
  228.                     break;
  229.             }
  230.             TypeCode t1 = Type.GetTypeCode(type1);
  231.             TypeCode t2 = Type.GetTypeCode(type2);
  232.             switch (t1) {
  233.                 case TypeCode.Empty:
  234.                 case TypeCode.DBNull:
  235.                 case TypeCode.Boolean:
  236.                     switch (t2) {
  237.                         case TypeCode.SByte:
  238.                             return Typeob.SByte;
  239.                         case TypeCode.Byte:
  240.                             return Typeob.Byte;
  241.                         case TypeCode.Char:
  242.                         case TypeCode.UInt16:
  243.                             return Typeob.UInt16;
  244.                         case TypeCode.Int16:
  245.                             return Typeob.Int16;
  246.                         case TypeCode.Empty:
  247.                         case TypeCode.DBNull:
  248.                         case TypeCode.Boolean:
  249.                         case TypeCode.Int32:
  250.                         case TypeCode.Single:
  251.                         case TypeCode.Double:
  252.                             return Typeob.Int32;
  253.                         case TypeCode.UInt32:
  254.                             return Typeob.UInt32;
  255.                         case TypeCode.Int64:
  256.                             return Typeob.Int64;
  257.                         case TypeCode.UInt64:
  258.                             return Typeob.UInt64;
  259.                         case TypeCode.Object:
  260.                             if (Typeob.JSObject.IsAssignableFrom(type2))
  261.                                 return Typeob.Int32;
  262.                             break;
  263.                         case TypeCode.Decimal:
  264.                         case TypeCode.DateTime:
  265.                         case TypeCode.String:
  266.                             break;
  267.                     }
  268.                     break;
  269.                 case TypeCode.SByte:
  270.                    
  271.                     switch (t2) {
  272.                         case TypeCode.Empty:
  273.                         case TypeCode.DBNull:
  274.                         case TypeCode.Boolean:
  275.                         case TypeCode.SByte:
  276.                             return Typeob.SByte;
  277.                         case TypeCode.Byte:
  278.                             return Typeob.Byte;
  279.                         case TypeCode.Char:
  280.                         case TypeCode.Int16:
  281.                             return Typeob.Int16;
  282.                         case TypeCode.UInt16:
  283.                             return Typeob.UInt16;
  284.                         case TypeCode.Int32:
  285.                         case TypeCode.Single:
  286.                         case TypeCode.Double:
  287.                             return Typeob.Int32;
  288.                         case TypeCode.UInt32:
  289.                             return Typeob.UInt32;
  290.                         case TypeCode.Int64:
  291.                             return Typeob.Int64;
  292.                         case TypeCode.UInt64:
  293.                             return Typeob.UInt64;
  294.                         case TypeCode.Object:
  295.                             if (Typeob.JSObject.IsAssignableFrom(type2))
  296.                                 return Typeob.Int32;
  297.                             break;
  298.                         case TypeCode.Decimal:
  299.                         case TypeCode.DateTime:
  300.                         case TypeCode.String:
  301.                             break;
  302.                     }
  303.                     break;
  304.                 case TypeCode.Byte:
  305.                    
  306.                     switch (t2) {
  307.                         case TypeCode.Empty:
  308.                         case TypeCode.DBNull:
  309.                         case TypeCode.Boolean:
  310.                         case TypeCode.Byte:
  311.                         case TypeCode.SByte:
  312.                             return Typeob.Byte;
  313.                         case TypeCode.Char:
  314.                         case TypeCode.UInt16:
  315.                         case TypeCode.Int16:
  316.                             return Typeob.UInt16;
  317.                         case TypeCode.Int32:
  318.                         case TypeCode.Single:
  319.                         case TypeCode.Double:
  320.                         case TypeCode.UInt32:
  321.                             return Typeob.UInt32;
  322.                         case TypeCode.Int64:
  323.                         case TypeCode.UInt64:
  324.                             return Typeob.UInt64;
  325.                         case TypeCode.Object:
  326.                             if (Typeob.JSObject.IsAssignableFrom(type2))
  327.                                 return Typeob.UInt32;
  328.                             break;
  329.                         case TypeCode.Decimal:
  330.                         case TypeCode.DateTime:
  331.                         case TypeCode.String:
  332.                             break;
  333.                     }
  334.                     break;
  335.                 case TypeCode.Int16:
  336.                    
  337.                     switch (t2) {
  338.                         case TypeCode.Empty:
  339.                         case TypeCode.DBNull:
  340.                         case TypeCode.Boolean:
  341.                         case TypeCode.SByte:
  342.                         case TypeCode.Int16:
  343.                             return Typeob.Int16;
  344.                         case TypeCode.Byte:
  345.                         case TypeCode.Char:
  346.                         case TypeCode.UInt16:
  347.                             return Typeob.UInt16;
  348.                         case TypeCode.Int32:
  349.                         case TypeCode.Single:
  350.                         case TypeCode.Double:
  351.                             return Typeob.Int32;
  352.                         case TypeCode.UInt32:
  353.                             return Typeob.UInt32;
  354.                         case TypeCode.Int64:
  355.                             return Typeob.Int64;
  356.                         case TypeCode.UInt64:
  357.                             return Typeob.UInt64;
  358.                         case TypeCode.Object:
  359.                             if (Typeob.JSObject.IsAssignableFrom(type2))
  360.                                 return Typeob.Int32;
  361.                             break;
  362.                         case TypeCode.Decimal:
  363.                         case TypeCode.DateTime:
  364.                         case TypeCode.String:
  365.                             break;
  366.                     }
  367.                     break;
  368.                 case TypeCode.Char:
  369.                 case TypeCode.UInt16:
  370.                    
  371.                     switch (t2) {
  372.                         case TypeCode.Empty:
  373.                         case TypeCode.DBNull:
  374.                         case TypeCode.Boolean:
  375.                         case TypeCode.Byte:
  376.                         case TypeCode.Char:
  377.                         case TypeCode.UInt16:
  378.                         case TypeCode.SByte:
  379.                         case TypeCode.Int16:
  380.                             return Typeob.UInt16;
  381.                         case TypeCode.Int32:
  382.                         case TypeCode.Single:
  383.                         case TypeCode.Double:
  384.                         case TypeCode.UInt32:
  385.                             return Typeob.UInt32;
  386.                         case TypeCode.Int64:
  387.                         case TypeCode.UInt64:
  388.                             return Typeob.UInt64;
  389.                         case TypeCode.Object:
  390.                             if (Typeob.JSObject.IsAssignableFrom(type2))
  391.                                 return Typeob.UInt32;
  392.                             break;
  393.                         case TypeCode.Decimal:
  394.                         case TypeCode.DateTime:
  395.                         case TypeCode.String:
  396.                             break;
  397.                     }
  398.                     break;
  399.                 case TypeCode.Int32:
  400.                 case TypeCode.Single:
  401.                 case TypeCode.Double:
  402.                    
  403.                     switch (t2) {
  404.                         case TypeCode.Empty:
  405.                         case TypeCode.DBNull:
  406.                         case TypeCode.Boolean:
  407.                         case TypeCode.SByte:
  408.                         case TypeCode.Int16:
  409.                         case TypeCode.Int32:
  410.                         case TypeCode.Single:
  411.                         case TypeCode.Double:
  412.                             return Typeob.Int32;
  413.                         case TypeCode.Byte:
  414.                         case TypeCode.Char:
  415.                         case TypeCode.UInt16:
  416.                         case TypeCode.UInt32:
  417.                             return Typeob.UInt32;
  418.                         case TypeCode.Int64:
  419.                             return Typeob.Int64;
  420.                         case TypeCode.UInt64:
  421.                             return Typeob.UInt64;
  422.                         case TypeCode.Object:
  423.                             if (Typeob.JSObject.IsAssignableFrom(type2))
  424.                                 return Typeob.Int32;
  425.                             break;
  426.                         case TypeCode.Decimal:
  427.                         case TypeCode.DateTime:
  428.                         case TypeCode.String:
  429.                             break;
  430.                     }
  431.                     break;
  432.                 case TypeCode.UInt32:
  433.                    
  434.                     switch (t2) {
  435.                         case TypeCode.Empty:
  436.                         case TypeCode.DBNull:
  437.                         case TypeCode.Boolean:
  438.                         case TypeCode.Byte:
  439.                         case TypeCode.UInt16:
  440.                         case TypeCode.Char:
  441.                         case TypeCode.UInt32:
  442.                         case TypeCode.SByte:
  443.                         case TypeCode.Int16:
  444.                         case TypeCode.Int32:
  445.                         case TypeCode.Single:
  446.                         case TypeCode.Double:
  447.                             return Typeob.UInt32;
  448.                         case TypeCode.Int64:
  449.                         case TypeCode.UInt64:
  450.                             return Typeob.UInt64;
  451.                         case TypeCode.Object:
  452.                             if (Typeob.JSObject.IsAssignableFrom(type2))
  453.                                 return Typeob.UInt32;
  454.                             break;
  455.                         case TypeCode.Decimal:
  456.                         case TypeCode.DateTime:
  457.                         case TypeCode.String:
  458.                             break;
  459.                     }
  460.                     break;
  461.                 case TypeCode.Int64:
  462.                    
  463.                     switch (t2) {
  464.                         case TypeCode.Empty:
  465.                         case TypeCode.DBNull:
  466.                         case TypeCode.Boolean:
  467.                         case TypeCode.SByte:
  468.                         case TypeCode.Int16:
  469.                         case TypeCode.Int32:
  470.                         case TypeCode.Int64:
  471.                         case TypeCode.Single:
  472.                         case TypeCode.Double:
  473.                             return Typeob.Int64;
  474.                         case TypeCode.Byte:
  475.                         case TypeCode.Char:
  476.                         case TypeCode.UInt16:
  477.                         case TypeCode.UInt32:
  478.                         case TypeCode.UInt64:
  479.                             return Typeob.UInt64;
  480.                         case TypeCode.Object:
  481.                             if (Typeob.JSObject.IsAssignableFrom(type2))
  482.                                 return Typeob.Int64;
  483.                             break;
  484.                         case TypeCode.Decimal:
  485.                         case TypeCode.DateTime:
  486.                         case TypeCode.String:
  487.                             break;
  488.                     }
  489.                     break;
  490.                 case TypeCode.UInt64:
  491.                    
  492.                     switch (t2) {
  493.                         case TypeCode.Empty:
  494.                         case TypeCode.DBNull:
  495.                         case TypeCode.Boolean:
  496.                         case TypeCode.Byte:
  497.                         case TypeCode.Char:
  498.                         case TypeCode.UInt16:
  499.                         case TypeCode.UInt32:
  500.                         case TypeCode.UInt64:
  501.                         case TypeCode.SByte:
  502.                         case TypeCode.Int16:
  503.                         case TypeCode.Int32:
  504.                         case TypeCode.Single:
  505.                         case TypeCode.Double:
  506.                         case TypeCode.Int64:
  507.                             return Typeob.UInt64;
  508.                         case TypeCode.Object:
  509.                             if (Typeob.JSObject.IsAssignableFrom(type2))
  510.                                 return Typeob.UInt64;
  511.                             break;
  512.                         case TypeCode.Decimal:
  513.                         case TypeCode.DateTime:
  514.                         case TypeCode.String:
  515.                             break;
  516.                     }
  517.                     break;
  518.                 case TypeCode.Object:
  519.                    
  520.                     if (Typeob.JSObject.IsAssignableFrom(type1))
  521.                         return Typeob.Int32;
  522.                     break;
  523.                 case TypeCode.Decimal:
  524.                 case TypeCode.DateTime:
  525.                 case TypeCode.String:
  526.                    
  527.                     break;
  528.             }
  529.             return Typeob.Object;
  530.         }
  531.        
  532.         static internal void TranslateToBitCountMask(ILGenerator il, Type type, AST operand2)
  533.         {
  534.             int mask = 0;
  535.             switch (Type.GetTypeCode(type)) {
  536.                 case TypeCode.SByte:
  537.                 case TypeCode.Byte:
  538.                     mask = 7;
  539.                     break;
  540.                 case TypeCode.UInt16:
  541.                 case TypeCode.Int16:
  542.                     mask = 15;
  543.                     break;
  544.                 case TypeCode.Int32:
  545.                 case TypeCode.UInt32:
  546.                     mask = 31;
  547.                     break;
  548.                 case TypeCode.Int64:
  549.                 case TypeCode.UInt64:
  550.                     mask = 63;
  551.                     break;
  552.             }
  553.             ConstantWrapper cw = operand2 as ConstantWrapper;
  554.             if (cw != null) {
  555.                 int m = Convert.ToInt32(cw.value);
  556.                 if (m <= mask)
  557.                     return;
  558.             }
  559.             il.Emit(OpCodes.Ldc_I4_S, mask);
  560.             il.Emit(OpCodes.And);
  561.         }
  562.        
  563.         internal override void TranslateToIL(ILGenerator il, Type rtype)
  564.         {
  565.             if (this.metaData == null) {
  566.                 Type bbrType = BitwiseBinary.ResultType(this.type1, this.type2, this.operatorTok);
  567.                 if (Convert.IsPrimitiveNumericType(this.type1)) {
  568.                     this.operand1.TranslateToIL(il, this.type1);
  569.                     Convert.Emit(this, il, this.type1, bbrType, true);
  570.                 }
  571.                 else {
  572.                     this.operand1.TranslateToIL(il, Typeob.Double);
  573.                     Convert.Emit(this, il, Typeob.Double, bbrType, true);
  574.                 }
  575.                 Type op2type = BitwiseBinary.Operand2Type(this.operatorTok, bbrType);
  576.                 if (Convert.IsPrimitiveNumericType(this.type2)) {
  577.                     this.operand2.TranslateToIL(il, this.type2);
  578.                     Convert.Emit(this, il, this.type2, op2type, true);
  579.                 }
  580.                 else {
  581.                     this.operand2.TranslateToIL(il, Typeob.Double);
  582.                     Convert.Emit(this, il, Typeob.Double, op2type, true);
  583.                 }
  584.                 switch (this.operatorTok) {
  585.                     case JSToken.BitwiseAnd:
  586.                         il.Emit(OpCodes.And);
  587.                         break;
  588.                     case JSToken.BitwiseOr:
  589.                         il.Emit(OpCodes.Or);
  590.                         break;
  591.                     case JSToken.BitwiseXor:
  592.                         il.Emit(OpCodes.Xor);
  593.                         break;
  594.                     case JSToken.LeftShift:
  595.                         BitwiseBinary.TranslateToBitCountMask(il, bbrType, this.operand2);
  596.                         il.Emit(OpCodes.Shl);
  597.                         break;
  598.                     case JSToken.RightShift:
  599.                         BitwiseBinary.TranslateToBitCountMask(il, bbrType, this.operand2);
  600.                         il.Emit(OpCodes.Shr);
  601.                         break;
  602.                     case JSToken.UnsignedRightShift:
  603.                         BitwiseBinary.TranslateToBitCountMask(il, bbrType, this.operand2);
  604.                         il.Emit(OpCodes.Shr_Un);
  605.                         break;
  606.                     default:
  607.                         throw new JScriptException(JSError.InternalError, this.context);
  608.                         break;
  609.                 }
  610.                 Convert.Emit(this, il, bbrType, rtype);
  611.                 return;
  612.             }
  613.             if (this.metaData is MethodInfo) {
  614.                 MethodInfo oper = (MethodInfo)this.metaData;
  615.                 ParameterInfo[] pars = oper.GetParameters();
  616.                 this.operand1.TranslateToIL(il, pars[0].ParameterType);
  617.                 this.operand2.TranslateToIL(il, pars[1].ParameterType);
  618.                 il.Emit(OpCodes.Call, oper);
  619.                 Convert.Emit(this, il, oper.ReturnType, rtype);
  620.                 return;
  621.             }
  622.             //Getting here is just too bad. We do not know until the code runs whether or not to call an overloaded operator method.
  623.             //Compile operands to objects and devolve the decision making to run time thunks
  624.             il.Emit(OpCodes.Ldloc, (LocalBuilder)this.metaData);
  625.             this.operand1.TranslateToIL(il, Typeob.Object);
  626.             this.operand2.TranslateToIL(il, Typeob.Object);
  627.             il.Emit(OpCodes.Call, CompilerGlobals.evaluateBitwiseBinaryMethod);
  628.             Convert.Emit(this, il, Typeob.Object, rtype);
  629.         }
  630.        
  631.         internal override void TranslateToILInitializer(ILGenerator il)
  632.         {
  633.             IReflect rtype = this.InferType(null);
  634.             this.operand1.TranslateToILInitializer(il);
  635.             this.operand2.TranslateToILInitializer(il);
  636.             if (rtype != Typeob.Object)
  637.                 return;
  638.             this.metaData = il.DeclareLocal(Typeob.BitwiseBinary);
  639.             ConstantWrapper.TranslateToILInt(il, (int)this.operatorTok);
  640.             il.Emit(OpCodes.Newobj, CompilerGlobals.bitwiseBinaryConstructor);
  641.             il.Emit(OpCodes.Stloc, (LocalBuilder)this.metaData);
  642.         }
  643.     }
  644. }

Developer Fusion