Browse Source

Fix assertion when call has unknown target type (due to missing assembly reference).

pull/1012/head
Daniel Grunwald 8 years ago
parent
commit
ae819526eb
  1. 2
      ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
  2. 6
      ICSharpCode.Decompiler/IL/ILReader.cs
  3. 2
      ICSharpCode.Decompiler/IL/ILTypeExtensions.cs
  4. 11
      ICSharpCode.Decompiler/IL/Instructions/CallInstruction.cs
  5. 5
      ICSharpCode.Decompiler/IL/Instructions/Conv.cs
  6. 3
      ICSharpCode.Decompiler/IL/PrimitiveType.cs

2
ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs

@ -132,7 +132,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -132,7 +132,7 @@ namespace ICSharpCode.Decompiler.CSharp
};
var cexpr = inst.AcceptVisitor(this, context);
#if DEBUG
if (inst.ResultType != StackType.Void && cexpr.Type.Kind != TypeKind.Unknown) {
if (inst.ResultType != StackType.Void && cexpr.Type.Kind != TypeKind.Unknown && inst.ResultType != StackType.Unknown) {
// Validate the Translate post-condition (documented at beginning of this file):
if (inst.ResultType.IsIntegerType()) {
Debug.Assert(cexpr.Type.GetStackType().IsIntegerType(), "IL instructions of integer type must convert into C# expressions of integer type");

6
ICSharpCode.Decompiler/IL/ILReader.cs

@ -376,10 +376,10 @@ namespace ICSharpCode.Decompiler.IL @@ -376,10 +376,10 @@ namespace ICSharpCode.Decompiler.IL
value = new Conv(value, PrimitiveType.I8, false, Sign.None);
break;
case StackType.F4:
value = new Conv(value, PrimitiveType.R4, false, Sign.None);
value = new Conv(value, PrimitiveType.R4, false, Sign.Signed);
break;
case StackType.F8:
value = new Conv(value, PrimitiveType.R8, false, Sign.None);
value = new Conv(value, PrimitiveType.R8, false, Sign.Signed);
break;
case StackType.Ref:
value = new Conv(value, PrimitiveType.Ref, false, Sign.None);
@ -1088,6 +1088,8 @@ namespace ICSharpCode.Decompiler.IL @@ -1088,6 +1088,8 @@ namespace ICSharpCode.Decompiler.IL
} else if (expectedType == StackType.F4 && inst.ResultType == StackType.F8) {
// IL allows implicit F8->F4 conversions, because in IL F4 and F8 are the same.
inst = new Conv(inst, PrimitiveType.R4, false, Sign.Signed);
} else if (expectedType == StackType.Unknown) {
inst = new Conv(inst, PrimitiveType.Unknown, false, Sign.None);
} else {
Warn($"Expected {expectedType}, but got {inst.ResultType}");
inst = new Conv(inst, expectedType.ToKnownTypeCode().ToPrimitiveType(), false, Sign.None);

2
ICSharpCode.Decompiler/IL/ILTypeExtensions.cs

@ -51,6 +51,8 @@ namespace ICSharpCode.Decompiler.IL @@ -51,6 +51,8 @@ namespace ICSharpCode.Decompiler.IL
return StackType.Ref;
case MetadataType.Void:
return StackType.Void;
case (MetadataType)PrimitiveType.Unknown:
return StackType.Unknown;
default:
return StackType.O;
}

11
ICSharpCode.Decompiler/IL/Instructions/CallInstruction.cs

@ -78,12 +78,21 @@ namespace ICSharpCode.Decompiler.IL @@ -78,12 +78,21 @@ namespace ICSharpCode.Decompiler.IL
/// Gets the expected stack type for passing the this pointer in a method call.
/// Returns StackType.O for reference types (this pointer passed as object reference),
/// and StackType.Ref for type parameters and value types (this pointer passed as managed reference).
///
/// Returns StackType.Unknown if the input type is unknown.
/// </summary>
internal static StackType ExpectedTypeForThisPointer(IType type)
{
if (type.Kind == TypeKind.TypeParameter)
return StackType.Ref;
return type.IsReferenceType == true ? StackType.O : StackType.Ref;
switch (type.IsReferenceType) {
case true:
return StackType.O;
case false:
return StackType.Ref;
default:
return StackType.Unknown;
}
}
internal override void CheckInvariant(ILPhase phase)

5
ICSharpCode.Decompiler/IL/Instructions/Conv.cs

@ -154,6 +154,7 @@ namespace ICSharpCode.Decompiler.IL @@ -154,6 +154,7 @@ namespace ICSharpCode.Decompiler.IL
public Conv(ILInstruction argument, StackType inputType, Sign inputSign, PrimitiveType targetType, bool checkForOverflow, bool isLifted = false)
: base(OpCode.Conv, argument)
{
Debug.Assert(targetType != PrimitiveType.None);
bool needsSign = checkForOverflow || targetType == PrimitiveType.R4 || targetType == PrimitiveType.R8;
Debug.Assert(!(needsSign && inputSign == Sign.None));
this.InputType = inputType;
@ -161,14 +162,14 @@ namespace ICSharpCode.Decompiler.IL @@ -161,14 +162,14 @@ namespace ICSharpCode.Decompiler.IL
this.TargetType = targetType;
this.CheckForOverflow = checkForOverflow;
this.Kind = GetConversionKind(targetType, this.InputType, this.InputSign);
Debug.Assert(Kind != ConversionKind.Invalid);
// Debug.Assert(Kind != ConversionKind.Invalid); // invalid conversion can happen with invalid IL/missing references
this.IsLifted = isLifted;
}
internal override void CheckInvariant(ILPhase phase)
{
base.CheckInvariant(phase);
Debug.Assert(Kind != ConversionKind.Invalid);
// Debug.Assert(Kind != ConversionKind.Invalid); // invalid conversion can happen with invalid IL/missing references
Debug.Assert(Argument.ResultType == (IsLifted ? StackType.O : InputType));
Debug.Assert(!(IsLifted && Kind == ConversionKind.StopGCTracking));
}

3
ICSharpCode.Decompiler/IL/PrimitiveType.cs

@ -35,6 +35,7 @@ namespace ICSharpCode.Decompiler.IL @@ -35,6 +35,7 @@ namespace ICSharpCode.Decompiler.IL
U8 = MetadataType.UInt64,
I = MetadataType.IntPtr,
U = MetadataType.UIntPtr,
Ref = MetadataType.ByReference
Ref = MetadataType.ByReference,
Unknown = 255
}
}

Loading…
Cancel
Save