Skip to content

Commit

Permalink
Add support for ref fields.
Browse files Browse the repository at this point in the history
  • Loading branch information
siegfriedpammer committed Jul 16, 2022
1 parent fc882b9 commit 5f324de
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 9 deletions.
32 changes: 23 additions & 9 deletions ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -357,16 +357,17 @@ bool IsAmbiguousAccess(out MemberResolveResult result)
mrr = new MemberResolveResult(target.ResolveResult, field);
}

if (requireTarget)
{
return new MemberReferenceExpression(target, field.Name)
.WithRR(mrr);
}
else
var expr = requireTarget
? new MemberReferenceExpression(target, field.Name).WithRR(mrr)
: new IdentifierExpression(field.Name).WithRR(mrr);

if (field.Type.Kind == TypeKind.ByReference)
{
return new IdentifierExpression(field.Name)
.WithRR(mrr);
expr = new DirectionExpression(FieldDirection.Ref, expr)
.WithRR(new ByReferenceResolveResult(mrr, ReferenceKind.Ref));
}

return expr;
}

TranslatedExpression IsType(IsInst inst)
Expand Down Expand Up @@ -2798,7 +2799,20 @@ protected internal override TranslatedExpression VisitStObj(StObj inst, Translat
{
value = Translate(inst.Value, typeHint: target.Type);
}
return Assignment(target, value).WithILInstruction(inst);
if (target.Expression is DirectionExpression dirExpr && target.ResolveResult is ByReferenceResolveResult lhsRefRR)
{
// ref (re-)assignment, emit "ref (a = ref b)".
target = target.UnwrapChild(dirExpr.Expression);
value = value.ConvertTo(lhsRefRR.Type, this, allowImplicitConversion: true);
var assign = new AssignmentExpression(target.Expression, value.Expression)
.WithRR(new OperatorResolveResult(target.Type, ExpressionType.Assign, lhsRefRR, value.ResolveResult));
return new DirectionExpression(FieldDirection.Ref, assign)
.WithoutILInstruction().WithRR(lhsRefRR);
}
else
{
return Assignment(target, value).WithILInstruction(inst);
}
}

private TranslatedExpression UnalignedStObj(StObj inst)
Expand Down
11 changes: 11 additions & 0 deletions ICSharpCode.Decompiler/CSharp/StatementBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,17 @@ protected internal override TranslatedStatement VisitStLoc(StLoc inst)
return new ExpressionStatement(expr).WithILInstruction(inst);
}

protected internal override TranslatedStatement VisitStObj(StObj inst)
{
var expr = exprBuilder.Translate(inst);
// strip top-level ref on ref re-assignment
if (expr.Expression is DirectionExpression dirExpr)
{
expr = expr.UnwrapChild(dirExpr.Expression);
}
return new ExpressionStatement(expr).WithILInstruction(inst);
}

protected internal override TranslatedStatement VisitNop(Nop inst)
{
var stmt = new EmptyStatement();
Expand Down

0 comments on commit 5f324de

Please sign in to comment.