diff --git a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs index 29262da59..c0617cbef 100644 --- a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs +++ b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs @@ -639,9 +639,7 @@ namespace ICSharpCode.Decompiler.CSharp // Target and value are incompatible, so convert value to the target type // inst.ResultType should match inst.Target.ResultType Debug.Assert(inst.ResultType == inst.Target.ResultType); - StackType targetStackType = inst.ResultType == StackType.I ? StackType.I8 : inst.ResultType; - IType targetType = compilation.FindType(targetStackType.ToKnownTypeCode(inst.Sign)); - value = value.ConvertTo(targetType, this); + value = value.ConvertTo(inst.Type, this); rr = resolverWithOverflowCheck.ResolveAssignment(op, target.ResolveResult, value.ResolveResult); } TranslatedExpression resultExpr; diff --git a/ICSharpCode.Decompiler/IL/Instructions.cs b/ICSharpCode.Decompiler/IL/Instructions.cs index 19d7ec780..3d9226f82 100644 --- a/ICSharpCode.Decompiler/IL/Instructions.cs +++ b/ICSharpCode.Decompiler/IL/Instructions.cs @@ -788,7 +788,10 @@ namespace ICSharpCode.Decompiler.IL clone.Value = this.value.Clone(); return clone; } - public override StackType ResultType { get { return target.ResultType; } } + readonly IType type; + /// Returns the type operand. + public IType Type { get { return type; } } + public override StackType ResultType { get { return type.GetStackType(); } } public override void AcceptVisitor(ILVisitor visitor) { visitor.VisitCompoundAssignmentInstruction(this); diff --git a/ICSharpCode.Decompiler/IL/Instructions.tt b/ICSharpCode.Decompiler/IL/Instructions.tt index 3b868b4fa..c632a22e2 100644 --- a/ICSharpCode.Decompiler/IL/Instructions.tt +++ b/ICSharpCode.Decompiler/IL/Instructions.tt @@ -62,7 +62,7 @@ CustomClassName("BinaryNumericInstruction"), Binary, CustomWriteTo, CustomConstructor, CustomComputeFlags), new OpCode("compound", "Common instruction for compound assignments.", CustomClassName("CompoundAssignmentInstruction"), CustomConstructor, CustomComputeFlags, - MayThrow, CustomArguments("target", "value"), ResultType("target.ResultType"), CustomWriteTo), + MayThrow, CustomArguments("target", "value"), HasTypeOperand, ResultType("type.GetStackType()"), CustomWriteTo), new OpCode("bit.not", "Bitwise NOT", Unary), new OpCode("arglist", "Retrieves the RuntimeArgumentHandle.", NoArguments, ResultType("O")), new OpCode("br", "Unconditional branch. goto target;", diff --git a/ICSharpCode.Decompiler/IL/Instructions/CompoundAssignmentInstruction.cs b/ICSharpCode.Decompiler/IL/Instructions/CompoundAssignmentInstruction.cs index b78fa11b1..ca9a3ac89 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/CompoundAssignmentInstruction.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/CompoundAssignmentInstruction.cs @@ -51,13 +51,14 @@ namespace ICSharpCode.Decompiler.IL public readonly CompoundAssignmentType CompoundAssignmentType; - public CompoundAssignmentInstruction(BinaryNumericOperator op, ILInstruction target, ILInstruction value, bool checkForOverflow, Sign sign, CompoundAssignmentType compoundAssigmentType) + public CompoundAssignmentInstruction(BinaryNumericOperator op, ILInstruction target, ILInstruction value, IType type, bool checkForOverflow, Sign sign, CompoundAssignmentType compoundAssigmentType) : base(OpCode.CompoundAssignmentInstruction) { this.CheckForOverflow = checkForOverflow; this.Sign = sign; this.Operator = op; this.Target = target; + this.type = type; this.Value = value; this.CompoundAssignmentType = compoundAssigmentType; Debug.Assert(compoundAssigmentType == CompoundAssignmentType.EvaluatesToNewValue || (op == BinaryNumericOperator.Add || op == BinaryNumericOperator.Sub)); diff --git a/ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs b/ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs index 1dd745931..29149b4cd 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs @@ -195,7 +195,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms if (binary != null && binary.Left.MatchLdObj(out target, out t) && IsSameTarget(inst.Target, target)) { // stobj(target, binary.op(ldobj(target), ...)) // => compound.op(target, ...) - inst.ReplaceWith(new CompoundAssignmentInstruction(binary.Operator, binary.Left, binary.Right, binary.CheckForOverflow, binary.Sign, CompoundAssignmentType.EvaluatesToNewValue)); + inst.ReplaceWith(new CompoundAssignmentInstruction(binary.Operator, binary.Left, binary.Right, t, binary.CheckForOverflow, binary.Sign, CompoundAssignmentType.EvaluatesToNewValue)); } } diff --git a/ICSharpCode.Decompiler/IL/Transforms/TransformAssignment.cs b/ICSharpCode.Decompiler/IL/Transforms/TransformAssignment.cs index 75b72481e..b18127d02 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/TransformAssignment.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/TransformAssignment.cs @@ -206,7 +206,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms if (binary == null || !binary.Left.MatchLdLoc(nextInst.Variable) || !binary.Right.MatchLdcI4(1) || (binary.Operator != BinaryNumericOperator.Add && binary.Operator != BinaryNumericOperator.Sub)) return false; - var assignment = new CompoundAssignmentInstruction(binary.Operator, new LdObj(inst.Value, targetType), binary.Right, binary.CheckForOverflow, binary.Sign, CompoundAssignmentType.EvaluatesToOldValue); + var assignment = new CompoundAssignmentInstruction(binary.Operator, new LdObj(inst.Value, targetType), binary.Right, targetType, binary.CheckForOverflow, binary.Sign, CompoundAssignmentType.EvaluatesToOldValue); stobj.ReplaceWith(new StLoc(nextInst.Variable, assignment)); block.Instructions.RemoveAt(i + 1); return true; @@ -255,7 +255,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms if (binary == null || !binary.Left.MatchLdLoc(fieldValue.Variable) || !binary.Right.MatchLdcI4(1) || (binary.Operator != BinaryNumericOperator.Add && binary.Operator != BinaryNumericOperator.Sub)) return false; - var assignment = new CompoundAssignmentInstruction(binary.Operator, new LdObj(baseAddress, t), binary.Right, binary.CheckForOverflow, binary.Sign, CompoundAssignmentType.EvaluatesToOldValue); + var assignment = new CompoundAssignmentInstruction(binary.Operator, new LdObj(baseAddress, t), binary.Right, t, binary.CheckForOverflow, binary.Sign, CompoundAssignmentType.EvaluatesToOldValue); stobj.ReplaceWith(new StLoc(fieldValueCopyToLocal.Variable, assignment)); block.Instructions.RemoveAt(i + 2); block.Instructions.RemoveAt(i + 1);