Browse Source

Handle special-cases with addressof:

- Never introduce casts for ldobj-address-chains
- Add special-case to TransformExpressionTrees: transform addressof(ldloc) to ldloca
- Classify foreach and using variables as readonly lvalues
pull/2726/head
Siegfried Pammer 3 years ago
parent
commit
d3f8912d53
  1. 19
      ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
  2. 5
      ICSharpCode.Decompiler/IL/Transforms/ILInlining.cs
  3. 8
      ICSharpCode.Decompiler/IL/Transforms/TransformExpressionTrees.cs

19
ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs

@ -3784,7 +3784,9 @@ namespace ICSharpCode.Decompiler.CSharp @@ -3784,7 +3784,9 @@ namespace ICSharpCode.Decompiler.CSharp
// on a mutable lvalue, we would end up modifying the original lvalue, not just the copy.
// We solve this by introducing a "redundant" cast. Casts are classified as rvalue
// and ensure that the C# compiler will also create a copy.
if (classification == ExpressionClassification.MutableLValue && value.Expression is not CastExpression)
if (classification == ExpressionClassification.MutableLValue
&& !CanIgnoreCopy()
&& value.Expression is not CastExpression)
{
value = new CastExpression(ConvertType(inst.Type), value.Expression)
.WithoutILInstruction()
@ -3793,6 +3795,21 @@ namespace ICSharpCode.Decompiler.CSharp @@ -3793,6 +3795,21 @@ namespace ICSharpCode.Decompiler.CSharp
return new DirectionExpression(FieldDirection.Ref, value)
.WithILInstruction(inst)
.WithRR(new ByReferenceResolveResult(value.ResolveResult, ReferenceKind.Ref));
bool CanIgnoreCopy()
{
ILInstruction loadAddress = inst;
while (loadAddress.Parent is LdFlda parent)
{
loadAddress = parent;
}
if (loadAddress.Parent is LdObj)
{
// Ignore copy, never introduce a cast
return true;
}
return false;
}
}
protected internal override TranslatedExpression VisitAwait(Await inst, TranslationContext context)

5
ICSharpCode.Decompiler/IL/Transforms/ILInlining.cs

@ -416,7 +416,10 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -416,7 +416,10 @@ namespace ICSharpCode.Decompiler.IL.Transforms
{
case OpCode.LdLoc:
case OpCode.StLoc:
if (((IInstructionWithVariableOperand)inst).Variable.IsRefReadOnly)
ILVariable v = ((IInstructionWithVariableOperand)inst).Variable;
if (v.IsRefReadOnly
|| v.Kind == VariableKind.ForeachLocal
|| v.Kind == VariableKind.UsingLocal)
{
return ExpressionClassification.ReadonlyLValue;
}

8
ICSharpCode.Decompiler/IL/Transforms/TransformExpressionTrees.cs

@ -637,9 +637,17 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -637,9 +637,17 @@ namespace ICSharpCode.Decompiler.IL.Transforms
{
case StackType.Ref:
if (target.ResultType == StackType.Ref)
{
return target;
}
else if (target is LdLoc ldloc)
{
return new LdLoca(ldloc.Variable).WithILRange(ldloc);
}
else
{
return new AddressOf(target, expectedType);
}
case StackType.O:
if (targetType.IsReferenceType == false)
{

Loading…
Cancel
Save