Example #1
0
        protected override ICode VisitBinary(ExprBinary e)
        {
            var forceInt = e.Op == BinaryOp.Div && e.Type.IsInteger();

            if (forceInt)
            {
                if (e.Type.IsUInt32())
                {
                    this.js.Append("(");
                }
                else
                {
                    this.js.Append("(~~");
                }
            }
            this.js.Append("(");
            this.Visit(e.Left);
            this.js.AppendFormat(" {0} ", binaryOps[e.Op]);
            this.Visit(e.Right);
            this.js.Append(")");
            if (forceInt)
            {
                if (e.Type.IsUInt32())
                {
                    this.js.Append(">>>0");
                }
                else
                {
                    this.js.Append(")");
                }
            }
            return(e);
        }
Example #2
0
        protected override ICode VisitUnary(ExprUnary e)
        {
            if (e.Expr.Type.IsInt64() || e.Expr.Type.IsUInt64())
            {
                var      ctx    = e.Ctx;
                var      signed = e.Expr.Type.IsInt64();
                Delegate d;
                switch (e.Op)
                {
                case UnaryOp.Negate:
                    var zero    = ctx.Literal(0L, ctx.Int64);
                    var subCall = new ExprBinary(ctx, BinaryOp.Sub, ctx.Int64, zero, e.Expr);
                    return(subCall);

                case UnaryOp.BitwiseNot:
                    d = signed ? (Delegate)(Func <Int64, Int64>)_Int64.BitwiseNot : (Func <UInt64, UInt64>)_UInt64.BitwiseNot;
                    break;

                default:
                    throw new NotImplementedException("Cannot handle: " + e.Op);
                }
                var m    = ctx.Module.Import(d.Method);
                var expr = (Expr)this.Visit(e.Expr);
                var call = new ExprCall(ctx, m, null, expr);
                return(call);
            }
            return(base.VisitUnary(e));
        }
 protected override ICode VisitBinary(ExprBinary e)
 {
     switch (e.Op)
     {
     case BinaryOp.And:
     case BinaryOp.Or:
         var leftPerms  = VisitorCreatePerms.V(e.Left);
         var rightPerms = VisitorCreatePerms.V(e.Right);
         foreach (var l in leftPerms)
         {
             foreach (var r in rightPerms)
             {
                 foreach (var t in new[] { Tuple.Create(l, r), Tuple.Create(r, l) })
                 {
                     Expr perm;
                     if (t.Item1 == e.Left && t.Item2 == e.Right)
                     {
                         perm = e;
                     }
                     else
                     {
                         perm = new ExprBinary(e.Ctx, e.Op, e.Type, t.Item1, t.Item2);
                     }
                     this.allPerms.Add((Expr)VisitorReplace.V(this.root, e, perm));
                 }
             }
         }
         break;
     }
     return(e);
 }
        public static Expr GetResourceFromDefault(ICall call)
        {
            var ctx  = call.Ctx;
            var pre  = new ExprLiteral(ctx, "GetResourceFromDefault_", ctx.String);
            var expr = new ExprBinary(ctx, BinaryOp.Add, ctx.String, pre, call.Args.First());

            return(expr);
        }
Example #5
0
            protected override void BooleanVisitOr(ExprBinary e)
            {
                base.BooleanVisitOr(e);
                var right = this.stack.Pop();
                var left  = this.stack.Pop();

                this.stack.Push(left || right);
            }
 protected override ICode VisitBinary(ExprBinary e)
 {
     this.code.Append("(");
     this.Visit(e.Left);
     this.code.AppendFormat(" {0} ", binaryOps[e.Op]);
     this.Visit(e.Right);
     this.code.Append(")");
     return(e);
 }
Example #7
0
        public static Expr op_Equality(ICall call)
        {
            var ctx  = call.Ctx;
            var a    = call.Args.ElementAt(0);
            var b    = call.Args.ElementAt(1);
            var expr = new ExprBinary(ctx, BinaryOp.Equal, ctx.Boolean, a, b);

            return(expr);
        }
Example #8
0
 protected override ICode VisitBinary(ExprBinary e)
 {
     if (e.Op == BinaryOp.Equal || e.Op == BinaryOp.NotEqual)
     {
         if (e.Right.Type.IsBoolean() && !e.Left.Type.IsBoolean())
         {
             return(new ExprBinary(e.Ctx, e.Op, e.Type, this.ConvertToBoolean(e.Left), e.Right));
         }
         else if (e.Left.Type.IsBoolean() && !e.Right.Type.IsBoolean())
         {
             return(new ExprBinary(e.Ctx, e.Op, e.Type, e.Left, this.ConvertToBoolean(e.Right)));
         }
     }
     return(base.VisitBinary(e));
 }
        protected virtual ICode VisitBinary(ExprBinary e)
        {
            this.ThrowOnNoOverride();
            var left  = this.Visit(e.Left);
            var right = this.Visit(e.Right);

            if (left == e.Left && right == e.Right)
            {
                return(e);
            }
            else
            {
                return(new ExprBinary(e.Ctx, e.Op, e.Type, (Expr)left, (Expr)right));
            }
        }
