diff --git a/ICSharpCode.Decompiler/ILAst/InitializerPeepholeTransforms.cs b/ICSharpCode.Decompiler/ILAst/InitializerPeepholeTransforms.cs index 7552f2db7..9c920f816 100644 --- a/ICSharpCode.Decompiler/ILAst/InitializerPeepholeTransforms.cs +++ b/ICSharpCode.Decompiler/ILAst/InitializerPeepholeTransforms.cs @@ -135,8 +135,7 @@ namespace ICSharpCode.Decompiler.ILAst FieldDefinition fieldDef = fieldRef.ResolveWithinSameModule(); if (fieldDef != null && fieldDef.InitialValue != null) { ILExpression[] newArr = new ILExpression[arrayLength]; - if (DecodeArrayInitializer(TypeAnalysis.GetTypeCode(arrayType.GetElementType()), - fieldDef.InitialValue, newArr)) + if (DecodeArrayInitializer(arrayType.GetElementType(), fieldDef.InitialValue, newArr)) { values = newArr; foundPos = pos; @@ -149,81 +148,101 @@ namespace ICSharpCode.Decompiler.ILAst return false; } - static bool DecodeArrayInitializer(TypeCode elementType, 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: - if (initialValue.Length >= output.Length) { - for (int j = 0; j < output.Length; j++) { - output[j] = new ILExpression(ILCode.Ldc_I4, (int)initialValue[j]); - } - return true; - } - return false; - case TypeCode.SByte: - if (initialValue.Length >= output.Length) { - for (int j = 0; j < output.Length; j++) { - output[j] = new ILExpression(ILCode.Ldc_I4, (int)unchecked((sbyte)initialValue[j])); - } - return true; - } - return false; - case TypeCode.Int16: - if (initialValue.Length >= output.Length * 2) { - for (int j = 0; j < output.Length; j++) { - output[j] = new ILExpression(ILCode.Ldc_I4, (int)BitConverter.ToInt16(initialValue, j * 2)); - } - return true; - } - return false; + case TypeCode.Byte: + return DecodeArrayInitializer(initialValue, output, elementType, (d, i) => (int)d[i]); + case TypeCode.SByte: + return DecodeArrayInitializer(initialValue, output, elementType, (d, i) => (int)unchecked((sbyte)d[i])); + case TypeCode.Int16: + return DecodeArrayInitializer(initialValue, output, elementType, (d, i) => (int)BitConverter.ToInt16(d, i)); case TypeCode.Char: - case TypeCode.UInt16: - if (initialValue.Length >= output.Length * 2) { - for (int j = 0; j < output.Length; j++) { - output[j] = new ILExpression(ILCode.Ldc_I4, (int)BitConverter.ToUInt16(initialValue, j * 2)); - } - return true; - } - return false; + case TypeCode.UInt16: + return DecodeArrayInitializer(initialValue, output, elementType, (d, i) => (int)BitConverter.ToUInt16(d, i)); case TypeCode.Int32: - case TypeCode.UInt32: - if (initialValue.Length >= output.Length * 4) { - for (int j = 0; j < output.Length; j++) { - output[j] = new ILExpression(ILCode.Ldc_I4, BitConverter.ToInt32(initialValue, j * 4)); - } - return true; - } - return false; + case TypeCode.UInt32: + return DecodeArrayInitializer(initialValue, output, elementType, BitConverter.ToInt32); case TypeCode.Int64: - case TypeCode.UInt64: - if (initialValue.Length >= output.Length * 8) { - for (int j = 0; j < output.Length; j++) { - output[j] = new ILExpression(ILCode.Ldc_I8, BitConverter.ToInt64(initialValue, j * 8)); - } - return true; - } - return false; - case TypeCode.Single: - if (initialValue.Length >= output.Length * 4) { - for (int j = 0; j < output.Length; j++) { - output[j] = new ILExpression(ILCode.Ldc_R4, BitConverter.ToSingle(initialValue, j * 4)); - } - return true; - } - return false; - case TypeCode.Double: - if (initialValue.Length >= output.Length * 8) { - for (int j = 0; j < output.Length; j++) { - output[j] = new ILExpression(ILCode.Ldc_R8, BitConverter.ToDouble(initialValue, j * 8)); - } - return true; - } + case TypeCode.UInt64: + return DecodeArrayInitializer(initialValue, output, elementType, BitConverter.ToInt64); + case TypeCode.Single: + return DecodeArrayInitializer(initialValue, output, elementType, BitConverter.ToSingle); + case TypeCode.Double: + return DecodeArrayInitializer(initialValue, output, elementType, BitConverter.ToDouble); + case TypeCode.Object: + var typeDef = elementTypeRef.ResolveWithinSameModule(); + if (typeDef != null && typeDef.IsEnum) + return DecodeArrayInitializer(typeDef.GetEnumUnderlyingType(), initialValue, output); + return false; default: return false; } } + + static bool DecodeArrayInitializer(byte[] initialValue, ILExpression[] output, TypeCode elementType, Func 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 ///