示例#1
0
            private void BinaryShiftExpression(BinaryExpression binaryExpression)
            {
                binaryExpression.Left.Accept(this);

                binaryExpression.Right.Accept(this);

                int bits = Marshal.SizeOf(binaryExpression.Left.Type) * 8;

                ILUtil.EmitConstant(_il, bits - 1);
                _il.Emit(OpCodes.And);

                switch (binaryExpression.ExpressionType)
                {
                case ExpressionType.ShiftLeft:
                    _il.Emit(OpCodes.Shl);
                    break;

                case ExpressionType.ShiftRight:
                    if (TypeUtil.IsUnsigned(binaryExpression.Left.Type))
                    {
                        _il.Emit(OpCodes.Shr_Un);
                    }
                    else
                    {
                        _il.Emit(OpCodes.Shr);
                    }
                    break;

                default:
                    throw new InvalidOperationException();
                }
            }
示例#2
0
            public void VariableAccess(VariableAccess variableAccess)
            {
                _il.Emit(OpCodes.Ldarg_0);
                ILUtil.EmitConstant(_il, variableAccess.ParameterIndex);
                _il.Emit(OpCodes.Ldelem_Ref);

                _compiler.ExtendedConvertToType(typeof(object), variableAccess.Type, false);
            }
示例#3
0
            public void Index(Index index)
            {
                index.Operand.Accept(this);

                Emit(index.Argument, typeof(int));

                ILUtil.EmitLoadElement(_il, index.Type);
            }
示例#4
0
            public void UnaryExpression(UnaryExpression unaryExpression)
            {
                switch (unaryExpression.ExpressionType)
                {
                case ExpressionType.Minus:
                    unaryExpression.Operand.Accept(this);

                    _il.Emit(OpCodes.Neg);
                    break;

                case ExpressionType.Not:
                    unaryExpression.Operand.Accept(this);

                    if (TypeUtil.IsInteger(unaryExpression.Operand.Type))
                    {
                        _il.Emit(OpCodes.Not);
                    }
                    else
                    {
                        ILUtil.EmitConstant(_il, 0);
                        _il.Emit(OpCodes.Ceq);
                    }
                    break;

                case ExpressionType.LogicalNot:
                    unaryExpression.Operand.Accept(this);

                    ILUtil.EmitConstant(_il, 0);
                    _il.Emit(OpCodes.Ceq);
                    break;

                case ExpressionType.BitwiseNot:
                    unaryExpression.Operand.Accept(this);

                    _il.Emit(OpCodes.Not);
                    break;

                case ExpressionType.Plus:
                case ExpressionType.Group:
                    // No-ops.

                    unaryExpression.Operand.Accept(this);
                    break;

                default:
                    throw new NotSupportedException();
                }
            }
示例#5
0
 public void Constant(Constant constant)
 {
     if (constant.Value == null)
     {
         ILUtil.EmitNull(_il);
     }
     else if (constant.Value is DateTime)
     {
         ILUtil.EmitConstant(_il, ((DateTime)constant.Value).Ticks);
         ILUtil.EmitNew(_il, typeof(DateTime).GetConstructor(new[] { typeof(long) }));
     }
     else if (constant.Value is TimeSpan)
     {
         ILUtil.EmitConstant(_il, ((TimeSpan)constant.Value).Ticks);
         ILUtil.EmitNew(_il, typeof(TimeSpan).GetConstructor(new[] { typeof(long) }));
     }
     else
     {
         ILUtil.EmitConstant(_il, constant.Value);
     }
 }