Example #10
0
        private Stmt BrFalse(Instruction inst)
        {
            var expr = this.stack.Pop();

            if (expr.Type.IsString() || expr.Type.IsObject())
            {
                // TODO: Move this JS-specific processing into a later, JS-specific stage
                // Special processing of string null-check required, as empty string == false in Javascript
                var check = new ExprBinary(this.ctx, BinaryOp.Equal, this.ctx.Boolean, expr, new ExprLiteral(this.ctx, null, this.ctx.String));
                return(this.SsaInstResultAssignment(inst, check));
            }
            else
            {
                return(this.SsaInstResultAssignment(inst, new ExprUnary(this.ctx, UnaryOp.Not, this.ctx.Boolean, expr)));
            }
        }
        protected override ICode VisitBinary(ExprBinary e)
        {
            var op    = e.Op;
            var left  = (Expr)this.Visit(e.Left);
            var right = (Expr)this.Visit(e.Right);
            var t     = Tuple.Create(left, right);

            if (op == BinaryOp.Equal && TypeCombiner.Combine(e.Ctx, left, right).IsBoolean())
            {
                if (left.IsLiteralBoolean(true))
                {
                    return(right);
                }
                if (right.IsLiteralBoolean(true))
                {
                    return(left);
                }
                if (left.IsLiteralBoolean(false))
                {
                    return(e.Ctx.ExprGen.NotAutoSimplify(right));
                }
                if (right.IsLiteralBoolean(false))
                {
                    return(e.Ctx.ExprGen.NotAutoSimplify(left));
                }
            }

            if (left != e.Left || right != e.Right)
            {
                return(new ExprBinary(e.Ctx, op, e.Type, left, right));
            }
            else
            {
                return(e);
            }
        }
