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); }
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); }
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); }
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); }
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)); } }
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); } }
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); }
protected virtual void BooleanVisitOr(ExprBinary e) { this.Visit(e.Left); this.Visit(e.Right); }