コード例 #1
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(YaleIlGenerator ilg, ExpressionContext context)
        {
            RightChild.Emit(ilg, context);
            var typeCode = Type.GetTypeCode(LeftChild.ResultType);

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

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

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

            ilg.Emit(OpCodes.And);
        }
コード例 #2
0
 /// <summary>
 /// Emit the value of a field in the object whose reference is currently on the evaluation stack.
 /// </summary>
 /// <param name="fieldInfo"></param>
 /// <param name="indirect"></param>
 /// <param name="ilGenerator"></param>
 private static void EmitLdfld(FieldInfo fieldInfo, bool indirect, YaleIlGenerator ilGenerator)
 {
     if (fieldInfo.IsStatic)
     {
         ilGenerator.Emit(indirect ? OpCodes.Ldsflda : OpCodes.Ldsfld, fieldInfo);
     }
     else
     {
         ilGenerator.Emit(indirect ? OpCodes.Ldflda : OpCodes.Ldfld, fieldInfo);
     }
 }
コード例 #3
0
        private void EmitCast(YaleIlGenerator ilg, Type sourceType, Type destType, ExpressionContext context)
        {
            var explicitOperator = GetExplictOverloadedOperator(sourceType, destType);

            if (ReferenceEquals(sourceType, destType))
            {
                // Identity cast; do nothing
                return;
            }

            if (explicitOperator != null)
            {
                ilg.Emit(OpCodes.Call, explicitOperator);
            }
            else if (sourceType.IsEnum | destType.IsEnum)
            {
                EmitEnumCast(ilg, sourceType, destType, context);
            }
            else if (ImplicitConverter.EmitImplicitConvert(sourceType, destType, ilg))
            {
                // Implicit numeric cast; do nothing
                return;
            }
            else if (IsCastableNumericType(sourceType) & IsCastableNumericType(destType))
            {
                // Explicit numeric cast
                EmitExplicitNumericCast(ilg, sourceType, destType, context);
            }
            else if (sourceType.IsValueType)
            {
                Debug.Assert(destType.IsValueType == false, "expecting reference type");
                ilg.Emit(OpCodes.Box, sourceType);
            }
            else
            {
                if (destType.IsValueType)
                {
                    // 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);
                    }
                }
            }
        }
コード例 #4
0
ファイル: LiteralElement.cs プロジェクト: Verent/Yale
 public static void EmitLoad(int value, YaleIlGenerator ilg)
 {
     if (value >= -1 & value <= 8)
     {
         EmitSuperShort(value, ilg);
     }
     else if (value >= sbyte.MinValue & value <= sbyte.MaxValue)
     {
         ilg.Emit(OpCodes.Ldc_I4_S, Convert.ToSByte(value));
     }
     else
     {
         ilg.Emit(OpCodes.Ldc_I4, value);
     }
 }
コード例 #5
0
ファイル: AndOrElement.cs プロジェクト: Verent/Yale
        private static void EmitBitwiseOperation(YaleIlGenerator ilg, AndOrOperation op)
        {
            switch (op)
            {
            case AndOrOperation.And:
                ilg.Emit(OpCodes.And);
                break;

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

            default:
                throw new InvalidOperationException("Unknown op type");
            }
        }
コード例 #6
0
ファイル: AndOrElement.cs プロジェクト: Verent/Yale
        /// <summary>
        /// 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.
        /// </summary>
        private void EmitLogical(YaleIlGenerator ilg, ShortCircuitInfo info, ExpressionContext context)
        {
            // We always have an end label
            info.Branches.GetLabel(OurEndLabelKey, ilg);

            // Populate our data structures
            PopulateData(info);

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

            // Get the last operand
            var terminalOperand = (BaseExpressionElement)info.Operands.Pop();

            // Emit it
            EmitOperand(terminalOperand, info, ilg, context);
            // And jump to the end
            var 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);
        }
