mirror of https://github.com/icsharpcode/ILSpy.git
11 changed files with 327 additions and 79 deletions
@ -0,0 +1,61 @@
@@ -0,0 +1,61 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under MIT X11 license (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Linq; |
||||
using Mono.Cecil; |
||||
|
||||
namespace Decompiler |
||||
{ |
||||
/// <summary>
|
||||
/// IL AST transformation that introduces array initializers.
|
||||
/// </summary>
|
||||
public class ArrayInitializers |
||||
{ |
||||
public static void Transform(ILBlock method) |
||||
{ |
||||
var newArrPattern = new StoreToGenerated(new ILExpression( |
||||
ILCode.Dup, null, |
||||
new ILExpression(ILCode.Newarr, ILExpression.AnyOperand, new ILExpression(ILCode.Ldc_I4, ILExpression.AnyOperand)) |
||||
)); |
||||
var arg1 = new StoreToGenerated(new LoadFromVariable(newArrPattern)); |
||||
var arg2 = new StoreToGenerated(new LoadFromVariable(newArrPattern)); |
||||
var initializeArrayPattern = new ILCall( |
||||
"System.Runtime.CompilerServices.RuntimeHelpers", "InitializeArray", |
||||
new LoadFromVariable(arg1), new ILExpression(ILCode.Ldtoken, ILExpression.AnyOperand)); |
||||
foreach (ILBlock block in method.GetSelfAndChildrenRecursive<ILBlock>()) { |
||||
for (int i = block.Body.Count - 4; i >= 0; i--) { |
||||
if (!newArrPattern.Match(block.Body[i])) |
||||
continue; |
||||
ILExpression newArrInst = ((ILExpression)block.Body[i]).Arguments[0].Arguments[0]; |
||||
int arrayLength = (int)newArrInst.Arguments[0].Operand; |
||||
if (!arg1.Match(block.Body[i + 1])) |
||||
continue; |
||||
if (!arg2.Match(block.Body[i + 2])) |
||||
continue; |
||||
if (initializeArrayPattern.Match(block.Body[i + 3])) { |
||||
FieldDefinition field = ((ILExpression)block.Body[i+3]).Arguments[1].Operand as FieldDefinition; |
||||
if (field == null || field.InitialValue == null) |
||||
continue; |
||||
switch (TypeAnalysis.GetTypeCode(newArrInst.Operand as TypeReference)) { |
||||
case TypeCode.Int32: |
||||
case TypeCode.UInt32: |
||||
if (field.InitialValue.Length == arrayLength * 4) { |
||||
ILExpression[] newArr = new ILExpression[arrayLength]; |
||||
for (int j = 0; j < newArr.Length; j++) { |
||||
newArr[j] = new ILExpression(ILCode.Ldc_I4, BitConverter.ToInt32(field.InitialValue, j * 4)); |
||||
} |
||||
block.Body[i] = new ILExpression(ILCode.Stloc, arg1.LastVariable, new ILExpression(ILCode.InitArray, newArrInst.Operand, newArr)); |
||||
block.Body.RemoveRange(i + 1, 3); |
||||
} |
||||
continue; |
||||
default: |
||||
continue; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
} |
||||
} |
@ -0,0 +1,102 @@
@@ -0,0 +1,102 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under MIT X11 license (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using Mono.Cecil; |
||||
|
||||
namespace Decompiler |
||||
{ |
||||
public interface IVariablePattern |
||||
{ |
||||
bool MatchVariable(ILVariable v); |
||||
} |
||||
|
||||
public class StoreToGenerated : ILExpression, IVariablePattern |
||||
{ |
||||
public ILExpression LastMatch; |
||||
|
||||
public ILVariable LastVariable { |
||||
get { |
||||
return LastMatch != null ? LastMatch.Operand as ILVariable : null; |
||||
} |
||||
} |
||||
|
||||
public StoreToGenerated(ILExpression arg) : base(ILCode.Pattern, null, arg) |
||||
{ |
||||
} |
||||
|
||||
public override bool Match(ILNode other) |
||||
{ |
||||
ILExpression expr = other as ILExpression; |
||||
if (expr != null && expr.Code == ILCode.Stloc && ((ILVariable)expr.Operand).IsGenerated && Match(this.Arguments, expr.Arguments)) { |
||||
this.LastMatch = expr; |
||||
return true; |
||||
} else { |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
bool IVariablePattern.MatchVariable(ILVariable v) |
||||
{ |
||||
return v == LastMatch.Operand; |
||||
} |
||||
} |
||||
|
||||
public class LoadFromVariable : ILExpression |
||||
{ |
||||
IVariablePattern v; |
||||
|
||||
public LoadFromVariable(IVariablePattern v) : base(ILCode.Pattern, null) |
||||
{ |
||||
this.v = v; |
||||
} |
||||
|
||||
public override bool Match(ILNode other) |
||||
{ |
||||
ILExpression expr = other as ILExpression; |
||||
return expr != null && expr.Code == ILCode.Ldloc && v.MatchVariable(expr.Operand as ILVariable); |
||||
} |
||||
} |
||||
|
||||
public class AnyILExpression : ILExpression |
||||
{ |
||||
public ILExpression LastMatch; |
||||
|
||||
public AnyILExpression() : base(ILCode.Pattern, null) |
||||
{ |
||||
} |
||||
|
||||
public override bool Match(ILNode other) |
||||
{ |
||||
if (other is ILExpression) { |
||||
LastMatch = (ILExpression)other; |
||||
return true; |
||||
} else { |
||||
return false; |
||||
} |
||||
} |
||||
} |
||||
|
||||
public class ILCall : ILExpression |
||||
{ |
||||
string fullClassName; |
||||
string methodName; |
||||
|
||||
public ILCall(string fullClassName, string methodName, params ILExpression[] args) : base(ILCode.Pattern, null, args) |
||||
{ |
||||
this.fullClassName = fullClassName; |
||||
this.methodName = methodName; |
||||
} |
||||
|
||||
public override bool Match(ILNode other) |
||||
{ |
||||
ILExpression expr = other as ILExpression; |
||||
if (expr != null && expr.Code == ILCode.Call) { |
||||
MethodReference r = (MethodReference)expr.Operand; |
||||
if (r.Name == methodName && r.DeclaringType.FullName == fullClassName) |
||||
return Match(this.Arguments, expr.Arguments); |
||||
} |
||||
return false; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,36 @@
@@ -0,0 +1,36 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under MIT X11 license (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
|
||||
public class ArrayInitializers |
||||
{ |
||||
// Helper methods used to ensure array initializers used within expressions work correctly
|
||||
static void X(object a, object b) |
||||
{ |
||||
} |
||||
|
||||
static object Y() |
||||
{ |
||||
return null; |
||||
} |
||||
|
||||
public static void Array1() |
||||
{ |
||||
X(Y(), new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }); |
||||
} |
||||
|
||||
public static void Array2(int a, int b, int c) |
||||
{ |
||||
X(Y(), new int[] { a, b, c }); |
||||
} |
||||
|
||||
public static void NestedArray(int a, int b, int c) |
||||
{ |
||||
X(Y(), new int[][] { |
||||
new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }, |
||||
new int[] { a, b, c }, |
||||
new int[] { 1, 2, 3, 4, 5, 6 } |
||||
}); |
||||
} |
||||
} |
Loading…
Reference in new issue