Browse Source

Fixed decompiling "new byte[length]" where length is a long.

pull/314/merge
Daniel Grunwald 14 years ago
parent
commit
0010be6add
  1. 11
      ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs
  2. 7
      ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs
  3. 148
      ICSharpCode.Decompiler/ILAst/InitializerPeepholeTransforms.cs
  4. 66
      ICSharpCode.Decompiler/ILAst/PeepholeTransform.cs
  5. 15
      ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs
  6. 10
      ICSharpCode.Decompiler/Tests/TypeAnalysisTests.cs

11
ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs

@ -525,6 +525,10 @@ namespace ICSharpCode.Decompiler.Ast
case ILCode.Conv_Ovf_U2_Un: case ILCode.Conv_Ovf_U2_Un:
case ILCode.Conv_Ovf_U4_Un: case ILCode.Conv_Ovf_U4_Un:
case ILCode.Conv_Ovf_U8_Un: case ILCode.Conv_Ovf_U8_Un:
case ILCode.Conv_Ovf_I:
case ILCode.Conv_Ovf_U:
case ILCode.Conv_Ovf_I_Un:
case ILCode.Conv_Ovf_U_Un:
{ {
// conversion was handled by Convert() function using the info from type analysis // conversion was handled by Convert() function using the info from type analysis
CastExpression cast = arg1 as CastExpression; CastExpression cast = arg1 as CastExpression;
@ -533,11 +537,8 @@ namespace ICSharpCode.Decompiler.Ast
} }
return arg1; return arg1;
} }
case ILCode.Conv_Ovf_I: return arg1.CastTo(new SimpleType("IntPtr")); // TODO case ILCode.Castclass:
case ILCode.Conv_Ovf_U: return arg1.CastTo(new SimpleType("UIntPtr")); return arg1.CastTo(operandAsTypeRef);
case ILCode.Conv_Ovf_I_Un: return arg1.CastTo(new SimpleType("IntPtr"));
case ILCode.Conv_Ovf_U_Un: return arg1.CastTo(new SimpleType("UIntPtr"));
case ILCode.Castclass: return arg1.CastTo(operandAsTypeRef);
case ILCode.Unbox_Any: case ILCode.Unbox_Any:
// unboxing does not require a cast if the argument was an isinst instruction // unboxing does not require a cast if the argument was an isinst instruction
if (arg1 is AsExpression && byteCode.Arguments[0].Code == ILCode.Isinst && TypeAnalysis.IsSameType(operand as TypeReference, byteCode.Arguments[0].Operand as TypeReference)) if (arg1 is AsExpression && byteCode.Arguments[0].Code == ILCode.Isinst && TypeAnalysis.IsSameType(operand as TypeReference, byteCode.Arguments[0].Operand as TypeReference))

7
ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs

@ -44,7 +44,7 @@ namespace ICSharpCode.Decompiler.ILAst
JoinBasicBlocks, JoinBasicBlocks,
SimplifyLogicNot, SimplifyLogicNot,
SimplifyShiftOperators, SimplifyShiftOperators,
TransformDecimalCtorToConstant, TypeConversionSimplifications,
SimplifyLdObjAndStObj, SimplifyLdObjAndStObj,
SimplifyCustomShortCircuit, SimplifyCustomShortCircuit,
SimplifyLiftedOperators, SimplifyLiftedOperators,
@ -143,9 +143,8 @@ namespace ICSharpCode.Decompiler.ILAst
if (abortBeforeStep == ILAstOptimizationStep.SimplifyShiftOperators) return; if (abortBeforeStep == ILAstOptimizationStep.SimplifyShiftOperators) return;
modified |= block.RunOptimization(SimplifyShiftOperators); modified |= block.RunOptimization(SimplifyShiftOperators);
if (abortBeforeStep == ILAstOptimizationStep.TransformDecimalCtorToConstant) return; if (abortBeforeStep == ILAstOptimizationStep.TypeConversionSimplifications) return;
modified |= block.RunOptimization(TransformDecimalCtorToConstant); modified |= block.RunOptimization(TypeConversionSimplifications);
modified |= block.RunOptimization(SimplifyLdcI4ConvI8);
if (abortBeforeStep == ILAstOptimizationStep.SimplifyLdObjAndStObj) return; if (abortBeforeStep == ILAstOptimizationStep.SimplifyLdObjAndStObj) return;
modified |= block.RunOptimization(SimplifyLdObjAndStObj); modified |= block.RunOptimization(SimplifyLdObjAndStObj);

