Example #1
0
        public static void EmitLoadLocal(FleeILGenerator ilg, int index)
        {
            Debug.Assert(index >= 0, "Invalid index");

            if (index >= 0 & index <= 3)
            {
                switch (index)
                {
                case 0:
                    ilg.Emit(OpCodes.Ldloc_0);
                    break;

                case 1:
                    ilg.Emit(OpCodes.Ldloc_1);
                    break;

                case 2:
                    ilg.Emit(OpCodes.Ldloc_2);
                    break;

                case 3:
                    ilg.Emit(OpCodes.Ldloc_3);
                    break;
                }
            }
            else
            {
                Debug.Assert(index < 256, "local index too large");
                ilg.Emit(OpCodes.Ldloc_S, (byte)index);
            }
        }
Example #2
0
        // Emit the end cases for a short-circuit
        private static void EmitTerminals(ShortCircuitInfo info, FleeILGenerator ilg, Label endLabel)
        {
            // Emit the false case if it was used
            if (info.Branches.HasLabel(OurFalseTerminalKey) == true)
            {
                Label falseLabel = info.Branches.FindLabel(OurFalseTerminalKey);

                // Mark the label and note its position
                ilg.MarkLabel(falseLabel);
                MarkBranchTarget(info, falseLabel, ilg);

                ilg.Emit(OpCodes.Ldc_I4_0);

                // If we also have a true terminal, then skip over it
                if (info.Branches.HasLabel(OurTrueTerminalKey) == true)
                {
                    ilg.Emit(OpCodes.Br_S, endLabel);
                }
            }

            // Emit the true case if it was used
            if (info.Branches.HasLabel(OurTrueTerminalKey) == true)
            {
                Label trueLabel = info.Branches.FindLabel(OurTrueTerminalKey);

                // Mark the label and note its position
                ilg.MarkLabel(trueLabel);
                MarkBranchTarget(info, trueLabel, ilg);

                ilg.Emit(OpCodes.Ldc_I4_1);
            }
        }
Example #3
0
        // If the shift count is greater than the number of bits in the number, the result is undefined.
        // So we play it safe and force the shift count to 32/64 bits by ANDing it with the appropriate mask.
        private void EmitShiftCount(FleeILGenerator ilg, IServiceProvider services)
        {
            MyRightChild.Emit(ilg, services);
            TypeCode tc = Type.GetTypeCode(MyLeftChild.ResultType);

            switch (tc)
            {
            case TypeCode.Byte:
            case TypeCode.SByte:
            case TypeCode.Int16:
            case TypeCode.UInt16:
            case TypeCode.Int32:
            case TypeCode.UInt32:
                ilg.Emit(OpCodes.Ldc_I4_S, (sbyte)0x1f);
                break;

            case TypeCode.Int64:
            case TypeCode.UInt64:
                ilg.Emit(OpCodes.Ldc_I4_S, (sbyte)0x3f);
                break;

            default:
                Debug.Assert(false, "unknown left shift operand");
                break;
            }

            ilg.Emit(OpCodes.And);
        }
        internal void EmitLoad(string tailName, FleeILGenerator ilg)
        {
            PropertyInfo pi = typeof(ExpressionContext).GetProperty("CalculationEngine");

            ilg.Emit(OpCodes.Callvirt, pi.GetGetMethod());

            // Load the tail
            MemberInfo[] methods = typeof(CalculationEngine).FindMembers(MemberTypes.Method, BindingFlags.Instance | BindingFlags.Public, Type.FilterNameIgnoreCase, "GetResult");
            MethodInfo   mi      = null;

            foreach (MethodInfo method in methods)
            {
                if (method.IsGenericMethod == true)
                {
                    mi = method;
                    break;                     // TODO: might not be correct. Was : Exit For
                }
            }

            Type resultType = this.ResolveTailType(tailName);

            mi = mi.MakeGenericMethod(resultType);

            ilg.Emit(OpCodes.Ldstr, tailName);
            ilg.Emit(OpCodes.Call, mi);
        }
 private static void EmitLdfld(FieldInfo fi, bool indirect, FleeILGenerator ilg)
 {
     if (fi.IsStatic == true)
     {
         if (indirect == true)
         {
             ilg.Emit(OpCodes.Ldsflda, fi);
         }
         else
         {
             ilg.Emit(OpCodes.Ldsfld, fi);
         }
     }
     else
     {
         if (indirect == true)
         {
             ilg.Emit(OpCodes.Ldflda, fi);
         }
         else
         {
             ilg.Emit(OpCodes.Ldfld, fi);
         }
     }
 }