コード例 #7
0
ファイル: InElement.cs プロジェクト: Verent/Yale
 private static void EmitBranchToTrueTerminal(YaleIlGenerator ilg, Label trueTerminal, BranchManager branchManager)
 {
     if (ilg.IsTemp)
     {
         branchManager.AddBranch(ilg, trueTerminal);
         ilg.Emit(OpCodes.Brtrue_S, trueTerminal);
     }
     else if (branchManager.IsLongBranch(ilg, trueTerminal) == false)
     {
         ilg.Emit(OpCodes.Brtrue_S, trueTerminal);
     }
     else
     {
         ilg.Emit(OpCodes.Brtrue, trueTerminal);
     }
 }
コード例 #8
0
        protected static void EmitValueTypeLoadAddress(YaleIlGenerator ilg, Type targetType)
        {
            var index = ilg.GetTempLocalIndex(targetType);

            Utility.EmitStoreLocal(ilg, index);
            ilg.Emit(OpCodes.Ldloca_S, Convert.ToByte(index));
        }
コード例 #9
0
        /// <summary>
        /// Emits il that loads a variable from the Variables collection
        /// </summary>
        /// <param name="ilg"></param>
        private void EmitVariableLoad(YaleIlGenerator ilg)
        {
            var methodInfo = VariableCollection.GetVariableLoadMethod(valueType);

            ilg.Emit(OpCodes.Ldstr, MemberName);
            EmitMethodCall(methodInfo, ilg);
        }
コード例 #10
0
ファイル: ComputeInstance.cs プロジェクト: Verent/Yale
        /// <summary>
        /// Create the IL used to load the result from another expression
        /// </summary>
        /// <param name="expressionKey"></param>
        /// <param name="ilGenerator"></param>
        internal void EmitLoad(string expressionKey, YaleIlGenerator ilGenerator)
        {
            var propertyInfo = typeof(ExpressionContext).GetProperty(nameof(ExpressionContext.ComputeInstance));

            ilGenerator.Emit(OpCodes.Callvirt, propertyInfo.GetGetMethod());

            //Find and load expression result
            var members    = typeof(ComputeInstance).FindMembers(MemberTypes.Method, BindingFlags.Instance | BindingFlags.Public, Type.FilterName, "GetResult");
            var methodInfo = members.Cast <MethodInfo>().First(method => method.IsGenericMethod);
            var resultType = ResultType(expressionKey);

            methodInfo = methodInfo.MakeGenericMethod(resultType);

            ilGenerator.Emit(OpCodes.Ldstr, expressionKey);
            ilGenerator.Emit(OpCodes.Call, methodInfo);
        }
コード例 #11
0
        private void EmitShift(YaleIlGenerator ilg)
        {
            var typeCode = Type.GetTypeCode(LeftChild.ResultType);
            var opCode   = default(OpCode);

            switch (typeCode)
            {
            case TypeCode.Byte:
            case TypeCode.SByte:
            case TypeCode.Int16:
            case TypeCode.UInt16:
            case TypeCode.Int32:
            case TypeCode.Int64:
                // Signed operand, emit a left shift or arithmetic right shift
                opCode = operation == ShiftOperation.LeftShift ? OpCodes.Shl : OpCodes.Shr;
                break;

            case TypeCode.UInt32:
            case TypeCode.UInt64:
                // Unsigned operand, emit left shift or logical right shift
                opCode = operation == ShiftOperation.LeftShift ? OpCodes.Shl : OpCodes.Shr_Un;
                break;

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

            ilg.Emit(opCode);
        }
コード例 #12
0
        /// <summary>
        /// Emit elements into an array
        /// </summary>
        private static void EmitElementArrayLoad(BaseExpressionElement[] elements, Type arrayElementType, YaleIlGenerator ilg, ExpressionContext context)
        {
            // Load the array length
            LiteralElement.EmitLoad(elements.Length, ilg);

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

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

            Utility.EmitStoreLocal(ilg, arrayLocalIndex);

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

            // Load the array
            Utility.EmitLoadLocal(ilg, arrayLocalIndex);
        }
コード例 #13
0
 private void EmitEnumCast(YaleIlGenerator ilg, Type sourceType, Type destType, ExpressionContext context)
 {
     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);
         EmitCast(ilg, sourceType, destType, context);
     }
 }
