コード例 #1
0
        private Stmt Conv(TypeReference convTo, bool forceFromUnsigned = false)
        {
            var expr = this.stack.Pop();
            var conv = new ExprConv(this.ctx, expr, convTo, forceFromUnsigned);

            return(this.SsaLocalAssignment(conv));
        }
コード例 #2
0
        protected override ICode VisitBox(ExprBox e)
        {
            var ctx  = e.Ctx;
            var expr = (Expr)this.Visit(e.Expr);

            if (e.Type.IsUnsignedInteger() && expr.Type.IsSignedInteger())
            {
                expr = new ExprConv(ctx, expr, e.Type, false);
            }
            if (!e.Type.IsValueType)
            {
                // For ref-types 'box' does nothing
                return(this.Visit(e.Expr));
            }
            var eType = new ExprJsTypeVarName(ctx, e.Type);

            if (e.Type.IsNullable())
            {
                var exprIsVar    = expr.IsVar();
                var innerType    = e.Type.GetNullableInnerType();
                var temp         = exprIsVar ? null : new ExprVarLocal(ctx, e.Type);
                var box          = new ExprBox(ctx, temp ?? expr, innerType).Named("box");
                var nullableJs   = exprIsVar ? "(expr !== null ? box : null)" : "((temp = expr) !== null ? box : null)";
                var nullableExpr = new ExprJsExplicit(ctx, nullableJs, innerType, temp.Named("temp"), expr.Named("expr"), box);
                return(nullableExpr);
            }
            else
            {
                var deepCopyExpr = InternalFunctions.ValueTypeDeepCopyIfRequired(e.Type, () => (Expr)this.Visit(expr));
                var int2bool     = e.Type.IsBoolean() && expr.Type.IsInteger() ? "!!" : "";
                var js           = "{v:" + int2bool + "expr,_:type}";
                var ret          = new ExprJsExplicit(ctx, js, e.Type, (deepCopyExpr ?? expr).Named("expr"), eType.Named("type"));
                return(ret);
            }
        }
コード例 #3
0
        protected override ICode VisitConv(ExprConv e)
        {
            var fromType = e.Expr.Type;
            var toType   = e.Type;

            var fromTypeMetadataType = fromType.MetadataType;
            var toTypeMetadataType   = toType.MetadataType;

            if (e.ForceFromUnsigned)
            {
                switch (fromTypeMetadataType)
                {
                case MetadataType.SByte: fromTypeMetadataType = MetadataType.Byte; break;

                case MetadataType.Int16: fromTypeMetadataType = MetadataType.UInt16; break;

                case MetadataType.Int32: fromTypeMetadataType = MetadataType.UInt32; break;

                case MetadataType.Int64: fromTypeMetadataType = MetadataType.UInt64; break;

                case MetadataType.IntPtr: fromTypeMetadataType = MetadataType.UIntPtr; break;
                }
            }
            if (fromTypeMetadataType == MetadataType.Char)
            {
                fromTypeMetadataType = MetadataType.UInt16;
            }
            if (toTypeMetadataType == MetadataType.Char)
            {
                toTypeMetadataType = MetadataType.UInt16;
            }

            var fromIdx = indexMap.ValueOrDefault(fromTypeMetadataType, -1);
            var toIdx   = indexMap.ValueOrDefault(toTypeMetadataType, -1);

            if (fromIdx == -1 || toIdx == -1)
            {
                return(e.Expr);
            }

            var ctx = e.Ctx;
            var js  = jss[fromIdx, toIdx];

            if (js != null)
            {
                // In-place conversion
                var expr = new ExprJsExplicit(ctx, js, e.Type, e.Expr.Named("e"));
                return(expr);
            }
            else
            {
                // Call conversion function
                var convMi   = ((Func <int, int>)InternalFunctions.Conv <int, int>).Method.GetGenericMethodDefinition();
                var mConv    = ctx.Module.Import(convMi).MakeGeneric(e.Expr.Type, e.Type);
                var convCall = new ExprCall(ctx, mConv, null, e.Expr);
                return(convCall);
            }
        }
コード例 #4
0
        private Expr InsertConvIfRequired(Expr expr, TypeReference requiredType)
        {
            if (requiredType.IsSame(expr.Type))
            {
                return(expr);
            }
            if (!requiredType.IsNumeric() || !expr.Type.IsNumeric())
            {
                return(expr);
            }
            var conv = new ExprConv(this.ctx, expr, requiredType, false);

            return(conv);
        }
コード例 #5
0
        protected virtual ICode VisitConv(ExprConv e)
        {
            this.ThrowOnNoOverride();
            var expr = (Expr)this.Visit(e.Expr);

            if (expr != e.Expr)
            {
                return(new ExprConv(e.Ctx, expr, e.Type, e.ForceFromUnsigned));
            }
            else
            {
                return(e);
            }
        }
コード例 #6
0
        protected override Expr VisitConv(ExprConv e)
        {
            this.Visit(e.ExprToConvert);
            Instruction instConv;

            switch (e.ConvToType)
            {
            case TypeCode.Int32:
                instConv = this.il.Create(OpCodes.Conv_I4);
                break;

            case TypeCode.Int64:
                instConv = this.il.Create(OpCodes.Conv_I8);
                break;

            default:
                throw new NotSupportedException("Cannot conv to: " + e.ConvToType);
            }
            this.Emit(e, instConv);
            return(e);
        }