Example #6
0
 private static void EmitReferenceTypeMethodCall(MethodInfo mi, FleeILGenerator ilg)
 {
     if (mi.IsStatic == true)
     {
         ilg.Emit(OpCodes.Call, mi);
     }
     else
     {
         ilg.Emit(OpCodes.Callvirt, mi);
     }
 }
Example #7
0
 public override void Emit(FleeILGenerator ilg, IServiceProvider services)
 {
     if (MyValue == true)
     {
         ilg.Emit(OpCodes.Ldc_I4_1);
     }
     else
     {
         ilg.Emit(OpCodes.Ldc_I4_0);
     }
 }
Example #8
0
        public static void EmitLoadLocalAddress(FleeILGenerator ilg, int index)
        {
            Debug.Assert(index >= 0, "Invalid index");

            if (index <= byte.MaxValue)
            {
                ilg.Emit(OpCodes.Ldloca_S, (byte)index);
            }
            else
            {
                ilg.Emit(OpCodes.Ldloca, index);
            }
        }
Example #9
0
        private void EmitCast(FleeILGenerator ilg, Type sourceType, Type destType, IServiceProvider services)
        {
            MethodInfo explicitOperator = this.GetExplictOverloadedOperator(sourceType, destType);

            if (object.ReferenceEquals(sourceType, destType))
            {
                // Identity cast; do nothing
                return;
            }
            else if ((explicitOperator != null))
            {
                ilg.Emit(OpCodes.Call, explicitOperator);
            }
            else if (sourceType.IsEnum == true | destType.IsEnum == true)
            {
                this.EmitEnumCast(ilg, sourceType, destType, services);
            }
            else if (ImplicitConverter.EmitImplicitConvert(sourceType, destType, ilg) == true)
            {
                // Implicit numeric cast; do nothing
                return;
            }
            else if (IsCastableNumericType(sourceType) & IsCastableNumericType(destType))
            {
                // Explicit numeric cast
                EmitExplicitNumericCast(ilg, sourceType, destType, services);
            }
            else if (sourceType.IsValueType == true)
            {
                Debug.Assert(destType.IsValueType == false, "expecting reference type");
                ilg.Emit(OpCodes.Box, sourceType);
            }
            else
            {
                if (destType.IsValueType == true)
                {
                    // Reference type to value type
                    ilg.Emit(OpCodes.Unbox_Any, destType);
                }
                else
                {
                    // Reference type to reference type
                    if (destType.IsAssignableFrom(sourceType) == false)
                    {
                        // Only emit cast if it is an explicit cast
                        ilg.Emit(OpCodes.Castclass, destType);
                    }
                }
            }
        }
Example #10
0
 public static void EmitInt32Load(Int32 value, FleeILGenerator ilg)
 {
     if (value >= -1 & value <= 8)
     {
         EmitSuperShort(value, ilg);
     }
     else if (value >= sbyte.MinValue & value <= sbyte.MaxValue)
     {
         ilg.Emit(OpCodes.Ldc_I4_S, (sbyte)value);
     }
     else
     {
         ilg.Emit(OpCodes.Ldc_I4, value);
     }
 }
Example #11
0
        // Emit a string concatenation
        private void EmitStringConcat(FleeILGenerator ilg, IServiceProvider services)
        {
            Type       argType          = default(Type);
            MethodInfo concatMethodInfo = default(MethodInfo);

            // Pick the most specific concat method
            if (this.AreBothChildrenOfType(typeof(string)) == true)
            {
                concatMethodInfo = OurStringConcatMethodInfo;
                argType          = typeof(string);
            }
            else
            {
                Debug.Assert(this.IsEitherChildOfType(typeof(string)), "one child must be a string");
                concatMethodInfo = OurObjectConcatMethodInfo;
                argType          = typeof(object);
            }

            // Emit the operands and call the function
            MyLeftChild.Emit(ilg, services);
            ImplicitConverter.EmitImplicitConvert(MyLeftChild.ResultType, argType, ilg);
            MyRightChild.Emit(ilg, services);
            ImplicitConverter.EmitImplicitConvert(MyRightChild.ResultType, argType, ilg);
            ilg.Emit(OpCodes.Call, concatMethodInfo);
        }
