예제 #1
0
 public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
 {
     WriteILRange(output, options);
     output.Write(OpCode);
     output.Write("." + BinaryNumericInstruction.GetOperatorName(Operator));
     if (CompoundAssignmentType == CompoundAssignmentType.EvaluatesToNewValue)
     {
         output.Write(".new");
     }
     else
     {
         output.Write(".old");
     }
     if (CheckForOverflow)
     {
         output.Write(".ovf");
     }
     if (Sign == Sign.Unsigned)
     {
         output.Write(".unsigned");
     }
     else if (Sign == Sign.Signed)
     {
         output.Write(".signed");
     }
     output.Write('(');
     Target.WriteTo(output, options);
     output.Write(", ");
     Value.WriteTo(output, options);
     output.Write(')');
 }
예제 #2
0
 public NumericCompoundAssign(BinaryNumericInstruction binary, ILInstruction target, ILInstruction value, IType type, CompoundAssignmentType compoundAssignmentType)
     : base(OpCode.NumericCompoundAssign, compoundAssignmentType, target, value)
 {
     Debug.Assert(IsBinaryCompatibleWithType(binary, type));
     this.CheckForOverflow     = binary.CheckForOverflow;
     this.Sign                 = binary.Sign;
     this.LeftInputType        = binary.LeftInputType;
     this.RightInputType       = binary.RightInputType;
     this.UnderlyingResultType = binary.UnderlyingResultType;
     this.Operator             = binary.Operator;
     this.IsLifted             = binary.IsLifted;
     this.type                 = type;
     this.AddILRange(binary);
     Debug.Assert(compoundAssignmentType == CompoundAssignmentType.EvaluatesToNewValue || (Operator == BinaryNumericOperator.Add || Operator == BinaryNumericOperator.Sub));
     Debug.Assert(IsValidCompoundAssignmentTarget(Target));
 }
예제 #3
0
        /// <summary>
        /// Gets whether the specific binary instruction is compatible with a compound operation on the specified type.
        /// </summary>
        internal static bool IsBinaryCompatibleWithType(BinaryNumericInstruction binary, IType type)
        {
            if (binary.IsLifted)
            {
                if (!NullableType.IsNullable(type))
                {
                    return(false);
                }
                type = NullableType.GetUnderlyingType(type);
            }
            if (type.Kind == TypeKind.Unknown)
            {
                return(false);                // avoid introducing a potentially-incorrect compound assignment
            }
            else if (type.Kind == TypeKind.Enum)
            {
                switch (binary.Operator)
                {
                case BinaryNumericOperator.Add:
                case BinaryNumericOperator.Sub:
                case BinaryNumericOperator.BitAnd:
                case BinaryNumericOperator.BitOr:
                case BinaryNumericOperator.BitXor:
                    break;                             // OK

                default:
                    return(false);                            // operator not supported on enum types
                }
            }
            else if (type.Kind == TypeKind.Pointer)
            {
                switch (binary.Operator)
                {
                case BinaryNumericOperator.Add:
                case BinaryNumericOperator.Sub:
                    // ensure that the byte offset is a multiple of the pointer size
                    return(PointerArithmeticOffset.Detect(
                               binary.Right,
                               ((PointerType)type).ElementType,
                               checkForOverflow: binary.CheckForOverflow
                               ) != null);

                default:
                    return(false);                            // operator not supported on pointer types
                }
            }
            if (binary.Sign != Sign.None)
            {
                if (type.IsCSharpSmallIntegerType())
                {
                    // C# will use numeric promotion to int, binary op must be signed
                    if (binary.Sign != Sign.Signed)
                    {
                        return(false);
                    }
                }
                else
                {
                    // C# will use sign from type
                    if (type.GetSign() != binary.Sign)
                    {
                        return(false);
                    }
                }
            }
            // Can't transform if the RHS value would be need to be truncated for the LHS type.
            if (Transforms.TransformAssignment.IsImplicitTruncation(binary.Right, type, null, binary.IsLifted))
            {
                return(false);
            }
            return(true);
        }