コード例 #14
0
ファイル: LiteralElement.cs プロジェクト: Verent/Yale
 protected static void EmitLoad(long value, YaleIlGenerator ilg)
 {
     if (value >= int.MinValue & value <= int.MaxValue)
     {
         EmitLoad(Convert.ToInt32(value), ilg);
         ilg.Emit(OpCodes.Conv_I8);
     }
     else if (value >= 0 & value <= int.MaxValue)
     {
         EmitLoad(Convert.ToInt32(value), ilg);
         ilg.Emit(OpCodes.Conv_U8);
     }
     else
     {
         ilg.Emit(OpCodes.Ldc_I8, value);
     }
 }
コード例 #15
0
ファイル: NegateElement.cs プロジェクト: Verent/Yale
        public override void Emit(YaleIlGenerator ilGenerator, ExpressionContext context)
        {
            var resultType = ResultType;

            MyChild.Emit(ilGenerator, context);
            ImplicitConverter.EmitImplicitConvert(MyChild.ResultType, resultType, ilGenerator);

            var methodInfo = Utility.GetSimpleOverloadedOperator(UnaryNegation, resultType, resultType);

            if (methodInfo == null)
            {
                ilGenerator.Emit(OpCodes.Neg);
            }
            else
            {
                ilGenerator.Emit(OpCodes.Call, methodInfo);
            }
        }
コード例 #16
0
        protected void EmitOverloadedOperatorCall(MethodInfo method, YaleIlGenerator ilg, ExpressionContext context)
        {
            var parameters         = method.GetParameters();
            var parameterInfoLeft  = parameters[0];
            var parameterInfoRight = parameters[1];

            EmitChildWithConvert(LeftChild, parameterInfoLeft.ParameterType, ilg, context);
            EmitChildWithConvert(RightChild, parameterInfoRight.ParameterType, ilg, context);
            ilg.Emit(OpCodes.Call, method);
        }
コード例 #17
0
        private static void EmitStringEquality(YaleIlGenerator ilg, LogicalCompareOperation op, ExpressionContext context)
        {
            // Get the StringComparison from the options
            var options             = context.BuilderOptions;
            var int32LiteralElement = new Int32LiteralElement((int)options.StringComparison);

            int32LiteralElement.Emit(ilg, context);

            // and emit the method call
            var methodInfo = typeof(string).GetMethod("Equals", new[] { typeof(string), typeof(string), typeof(StringComparison) }, null);

            ilg.Emit(OpCodes.Call, methodInfo);

            if (op == LogicalCompareOperation.NotEqual)
            {
                ilg.Emit(OpCodes.Ldc_I4_0);
                ilg.Emit(OpCodes.Ceq);
            }
        }
コード例 #18
0
ファイル: XorElement.cs プロジェクト: Verent/Yale
        public override void Emit(YaleIlGenerator ilGenerator, ExpressionContext context)
        {
            var resultType = ResultType;

            LeftChild.Emit(ilGenerator, context);
            ImplicitConverter.EmitImplicitConvert(LeftChild.ResultType, resultType, ilGenerator);
            RightChild.Emit(ilGenerator, context);
            ImplicitConverter.EmitImplicitConvert(RightChild.ResultType, resultType, ilGenerator);
            ilGenerator.Emit(OpCodes.Xor);
        }
コード例 #19
0
        protected void EmitLoadOwner(YaleIlGenerator ilg)
        {
            ilg.Emit(OpCodes.Ldarg_0);

            var ownerType = Context.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 (RequiresAddress)
            {
                EmitValueTypeLoadAddress(ilg, ownerType);
            }
        }
コード例 #20
0
 private void EmitValueTypeArrayLoad(YaleIlGenerator ilg, Type elementType)
 {
     if (NextRequiresAddress)
     {
         ilg.Emit(OpCodes.Ldelema, elementType);
     }
     else
     {
         Utility.EmitArrayLoad(ilg, elementType);
     }
 }