Example #12
0
        // Emit elements into an array
        private static void EmitElementArrayLoad(ExpressionElement[] elements, Type arrayElementType, FleeILGenerator ilg, IServiceProvider services)
        {
            // Load the array length
            LiteralElement.EmitInt32Load(elements.Length, ilg);

            // Create the array
            ilg.Emit(OpCodes.Newarr, arrayElementType);

            // Store the new array in a unique local and remember the index
            LocalBuilder local           = ilg.DeclareLocal(arrayElementType.MakeArrayType());
            int          arrayLocalIndex = local.LocalIndex;

            Utility.EmitStoreLocal(ilg, arrayLocalIndex);

            for (int i = 0; i <= elements.Length - 1; i++)
            {
                // Load the array
                Utility.EmitLoadLocal(ilg, arrayLocalIndex);
                // Load the index
                LiteralElement.EmitInt32Load(i, ilg);
                // Emit the element (with any required conversions)
                ExpressionElement element = elements[i];
                element.Emit(ilg, services);
                ImplicitConverter.EmitImplicitConvert(element.ResultType, arrayElementType, ilg);
                // Store it into the array
                Utility.EmitArrayStore(ilg, arrayElementType);
            }

            // Load the array
            Utility.EmitLoadLocal(ilg, arrayLocalIndex);
        }
Example #13
0
 private static void EmitConvert(FleeILGenerator ilg, OpCode convertOpcode)
 {
     if ((ilg != null))
     {
         ilg.Emit(convertOpcode);
     }
 }
Example #14
0
        private static bool ImplicitConvertToReferenceType(Type sourceType, Type destType, FleeILGenerator ilg)
        {
            if (destType.IsValueType == true)
            {
                return(false);
            }

            if (object.ReferenceEquals(sourceType, typeof(Null)))
            {
                // Null is always convertible to a reference type
                return(true);
            }

            if (destType.IsAssignableFrom(sourceType) == false)
            {
                return(false);
            }

            if (sourceType.IsValueType == true)
            {
                if ((ilg != null))
                {
                    ilg.Emit(OpCodes.Box, sourceType);
                }
            }

            return(true);
        }
Example #15
0
        protected static void EmitValueTypeLoadAddress(FleeILGenerator ilg, Type targetType)
        {
            int index = ilg.GetTempLocalIndex(targetType);

            Utility.EmitStoreLocal(ilg, index);
            ilg.Emit(OpCodes.Ldloca_S, (byte)index);
        }
Example #16
0
 private static void EmitBranchToTrueTerminal(FleeILGenerator ilg, Label trueTerminal, BranchManager bm)
 {
     if (ilg.IsTemp == true)
     {
         bm.AddBranch(ilg, trueTerminal);
         ilg.Emit(OpCodes.Brtrue_S, trueTerminal);
     }
     else if (bm.IsLongBranch(ilg, trueTerminal) == false)
     {
         ilg.Emit(OpCodes.Brtrue_S, trueTerminal);
     }
     else
     {
         ilg.Emit(OpCodes.Brtrue, trueTerminal);
     }
 }
Example #17
0
        private void EmitVariableLoad(FleeILGenerator ilg)
        {
            MethodInfo mi = VariableCollection.GetVariableLoadMethod(MyVariableType);

            ilg.Emit(OpCodes.Ldstr, MyName);
            this.EmitMethodCall(mi, ilg);
        }
