public static bool TryTransformEnumHasFlagToIntOps(this CallMethod s, Log log, ref Expression result) { // Enum.HasFlag() -> (((int)a & (int)b) == (int)b) if (s.Method.DeclaringType is EnumType && s.Method.UnoName == "HasFlag" && s.Arguments.Length == 1) { var bt = s.Method.DeclaringType.Base; foreach (var o in bt.Operators) { if (o.UnoName == "op_BitwiseAnd") { var a = new CastOp(s.Source, bt, s.Object.ActualValue); var b = new CastOp(s.Source, bt, s.Arguments[0]); foreach (var p in bt.Operators) { if (p.UnoName == "op_Equality") { result = new CallBinOp(s.Source, p, new CallBinOp(s.Source, o, a, b), b); return(true); } } log.Error(s.Source, ErrorCode.I0069, "'" + bt + ".op_Equality(" + bt + "," + bt + ")' was not found"); return(false); } } log.Error(s.Source, ErrorCode.I0069, "'" + bt + ".op_BitwiseAnd(" + bt + "," + bt + ")' was not found"); } return(false); }
public static bool TryTransformEnumBinOpToIntBinOp(this CallBinOp s, Log log, ref Expression result) { // Enum.BinOps -> Int.BinOps if (s.Operator.DeclaringType is EnumType) { var bt = s.Operator.DeclaringType.Base; foreach (var o in bt.Operators) { if (o.UnoName == s.Operator.UnoName) { result = new CallBinOp(s.Source, o, new CastOp(s.Source, bt, s.Left), new CastOp(s.Source, bt, s.Right)); if (s.ReturnType == s.Operator.DeclaringType) { result = new CastOp(s.Source, s.Operator.DeclaringType, result); } return(true); } } log.Error(s.Source, ErrorCode.I0072, "'" + bt + "." + s.Operator.UnoName + "(" + bt + "," + bt + ")' was not found"); } return(false); }
public virtual void WriteCallBinOp(CallBinOp s, ExpressionUsage u) { Begin(u); WriteExpression(s.Left, ExpressionUsage.Operand); Write(Space + s.Operator.Symbol + Space); WriteExpression(s.Right, ExpressionUsage.Operand); End(u); }
public override void WriteCallBinOp(CallBinOp s, ExpressionUsage u) { // Integer division if (s.Left.ReturnType.IsIntegralType && s.Operator.Type == OperatorType.Division) { Begin(u); base.WriteCallBinOp(s, ExpressionUsage.Operand); Write(" | 0"); End(u); return; } base.WriteCallBinOp(s, u); }
public static bool TryTransformDelegateBinOp(this CallBinOp s, ILFactory ilf, ref Expression result) { DataType dt = s.Operator.DeclaringType; if (dt is DelegateType) { if (s.Operator.Symbol == "+") { result = new CastOp(s.Source, dt, ilf.CallMethod(s.Source, dt, "Combine", s.Left, s.Right)); return(true); } if (s.Operator.Symbol == "-") { result = new CastOp(s.Source, dt, ilf.CallMethod(s.Source, dt, "Remove", s.Left, s.Right)); return(true); } } return(false); }
public void CompileBinOp(CallBinOp s, bool pop, Condition cond) { Opcodes builtInOp = Opcodes.Null; bool isIntrinsic = false; switch (s.Operator.DeclaringType.BuiltinType) { case BuiltinType.Bool: case BuiltinType.Char: case BuiltinType.Byte: case BuiltinType.SByte: case BuiltinType.UShort: case BuiltinType.Short: case BuiltinType.ULong: case BuiltinType.Long: case BuiltinType.UInt: case BuiltinType.Int: case BuiltinType.Float: case BuiltinType.Double: case BuiltinType.Object: { isIntrinsic = true; switch (s.Operator.Type) { case OperatorType.Addition: builtInOp = Opcodes.Add; break; case OperatorType.Subtraction: builtInOp = Opcodes.Sub; break; case OperatorType.Multiply: builtInOp = Opcodes.Mul; break; case OperatorType.Division: if (s.Left.ReturnType.IsUnsignedType) { builtInOp = Opcodes.Div_Un; } else { builtInOp = Opcodes.Div; } break; case OperatorType.Modulus: if (s.Left.ReturnType.IsUnsignedType) { builtInOp = Opcodes.Rem_Un; } else { builtInOp = Opcodes.Rem; } break; case OperatorType.BitwiseAnd: builtInOp = Opcodes.And; break; case OperatorType.BitwiseOr: builtInOp = Opcodes.Or; break; case OperatorType.ExclusiveOr: builtInOp = Opcodes.Xor; break; case OperatorType.LeftShift: builtInOp = Opcodes.Shl; break; case OperatorType.RightShift: if (s.Left.ReturnType.IsUnsignedType) { builtInOp = Opcodes.Shr_Un; } else { builtInOp = Opcodes.Shr; } break; } } break; } if (builtInOp != Opcodes.Null) { CompileExpression(s.Left); CompileExpression(s.Right); Emit(builtInOp); return; } if (isIntrinsic) { switch (s.Operator.Type) { case OperatorType.LessThan: builtInOp = Opcodes.Lt; break; case OperatorType.LessThanOrEqual: builtInOp = Opcodes.Lte; break; case OperatorType.GreaterThan: builtInOp = Opcodes.Gt; break; case OperatorType.GreaterThanOrEqual: builtInOp = Opcodes.Gte; break; case OperatorType.Equality: builtInOp = Opcodes.Eq; break; case OperatorType.Inequality: builtInOp = Opcodes.Neq; break; } if (s.Left.ReturnType.IsUnsignedType) { switch (s.Operator.Type) { case OperatorType.LessThan: builtInOp = Opcodes.Lt_Unsigned; break; case OperatorType.LessThanOrEqual: builtInOp = Opcodes.Lte_Unsigned; break; case OperatorType.GreaterThan: builtInOp = Opcodes.Gt_Unsigned; break; case OperatorType.GreaterThanOrEqual: builtInOp = Opcodes.Gte_Unsigned; break; } } if (builtInOp != Opcodes.Null) { CompileExpression(s.Left); CompileExpression(s.Right); if (cond != null && !cond.Handled) { if (cond.Sequence == ConditionSequence.TrueFollows) { builtInOp = InvertOp(builtInOp); builtInOp = ToBranchOp(builtInOp); Branch(builtInOp, cond.FalseLabel ?? (cond.FalseLabel = NewLabel())); } else if (cond.Sequence == ConditionSequence.FalseFollows) { builtInOp = ToBranchOp(builtInOp); Branch(builtInOp, cond.TrueLabel ?? (cond.TrueLabel = NewLabel())); } else { builtInOp = ToBranchOp(builtInOp); Branch(builtInOp, cond.TrueLabel ?? (cond.TrueLabel = NewLabel())); Branch(Opcodes.Br, (cond.FalseLabel ?? (cond.FalseLabel = NewLabel()))); } cond.Handled = true; return; } Emit(builtInOp); return; } } CompileExpression(s.Left); CompileExpression(s.Right); Call(null, s.Operator); if (pop && !s.Operator.ReturnType.IsVoid) { Pop(); } }