in src/Compilers/CSharp/Portable/Binder/Binder_Operators.cs [1621:1817]
private static object FoldNeverOverflowBinaryOperators(BinaryOperatorKind kind, ConstantValue valueLeft, ConstantValue valueRight)
{
Debug.Assert(valueLeft != null);
Debug.Assert(valueRight != null);
// Note that we *cannot* do folding on single-precision floats as doubles to preserve precision,
// as that would cause incorrect rounding that would be impossible to correct afterwards.
switch (kind)
{
case BinaryOperatorKind.ObjectEqual:
if (valueLeft.IsNull) return valueRight.IsNull;
if (valueRight.IsNull) return false;
break;
case BinaryOperatorKind.ObjectNotEqual:
if (valueLeft.IsNull) return !valueRight.IsNull;
if (valueRight.IsNull) return true;
break;
case BinaryOperatorKind.DoubleAddition:
return valueLeft.DoubleValue + valueRight.DoubleValue;
case BinaryOperatorKind.FloatAddition:
return valueLeft.SingleValue + valueRight.SingleValue;
case BinaryOperatorKind.DoubleSubtraction:
return valueLeft.DoubleValue - valueRight.DoubleValue;
case BinaryOperatorKind.FloatSubtraction:
return valueLeft.SingleValue - valueRight.SingleValue;
case BinaryOperatorKind.DoubleMultiplication:
return valueLeft.DoubleValue * valueRight.DoubleValue;
case BinaryOperatorKind.FloatMultiplication:
return valueLeft.SingleValue * valueRight.SingleValue;
case BinaryOperatorKind.DoubleDivision:
return valueLeft.DoubleValue / valueRight.DoubleValue;
case BinaryOperatorKind.FloatDivision:
return valueLeft.SingleValue / valueRight.SingleValue;
case BinaryOperatorKind.DoubleRemainder:
return valueLeft.DoubleValue % valueRight.DoubleValue;
case BinaryOperatorKind.FloatRemainder:
return valueLeft.SingleValue % valueRight.SingleValue;
case BinaryOperatorKind.IntLeftShift:
return valueLeft.Int32Value << valueRight.Int32Value;
case BinaryOperatorKind.LongLeftShift:
return valueLeft.Int64Value << valueRight.Int32Value;
case BinaryOperatorKind.UIntLeftShift:
return valueLeft.UInt32Value << valueRight.Int32Value;
case BinaryOperatorKind.ULongLeftShift:
return valueLeft.UInt64Value << valueRight.Int32Value;
case BinaryOperatorKind.IntRightShift:
return valueLeft.Int32Value >> valueRight.Int32Value;
case BinaryOperatorKind.LongRightShift:
return valueLeft.Int64Value >> valueRight.Int32Value;
case BinaryOperatorKind.UIntRightShift:
return valueLeft.UInt32Value >> valueRight.Int32Value;
case BinaryOperatorKind.ULongRightShift:
return valueLeft.UInt64Value >> valueRight.Int32Value;
case BinaryOperatorKind.BoolAnd:
return valueLeft.BooleanValue & valueRight.BooleanValue;
case BinaryOperatorKind.IntAnd:
return valueLeft.Int32Value & valueRight.Int32Value;
case BinaryOperatorKind.LongAnd:
return valueLeft.Int64Value & valueRight.Int64Value;
case BinaryOperatorKind.UIntAnd:
return valueLeft.UInt32Value & valueRight.UInt32Value;
case BinaryOperatorKind.ULongAnd:
return valueLeft.UInt64Value & valueRight.UInt64Value;
case BinaryOperatorKind.BoolOr:
return valueLeft.BooleanValue | valueRight.BooleanValue;
case BinaryOperatorKind.IntOr:
return valueLeft.Int32Value | valueRight.Int32Value;
case BinaryOperatorKind.LongOr:
return valueLeft.Int64Value | valueRight.Int64Value;
case BinaryOperatorKind.UIntOr:
return valueLeft.UInt32Value | valueRight.UInt32Value;
case BinaryOperatorKind.ULongOr:
return valueLeft.UInt64Value | valueRight.UInt64Value;
case BinaryOperatorKind.BoolXor:
return valueLeft.BooleanValue ^ valueRight.BooleanValue;
case BinaryOperatorKind.IntXor:
return valueLeft.Int32Value ^ valueRight.Int32Value;
case BinaryOperatorKind.LongXor:
return valueLeft.Int64Value ^ valueRight.Int64Value;
case BinaryOperatorKind.UIntXor:
return valueLeft.UInt32Value ^ valueRight.UInt32Value;
case BinaryOperatorKind.ULongXor:
return valueLeft.UInt64Value ^ valueRight.UInt64Value;
case BinaryOperatorKind.LogicalBoolAnd:
return valueLeft.BooleanValue && valueRight.BooleanValue;
case BinaryOperatorKind.LogicalBoolOr:
return valueLeft.BooleanValue || valueRight.BooleanValue;
case BinaryOperatorKind.BoolEqual:
return valueLeft.BooleanValue == valueRight.BooleanValue;
case BinaryOperatorKind.StringEqual:
return valueLeft.StringValue == valueRight.StringValue;
case BinaryOperatorKind.DecimalEqual:
return valueLeft.DecimalValue == valueRight.DecimalValue;
case BinaryOperatorKind.FloatEqual:
return valueLeft.SingleValue == valueRight.SingleValue;
case BinaryOperatorKind.DoubleEqual:
return valueLeft.DoubleValue == valueRight.DoubleValue;
case BinaryOperatorKind.IntEqual:
return valueLeft.Int32Value == valueRight.Int32Value;
case BinaryOperatorKind.LongEqual:
return valueLeft.Int64Value == valueRight.Int64Value;
case BinaryOperatorKind.UIntEqual:
return valueLeft.UInt32Value == valueRight.UInt32Value;
case BinaryOperatorKind.ULongEqual:
return valueLeft.UInt64Value == valueRight.UInt64Value;
case BinaryOperatorKind.BoolNotEqual:
return valueLeft.BooleanValue != valueRight.BooleanValue;
case BinaryOperatorKind.StringNotEqual:
return valueLeft.StringValue != valueRight.StringValue;
case BinaryOperatorKind.DecimalNotEqual:
return valueLeft.DecimalValue != valueRight.DecimalValue;
case BinaryOperatorKind.FloatNotEqual:
return valueLeft.SingleValue != valueRight.SingleValue;
case BinaryOperatorKind.DoubleNotEqual:
return valueLeft.DoubleValue != valueRight.DoubleValue;
case BinaryOperatorKind.IntNotEqual:
return valueLeft.Int32Value != valueRight.Int32Value;
case BinaryOperatorKind.LongNotEqual:
return valueLeft.Int64Value != valueRight.Int64Value;
case BinaryOperatorKind.UIntNotEqual:
return valueLeft.UInt32Value != valueRight.UInt32Value;
case BinaryOperatorKind.ULongNotEqual:
return valueLeft.UInt64Value != valueRight.UInt64Value;
case BinaryOperatorKind.DecimalLessThan:
return valueLeft.DecimalValue < valueRight.DecimalValue;
case BinaryOperatorKind.FloatLessThan:
return valueLeft.SingleValue < valueRight.SingleValue;
case BinaryOperatorKind.DoubleLessThan:
return valueLeft.DoubleValue < valueRight.DoubleValue;
case BinaryOperatorKind.IntLessThan:
return valueLeft.Int32Value < valueRight.Int32Value;
case BinaryOperatorKind.LongLessThan:
return valueLeft.Int64Value < valueRight.Int64Value;
case BinaryOperatorKind.UIntLessThan:
return valueLeft.UInt32Value < valueRight.UInt32Value;
case BinaryOperatorKind.ULongLessThan:
return valueLeft.UInt64Value < valueRight.UInt64Value;
case BinaryOperatorKind.DecimalGreaterThan:
return valueLeft.DecimalValue > valueRight.DecimalValue;
case BinaryOperatorKind.FloatGreaterThan:
return valueLeft.SingleValue > valueRight.SingleValue;
case BinaryOperatorKind.DoubleGreaterThan:
return valueLeft.DoubleValue > valueRight.DoubleValue;
case BinaryOperatorKind.IntGreaterThan:
return valueLeft.Int32Value > valueRight.Int32Value;
case BinaryOperatorKind.LongGreaterThan:
return valueLeft.Int64Value > valueRight.Int64Value;
case BinaryOperatorKind.UIntGreaterThan:
return valueLeft.UInt32Value > valueRight.UInt32Value;
case BinaryOperatorKind.ULongGreaterThan:
return valueLeft.UInt64Value > valueRight.UInt64Value;
case BinaryOperatorKind.DecimalLessThanOrEqual:
return valueLeft.DecimalValue <= valueRight.DecimalValue;
case BinaryOperatorKind.FloatLessThanOrEqual:
return valueLeft.SingleValue <= valueRight.SingleValue;
case BinaryOperatorKind.DoubleLessThanOrEqual:
return valueLeft.DoubleValue <= valueRight.DoubleValue;
case BinaryOperatorKind.IntLessThanOrEqual:
return valueLeft.Int32Value <= valueRight.Int32Value;
case BinaryOperatorKind.LongLessThanOrEqual:
return valueLeft.Int64Value <= valueRight.Int64Value;
case BinaryOperatorKind.UIntLessThanOrEqual:
return valueLeft.UInt32Value <= valueRight.UInt32Value;
case BinaryOperatorKind.ULongLessThanOrEqual:
return valueLeft.UInt64Value <= valueRight.UInt64Value;
case BinaryOperatorKind.DecimalGreaterThanOrEqual:
return valueLeft.DecimalValue >= valueRight.DecimalValue;
case BinaryOperatorKind.FloatGreaterThanOrEqual:
return valueLeft.SingleValue >= valueRight.SingleValue;
case BinaryOperatorKind.DoubleGreaterThanOrEqual:
return valueLeft.DoubleValue >= valueRight.DoubleValue;
case BinaryOperatorKind.IntGreaterThanOrEqual:
return valueLeft.Int32Value >= valueRight.Int32Value;
case BinaryOperatorKind.LongGreaterThanOrEqual:
return valueLeft.Int64Value >= valueRight.Int64Value;
case BinaryOperatorKind.UIntGreaterThanOrEqual:
return valueLeft.UInt32Value >= valueRight.UInt32Value;
case BinaryOperatorKind.ULongGreaterThanOrEqual:
return valueLeft.UInt64Value >= valueRight.UInt64Value;
case BinaryOperatorKind.UIntDivision:
return valueLeft.UInt32Value / valueRight.UInt32Value;
case BinaryOperatorKind.ULongDivision:
return valueLeft.UInt64Value / valueRight.UInt64Value;
// MinValue % -1 always overflows at runtime but never at compile time
case BinaryOperatorKind.IntRemainder:
return (valueRight.Int32Value != -1) ? valueLeft.Int32Value % valueRight.Int32Value : 0;
case BinaryOperatorKind.LongRemainder:
return (valueRight.Int64Value != -1) ? valueLeft.Int64Value % valueRight.Int64Value : 0;
case BinaryOperatorKind.UIntRemainder:
return valueLeft.UInt32Value % valueRight.UInt32Value;
case BinaryOperatorKind.ULongRemainder:
return valueLeft.UInt64Value % valueRight.UInt64Value;
}
return null;
}