Browse Source

Merge d511e768df into 0bfe222cf4

pull/3472/merge
Jeremy Pritts 4 days ago committed by GitHub
parent
commit
a43c330b63
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 16
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.cs
  2. 80
      ICSharpCode.Decompiler/IL/Transforms/TransformAssignment.cs

16
ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.cs

@ -4946,5 +4946,21 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -4946,5 +4946,21 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
CustomStruct2 customStruct = GetStruct();
customStruct.IntProp += value;
}
public static string PreincrementWithMethodCall(int value)
{
return (++value).ToString();
}
#if CS72
public static string PreincrementWithInParameter(int value)
{
PreincrementWithInParameter_Helper(++value);
return value.ToString();
}
public static void PreincrementWithInParameter_Helper(in int value)
{
}
#endif
}
}

80
ICSharpCode.Decompiler/IL/Transforms/TransformAssignment.cs

@ -54,7 +54,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -54,7 +54,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms
if (context.Settings.IntroduceIncrementAndDecrement)
{
if (TransformPostIncDecOperatorWithInlineStore(block, pos)
|| TransformPostIncDecOperator(block, pos))
|| TransformPostIncDecOperator(block, pos)
|| TransformPreIncDecOperatorWithInlineStore(block, pos))
{
// again, new top-level stloc might need inlining:
context.RequestRerun();
@ -844,6 +845,83 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -844,6 +845,83 @@ namespace ICSharpCode.Decompiler.IL.Transforms
}
}
/// <code>
/// stloc l(stloc target(binary.add(ldloc target, ldc.i4 1)))
/// </code>
bool TransformPreIncDecOperatorWithInlineStore(Block block, int pos)
{
var store = block.Instructions[pos];
if (!IsCompoundStore(store, out var targetType1, out var value1, context.TypeSystem))
{
return false;
}
if (!IsCompoundStore(value1, out var targetType2, out var value2, context.TypeSystem))
{
return false;
}
if (targetType1 != targetType2)
return false;
var targetType = targetType1;
var stloc_outer = store as StLoc;
var stloc_inner = value1 as StLoc;
LdLoc ldloc;
var binary = UnwrapSmallIntegerConv(value2, out var conv) as BinaryNumericInstruction;
if (binary != null && (binary.Right.MatchLdcI(1) || binary.Right.MatchLdcF4(1) || binary.Right.MatchLdcF8(1)))
{
if (!(binary.Operator == BinaryNumericOperator.Add || binary.Operator == BinaryNumericOperator.Sub))
return false;
if (conv is not null)
{
var primitiveType = targetType.ToPrimitiveType();
if (primitiveType.GetSize() == conv.TargetType.GetSize() && primitiveType.GetSign() != conv.TargetType.GetSign())
targetType = SwapSign(targetType, context.TypeSystem);
}
if (!ValidateCompoundAssign(binary, conv, targetType, context.Settings))
return false;
ldloc = binary.Left as LdLoc;
}
else if (value2 is Call operatorCall && operatorCall.Method.IsOperator && operatorCall.Arguments.Count == 1)
{
if (!(operatorCall.Method.Name == "op_Increment" || operatorCall.Method.Name == "op_Decrement"))
return false;
if (operatorCall.IsLifted)
return false; // TODO: add tests and think about whether nullables need special considerations
ldloc = operatorCall.Arguments[0] as LdLoc;
}
else
{
return false;
}
if (stloc_outer == null)
return false;
if (stloc_inner == null)
return false;
if (ldloc == null)
return false;
if (!(stloc_outer.Variable.Kind == VariableKind.Local || stloc_outer.Variable.Kind == VariableKind.StackSlot))
return false;
if (!IsMatchingCompoundLoad(ldloc, stloc_inner, out var target, out var targetKind, out var finalizeMatch))
return false;
if (IsImplicitTruncation(stloc_outer.Value, stloc_outer.Variable.Type, context.TypeSystem))
return false;
context.Step(nameof(TransformPreIncDecOperatorWithInlineStore), store);
finalizeMatch?.Invoke(context);
if (binary != null)
{
block.Instructions[pos] = new StLoc(stloc_outer.Variable, new NumericCompoundAssign(
binary, target, targetKind, binary.Right, targetType, CompoundEvalMode.EvaluatesToNewValue));
}
else
{
Call operatorCall = (Call)value2;
block.Instructions[pos] = new StLoc(stloc_outer.Variable, new UserDefinedCompoundAssign(
operatorCall.Method, CompoundEvalMode.EvaluatesToNewValue, target, targetKind, new LdcI4(1)));
}
return true;
}
/// <code>
/// stobj(target, binary.add(stloc l(ldobj(target)), ldc.i4 1))
/// where target is pure and does not use 'l', and the 'stloc l' does not truncate

Loading…
Cancel
Save