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 @@ -525,6 +525,10 @@ namespace ICSharpCode.Decompiler.Ast
case ILCode.Conv_Ovf_U2_Un:
case ILCode.Conv_Ovf_U4_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
CastExpression cast = arg1 as CastExpression;
@ -533,11 +537,8 @@ namespace ICSharpCode.Decompiler.Ast @@ -533,11 +537,8 @@ namespace ICSharpCode.Decompiler.Ast
}
return arg1;
}
case ILCode.Conv_Ovf_I: return arg1.CastTo(new SimpleType("IntPtr")); // TODO
case ILCode.Conv_Ovf_U: return arg1.CastTo(new SimpleType("UIntPtr"));
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.Castclass:
return arg1.CastTo(operandAsTypeRef);
case ILCode.Unbox_Any:
// 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))

7
ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs

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

148
ICSharpCode.Decompiler/ILAst/InitializerPeepholeTransforms.cs

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

66
ICSharpCode.Decompiler/ILAst/PeepholeTransform.cs

@ -28,8 +28,20 @@ namespace ICSharpCode.Decompiler.ILAst @@ -28,8 +28,20 @@ namespace ICSharpCode.Decompiler.ILAst
{
public partial class ILAstOptimizer
{
#region TransformDecimalCtorToConstant
static bool TransformDecimalCtorToConstant(List<ILNode> body, ILExpression expr, int pos)
#region TypeConversionSimplifications
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;
List<ILExpression> args;
@ -62,11 +74,34 @@ namespace ICSharpCode.Decompiler.ILAst @@ -62,11 +74,34 @@ namespace ICSharpCode.Decompiler.ILAst
}
}
}
bool modified = false;
foreach(ILExpression arg in expr.Arguments) {
modified |= TransformDecimalCtorToConstant(null, arg, -1);
return false;
}
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
@ -129,25 +164,6 @@ namespace ICSharpCode.Decompiler.ILAst @@ -129,25 +164,6 @@ namespace ICSharpCode.Decompiler.ILAst
}
#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
void CachedDelegateInitializationWithField(ILBlock block, ref int i)
{

15
ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs

@ -606,8 +606,19 @@ namespace ICSharpCode.Decompiler.ILAst @@ -606,8 +606,19 @@ namespace ICSharpCode.Decompiler.ILAst
#endregion
#region Array instructions
case ILCode.Newarr:
if (forceInferChildren)
InferTypeForExpression(expr.Arguments.Single(), typeSystem.Int32);
if (forceInferChildren) {
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);
case ILCode.InitArray:
var operandAsArrayType = (ArrayType)expr.Operand;

10
ICSharpCode.Decompiler/Tests/TypeAnalysisTests.cs

@ -120,4 +120,14 @@ public class TypeAnalysisTests @@ -120,4 +120,14 @@ public class TypeAnalysisTests
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