|
|
|
@ -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>
|
|
|
|
|