148
ICSharpCode.Decompiler/ILAst/InitializerPeepholeTransforms.cs

@ -147,101 +147,101 @@ namespace ICSharpCode.Decompiler.ILAst
return false; return false;
} }
static bool DecodeArrayInitializer(TypeReference elementTypeRef, byte[] initialValue, ILExpression[] output) static bool DecodeArrayInitializer(TypeReference elementTypeRef, byte[] initialValue, ILExpression[] output)
{ {
TypeCode elementType = TypeAnalysis.GetTypeCode(elementTypeRef); TypeCode elementType = TypeAnalysis.GetTypeCode(elementTypeRef);
switch (elementType) { switch (elementType) {
case TypeCode.Boolean: case TypeCode.Boolean:
case TypeCode.Byte: case TypeCode.Byte:
return DecodeArrayInitializer(initialValue, output, elementType, (d, i) => (int)d[i]); return DecodeArrayInitializer(initialValue, output, elementType, (d, i) => (int)d[i]);
case TypeCode.SByte: case TypeCode.SByte:
return DecodeArrayInitializer(initialValue, output, elementType, (d, i) => (int)unchecked((sbyte)d[i])); return DecodeArrayInitializer(initialValue, output, elementType, (d, i) => (int)unchecked((sbyte)d[i]));
case TypeCode.Int16: case TypeCode.Int16:
return DecodeArrayInitializer(initialValue, output, elementType, (d, i) => (int)BitConverter.ToInt16(d, i)); return DecodeArrayInitializer(initialValue, output, elementType, (d, i) => (int)BitConverter.ToInt16(d, i));
case TypeCode.Char: case TypeCode.Char:
case TypeCode.UInt16: case TypeCode.UInt16:
return DecodeArrayInitializer(initialValue, output, elementType, (d, i) => (int)BitConverter.ToUInt16(d, i)); return DecodeArrayInitializer(initialValue, output, elementType, (d, i) => (int)BitConverter.ToUInt16(d, i));
case TypeCode.Int32: case TypeCode.Int32:
case TypeCode.UInt32: case TypeCode.UInt32:
return DecodeArrayInitializer(initialValue, output, elementType, BitConverter.ToInt32); return DecodeArrayInitializer(initialValue, output, elementType, BitConverter.ToInt32);
case TypeCode.Int64: case TypeCode.Int64:
case TypeCode.UInt64: case TypeCode.UInt64:
return DecodeArrayInitializer(initialValue, output, elementType, BitConverter.ToInt64); return DecodeArrayInitializer(initialValue, output, elementType, BitConverter.ToInt64);
case TypeCode.Single: case TypeCode.Single:
return DecodeArrayInitializer(initialValue, output, elementType, BitConverter.ToSingle); return DecodeArrayInitializer(initialValue, output, elementType, BitConverter.ToSingle);
case TypeCode.Double: case TypeCode.Double:
return DecodeArrayInitializer(initialValue, output, elementType, BitConverter.ToDouble); return DecodeArrayInitializer(initialValue, output, elementType, BitConverter.ToDouble);
case TypeCode.Object: case TypeCode.Object:
var typeDef = elementTypeRef.ResolveWithinSameModule(); var typeDef = elementTypeRef.ResolveWithinSameModule();
if (typeDef != null && typeDef.IsEnum) if (typeDef != null && typeDef.IsEnum)
return DecodeArrayInitializer(typeDef.GetEnumUnderlyingType(), initialValue, output); return DecodeArrayInitializer(typeDef.GetEnumUnderlyingType(), initialValue, output);
return false; return false;
default: default:
return false; return false;
} }
} }
static bool DecodeArrayInitializer<T>(byte[] initialValue, ILExpression[] output, TypeCode elementType, Func<byte[], int, T> decoder) static bool DecodeArrayInitializer<T>(byte[] initialValue, ILExpression[] output, TypeCode elementType, Func<byte[], int, T> decoder)
{ {
int elementSize = ElementSizeOf(elementType); int elementSize = ElementSizeOf(elementType);
if (initialValue.Length < (output.Length * elementSize)) if (initialValue.Length < (output.Length * elementSize))
return false; return false;
ILCode code = LoadCodeFor(elementType); ILCode code = LoadCodeFor(elementType);
for (int i = 0; i < output.Length; i++) for (int i = 0; i < output.Length; i++)
output[i] = new ILExpression(code, decoder(initialValue, i * elementSize)); output[i] = new ILExpression(code, decoder(initialValue, i * elementSize));
return true; return true;
} }
private static ILCode LoadCodeFor(TypeCode elementType) private static ILCode LoadCodeFor(TypeCode elementType)
{ {
switch (elementType) { switch (elementType) {
case TypeCode.Boolean: case TypeCode.Boolean:
case TypeCode.Byte: case TypeCode.Byte:
case TypeCode.SByte: case TypeCode.SByte:
case TypeCode.Char: case TypeCode.Char:
case TypeCode.Int16: case TypeCode.Int16:
case TypeCode.UInt16: case TypeCode.UInt16:
case TypeCode.Int32: case TypeCode.Int32:
case TypeCode.UInt32: case TypeCode.UInt32:
return ILCode.Ldc_I4; return ILCode.Ldc_I4;
case TypeCode.Int64: case TypeCode.Int64:
case TypeCode.UInt64: case TypeCode.UInt64:
return ILCode.Ldc_I8; return ILCode.Ldc_I8;
case TypeCode.Single: case TypeCode.Single:
return ILCode.Ldc_R4; return ILCode.Ldc_R4;
case TypeCode.Double: case TypeCode.Double:
return ILCode.Ldc_R8; return ILCode.Ldc_R8;
default: default:
throw new ArgumentOutOfRangeException("elementType"); throw new ArgumentOutOfRangeException("elementType");
} }
} }
private static int ElementSizeOf(TypeCode elementType) private static int ElementSizeOf(TypeCode elementType)
{ {
switch (elementType) { switch (elementType) {
case TypeCode.Boolean: case TypeCode.Boolean:
case TypeCode.Byte: case TypeCode.Byte:
case TypeCode.SByte: case TypeCode.SByte:
return 1; return 1;
case TypeCode.Char: case TypeCode.Char:
case TypeCode.Int16: case TypeCode.Int16:
case TypeCode.UInt16: case TypeCode.UInt16:
return 2; return 2;
case TypeCode.Int32: case TypeCode.Int32:
case TypeCode.UInt32: case TypeCode.UInt32:
case TypeCode.Single: case TypeCode.Single:
return 4; return 4;
case TypeCode.Int64: case TypeCode.Int64:
case TypeCode.UInt64: case TypeCode.UInt64:
case TypeCode.Double: case TypeCode.Double:
return 8; return 8;
default: default:
throw new ArgumentOutOfRangeException("elementType"); throw new ArgumentOutOfRangeException("elementType");
} }
} }
#endregion #endregion
/// <summary> /// <summary>

