diff --git a/ICSharpCode.Decompiler/IL/ILTypeExtensions.cs b/ICSharpCode.Decompiler/IL/ILTypeExtensions.cs index ca8da349a..1c0a436cb 100644 --- a/ICSharpCode.Decompiler/IL/ILTypeExtensions.cs +++ b/ICSharpCode.Decompiler/IL/ILTypeExtensions.cs @@ -17,6 +17,7 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. +using System.Diagnostics; using System.Linq; using ICSharpCode.Decompiler.TypeSystem; @@ -215,17 +216,15 @@ namespace ICSharpCode.Decompiler.IL /// If not returning UnknownType, must return a type that can store /// the result of the instruction without loss of information. /// - public static IType InferType(this ILInstruction inst, ICompilation? compilation) + public static IType InferType(this ILInstruction inst, ICompilation compilation) { + Debug.Assert(compilation != null); switch (inst) { case NewObj newObj: return newObj.Method.DeclaringType ?? SpecialType.UnknownType; case NewArr newArr: - if (compilation != null) - return new ArrayType(compilation, newArr.Type, newArr.Indices.Count); - else - return SpecialType.UnknownType; + return new ArrayType(compilation, newArr.Type, newArr.Indices.Count); case Call call: return call.Method.ReturnType; case CallVirt callVirt: @@ -258,8 +257,6 @@ namespace ICSharpCode.Decompiler.IL } return new ByReferenceType(ldelema.Type); case Comp comp: - if (compilation == null) - return SpecialType.UnknownType; switch (comp.LiftingKind) { case ComparisonLiftingKind.None: diff --git a/ICSharpCode.Decompiler/IL/Instructions/CompoundAssignmentInstruction.cs b/ICSharpCode.Decompiler/IL/Instructions/CompoundAssignmentInstruction.cs index b456173ed..634ecf832 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/CompoundAssignmentInstruction.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/CompoundAssignmentInstruction.cs @@ -153,10 +153,11 @@ namespace ICSharpCode.Decompiler.IL public bool IsLifted { get; } public NumericCompoundAssign(BinaryNumericInstruction binary, ILInstruction target, - CompoundTargetKind targetKind, ILInstruction value, IType type, CompoundEvalMode evalMode) + CompoundTargetKind targetKind, ILInstruction value, IType type, CompoundEvalMode evalMode, + Transforms.ILTransformContext context) : base(OpCode.NumericCompoundAssign, evalMode, target, targetKind, value) { - Debug.Assert(IsBinaryCompatibleWithType(binary, type, null)); + Debug.Assert(IsBinaryCompatibleWithType(binary, type, context)); this.CheckForOverflow = binary.CheckForOverflow; this.Sign = binary.Sign; this.LeftInputType = binary.LeftInputType; @@ -166,14 +167,14 @@ namespace ICSharpCode.Decompiler.IL this.IsLifted = binary.IsLifted; this.type = type; this.AddILRange(binary); - Debug.Assert(evalMode == CompoundEvalMode.EvaluatesToNewValue || (Operator == BinaryNumericOperator.Add || Operator == BinaryNumericOperator.Sub)); + Debug.Assert(evalMode == CompoundEvalMode.EvaluatesToNewValue || Operator == BinaryNumericOperator.Add || Operator == BinaryNumericOperator.Sub); Debug.Assert(this.ResultType == (IsLifted ? StackType.O : UnderlyingResultType)); } /// /// Gets whether the specific binary instruction is compatible with a compound operation on the specified type. /// - internal static bool IsBinaryCompatibleWithType(BinaryNumericInstruction binary, IType type, DecompilerSettings? settings) + internal static bool IsBinaryCompatibleWithType(BinaryNumericInstruction binary, IType type, Transforms.ILTransformContext context) { if (binary.IsLifted) { @@ -220,7 +221,7 @@ namespace ICSharpCode.Decompiler.IL // If the LHS is C# 9 IntPtr (but not nint or C# 11 IntPtr): // "target.intptr *= 2;" is compiler error, but // "target.intptr *= (nint)2;" works - if (settings != null && !settings.NativeIntegers) + if (!context.Settings.NativeIntegers) { // But if native integers are not available, we cannot use compound assignment. return false; @@ -235,7 +236,7 @@ namespace ICSharpCode.Decompiler.IL } if (binary.Sign != Sign.None) { - bool signMismatchAllowed = (binary.Sign == Sign.Unsigned && binary.Operator == BinaryNumericOperator.ShiftRight && (settings == null || settings.UnsignedRightShift)); + bool signMismatchAllowed = binary.Sign == Sign.Unsigned && binary.Operator == BinaryNumericOperator.ShiftRight && context.Settings.UnsignedRightShift; if (type.IsCSharpSmallIntegerType()) { // C# will use numeric promotion to int, binary op must be signed @@ -250,7 +251,7 @@ namespace ICSharpCode.Decompiler.IL } } // 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)) + if (Transforms.TransformAssignment.IsImplicitTruncation(binary.Right, type, context.TypeSystem, binary.IsLifted)) return false; return true; } diff --git a/ICSharpCode.Decompiler/IL/Transforms/TransformAssignment.cs b/ICSharpCode.Decompiler/IL/Transforms/TransformAssignment.cs index 9fb4a948b..bf22be536 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/TransformAssignment.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/TransformAssignment.cs @@ -25,6 +25,7 @@ using System.Linq; using System.Linq.Expressions; using ICSharpCode.Decompiler.CSharp; +using ICSharpCode.Decompiler.CSharp.Transforms; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.Util; @@ -263,9 +264,9 @@ namespace ICSharpCode.Decompiler.IL.Transforms return inst; } - static bool ValidateCompoundAssign(BinaryNumericInstruction binary, Conv? conv, IType targetType, DecompilerSettings settings) + static bool ValidateCompoundAssign(BinaryNumericInstruction binary, Conv? conv, IType targetType, ILTransformContext context) { - if (!NumericCompoundAssign.IsBinaryCompatibleWithType(binary, targetType, settings)) + if (!NumericCompoundAssign.IsBinaryCompatibleWithType(binary, targetType, context)) return false; if (conv != null && !(conv.TargetType == targetType.ToPrimitiveType() && conv.CheckForOverflow == binary.CheckForOverflow)) return false; // conv does not match binary operation @@ -381,13 +382,13 @@ namespace ICSharpCode.Decompiler.IL.Transforms } if (!IsMatchingCompoundLoad(binary.Left, compoundStore, out var target, out var targetKind, out var finalizeMatch, forbiddenVariable: storeInSetter?.Variable)) return false; - if (!ValidateCompoundAssign(binary, smallIntConv, targetType, context.Settings)) + if (!ValidateCompoundAssign(binary, smallIntConv, targetType, context)) return false; context.Step($"Compound assignment (binary.numeric)", compoundStore); finalizeMatch?.Invoke(context); newInst = new NumericCompoundAssign( binary, target, targetKind, binary.Right, - targetType, CompoundEvalMode.EvaluatesToNewValue); + targetType, CompoundEvalMode.EvaluatesToNewValue, context); } else if (setterValue is Call operatorCall && operatorCall.Method.IsOperator) { @@ -887,7 +888,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms targetType = SwapSign(targetType, context.TypeSystem); } - if (!ValidateCompoundAssign(binary, conv, targetType, context.Settings)) + if (!ValidateCompoundAssign(binary, conv, targetType, context)) return false; ldloc = binary.Left as LdLoc; } @@ -920,7 +921,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms if (binary != null) { block.Instructions[pos] = new StLoc(stloc_outer.Variable, new NumericCompoundAssign( - binary, target, targetKind, binary.Right, targetType, CompoundEvalMode.EvaluatesToNewValue)); + binary, target, targetKind, binary.Right, targetType, CompoundEvalMode.EvaluatesToNewValue, context)); } else { @@ -972,7 +973,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms targetType = SwapSign(targetType, context.TypeSystem); } - if (!ValidateCompoundAssign(binary, conv, targetType, context.Settings)) + if (!ValidateCompoundAssign(binary, conv, targetType, context)) return false; stloc = binary.Left as StLoc; } @@ -1001,7 +1002,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms if (binary != null) { block.Instructions[pos] = new StLoc(stloc.Variable, new NumericCompoundAssign( - binary, target, targetKind, binary.Right, targetType, CompoundEvalMode.EvaluatesToOldValue)); + binary, target, targetKind, binary.Right, targetType, CompoundEvalMode.EvaluatesToOldValue, context)); } else { @@ -1080,12 +1081,12 @@ namespace ICSharpCode.Decompiler.IL.Transforms // Change the sign of the type to skip implicit truncation stObj.Type = targetType = SwapSign(targetType, context.TypeSystem); } - if (!ValidateCompoundAssign(binary, conv, targetType, context.Settings)) + if (!ValidateCompoundAssign(binary, conv, targetType, context)) return false; context.Step("TransformPostIncDecOperator (builtin)", inst); finalizeMatch?.Invoke(context); inst.Value = new NumericCompoundAssign(binary, target, targetKind, binary.Right, - targetType, CompoundEvalMode.EvaluatesToOldValue); + targetType, CompoundEvalMode.EvaluatesToOldValue, context); } else if (value is Call operatorCall && operatorCall.Method.IsOperator && operatorCall.Arguments.Count == 1) {