Browse Source

Fix assertion with fields declared in an unresolved class type.

pull/1213/head
Daniel Grunwald 7 years ago
parent
commit
367b396b35
  1. 38
      ICSharpCode.Decompiler/IL/ILReader.cs
  2. 15
      ICSharpCode.Decompiler/IL/Instructions/LdFlda.cs

38
ICSharpCode.Decompiler/IL/ILReader.cs

@ -1093,21 +1093,47 @@ namespace ICSharpCode.Decompiler.IL
return inst; return inst;
default: default:
Warn("Expected native int or pointer, but got " + inst.ResultType); Warn("Expected native int or pointer, but got " + inst.ResultType);
return inst; return new Conv(inst, PrimitiveType.I, false, Sign.None);
} }
} }
ILInstruction PopFieldTarget(IField field) ILInstruction PopFieldTarget(IField field)
{ {
return field.DeclaringType.IsReferenceType == true ? Pop(StackType.O) : PopPointer(); switch (field.DeclaringType.IsReferenceType) {
case true:
return Pop(StackType.O);
case false:
return PopPointer();
default:
// field in unresolved type
if (PeekStackType() == StackType.O)
return Pop();
else
return PopPointer();
}
} }
/// <summary>
/// Like PopFieldTarget, but supports ldfld's special behavior for fields of temporary value types.
/// </summary>
ILInstruction PopLdFldTarget(IField field) ILInstruction PopLdFldTarget(IField field)
{ {
if (field.DeclaringType.IsReferenceType == true) switch (field.DeclaringType.IsReferenceType) {
return Pop(StackType.O); case true:
return Pop(StackType.O);
return PeekStackType() == StackType.O ? new AddressOf(Pop()) : PopPointer(); case false:
// field of value type: ldfld can handle temporaries
if (PeekStackType() == StackType.O)
return new AddressOf(Pop());
else
return PopPointer();
default:
// field in unresolved type
if (PeekStackType() == StackType.O)
return Pop(StackType.O);
else
return PopPointer();
}
} }
private ILInstruction Return() private ILInstruction Return()

15
ICSharpCode.Decompiler/IL/Instructions/LdFlda.cs

@ -25,7 +25,20 @@ namespace ICSharpCode.Decompiler.IL
internal override void CheckInvariant(ILPhase phase) internal override void CheckInvariant(ILPhase phase)
{ {
base.CheckInvariant(phase); base.CheckInvariant(phase);
Debug.Assert(field.DeclaringType.IsReferenceType == true ? (target.ResultType == StackType.O) : (target.ResultType == StackType.I || target.ResultType == StackType.Ref)); switch (field.DeclaringType.IsReferenceType) {
case true:
Debug.Assert(target.ResultType == StackType.O,
"Class fields can only be accessed with an object on the stack");
break;
case false:
Debug.Assert(target.ResultType == StackType.I || target.ResultType == StackType.Ref,
"Struct fields can only be accessed with a pointer on the stack");
break;
case null:
// field of unresolved type
Debug.Assert(target.ResultType == StackType.O || target.ResultType == StackType.I || target.ResultType == StackType.Ref);
break;
}
} }
} }
} }

Loading…
Cancel
Save