Example #18
0
        // Emit a short-circuited logical operation sequence
        // The idea: Store all the leaf operands in a stack with the leftmost at the top and rightmost at the bottom.
        // For each operand, emit it and try to find an end point for when it short-circuits. This means we go up through
        // the stack of operators (ignoring siblings) until we find a different operation (then emit a branch to its right operand)
        // or we reach the root (emit a branch to a true/false).
        // Repeat the process for all operands and then emit the true/false/last operand end cases.
        private void EmitLogical(FleeILGenerator ilg, ShortCircuitInfo info, IServiceProvider services)
        {
            // We always have an end label
            info.Branches.GetLabel(OurEndLabelKey, ilg);

            // Populate our data structures
            this.PopulateData(info);

            // Emit the sequence
            EmitLogicalShortCircuit(ilg, info, services);

            // Get the last operand
            ExpressionElement terminalOperand = info.Operands.Pop() as ExpressionElement;

            // Emit it
            EmitOperand(terminalOperand, info, ilg, services);
            // And jump to the end
            Label endLabel = info.Branches.FindLabel(OurEndLabelKey);

            ilg.Emit(OpCodes.Br_S, endLabel);

            // Emit our true/false terminals
            EmitTerminals(info, ilg, endLabel);

            // Mark the end
            ilg.MarkLabel(endLabel);
        }
Example #19
0
 protected static void EmitInt64Load(Int64 value, FleeILGenerator ilg)
 {
     if (value >= Int32.MinValue & value <= Int32.MaxValue)
     {
         EmitInt32Load((int)value, ilg);
         ilg.Emit(OpCodes.Conv_I8);
     }
     else if (value >= 0 & value <= UInt32.MaxValue)
     {
         EmitInt32Load((int)value, ilg);
         ilg.Emit(OpCodes.Conv_U8);
     }
     else
     {
         ilg.Emit(OpCodes.Ldc_I8, value);
     }
 }
Example #20
0
 private void EmitEnumCast(FleeILGenerator ilg, Type sourceType, Type destType, IServiceProvider services)
 {
     if (destType.IsValueType == false)
     {
         ilg.Emit(OpCodes.Box, sourceType);
     }
     else if (sourceType.IsValueType == false)
     {
         ilg.Emit(OpCodes.Unbox_Any, destType);
     }
     else
     {
         sourceType = GetUnderlyingEnumType(sourceType);
         destType   = GetUnderlyingEnumType(destType);
         this.EmitCast(ilg, sourceType, destType, services);
     }
 }
Example #21
0
        private static void EmitBitwiseOperation(FleeILGenerator ilg, AndOrOperation op)
        {
            switch (op)
            {
            case AndOrOperation.And:
                ilg.Emit(OpCodes.And);
                break;

            case AndOrOperation.Or:
                ilg.Emit(OpCodes.Or);
                break;

            default:
                Debug.Fail("Unknown op type");
                break;
            }
        }
Example #22
0
        public override void Emit(FleeILGenerator ilg, IServiceProvider services)
        {
            Type resultType = this.ResultType;

            MyChild.Emit(ilg, services);
            ImplicitConverter.EmitImplicitConvert(MyChild.ResultType, resultType, ilg);

            MethodInfo mi = Utility.GetSimpleOverloadedOperator("UnaryNegation", resultType, resultType);

            if (mi == null)
            {
                ilg.Emit(OpCodes.Neg);
            }
            else
            {
                ilg.Emit(OpCodes.Call, mi);
            }
        }
Example #23
0
        public override void Emit(FleeILGenerator ilg, IServiceProvider services)
        {
            Type resultType = this.ResultType;

            MyLeftChild.Emit(ilg, services);
            ImplicitConverter.EmitImplicitConvert(MyLeftChild.ResultType, resultType, ilg);
            MyRightChild.Emit(ilg, services);
            ImplicitConverter.EmitImplicitConvert(MyRightChild.ResultType, resultType, ilg);
            ilg.Emit(OpCodes.Xor);
        }
Example #24
0
        protected void EmitOverloadedOperatorCall(MethodInfo method, FleeILGenerator ilg, IServiceProvider services)
        {
            ParameterInfo[] parameters = method.GetParameters();
            ParameterInfo   pLeft      = parameters[0];
            ParameterInfo   pRight     = parameters[1];

            EmitChildWithConvert(MyLeftChild, pLeft.ParameterType, ilg, services);
            EmitChildWithConvert(MyRightChild, pRight.ParameterType, ilg, services);
            ilg.Emit(OpCodes.Call, method);
        }