コード例 #21
0
ファイル: LiteralElement.cs プロジェクト: Verent/Yale
        private static void EmitSuperShort(int value, YaleIlGenerator ilGenerator)
        {
            var 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;
            }

            ilGenerator.Emit(ldcOpcode);
        }
コード例 #22
0
 public override void Emit(YaleIlGenerator ilGenerator, ExpressionContext context)
 {
     if (ReferenceEquals(MyChild.ResultType, typeof(bool)))
     {
         EmitLogical(ilGenerator, context);
     }
     else
     {
         MyChild.Emit(ilGenerator, context);
         ilGenerator.Emit(OpCodes.Not);
     }
 }
コード例 #23
0
 /// <summary>
 /// Emit a function call for a value type
 /// </summary>
 /// <param name="mi"></param>
 /// <param name="ilg"></param>
 private static void EmitValueTypeMethodCall(MethodInfo mi, YaleIlGenerator ilg)
 {
     if (mi.IsStatic)
     {
         ilg.Emit(OpCodes.Call, mi);
     }
     else if ((!ReferenceEquals(mi.DeclaringType, mi.ReflectedType)))
     {
         // Method is not defined on the value type
         if (IsGetTypeMethod(mi))
         {
             // 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 implementation
         ilg.Emit(OpCodes.Call, mi);
     }
 }
コード例 #24
0
        //Entry point of IL Creation
        public override void Emit(YaleIlGenerator ilGenerator, ExpressionContext context)
        {
            _child.Emit(ilGenerator, context);

            ImplicitConverter.EmitImplicitConvert(_child.ResultType, _resultType, ilGenerator);

            //Todo: Verify if this convert stuff works
            if ("isGeneric".Equals("false"))
            {
                ImplicitConverter.EmitImplicitConvert(_resultType, typeof(object), ilGenerator);
            }

            ilGenerator.Emit(OpCodes.Ret);
        }
コード例 #25
0
ファイル: DateTimeLiteralElement.cs プロジェクト: Verent/Yale
        public override void Emit(YaleIlGenerator ilGenerator, ExpressionContext context)
        {
            var index = ilGenerator.GetTempLocalIndex(typeof(DateTime));

            Utility.EmitLoadLocalAddress(ilGenerator, index);

            EmitLoad(_value.Ticks, ilGenerator);

            var constructor = typeof(DateTime).GetConstructor(new[] { typeof(Int64) });

            ilGenerator.Emit(OpCodes.Call, constructor);

            Utility.EmitLoadLocal(ilGenerator, index);
        }
コード例 #26
0
ファイル: AndOrElement.cs プロジェクト: Verent/Yale
        private static void EmitBranch(AndOrElement op, YaleIlGenerator ilg, Label target, ShortCircuitInfo info)
        {
            if (ilg.IsTemp)
            {
                info.Branches.AddBranch(ilg, target);

                // Temp mode; just emit a short branch and return
                var shortBranch = GetBranchOpcode(op, false);
                ilg.Emit(shortBranch, target);

                return;
            }

            // Emit the proper branch opcode

            // Determine if it is a long branch
            var longBranch = info.Branches.IsLongBranch(ilg, target);

            // Get the branch opcode
            var brOpcode = GetBranchOpcode(op, longBranch);

            // Emit the branch
            ilg.Emit(brOpcode, target);
        }
コード例 #27
0
ファイル: InElement.cs プロジェクト: Verent/Yale
        private void EmitCollectionIn(YaleIlGenerator ilg, ExpressionContext context)
        {
            // Get the contains method
            var methodInfo     = GetCollectionContainsMethod();
            var firstParameter = methodInfo.GetParameters()[0];

            // Load the collection
            targetCollectionElement.Emit(ilg, context);
            // Load the argument
            operand.Emit(ilg, context);
            // Do an implicit convert if necessary
            ImplicitConverter.EmitImplicitConvert(operand.ResultType, firstParameter.ParameterType, ilg);
            // Call the contains method
            ilg.Emit(OpCodes.Callvirt, methodInfo);
        }
コード例 #28
0
ファイル: InElement.cs プロジェクト: Verent/Yale
        private void EmitListIn(YaleIlGenerator ilg, ExpressionContext context, BranchManager branchManager)
        {
            var compareElement = new CompareElement();
            var endLabel       = branchManager.FindLabel("endLabel");
            var trueTerminal   = branchManager.FindLabel("trueTerminal");

            // Cache the operand since we will be comparing against it a lot
            var lb          = ilg.DeclareLocal(operand.ResultType);
            var targetIndex = lb.LocalIndex;

            operand.Emit(ilg, context);
            Utility.EmitStoreLocal(ilg, targetIndex);

            // Wrap our operand in a local shim
            var targetShim = new LocalBasedElement(operand, targetIndex);

            // Emit the compares
            foreach (var argumentElement in arguments)
            {
                compareElement.Initialize(targetShim, argumentElement, LogicalCompareOperation.Equal);
                compareElement.Emit(ilg, context);

                EmitBranchToTrueTerminal(ilg, trueTerminal, branchManager);
            }

            ilg.Emit(OpCodes.Ldc_I4_0);
            ilg.Emit(OpCodes.Br_S, endLabel);

            branchManager.MarkLabel(ilg, trueTerminal);
            ilg.MarkLabel(trueTerminal);

            ilg.Emit(OpCodes.Ldc_I4_1);

            branchManager.MarkLabel(ilg, endLabel);
            ilg.MarkLabel(endLabel);
        }
コード例 #29
0
        private void EmitArrayLoad(YaleIlGenerator ilg, ExpressionContext context)
        {
            _indexerElement.Emit(ilg, context);
            ImplicitConverter.EmitImplicitConvert(_indexerElement.ResultType, typeof(Int32), ilg);

            var elementType = ResultType;

            if (elementType.IsValueType == false)
            {
                // Simple reference load
                ilg.Emit(OpCodes.Ldelem_Ref);
            }
            else
            {
                EmitValueTypeArrayLoad(ilg, elementType);
            }
        }
コード例 #30
0
        private void EmitConditional(YaleIlGenerator ilg, ExpressionContext context, BranchManager branchManager)
        {
            var falseLabel = branchManager.FindLabel("falseLabel");
            var endLabel   = branchManager.FindLabel("endLabel");

            // Emit the condition
            condition.Emit(ilg, context);

            // On false go to the false operand
            if (ilg.IsTemp)
            {
                branchManager.AddBranch(ilg, falseLabel);
                ilg.Emit(OpCodes.Brfalse_S, falseLabel);
            }
            else if (branchManager.IsLongBranch(ilg, falseLabel) == false)
            {
                ilg.Emit(OpCodes.Brfalse_S, falseLabel);
            }
            else
            {
                ilg.Emit(OpCodes.Brfalse, falseLabel);
            }

            // Emit the true operand
            whenTrue.Emit(ilg, context);
            ImplicitConverter.EmitImplicitConvert(whenTrue.ResultType, resultType, ilg);

            // Jump to end
            if (ilg.IsTemp)
            {
                branchManager.AddBranch(ilg, endLabel);
                ilg.Emit(OpCodes.Br_S, endLabel);
            }
            else if (branchManager.IsLongBranch(ilg, endLabel) == false)
            {
                ilg.Emit(OpCodes.Br_S, endLabel);
            }
            else
            {
                ilg.Emit(OpCodes.Br, endLabel);
            }

            branchManager.MarkLabel(ilg, falseLabel);
            ilg.MarkLabel(falseLabel);

            // Emit the false operand
            whenFalse.Emit(ilg, context);
            ImplicitConverter.EmitImplicitConvert(whenFalse.ResultType, resultType, ilg);
            // Fall through to end
            branchManager.MarkLabel(ilg, endLabel);
            ilg.MarkLabel(endLabel);
        }