コード例 #7
0
        protected override ICode VisitAssignment(ExprAssignment e)
        {
            var ctx    = e.Ctx;
            var expr   = (Expr)this.Visit(e.Expr);
            var target = (ExprVar)this.Visit(e.Target);

            if (target.Type.IsBoolean() && expr.Type.IsInteger())
            {
                expr = new ExprJsExplicit(ctx, "!!expr", ctx.Boolean, expr.Named("expr"));
            }
            else if (target.Type.IsUnsignedInteger() && expr.Type.IsSignedInteger())
            {
                expr = new ExprConv(ctx, expr, expr.Type.UnsignedEquivilent(ctx.TypeSystem), false);
            }
            if (expr != e.Expr || target != e.Target)
            {
                return(new ExprAssignment(ctx, target, expr));
            }
            else
            {
                return(e);
            }
        }
コード例 #8
0
 protected override ICode VisitConv(ExprConv e)
 {
     throw new InvalidOperationException("This should never occur");
 }
コード例 #9
0
        protected override ICode VisitBinary(ExprBinary e)
        {
            var ctx = e.Ctx;

            // Special cases for == and != needed as an empty string is false, not true
            if (e.Op == BinaryOp.Equal)
            {
                if (e.Left.IsLiteralNull())
                {
                    if (e.Right.IsVar() && e.Right.Type.IsValueType && !e.Right.Type.IsNullable())
                    {
                        return(ctx.Literal(false)); // Non-nullable Value-type can never be null
                    }
                    else
                    {
                        return(new ExprJsExplicit(ctx, "(e == null)", ctx.Boolean, e.Right.Named("e")));
                    }
                }
                if (e.Right.IsLiteralNull())
                {
                    if (e.Left.IsVar() && e.Left.Type.IsValueType && !e.Left.Type.IsNullable())
                    {
                        return(ctx.Literal(false)); // Non-nullable Value-type can never be null
                    }
                    else
                    {
                        return(new ExprJsExplicit(ctx, "(e == null)", ctx.Boolean, e.Left.Named("e")));
                    }
                }
            }
            if (e.Op == BinaryOp.NotEqual || e.Op == BinaryOp.GreaterThan_Un)
            {
                if (e.Left.IsLiteralNull())
                {
                    if (e.Right.IsVar() && e.Right.Type.IsValueType && !e.Right.Type.IsNullable())
                    {
                        return(ctx.Literal(true)); // Non-nullable Value-type can never be null
                    }
                    else
                    {
                        return(new ExprJsExplicit(ctx, "(e != null)", ctx.Boolean, e.Right.Named("e")));
                    }
                }
                if (e.Right.IsLiteralNull())
                {
                    if (e.Left.IsVar() && e.Left.Type.IsValueType && !e.Left.Type.IsNullable())
                    {
                        return(ctx.Literal(true)); // Non-nullable Value-type can never be null
                    }
                    else
                    {
                        return(new ExprJsExplicit(ctx, "(e != null)", ctx.Boolean, e.Left.Named("e")));
                    }
                }
            }
            // Special case for eq and neq with unsigned integer types.
            // If either side of the eq/neq is unsigned, then ensure that both sides are unsigned
            if (e.Op == BinaryOp.Equal || e.Op == BinaryOp.NotEqual)
            {
                if (e.Left.Type.IsUnsignedInteger())
                {
                    if (e.Right.Type.IsSignedInteger())
                    {
                        return(new ExprBinary(ctx, e.Op, e.Type, e.Left, new ExprConv(ctx, e.Right, e.Left.Type, false)));
                    }
                }
                else if (e.Right.Type.IsUnsignedInteger())
                {
                    if (e.Left.Type.IsSignedInteger())
                    {
                        return(new ExprBinary(ctx, e.Op, e.Type, new ExprConv(ctx, e.Left, e.Right.Type, false), e.Right));
                    }
                }
            }
            // Special case for unsigned <, <=, >, >=
            // Force conversions to unsigned if either side is signed
            if (e.Op == BinaryOp.LessThan_Un || e.Op == BinaryOp.LessThanOrEqual_Un ||
                e.Op == BinaryOp.GreaterThan_Un || e.Op == BinaryOp.GreaterThanOrEqual_Un)
            {
                Expr newLeft = null, newRight = null;
                if (e.Left.Type.IsSignedInteger())
                {
                    newLeft = new ExprConv(ctx, e.Left, e.Left.Type.UnsignedEquivilent(ctx.TypeSystem), false);
                }
                if (e.Right.Type.IsSignedInteger())
                {
                    newRight = new ExprConv(ctx, e.Right, e.Right.Type.UnsignedEquivilent(ctx.TypeSystem), false);
                }
                if (newLeft != null || newRight != null)
                {
                    return(new ExprBinary(ctx, e.Op, e.Type, newLeft ?? e.Left, newRight ?? e.Right));
                }
            }
            return(base.VisitBinary(e));
        }
コード例 #10
0
 protected virtual Expr VisitConv (ExprConv e)
 {
     return this.VisitCollection (e, exprs => new ExprConv (e.MethodInfo, exprs.First (), e.ConvToType), e.ExprToConvert);
 }
コード例 #11
0
 protected override ICode VisitConv(ExprConv e)
 {
     this.code.AppendFormat("(conv:{0})", e.Type);
     this.Visit(e.Expr);
     return(e);
 }