示例#6
0
            public void MethodCall(MethodCall methodCall)
            {
                bool isStatic = methodCall.Operand is TypeAccess;

                if (!isStatic)
                {
                    bool emitBox       = false;
                    bool emitStoreLoad = false;

                    if (
                        (methodCall.Operand is FieldAccess || methodCall.Operand is Constant) &&
                        methodCall.Operand.Type.IsValueType &&
                        !methodCall.MethodInfo.DeclaringType.IsValueType
                        )
                    {
                        emitBox = true;
                    }
                    else if (
                        methodCall.Operand.Type.IsValueType && (
                            !(methodCall.Operand is FieldAccess) ||
                            methodCall.MethodInfo.DeclaringType.IsValueType
                            )
                        )
                    {
                        emitStoreLoad = true;
                    }

                    // Signal field access that we're using the field as a
                    // parameter.

                    _fieldAsParameter =
                        methodCall.Operand is FieldAccess &&
                        methodCall.MethodInfo.DeclaringType.IsValueType &&
                        !emitStoreLoad;

                    try
                    {
                        methodCall.Operand.Accept(this);
                    }
                    finally
                    {
                        _fieldAsParameter = false;
                    }

                    if (emitBox)
                    {
                        _il.Emit(OpCodes.Box, methodCall.Operand.Type);
                    }
                    else if (emitStoreLoad)
                    {
                        Debug.Assert(methodCall.Operand.Type == methodCall.MethodInfo.DeclaringType);

                        var builder = _il.DeclareLocal(methodCall.Operand.Type);

                        _il.Emit(OpCodes.Stloc, builder);
                        _il.Emit(OpCodes.Ldloca, builder);
                    }
                }

                var parameters = methodCall.MethodInfo.GetParameters();
                var arguments  = methodCall.Arguments;

                bool paramsMethod =
                    parameters.Length > 0 &&
                    parameters[parameters.Length - 1].GetCustomAttributes(typeof(ParamArrayAttribute), true).Length == 1;

                int mandatoryParameterCount =
                    paramsMethod
                    ? parameters.Length - 1
                    : parameters.Length;

                for (int i = 0; i < mandatoryParameterCount; i++)
                {
                    Emit(arguments[i], parameters[i].ParameterType);
                }

                if (paramsMethod)
                {
                    var  paramsType  = parameters[parameters.Length - 1].ParameterType;
                    var  elementType = paramsType.GetElementType();
                    bool emitted     = false;

                    // When the params argument is missing, a new array is issued.

                    if (arguments.Count == mandatoryParameterCount)
                    {
                        ILUtil.EmitEmptyArray(_il, elementType);
                        emitted = true;
                    }
                    else if (arguments.Count == mandatoryParameterCount + 1)
                    {
                        var lastArgument = arguments[arguments.Count - 1];

                        // Null arguments are passed blindly.
                        if (lastArgument is Constant constant && constant.Value == null)
                        {
                            ILUtil.EmitNull(_il);
                            emitted = true;
                        }
                        else
                        {
                            // So are array arguments that can be casted.

                            if (
                                lastArgument.Type.IsArray &&
                                TypeUtil.CanCastImplicitely(lastArgument.Type, paramsType, false)
                                )
                            {
                                Emit(lastArgument, paramsType);
                                emitted = true;
                            }
                        }
                    }

                    // If we didn't find a shortcut, emit the array with all
                    // arguments.

                    if (!emitted)
                    {
                        ILUtil.EmitArray(
                            _il,
                            elementType,
                            arguments.Count - mandatoryParameterCount,
                            p => Emit(arguments[mandatoryParameterCount + p], elementType)
                            );
                    }
                }
示例#7
0
        private void ExtendedConvertToType(Type fromType, Type toType, bool allowExplicit)
        {
            try
            {
                // See whether we can find a constructor on target type.

                var constructor = _resolver.ResolveMethodGroup(
                    toType.GetConstructors(_resolver.Options.AccessBindingFlags | BindingFlags.CreateInstance),
                    new[] { fromType },
                    new[] { false }
                    );

                if (constructor != null)
                {
                    ILUtil.EmitNew(_il, (ConstructorInfo)constructor);

                    return;
                }

                // See whether we have an implicit cast.

                var castMethod = _resolver.FindOperatorMethod(
                    "op_Implicit",
                    new[] { fromType, toType },
                    toType,
                    new[] { fromType }
                    );

                if (castMethod == null && allowExplicit)
                {
                    castMethod = _resolver.FindOperatorMethod(
                        "op_Explicit",
                        new[] { fromType, toType },
                        toType,
                        new[] { fromType }
                        );
                }

                if (castMethod != null)
                {
                    var parameterType = castMethod.GetParameters()[0].ParameterType;

                    if (fromType != parameterType)
                    {
                        ILUtil.EmitConvertToType(_il, fromType, parameterType, _resolver.Options.Checked);
                    }

                    _il.Emit(OpCodes.Call, castMethod);

                    if (toType != castMethod.ReturnType)
                    {
                        ILUtil.EmitConvertToType(_il, castMethod.ReturnType, toType, _resolver.Options.Checked);
                    }

                    return;
                }

                // Let ILUtill handle it.

                ILUtil.EmitConvertToType(_il, fromType, toType, _resolver.Options.Checked);
            }
            catch (Exception ex)
            {
                throw new ExpressionsException(
                          "Invalid explicit cast",
                          ExpressionsExceptionType.InvalidExplicitCast,
                          ex
                          );
            }
        }
示例#8
0
            private void BinaryLogicalExpression(BinaryExpression binaryExpression)
            {
                Label beforeLabel;
                Label afterLabel;

                switch (binaryExpression.ExpressionType)
                {
                case ExpressionType.And:
                case ExpressionType.LogicalAnd:
                    beforeLabel = _il.DefineLabel();
                    afterLabel  = _il.DefineLabel();

                    binaryExpression.Left.Accept(this);
                    _il.Emit(OpCodes.Brfalse, beforeLabel);

                    binaryExpression.Right.Accept(this);
                    _il.Emit(OpCodes.Br, afterLabel);

                    _il.MarkLabel(beforeLabel);
                    ILUtil.EmitConstant(_il, 0);
                    _il.MarkLabel(afterLabel);
                    break;

                case ExpressionType.AndBoth:
                    binaryExpression.Left.Accept(this);
                    binaryExpression.Right.Accept(this);

                    _il.Emit(OpCodes.And);
                    break;

                case ExpressionType.Or:
                case ExpressionType.LogicalOr:
                    beforeLabel = _il.DefineLabel();
                    afterLabel  = _il.DefineLabel();

                    binaryExpression.Left.Accept(this);
                    _il.Emit(OpCodes.Brtrue, beforeLabel);

                    binaryExpression.Right.Accept(this);
                    _il.Emit(OpCodes.Br, afterLabel);

                    _il.MarkLabel(beforeLabel);
                    ILUtil.EmitConstant(_il, 1);
                    _il.MarkLabel(afterLabel);
                    break;

                case ExpressionType.OrBoth:
                    binaryExpression.Left.Accept(this);
                    binaryExpression.Right.Accept(this);

                    _il.Emit(OpCodes.Or);
                    break;

                case ExpressionType.Xor:
                    binaryExpression.Left.Accept(this);
                    binaryExpression.Right.Accept(this);

                    _il.Emit(OpCodes.Xor);
                    break;

                default:
                    throw new InvalidOperationException();
                }
            }