Example #12
0
        protected override ICode VisitBinary(ExprBinary e)
        {
            if (e.Left.Type.IsInt64() || e.Left.Type.IsUInt64())
            {
                var      ctx    = e.Ctx;
                var      signed = e.Left.Type.IsInt64();
                Delegate d;
                switch (e.Op)
                {
                case BinaryOp.Add:
                    d = signed ? (Delegate)(Func <Int64, Int64, Int64>)_Int64.Add : (Func <UInt64, UInt64, UInt64>)_UInt64.Add;
                    break;

                case BinaryOp.Sub:
                    d = signed ? (Delegate)(Func <Int64, Int64, Int64>)_Int64.Subtract : (Func <UInt64, UInt64, UInt64>)_UInt64.Subtract;
                    break;

                case BinaryOp.Mul:
                    d = signed ? (Delegate)(Func <Int64, Int64, Int64>)_Int64.Multiply : (Func <UInt64, UInt64, UInt64>)_UInt64.Multiply;
                    break;

                case BinaryOp.Div:
                    d = (Func <Int64, Int64, Int64>)_Int64.Divide;
                    break;

                case BinaryOp.Div_Un:
                    d = (Func <UInt64, UInt64, UInt64>)_UInt64.Divide;
                    break;

                case BinaryOp.Rem:
                    d = (Func <Int64, Int64, Int64>)_Int64.Remainder;
                    break;

                case BinaryOp.Rem_Un:
                    d = (Func <UInt64, UInt64, UInt64>)_UInt64.Remainder;
                    break;

                case BinaryOp.BitwiseAnd:
                    d = signed ? (Delegate)(Func <Int64, Int64, Int64>)_Int64.BitwiseAnd : (Func <UInt64, UInt64, UInt64>)_UInt64.BitwiseAnd;
                    break;

                case BinaryOp.BitwiseOr:
                    d = signed ? (Delegate)(Func <Int64, Int64, Int64>)_Int64.BitwiseOr : (Func <UInt64, UInt64, UInt64>)_UInt64.BitwiseOr;
                    break;

                case BinaryOp.BitwiseXor:
                    d = signed ? (Delegate)(Func <Int64, Int64, Int64>)_Int64.BitwiseXor : (Func <UInt64, UInt64, UInt64>)_UInt64.BitwiseXor;
                    break;

                case BinaryOp.Equal:
                    d = signed ? (Delegate)(Func <Int64, Int64, bool>)_Int64.Equals_ : (Func <UInt64, UInt64, bool>)_UInt64.Equals_;
                    break;

                case BinaryOp.NotEqual:
                    d = signed ? (Delegate)(Func <Int64, Int64, bool>)_Int64.NotEquals : (Func <UInt64, UInt64, bool>)_UInt64.NotEquals;
                    break;

                case BinaryOp.LessThan:
                    d = (Func <Int64, Int64, bool>)_Int64.LessThan;
                    break;

                case BinaryOp.LessThan_Un:
                    d = (Func <UInt64, UInt64, bool>)_UInt64.LessThan;
                    break;

                case BinaryOp.LessThanOrEqual:
                    d = (Func <Int64, Int64, bool>)_Int64.LessThanOrEqual;
                    break;

                case BinaryOp.LessThanOrEqual_Un:
                    d = (Func <UInt64, UInt64, bool>)_UInt64.LessThanOrEqual;
                    break;

                case BinaryOp.GreaterThan:
                    d = (Func <Int64, Int64, bool>)_Int64.GreaterThan;
                    break;

                case BinaryOp.GreaterThan_Un:
                    d = (Func <UInt64, UInt64, bool>)_UInt64.GreaterThan;
                    break;

                case BinaryOp.GreaterThanOrEqual:
                    d = (Func <Int64, Int64, bool>)_Int64.GreaterThanOrEqual;
                    break;

                case BinaryOp.GreaterThanOrEqual_Un:
                    d = (Func <UInt64, UInt64, bool>)_UInt64.GreaterThanOrEqual;
                    break;

                default:
                    throw new NotImplementedException("Cannot handle: " + e.Op);
                }
                var m     = ctx.Module.Import(d.Method);
                var left  = (Expr)this.Visit(e.Left);
                var right = (Expr)this.Visit(e.Right);
                var call  = new ExprCall(ctx, m, null, left, right);
                return(call);
            }
            return(base.VisitBinary(e));
        }
        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));
        }
            public Stmt GetImpl(Ctx ctx)
            {
                var  mGenInst = (GenericInstanceMethod)ctx.MRef;
                var  tFrom    = mGenInst.GenericArguments[0];
                var  mtFrom   = tFrom.MetadataType;
                var  tTo      = mGenInst.GenericArguments[1];
                var  mtTo     = tTo.MetadataType;
                var  e        = ctx.MethodParameter(0, "e");
                Stmt stmt;

                if ((mtFrom == MDT.SByte || mtFrom == MDT.Int16 || mtFrom == MDT.Int32) && (mtTo == MDT.Int64 || mtTo == MDT.UInt64))
                {
                    var u32max   = ctx.Literal(0xffffffff, ctx.UInt32, "u32max");
                    var u32limit = ctx.Literal(0x100000000, ctx._UInt64, "u32limit");
                    var js       = "return e < 0 ? [u32max, u32limit + e] : [0, e];";
                    stmt = new StmtJsExplicit(ctx, js, e, u32max, u32limit);
                }
                else if (mtFrom == MDT.Int64 && (mtTo == MDT.Single || mtTo == MDT.Double))
                {
                    var v              = ctx.Local(ctx.Double, "v");
                    var u32limit       = ctx.Literal(0x100000000, ctx._UInt64, "u32limit");
                    var negCall        = new ExprBinary(ctx, BinaryOp.Sub, ctx.Int64, ctx.Literal((Int64)0, ctx.Int64), e.Expr).Named("negCall");
                    var i32Minu32      = ctx.Literal(unchecked ((UInt32)Int32.MinValue), ctx.UInt32, "i32Minu32");
                    var doubleMinInt64 = ctx.Literal((double)Int64.MinValue, ctx.Double, "doubleMinInt64");
                    var isNeg          = ctx.Local(ctx.Boolean, "isNeg");
                    var js             = @"
if (e[0] === i32Minu32 && !e[1]) return doubleMinInt64;
isNeg = e[0] >>> 31;
if (isNeg) e = negCall;
v = e[0] * u32limit + e[1];
return isNeg ? -v : v;
";
                    stmt = new StmtJsExplicit(ctx, js, e, v, u32limit, i32Minu32, negCall, doubleMinInt64, isNeg);
                }
                else if (mtFrom == MDT.UInt64 && (mtTo == MDT.Single || mtTo == MDT.Double))
                {
                    var u32limit = ctx.Literal(0x100000000, ctx._UInt64, "u32limit");
                    var js       = "return e[0] * u32limit + e[1];";
                    stmt = new StmtJsExplicit(ctx, js, e, u32limit);
                }
                else if ((mtFrom == MDT.Single || mtFrom == MDT.Double) && (mtTo == MDT.Int64))
                {
                    var isNeg = ctx.Local(ctx.Boolean, "isNeg");
                    var r = ctx.Local(ctx.Int64, "r");
                    var u32limit = ctx.Literal(0x100000000, ctx._UInt64, "u32limit");
                    var negCall = new ExprBinary(ctx, BinaryOp.Sub, ctx.Int64, ctx.Literal((Int64)0, ctx.Int64), r.Expr).Named("negCall"); var js = @"
isNeg = e < 0;
if (isNeg) e = -e;
r = [(e / u32limit) >>> 0, e >>> 0];
return isNeg ? negCall : r;
";
                    stmt = new StmtJsExplicit(ctx, js, e, isNeg, u32limit, negCall, r);
                }
                else if ((mtFrom == MDT.Single || mtFrom == MDT.Double) && (mtTo == MDT.UInt64))
                {
                    var u32limit = ctx.Literal(0x100000000, ctx._UInt64, "u32limit");
                    var js       = "return [(e / u32limit) >>> 0, e >>> 0];";
                    stmt = new StmtJsExplicit(ctx, js, e, u32limit);
                }
                else
                {
                    throw new NotImplementedException("Conversion not implemented (should never occur)");
                }
                return(stmt);
            }
Example #15
0
 protected virtual void BooleanVisitOr(ExprBinary e)
 {
     this.Visit(e.Left);
     this.Visit(e.Right);
 }