Пример #1
0
 public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
 {
     ILRange.WriteTo(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(')');
 }
        /// <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.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
                }
            }
            if (binary.Sign != Sign.None)
            {
                if (type.GetSign() != binary.Sign)
                {
                    return(false);
                }
            }
            return(true);
        }
 public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
 {
     WriteILRange(output, options);
     output.Write(OpCode);
     output.Write("." + BinaryNumericInstruction.GetOperatorName(Operator));
     if (CheckForOverflow)
     {
         output.Write(".ovf");
     }
     if (Sign == Sign.Unsigned)
     {
         output.Write(".unsigned");
     }
     else if (Sign == Sign.Signed)
     {
         output.Write(".signed");
     }
     output.Write('.');
     output.Write(UnderlyingResultType.ToString().ToLowerInvariant());
     if (IsLifted)
     {
         output.Write(".lifted");
     }
     base.WriteSuffix(output);
     output.Write('(');
     Target.WriteTo(output, options);
     output.Write(", ");
     Value.WriteTo(output, options);
     output.Write(')');
 }
Пример #4
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.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,
                               checkForOverflow: binary.CheckForOverflow
                               ) != null);

                default:
                    return(false);                            // operator not supported on pointer types
                }
            }
            if (binary.Sign != Sign.None)
            {
                if (type.GetSign() != binary.Sign)
                {
                    return(false);
                }
            }
            return(true);
        }
Пример #5
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.ILRange              = binary.ILRange;
     Debug.Assert(compoundAssignmentType == CompoundAssignmentType.EvaluatesToNewValue || (Operator == BinaryNumericOperator.Add || Operator == BinaryNumericOperator.Sub));
     Debug.Assert(IsValidCompoundAssignmentTarget(Target));
 }
 public NumericCompoundAssign(BinaryNumericInstruction binary, ILInstruction target,
                              CompoundTargetKind targetKind, ILInstruction value, IType type, CompoundEvalMode evalMode)
     : base(OpCode.NumericCompoundAssign, evalMode, target, targetKind, 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(evalMode == CompoundEvalMode.EvaluatesToNewValue || (Operator == BinaryNumericOperator.Add || Operator == BinaryNumericOperator.Sub));
     Debug.Assert(this.ResultType == (IsLifted ? StackType.O : UnderlyingResultType));
 }
 /// <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 (binary.Sign != Sign.None)
     {
         if (type.GetSign() != binary.Sign)
         {
             return(false);
         }
     }
     return(true);
 }
Пример #8
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,
                               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, binary.IsLifted))
            {
                return(false);
            }
            return(true);
        }
Пример #9
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, DecompilerSettings settings)
        {
            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
                }
            }
            else if (type.IsKnownType(KnownTypeCode.IntPtr) || type.IsKnownType(KnownTypeCode.UIntPtr))
            {
                // "target.intptr *= 2;" is compiler error, but
                // "target.intptr *= (nint)2;" works
                if (settings != null && !settings.NativeIntegers)
                {
                    // But if native integers are not available, we cannot use compound assignment.
                    return(false);
                }
                // The trick with casting the RHS to n(u)int doesn't work for shifts:
                switch (binary.Operator)
                {
                case BinaryNumericOperator.ShiftLeft:
                case BinaryNumericOperator.ShiftRight:
                    return(false);
                }
            }
            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);
        }