66
ICSharpCode.Decompiler/ILAst/PeepholeTransform.cs

@ -28,8 +28,20 @@ namespace ICSharpCode.Decompiler.ILAst
{ {
public partial class ILAstOptimizer public partial class ILAstOptimizer
{ {
#region TransformDecimalCtorToConstant #region TypeConversionSimplifications
static bool TransformDecimalCtorToConstant(List<ILNode> body, ILExpression expr, int pos) static bool TypeConversionSimplifications(List<ILNode> body, ILExpression expr, int pos)
{
bool modified = false;
modified |= TransformDecimalCtorToConstant(expr);
modified |= SimplifyLdcI4ConvI8(expr);
modified |= RemoveConvIFromArrayCreation(expr);
foreach(ILExpression arg in expr.Arguments) {
modified |= TypeConversionSimplifications(null, arg, -1);
}
return modified;
}
static bool TransformDecimalCtorToConstant(ILExpression expr)
{ {
MethodReference r; MethodReference r;
List<ILExpression> args; List<ILExpression> args;
@ -62,11 +74,34 @@ namespace ICSharpCode.Decompiler.ILAst
} }
} }
} }
bool modified = false; return false;
foreach(ILExpression arg in expr.Arguments) { }
modified |= TransformDecimalCtorToConstant(null, arg, -1);
static bool SimplifyLdcI4ConvI8(ILExpression expr)
{
ILExpression ldc;
int val;
if (expr.Match(ILCode.Conv_I8, out ldc) && ldc.Match(ILCode.Ldc_I4, out val)) {
expr.Code = ILCode.Ldc_I8;
expr.Operand = (long)val;
expr.Arguments.Clear();
return true;
} }
return modified; return false;
}
static bool RemoveConvIFromArrayCreation(ILExpression expr)
{
TypeReference typeRef;
ILExpression length;
ILExpression input;
if (expr.Match(ILCode.Newarr, out typeRef, out length)) {
if (length.Match(ILCode.Conv_Ovf_I, out input) || length.Match(ILCode.Conv_I, out input)) {
expr.Arguments[0] = input;
return true;
}
}
return false;
} }
#endregion #endregion
@ -129,25 +164,6 @@ namespace ICSharpCode.Decompiler.ILAst
} }
#endregion #endregion
#region SimplifyLdcI4ConvI8
static bool SimplifyLdcI4ConvI8(List<ILNode> body, ILExpression expr, int pos)
{
ILExpression ldc;
int val;
if (expr.Match(ILCode.Conv_I8, out ldc) && ldc.Match(ILCode.Ldc_I4, out val)) {
expr.Code = ILCode.Ldc_I8;
expr.Operand = (long)val;
expr.Arguments.Clear();
return true;
}
bool modified = false;
foreach(ILExpression arg in expr.Arguments) {
modified |= SimplifyLdcI4ConvI8(null, arg, -1);
}
return modified;
}
#endregion
#region CachedDelegateInitialization #region CachedDelegateInitialization
void CachedDelegateInitializationWithField(ILBlock block, ref int i) void CachedDelegateInitializationWithField(ILBlock block, ref int i)
{ {

15
ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs

@ -606,8 +606,19 @@ namespace ICSharpCode.Decompiler.ILAst
#endregion #endregion
#region Array instructions #region Array instructions
case ILCode.Newarr: case ILCode.Newarr:
if (forceInferChildren) if (forceInferChildren) {
InferTypeForExpression(expr.Arguments.Single(), typeSystem.Int32); var lengthType = InferTypeForExpression(expr.Arguments.Single(), null);
if (lengthType == typeSystem.IntPtr) {
lengthType = typeSystem.Int64;
} else if (lengthType == typeSystem.UIntPtr) {
lengthType = typeSystem.UInt64;
} else if (lengthType != typeSystem.UInt32 && lengthType != typeSystem.Int64 && lengthType != typeSystem.UInt64) {
lengthType = typeSystem.Int32;
}
if (forceInferChildren) {
InferTypeForExpression(expr.Arguments.Single(), lengthType);
}
}
return new ArrayType((TypeReference)expr.Operand); return new ArrayType((TypeReference)expr.Operand);
case ILCode.InitArray: case ILCode.InitArray:
var operandAsArrayType = (ArrayType)expr.Operand; var operandAsArrayType = (ArrayType)expr.Operand;

10
ICSharpCode.Decompiler/Tests/TypeAnalysisTests.cs

@ -120,4 +120,14 @@ public class TypeAnalysisTests
Console.WriteLine(o is Random); Console.WriteLine(o is Random);
Console.WriteLine(!(o is Random)); Console.WriteLine(!(o is Random));
} }
public byte[] CreateArrayWithInt(int length)
{
return new byte[length];
}
public byte[] CreateArrayWithLong(long length)
{
return new byte[length];
}
} }

Loading…
Cancel
Save