Browse Source

Avoid casting pointer prior to dereference if the existing pointer type performs the same kind of memory access.

pull/924/head
Daniel Grunwald 8 years ago
parent
commit
b2c18fcc95
  1. 28
      ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs

28
ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs

@ -1199,19 +1199,35 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1199,19 +1199,35 @@ namespace ICSharpCode.Decompiler.CSharp
protected internal override TranslatedExpression VisitLdObj(LdObj inst, TranslationContext context)
{
var target = Translate(inst.Target);
if (target.Expression is DirectionExpression && TypeUtils.IsCompatibleTypeForMemoryAccess(target.Type, inst.Type)) {
// we can dereference the managed reference by stripping away the 'ref'
var result = target.UnwrapChild(((DirectionExpression)target.Expression).Expression);
if (TypeUtils.IsCompatibleTypeForMemoryAccess(target.Type, inst.Type)) {
TranslatedExpression result;
if (target.Expression is DirectionExpression dirExpr) {
// we can dereference the managed reference by stripping away the 'ref'
result = target.UnwrapChild(dirExpr.Expression);
result.Expression.AddAnnotation(inst); // add LdObj in addition to the existing ILInstruction annotation
} else if (target.Type is PointerType pointerType) {
// Dereference the existing pointer
result = new UnaryOperatorExpression(UnaryOperatorType.Dereference, target.Expression)
.WithILInstruction(inst)
.WithRR(new ResolveResult(pointerType.ElementType));
} else {
// reference type behind non-DirectionExpression?
// this case should be impossible, but we can use a pointer cast
// just to make sure
target = target.ConvertTo(new PointerType(inst.Type), this);
return new UnaryOperatorExpression(UnaryOperatorType.Dereference, target.Expression)
.WithILInstruction(inst)
.WithRR(new ResolveResult(inst.Type));
}
// we don't convert result to inst.Type, because the LdObj type
// might be inaccurate (it's often System.Object for all reference types),
// and our parent node should already insert casts where necessary
result.Expression.AddAnnotation(inst); // add LdObj in addition to the existing ILInstruction annotation
if (target.Type.IsSmallIntegerType() && inst.Type.IsSmallIntegerType() && target.Type.GetSign() != inst.Type.GetSign())
return result.ConvertTo(inst.Type, this);
return result;
} else {
// Cast pointer type if necessary:
// We need to cast the pointer type:
target = target.ConvertTo(new PointerType(inst.Type), this);
return new UnaryOperatorExpression(UnaryOperatorType.Dereference, target.Expression)
.WithILInstruction(inst)

Loading…
Cancel
Save