Example #25
0
        private static void EmitStringEquality(FleeILGenerator ilg, LogicalCompareOperation op, IServiceProvider services)
        {
            // Get the StringComparison from the options
            ExpressionOptions   options = services.GetService(typeof(ExpressionOptions)) as ExpressionOptions;
            Int32LiteralElement ic      = new Int32LiteralElement((int)options.StringComparison);

            ic.Emit(ilg, services);

            // and emit the method call
            MethodInfo mi = typeof(string).GetMethod("Equals", BindingFlags.Public | BindingFlags.Static, null, new Type[] { typeof(string), typeof(string), typeof(StringComparison) }, null);

            ilg.Emit(OpCodes.Call, mi);

            if (op == LogicalCompareOperation.NotEqual)
            {
                ilg.Emit(OpCodes.Ldc_I4_0);
                ilg.Emit(OpCodes.Ceq);
            }
        }
Example #26
0
 private void EmitValueTypeArrayLoad(FleeILGenerator ilg, Type elementType)
 {
     if (this.NextRequiresAddress == true)
     {
         ilg.Emit(OpCodes.Ldelema, elementType);
     }
     else
     {
         Utility.EmitArrayLoad(ilg, elementType);
     }
 }
Example #27
0
        protected void EmitLoadOwner(FleeILGenerator ilg)
        {
            ilg.Emit(OpCodes.Ldarg_0);

            Type ownerType = MyOptions.OwnerType;

            if (ownerType.IsValueType == false)
            {
                return;
            }

            ilg.Emit(OpCodes.Unbox, ownerType);
            ilg.Emit(OpCodes.Ldobj, ownerType);

            // Emit usual stuff for value types but use the owner type as the target
            if (this.RequiresAddress == true)
            {
                EmitValueTypeLoadAddress(ilg, ownerType);
            }
        }
Example #28
0
 public override void Emit(FleeILGenerator ilg, IServiceProvider services)
 {
     if (object.ReferenceEquals(MyChild.ResultType, typeof(bool)))
     {
         this.EmitLogical(ilg, services);
     }
     else
     {
         MyChild.Emit(ilg, services);
         ilg.Emit(OpCodes.Not);
     }
 }
Example #29
0
        private static void EmitSuperShort(Int32 value, FleeILGenerator ilg)
        {
            OpCode ldcOpcode = default(OpCode);

            switch (value)
            {
            case 0:
                ldcOpcode = OpCodes.Ldc_I4_0;
                break;

            case 1:
                ldcOpcode = OpCodes.Ldc_I4_1;
                break;

            case 2:
                ldcOpcode = OpCodes.Ldc_I4_2;
                break;

            case 3:
                ldcOpcode = OpCodes.Ldc_I4_3;
                break;

            case 4:
                ldcOpcode = OpCodes.Ldc_I4_4;
                break;

            case 5:
                ldcOpcode = OpCodes.Ldc_I4_5;
                break;

            case 6:
                ldcOpcode = OpCodes.Ldc_I4_6;
                break;

            case 7:
                ldcOpcode = OpCodes.Ldc_I4_7;
                break;

            case 8:
                ldcOpcode = OpCodes.Ldc_I4_8;
                break;

            case -1:
                ldcOpcode = OpCodes.Ldc_I4_M1;
                break;

            default:
                Debug.Assert(false, "value out of range");
                break;
            }

            ilg.Emit(ldcOpcode);
        }
Example #30
0
        // Emit a function call for a value type
        private static void EmitValueTypeMethodCall(MethodInfo mi, FleeILGenerator ilg)
        {
            if (mi.IsStatic == true)
            {
                ilg.Emit(OpCodes.Call, mi);
            }
            else if ((!object.ReferenceEquals(mi.DeclaringType, mi.ReflectedType)))
            {
                // Method is not defined on the value type

                if (IsGetTypeMethod(mi) == true)
                {
                    // Special GetType method which requires a box
                    ilg.Emit(OpCodes.Box, mi.ReflectedType);
                    ilg.Emit(OpCodes.Call, mi);
                }
                else
                {
                    // Equals, GetHashCode, and ToString methods on the base
                    ilg.Emit(OpCodes.Constrained, mi.ReflectedType);
                    ilg.Emit(OpCodes.Callvirt, mi);
                }
            }
            else
            {
                // Call value type's implementation
                ilg.Emit(OpCodes.Call, mi);
            }
        }