private bool ConvertRefTypeToValueType(CilExpression argument)
        {
            if (argument.ExpressionType.IsTypeOf("System", "Object"))
            {
                if (argument is CilInstructionExpression e &&
                    e.Instructions.Count == 1)
                {
                    switch (e.Instructions[0].OpCode.Code)
                    {
                    case CilCode.Ldind_Ref:
                        // Load from pointer.
                        LdObj(e);
                        break;

                    case CilCode.Box:
                        // If argument is a box expression, then we can apply an optimisation; remove both
                        // box and unbox, and convert the embedded expression directly:
                        e.Arguments[0].ExpectedType = argument.ExpectedType;
                        argument.ReplaceWith(ConvertValueType(e.Arguments[0]).Remove());
                        return(true);

                    default:
                        // Argument is something else. We need to unbox.
                        UnboxAny(argument);
                        break;
                    }
                }
                else
                {
                    UnboxAny(argument);
                }

                return(true);
            }
        private bool EnsureTypeSafety(CilExpression argument)
        {
            bool changed = false;

            if (!_context.TypeHelper.IsAssignableTo(argument.ExpressionType, argument.ExpectedType))
            {
                if (!argument.ExpressionType.IsValueType && argument.ExpectedType.IsValueType)
                {
                    // Reference type -> Value type.
                    if (argument.ExpressionType.IsTypeOf("System", "Object"))
                    {
                        if (argument is CilInstructionExpression e &&
                            e.Instructions.Count == 1 &&
                            e.Instructions[0].OpCode.Code == CilCode.Ldind_Ref)
                        {
                            LdObj(e);
                        }
                        else
                        {
                            UnboxAny(argument);
                        }

                        changed = true;
                    }
                    else if (argument.ExpressionType is PointerTypeSignature)
                    {
                        ConvertValueType(argument);
                        changed = true;
                    }
                }
                else if (!argument.ExpressionType.IsValueType && !argument.ExpectedType.IsValueType)
                {
                    // Reference type -> Reference type.
                    CastClass(argument);
                    changed = true;
                }
                else if (argument.ExpressionType.IsValueType && !argument.ExpectedType.IsValueType)
                {
                    // Value type -> Reference type.
                    var newArg = Box(argument);
                    if (!newArg.ExpectedType.IsTypeOf("System", "Object"))
                    {
                        CastClass(newArg);
                    }

                    changed = true;
                }
                else if (argument.ExpressionType.IsValueType && argument.ExpectedType.IsValueType)
                {
                    // Value type -> Value type.
                    ConvertValueType(argument);
                    changed = true;
                }
            }
Exemple #3
0
        private bool IsBoxExpression(CilExpression expression, out CilExpression argument, out ITypeDefOrRef boxedType)
        {
            if (expression is CilInstructionExpression arg &&
                arg.Instructions.Count == 1 &&
                arg.Instructions[0].OpCode.Code == CilCode.Box)
            {
                argument  = arg.Arguments[0];
                boxedType = (ITypeDefOrRef)arg.Instructions[0].Operand;
                return(true);
            }

            argument  = null;
            boxedType = null;
            return(false);
        }
        private bool EnsureTypeSafety(CilExpression argument)
        {
            bool changed = false;

            if (!_context.TypeHelper.IsAssignableTo(argument.ExpressionType, argument.ExpectedType))
            {
                if (!argument.ExpressionType.IsValueType && argument.ExpectedType.IsValueType)
                {
                    // Reference type -> Value type.
                    changed = ConvertRefTypeToValueType(argument);
                }
                else if (!argument.ExpressionType.IsValueType && !argument.ExpectedType.IsValueType)
                {
                    // Reference type -> Reference type.
                    CastClass(argument);
                    changed = true;
                }
                else if (argument.ExpressionType.IsValueType && !argument.ExpectedType.IsValueType)
                {
                    // Value type -> Reference type.
                    var newArg = Box(argument);
                    if (!newArg.ExpectedType.IsTypeOf("System", "Object"))
                    {
                        CastClass(newArg);
                    }

                    changed = true;
                }
                else if (argument.ExpressionType.IsValueType && argument.ExpectedType.IsValueType)
                {
                    // Value type -> Value type.
                    ConvertValueType(argument);
                    changed = true;
                }
            }

            return(changed);
        }