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)); }
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); } }
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); } }
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); }
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); } }
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); }
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); } }
protected override ICode VisitConv(ExprConv e) { throw new InvalidOperationException("This should never occur"); }
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)); }
protected virtual Expr VisitConv (ExprConv e) { return this.VisitCollection (e, exprs => new ExprConv (e.MethodInfo, exprs.First (), e.ConvToType), e.ExprToConvert); }
protected override ICode VisitConv(ExprConv e) { this.code.AppendFormat("(conv:{0})", e.Type); this.Visit(e.Expr); return(e); }