Browse Source

Use the same representation for parameters and variables.

pull/100/head
Daniel Grunwald 15 years ago
parent
commit
01d7e2abbd
  1. 52
      ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs
  2. 22
      ICSharpCode.Decompiler/Ast/NameVariables.cs
  3. 9
      ICSharpCode.Decompiler/Ast/Transforms/DelegateConstruction.cs
  4. 42
      ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs
  5. 1
      ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs
  6. 5
      ICSharpCode.Decompiler/ILAst/ILAstTypes.cs
  7. 20
      ICSharpCode.Decompiler/ILAst/ILCodes.cs
  8. 58
      ICSharpCode.Decompiler/ILAst/ILInlining.cs
  9. 4
      ICSharpCode.Decompiler/ILAst/PatternMatching.cs
  10. 4
      ICSharpCode.Decompiler/ILAst/PeepholeTransform.cs
  11. 8
      ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs
  12. 52
      ICSharpCode.Decompiler/ILAst/YieldReturnDecompiler.cs
  13. 3
      ILSpy/ILAstLanguage.cs

52
ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs

@ -64,9 +64,10 @@ namespace ICSharpCode.Decompiler.Ast @@ -64,9 +64,10 @@ namespace ICSharpCode.Decompiler.Ast
bodyGraph.Optimize(context, ilMethod);
context.CancellationToken.ThrowIfCancellationRequested();
var allVariables = ilMethod.GetSelfAndChildrenRecursive<ILExpression>(e => e.Operand is ILVariable).Select(e => (ILVariable)e.Operand).Distinct();
var allVariables = ilMethod.GetSelfAndChildrenRecursive<ILExpression>().Select(e => e.Operand as ILVariable)
.Where(v => v != null && !v.IsParameter).Distinct();
Debug.Assert(context.CurrentMethod == methodDef);
NameVariables.AssignNamesToVariables(context, allVariables, ilMethod);
NameVariables.AssignNamesToVariables(context, astBuilder.Parameters, allVariables, ilMethod);
context.CancellationToken.ThrowIfCancellationRequested();
Ast.BlockStatement astBlock = TransformBlock(ilMethod);
@ -401,26 +402,6 @@ namespace ICSharpCode.Decompiler.Ast @@ -401,26 +402,6 @@ namespace ICSharpCode.Decompiler.Ast
case ILCode.DefaultValue:
return MakeDefaultValue((TypeReference)operand);
case ILCode.Jmp: return InlineAssembly(byteCode, args);
case ILCode.Ldarg: {
if (methodDef.HasThis && ((ParameterDefinition)operand).Index < 0) {
if (context.CurrentMethod.DeclaringType.IsValueType)
return MakeRef(new Ast.ThisReferenceExpression());
else
return new Ast.ThisReferenceExpression();
} else {
var expr = new Ast.IdentifierExpression(((ParameterDefinition)operand).Name).WithAnnotation(operand);
if (((ParameterDefinition)operand).ParameterType is ByReferenceType)
return MakeRef(expr);
else
return expr;
}
}
case ILCode.Ldarga:
if (methodDef.HasThis && ((ParameterDefinition)operand).Index < 0) {
return MakeRef(new Ast.ThisReferenceExpression());
} else {
return MakeRef(new Ast.IdentifierExpression(((ParameterDefinition)operand).Name).WithAnnotation(operand));
}
case ILCode.Ldc_I4: return AstBuilder.MakePrimitive((int)operand, byteCode.InferredType);
case ILCode.Ldc_I8: return AstBuilder.MakePrimitive((long)operand, byteCode.InferredType);
case ILCode.Ldc_R4:
@ -448,12 +429,25 @@ namespace ICSharpCode.Decompiler.Ast @@ -448,12 +429,25 @@ namespace ICSharpCode.Decompiler.Ast
return MakeRef(
AstBuilder.ConvertType(((FieldReference)operand).DeclaringType)
.Member(((FieldReference)operand).Name).WithAnnotation(operand));
case ILCode.Ldloc:
localVariablesToDefine.Add((ILVariable)operand);
return new Ast.IdentifierExpression(((ILVariable)operand).Name).WithAnnotation(operand);
case ILCode.Ldloca:
localVariablesToDefine.Add((ILVariable)operand);
case ILCode.Ldloc: {
ILVariable v = (ILVariable)operand;
if (!v.IsParameter)
localVariablesToDefine.Add((ILVariable)operand);
Expression expr;
if (v.IsParameter && v.OriginalParameter.Index < 0)
expr = new ThisReferenceExpression();
else
expr = new Ast.IdentifierExpression(((ILVariable)operand).Name).WithAnnotation(operand);
return v.IsParameter && v.Type is ByReferenceType ? MakeRef(expr) : expr;
}
case ILCode.Ldloca: {
ILVariable v = (ILVariable)operand;
if (v.IsParameter && v.OriginalParameter.Index < 0)
return MakeRef(new ThisReferenceExpression());
if (!v.IsParameter)
localVariablesToDefine.Add((ILVariable)operand);
return MakeRef(new Ast.IdentifierExpression(((ILVariable)operand).Name).WithAnnotation(operand));
}
case ILCode.Ldnull: return new Ast.NullReferenceExpression();
case ILCode.Ldstr: return new Ast.PrimitiveExpression(operand);
case ILCode.Ldtoken:
@ -497,10 +491,10 @@ namespace ICSharpCode.Decompiler.Ast @@ -497,10 +491,10 @@ namespace ICSharpCode.Decompiler.Ast
}
case ILCode.Rethrow: return new Ast.ThrowStatement();
case ILCode.Sizeof: return new Ast.SizeOfExpression { Type = operandAsTypeRef };
case ILCode.Starg: return new Ast.AssignmentExpression(new Ast.IdentifierExpression(((ParameterDefinition)operand).Name).WithAnnotation(operand), arg1);
case ILCode.Stloc: {
ILVariable locVar = (ILVariable)operand;
localVariablesToDefine.Add(locVar);
if (!locVar.IsParameter)
localVariablesToDefine.Add(locVar);
return new Ast.AssignmentExpression(new Ast.IdentifierExpression(locVar.Name).WithAnnotation(locVar), arg1);
}
case ILCode.Switch: return InlineAssembly(byteCode, args);

22
ICSharpCode.Decompiler/Ast/NameVariables.cs

@ -31,20 +31,20 @@ namespace ICSharpCode.Decompiler.Ast @@ -31,20 +31,20 @@ namespace ICSharpCode.Decompiler.Ast
};
public static void AssignNamesToVariables(DecompilerContext context, IEnumerable<ILVariable> variables, ILBlock methodBody)
public static void AssignNamesToVariables(DecompilerContext context, IEnumerable<ILVariable> parameters, IEnumerable<ILVariable> variables, ILBlock methodBody)
{
NameVariables nv = new NameVariables();
nv.context = context;
nv.fieldNamesInCurrentType = context.CurrentType.Fields.Select(f => f.Name).ToList();
nv.AddExistingNames(context.CurrentMethod.Parameters.Select(p => p.Name));
nv.AddExistingNames(parameters.Select(p => p.Name));
nv.AddExistingNames(variables.Where(v => v.IsGenerated).Select(v => v.Name));
foreach (ParameterDefinition p in context.CurrentMethod.Parameters) {
foreach (ILVariable p in parameters) {
if (string.IsNullOrEmpty(p.Name))
p.Name = nv.GenerateNameForVariableOrParameter(p, p.ParameterType, methodBody);
p.Name = nv.GenerateNameForVariable(p, methodBody);
}
foreach (ILVariable varDef in variables) {
if (!varDef.IsGenerated) {
varDef.Name = nv.GenerateNameForVariableOrParameter(varDef, varDef.Type, methodBody);
varDef.Name = nv.GenerateNameForVariable(varDef, methodBody);
}
}
}
@ -80,10 +80,10 @@ namespace ICSharpCode.Decompiler.Ast @@ -80,10 +80,10 @@ namespace ICSharpCode.Decompiler.Ast
}
}
string GenerateNameForVariableOrParameter(object variableOrParameter, TypeReference varType, ILBlock methodBody)
string GenerateNameForVariable(ILVariable variable, ILBlock methodBody)
{
string proposedName = null;
if (varType == context.CurrentType.Module.TypeSystem.Int32) {
if (variable.Type == context.CurrentType.Module.TypeSystem.Int32) {
// test whether the variable might be a loop counter
bool isLoopCounter = false;
foreach (ILWhileLoop loop in methodBody.GetSelfAndChildrenRecursive<ILWhileLoop>()) {
@ -97,7 +97,7 @@ namespace ICSharpCode.Decompiler.Ast @@ -97,7 +97,7 @@ namespace ICSharpCode.Decompiler.Ast
case ILCode.Cgt:
case ILCode.Cgt_Un:
ILVariable loadVar;
if (expr.Arguments[0].Match(ILCode.Ldloc, out loadVar) && loadVar == variableOrParameter) {
if (expr.Arguments[0].Match(ILCode.Ldloc, out loadVar) && loadVar == variable) {
isLoopCounter = true;
}
break;
@ -117,7 +117,7 @@ namespace ICSharpCode.Decompiler.Ast @@ -117,7 +117,7 @@ namespace ICSharpCode.Decompiler.Ast
if (string.IsNullOrEmpty(proposedName)) {
var proposedNameForStores =
(from expr in methodBody.GetSelfAndChildrenRecursive<ILExpression>()
where expr.Code == ILCode.Stloc && expr.Operand == variableOrParameter
where expr.Code == ILCode.Stloc && expr.Operand == variable
select GetNameFromExpression(expr.Arguments.Single())
).Except(fieldNamesInCurrentType).ToList();
if (proposedNameForStores.Count == 1) {
@ -129,7 +129,7 @@ namespace ICSharpCode.Decompiler.Ast @@ -129,7 +129,7 @@ namespace ICSharpCode.Decompiler.Ast
(from expr in methodBody.GetSelfAndChildrenRecursive<ILExpression>()
from i in Enumerable.Range(0, expr.Arguments.Count)
let arg = expr.Arguments[i]
where (arg.Code == ILCode.Ldloc || arg.Code == ILCode.Ldarg) && arg.Operand == variableOrParameter
where arg.Code == ILCode.Ldloc && arg.Operand == variable
select GetNameForArgument(expr, i)
).Except(fieldNamesInCurrentType).ToList();
if (proposedNameForLoads.Count == 1) {
@ -137,7 +137,7 @@ namespace ICSharpCode.Decompiler.Ast @@ -137,7 +137,7 @@ namespace ICSharpCode.Decompiler.Ast
}
}
if (string.IsNullOrEmpty(proposedName)) {
proposedName = GetNameByType(varType);
proposedName = GetNameByType(variable.Type);
}
if (!typeNames.ContainsKey(proposedName)) {

9
ICSharpCode.Decompiler/Ast/Transforms/DelegateConstruction.cs

@ -6,6 +6,7 @@ using System.Collections.Generic; @@ -6,6 +6,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Threading;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.ILAst;
using ICSharpCode.NRefactory.CSharp;
using ICSharpCode.NRefactory.CSharp.PatternMatching;
using Mono.Cecil;
@ -196,8 +197,8 @@ namespace ICSharpCode.Decompiler.Ast.Transforms @@ -196,8 +197,8 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
if (blockStatement.Parent.NodeType == NodeType.Member || blockStatement.Parent is Accessor) {
// Delete any following statements as long as they assign parameters to the display class
// Do parameter handling only for closures created in the top scope (direct child of method/accessor)
List<ParameterReference> parameterOccurrances = blockStatement.Descendants.OfType<IdentifierExpression>()
.Select(n => n.Annotation<ParameterReference>()).Where(p => p != null).ToList();
List<ILVariable> parameterOccurrances = blockStatement.Descendants.OfType<IdentifierExpression>()
.Select(n => n.Annotation<ILVariable>()).Where(p => p != null && p.IsParameter).ToList();
AstNode next;
for (; cur != null; cur = next) {
next = cur.NextSibling;
@ -218,8 +219,8 @@ namespace ICSharpCode.Decompiler.Ast.Transforms @@ -218,8 +219,8 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
isParameter = true;
} else if (right is IdentifierExpression) {
// handle parameters only if the whole method contains no other occurrance except for 'right'
ParameterReference param = right.Annotation<ParameterReference>();
isParameter = parameterOccurrances.Count(c => c == param) == 1;
ILVariable param = right.Annotation<ILVariable>();
isParameter = param.IsParameter && parameterOccurrances.Count(c => c == param) == 1;
}
if (isParameter) {
dict[m.Get<MemberReferenceExpression>("left").Single().Annotation<FieldReference>().ResolveWithinSameModule()] = right;

42
ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs

@ -450,6 +450,9 @@ namespace ICSharpCode.Decompiler.ILAst @@ -450,6 +450,9 @@ namespace ICSharpCode.Decompiler.ILAst
}
}
// Convert parameters to ILVariables
ConvertParameters(body);
return body;
}
@ -544,6 +547,45 @@ namespace ICSharpCode.Decompiler.ILAst @@ -544,6 +547,45 @@ namespace ICSharpCode.Decompiler.ILAst
}
}
public List<ILVariable> Parameters = new List<ILVariable>();
void ConvertParameters(List<ByteCode> body)
{
ILVariable thisParameter = null;
if (methodDef.HasThis) {
TypeReference type = methodDef.DeclaringType;
thisParameter = new ILVariable();
thisParameter.Type = type.IsValueType ? new ByReferenceType(type) : type;
thisParameter.Name = "this";
thisParameter.OriginalParameter = methodDef.Body.ThisParameter;
}
foreach (ParameterDefinition p in methodDef.Parameters) {
this.Parameters.Add(new ILVariable { Type = p.ParameterType, Name = p.Name, OriginalParameter = p });
}
foreach (ByteCode byteCode in body) {
ParameterDefinition p;
switch (byteCode.Code) {
case ILCode.__Ldarg:
p = (ParameterDefinition)byteCode.Operand;
byteCode.Code = ILCode.Ldloc;
byteCode.Operand = p.Index < 0 ? thisParameter : this.Parameters[p.Index];
break;
case ILCode.__Starg:
p = (ParameterDefinition)byteCode.Operand;
byteCode.Code = ILCode.Stloc;
byteCode.Operand = p.Index < 0 ? thisParameter : this.Parameters[p.Index];
break;
case ILCode.__Ldarga:
p = (ParameterDefinition)byteCode.Operand;
byteCode.Code = ILCode.Ldloca;
byteCode.Operand = p.Index < 0 ? thisParameter : this.Parameters[p.Index];
break;
}
}
if (thisParameter != null)
this.Parameters.Add(thisParameter);
}
List<ILNode> ConvertToAst(List<ByteCode> body, HashSet<ExceptionHandler> ehs)
{
List<ILNode> ast = new List<ILNode>();

1
ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs

@ -680,7 +680,6 @@ namespace ICSharpCode.Decompiler.ILAst @@ -680,7 +680,6 @@ namespace ICSharpCode.Decompiler.ILAst
switch(expr.Code) {
case ILCode.Ldloc:
case ILCode.Ldloca:
case ILCode.Ldarg:
case ILCode.Ldstr:
case ILCode.Ldnull:
case ILCode.Ldc_I4:

5
ICSharpCode.Decompiler/ILAst/ILAstTypes.cs

@ -200,6 +200,11 @@ namespace ICSharpCode.Decompiler.ILAst @@ -200,6 +200,11 @@ namespace ICSharpCode.Decompiler.ILAst
public bool IsGenerated;
public TypeReference Type;
public VariableDefinition OriginalVariable;
public ParameterDefinition OriginalParameter;
public bool IsParameter {
get { return OriginalParameter != null; }
}
public override string ToString()
{

20
ICSharpCode.Decompiler/ILAst/ILCodes.cs

@ -232,9 +232,9 @@ namespace ICSharpCode.Decompiler.ILAst @@ -232,9 +232,9 @@ namespace ICSharpCode.Decompiler.ILAst
Clt_Un,
Ldftn,
Ldvirtftn,
Ldarg,
Ldarga,
Starg,
__Ldarg,
__Ldarga,
__Starg,
Ldloc,
Ldloca,
Stloc,
@ -375,10 +375,10 @@ namespace ICSharpCode.Decompiler.ILAst @@ -375,10 +375,10 @@ namespace ICSharpCode.Decompiler.ILAst
public static void ExpandMacro(ref ILCode code, ref object operand, MethodBody methodBody)
{
switch (code) {
case ILCode.__Ldarg_0: code = ILCode.Ldarg; operand = methodBody.GetParameter(0); break;
case ILCode.__Ldarg_1: code = ILCode.Ldarg; operand = methodBody.GetParameter(1); break;
case ILCode.__Ldarg_2: code = ILCode.Ldarg; operand = methodBody.GetParameter(2); break;
case ILCode.__Ldarg_3: code = ILCode.Ldarg; operand = methodBody.GetParameter(3); break;
case ILCode.__Ldarg_0: code = ILCode.__Ldarg; operand = methodBody.GetParameter(0); break;
case ILCode.__Ldarg_1: code = ILCode.__Ldarg; operand = methodBody.GetParameter(1); break;
case ILCode.__Ldarg_2: code = ILCode.__Ldarg; operand = methodBody.GetParameter(2); break;
case ILCode.__Ldarg_3: code = ILCode.__Ldarg; operand = methodBody.GetParameter(3); break;
case ILCode.__Ldloc_0: code = ILCode.Ldloc; operand = methodBody.Variables[0]; break;
case ILCode.__Ldloc_1: code = ILCode.Ldloc; operand = methodBody.Variables[1]; break;
case ILCode.__Ldloc_2: code = ILCode.Ldloc; operand = methodBody.Variables[2]; break;
@ -387,9 +387,9 @@ namespace ICSharpCode.Decompiler.ILAst @@ -387,9 +387,9 @@ namespace ICSharpCode.Decompiler.ILAst
case ILCode.__Stloc_1: code = ILCode.Stloc; operand = methodBody.Variables[1]; break;
case ILCode.__Stloc_2: code = ILCode.Stloc; operand = methodBody.Variables[2]; break;
case ILCode.__Stloc_3: code = ILCode.Stloc; operand = methodBody.Variables[3]; break;
case ILCode.__Ldarg_S: code = ILCode.Ldarg; break;
case ILCode.__Ldarga_S: code = ILCode.Ldarga; break;
case ILCode.__Starg_S: code = ILCode.Starg; break;
case ILCode.__Ldarg_S: code = ILCode.__Ldarg; break;
case ILCode.__Ldarga_S: code = ILCode.__Ldarga; break;
case ILCode.__Starg_S: code = ILCode.__Starg; break;
case ILCode.__Ldloc_S: code = ILCode.Ldloc; break;
case ILCode.__Ldloca_S: code = ILCode.Ldloca; break;
case ILCode.__Stloc_S: code = ILCode.Stloc; break;

58
ICSharpCode.Decompiler/ILAst/ILInlining.cs

@ -17,10 +17,7 @@ namespace ICSharpCode.Decompiler.ILAst @@ -17,10 +17,7 @@ namespace ICSharpCode.Decompiler.ILAst
readonly ILBlock method;
internal Dictionary<ILVariable, int> numStloc = new Dictionary<ILVariable, int>();
internal Dictionary<ILVariable, int> numLdloc = new Dictionary<ILVariable, int>();
Dictionary<ILVariable, int> numLdloca = new Dictionary<ILVariable, int>();
Dictionary<ParameterDefinition, int> numStarg = new Dictionary<ParameterDefinition, int>();
Dictionary<ParameterDefinition, int> numLdarga = new Dictionary<ParameterDefinition, int>();
internal Dictionary<ILVariable, int> numLdloca = new Dictionary<ILVariable, int>();
public ILInlining(ILBlock method)
{
@ -33,8 +30,6 @@ namespace ICSharpCode.Decompiler.ILAst @@ -33,8 +30,6 @@ namespace ICSharpCode.Decompiler.ILAst
numStloc.Clear();
numLdloc.Clear();
numLdloca.Clear();
numStarg.Clear();
numLdarga.Clear();
// Analyse the whole method
foreach(ILExpression expr in method.GetSelfAndChildrenRecursive<ILExpression>()) {
@ -49,14 +44,6 @@ namespace ICSharpCode.Decompiler.ILAst @@ -49,14 +44,6 @@ namespace ICSharpCode.Decompiler.ILAst
} else {
throw new NotSupportedException(expr.Code.ToString());
}
} else {
ParameterDefinition pd = expr.Operand as ParameterDefinition;
if (pd != null) {
if (expr.Code == ILCode.Starg)
numStarg[pd] = numStarg.GetOrDefault(pd) + 1;
else if (expr.Code == ILCode.Ldarga)
numLdarga[pd] = numLdarga.GetOrDefault(pd) + 1;
}
}
}
}
@ -256,19 +243,7 @@ namespace ICSharpCode.Decompiler.ILAst @@ -256,19 +243,7 @@ namespace ICSharpCode.Decompiler.ILAst
}
// the expression is loading a non-forbidden variable
return true;
case ILCode.Ldarg:
// Also try moving over ldarg instructions - this is necessary because an earlier copy propagation
// step might have introduced ldarg in place of an ldloc that would be skipped.
ParameterDefinition loadedParam = (ParameterDefinition)expr.Operand;
if (numLdarga.GetOrDefault(loadedParam) != 0)
return false;
foreach (ILExpression potentialStore in expressionBeingMoved.GetSelfAndChildrenRecursive<ILExpression>()) {
if (potentialStore.Code == ILCode.Starg && potentialStore.Operand == loadedParam)
return false;
}
return true;
case ILCode.Ldloca:
case ILCode.Ldarga:
case ILCode.Ldflda:
case ILCode.Ldsflda:
case ILCode.Ldelema:
@ -290,30 +265,30 @@ namespace ICSharpCode.Decompiler.ILAst @@ -290,30 +265,30 @@ namespace ICSharpCode.Decompiler.ILAst
/// 1) assignments from arguments to local variables
/// If the target variable is assigned to only once (so always is that argument) and the argument is never changed (no ldarga/starg),
/// then we can replace the variable with the argument.
/// 2) assignments of 'ldloca/ldarga' to local variables
/// 2) assignments of address-loading instructions to local variables
/// </summary>
public void CopyPropagation()
{
foreach (ILBlock block in method.GetSelfAndChildrenRecursive<ILBlock>()) {
for (int i = 0; i < block.Body.Count; i++) {
ILVariable v;
ILExpression ldArg;
if (block.Body[i].Match(ILCode.Stloc, out v, out ldArg)
&& numStloc.GetOrDefault(v) == 1 && numLdloca.GetOrDefault(v) == 0
&& CanPerformCopyPropagation(ldArg))
ILExpression copiedExpr;
if (block.Body[i].Match(ILCode.Stloc, out v, out copiedExpr)
&& !v.IsParameter && numStloc.GetOrDefault(v) == 1 && numLdloca.GetOrDefault(v) == 0
&& CanPerformCopyPropagation(copiedExpr))
{
// un-inline the arguments of the ldArg instruction
ILVariable[] uninlinedArgs = new ILVariable[ldArg.Arguments.Count];
ILVariable[] uninlinedArgs = new ILVariable[copiedExpr.Arguments.Count];
for (int j = 0; j < uninlinedArgs.Length; j++) {
uninlinedArgs[j] = new ILVariable { IsGenerated = true, Name = v.Name + "_cp_" + j };
block.Body.Insert(i++, new ILExpression(ILCode.Stloc, uninlinedArgs[j], ldArg.Arguments[j]));
block.Body.Insert(i++, new ILExpression(ILCode.Stloc, uninlinedArgs[j], copiedExpr.Arguments[j]));
}
// perform copy propagation:
foreach (var expr in method.GetSelfAndChildrenRecursive<ILExpression>()) {
if (expr.Code == ILCode.Ldloc && expr.Operand == v) {
expr.Code = ldArg.Code;
expr.Operand = ldArg.Operand;
expr.Code = copiedExpr.Code;
expr.Operand = copiedExpr.Operand;
for (int j = 0; j < uninlinedArgs.Length; j++) {
expr.Arguments.Add(new ILExpression(ILCode.Ldloc, uninlinedArgs[j]));
}
@ -332,21 +307,20 @@ namespace ICSharpCode.Decompiler.ILAst @@ -332,21 +307,20 @@ namespace ICSharpCode.Decompiler.ILAst
}
}
bool CanPerformCopyPropagation(ILExpression ldArg)
bool CanPerformCopyPropagation(ILExpression expr)
{
switch (ldArg.Code) {
switch (expr.Code) {
case ILCode.Ldloca:
case ILCode.Ldarga:
case ILCode.Ldelema:
case ILCode.Ldflda:
case ILCode.Ldsflda:
// All address-loading instructions always return the same value for a given operand/argument combination,
// so they can be safely copied.
return true;
case ILCode.Ldarg:
// arguments can be copied only if they aren't assigned to (directly or indirectly via ldarga)
ParameterDefinition pd = (ParameterDefinition)ldArg.Operand;
return numLdarga.GetOrDefault(pd) == 0 && numStarg.GetOrDefault(pd) == 0;
case ILCode.Ldloc:
// Parameters can be copied only if they aren't assigned to (directly or indirectly via ldarga)
ILVariable v = (ILVariable)expr.Operand;
return v.IsParameter && numLdloca.GetOrDefault(v) == 0 && numStloc.GetOrDefault(v) == 0;
default:
return false;
}

4
ICSharpCode.Decompiler/ILAst/PatternMatching.cs

@ -105,8 +105,8 @@ namespace ICSharpCode.Decompiler.ILAst @@ -105,8 +105,8 @@ namespace ICSharpCode.Decompiler.ILAst
public static bool MatchThis(this ILNode node)
{
ParameterDefinition parDef;
return node.Match(ILCode.Ldarg, out parDef) && parDef.Index == -1;
ILVariable v;
return node.Match(ILCode.Ldloc, out v) && v.IsParameter && v.OriginalParameter.Index == -1;
}
}
}

4
ICSharpCode.Decompiler/ILAst/PeepholeTransform.cs

@ -151,8 +151,6 @@ namespace ICSharpCode.Decompiler.ILAst @@ -151,8 +151,6 @@ namespace ICSharpCode.Decompiler.ILAst
return SimplifyLdObjOrStObj(expr, ILCode.Stelem_Any);
case ILCode.Ldloca:
return SimplifyLdObjOrStObj(expr, ILCode.Stloc);
case ILCode.Ldarga:
return SimplifyLdObjOrStObj(expr, ILCode.Starg);
case ILCode.Ldflda:
return SimplifyLdObjOrStObj(expr, ILCode.Stfld);
case ILCode.Ldsflda:
@ -164,8 +162,6 @@ namespace ICSharpCode.Decompiler.ILAst @@ -164,8 +162,6 @@ namespace ICSharpCode.Decompiler.ILAst
return SimplifyLdObjOrStObj(expr, ILCode.Ldelem_Any);
case ILCode.Ldloca:
return SimplifyLdObjOrStObj(expr, ILCode.Ldloc);
case ILCode.Ldarga:
return SimplifyLdObjOrStObj(expr, ILCode.Ldarg);
case ILCode.Ldflda:
return SimplifyLdObjOrStObj(expr, ILCode.Ldfld);
case ILCode.Ldsflda:

8
ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs

@ -167,16 +167,8 @@ namespace ICSharpCode.Decompiler.ILAst @@ -167,16 +167,8 @@ namespace ICSharpCode.Decompiler.ILAst
}
return v.Type;
}
case ILCode.Starg:
if (forceInferChildren)
InferTypeForExpression(expr.Arguments.Single(), ((ParameterReference)expr.Operand).ParameterType);
return null;
case ILCode.Ldarg:
return ((ParameterReference)expr.Operand).ParameterType;
case ILCode.Ldloca:
return new ByReferenceType(((ILVariable)expr.Operand).Type);
case ILCode.Ldarga:
return new ByReferenceType(((ParameterReference)expr.Operand).ParameterType);
#endregion
#region Call / NewObj
case ILCode.Call:

52
ICSharpCode.Decompiler/ILAst/YieldReturnDecompiler.cs

@ -31,7 +31,7 @@ namespace ICSharpCode.Decompiler.ILAst @@ -31,7 +31,7 @@ namespace ICSharpCode.Decompiler.ILAst
MethodDefinition disposeMethod;
FieldDefinition stateField;
FieldDefinition currentField;
Dictionary<FieldDefinition, ParameterDefinition> fieldToParameterMap = new Dictionary<FieldDefinition, ParameterDefinition>();
Dictionary<FieldDefinition, ILVariable> fieldToParameterMap = new Dictionary<FieldDefinition, ILVariable>();
List<ILNode> newBody;
#region Run() method
@ -101,17 +101,18 @@ namespace ICSharpCode.Decompiler.ILAst @@ -101,17 +101,18 @@ namespace ICSharpCode.Decompiler.ILAst
int i;
for (i = 1; i < method.Body.Count; i++) {
// stfld(..., ldloc(var_1), ldarg(...))
// stfld(..., ldloc(var_1), ldloc(parameter))
FieldReference storedField;
ILExpression ldloc, ldarg;
if (!method.Body[i].Match(ILCode.Stfld, out storedField, out ldloc, out ldarg))
ILExpression ldloc, loadParameter;
if (!method.Body[i].Match(ILCode.Stfld, out storedField, out ldloc, out loadParameter))
break;
if (ldloc.Code != ILCode.Ldloc || ldarg.Code != ILCode.Ldarg)
ILVariable loadedVar, loadedArg;
if (!ldloc.Match(ILCode.Ldloc, out loadedVar) || !loadParameter.Match(ILCode.Ldloc, out loadedArg))
return false;
storedField = GetFieldDefinition(storedField);
if (ldloc.Operand != var1 || storedField == null)
if (loadedVar != var1 || storedField == null || !loadedArg.IsParameter)
return false;
fieldToParameterMap[(FieldDefinition)storedField] = (ParameterDefinition)ldarg.Operand;
fieldToParameterMap[(FieldDefinition)storedField] = loadedArg;
}
ILVariable var2;
ILExpression ldlocForStloc2;
@ -185,11 +186,11 @@ namespace ICSharpCode.Decompiler.ILAst @@ -185,11 +186,11 @@ namespace ICSharpCode.Decompiler.ILAst
FieldReference field;
ILExpression instExpr;
ILExpression stExpr;
ParameterDefinition arg;
ILVariable arg;
if (node.Match(ILCode.Stfld, out field, out instExpr, out stExpr) &&
instExpr.MatchThis() &&
stExpr.Match(ILCode.Ldarg, out arg) &&
arg.Index == 0)
stExpr.Match(ILCode.Ldloc, out arg) &&
arg.IsParameter && arg.OriginalParameter.Index == 0)
{
stateField = GetFieldDefinition(field);
}
@ -280,7 +281,7 @@ namespace ICSharpCode.Decompiler.ILAst @@ -280,7 +281,7 @@ namespace ICSharpCode.Decompiler.ILAst
FieldDefinition storedField = GetFieldDefinition(stField);
FieldDefinition loadedField = GetFieldDefinition(ldField);
if (storedField != null && loadedField != null) {
ParameterDefinition mappedParameter;
ILVariable mappedParameter;
if (fieldToParameterMap.TryGetValue(loadedField, out mappedParameter))
fieldToParameterMap[storedField] = mappedParameter;
}
@ -320,7 +321,7 @@ namespace ICSharpCode.Decompiler.ILAst @@ -320,7 +321,7 @@ namespace ICSharpCode.Decompiler.ILAst
ILExpression call = finallyBody[0] as ILExpression;
if (call == null || call.Code != ILCode.Call || call.Arguments.Count != 1)
throw new YieldAnalysisFailedException();
if (call.Arguments[0].Code != ILCode.Ldarg || ((ParameterDefinition)call.Arguments[0].Operand).Index >= 0)
if (!call.Arguments[0].MatchThis())
throw new YieldAnalysisFailedException();
if (!finallyBody[1].Match(ILCode.Endfinally))
throw new YieldAnalysisFailedException();
@ -605,12 +606,10 @@ namespace ICSharpCode.Decompiler.ILAst @@ -605,12 +606,10 @@ namespace ICSharpCode.Decompiler.ILAst
throw new YieldAnalysisFailedException();
return new SymbolicValue(SymbolicValueType.State);
case ILCode.Ldloc:
if (expr.Operand == rangeAnalysisStateVariable)
ILVariable loadedVariable = (ILVariable)expr.Operand;
if (loadedVariable == rangeAnalysisStateVariable)
return new SymbolicValue(SymbolicValueType.State);
else
throw new YieldAnalysisFailedException();
case ILCode.Ldarg:
if (((ParameterDefinition)expr.Operand).Index < 0)
else if (loadedVariable.IsParameter && loadedVariable.OriginalParameter.Index < 0)
return new SymbolicValue(SymbolicValueType.This);
else
throw new YieldAnalysisFailedException();
@ -898,11 +897,10 @@ namespace ICSharpCode.Decompiler.ILAst @@ -898,11 +897,10 @@ namespace ICSharpCode.Decompiler.ILAst
switch (expr.Code) {
case ILCode.Ldfld:
if (expr.Arguments[0].MatchThis()) {
expr.Code = ILCode.Ldloc;
if (fieldToParameterMap.ContainsKey(field)) {
expr.Code = ILCode.Ldarg;
expr.Operand = fieldToParameterMap[field];
} else {
expr.Code = ILCode.Ldloc;
expr.Operand = fieldToLocalMap[field];
}
expr.Arguments.Clear();
@ -910,25 +908,25 @@ namespace ICSharpCode.Decompiler.ILAst @@ -910,25 +908,25 @@ namespace ICSharpCode.Decompiler.ILAst
break;
case ILCode.Stfld:
if (expr.Arguments[0].MatchThis()) {
expr.Code = ILCode.Stloc;
if (fieldToParameterMap.ContainsKey(field)) {
expr.Code = ILCode.Starg;
expr.Operand = fieldToParameterMap[field];
} else {
expr.Code = ILCode.Stloc;
expr.Operand = fieldToLocalMap[field];
}
expr.Arguments.RemoveAt(0);
}
break;
case ILCode.Ldflda:
if (fieldToParameterMap.ContainsKey(field)) {
expr.Code = ILCode.Ldarga;
expr.Operand = fieldToParameterMap[field];
} else {
if (expr.Arguments[0].MatchThis()) {
expr.Code = ILCode.Ldloca;
expr.Operand = fieldToLocalMap[field];
if (fieldToParameterMap.ContainsKey(field)) {
expr.Operand = fieldToParameterMap[field];
} else {
expr.Operand = fieldToLocalMap[field];
}
expr.Arguments.Clear();
}
expr.Arguments.Clear();
break;
}
}

3
ILSpy/ILAstLanguage.cs

@ -60,7 +60,8 @@ namespace ICSharpCode.ILSpy @@ -60,7 +60,8 @@ namespace ICSharpCode.ILSpy
new ILAstOptimizer().Optimize(context, ilMethod, abortBeforeStep.Value);
}
var allVariables = ilMethod.GetSelfAndChildrenRecursive<ILExpression>(e => e.Operand is ILVariable).Select(e => (ILVariable)e.Operand).Distinct();
var allVariables = ilMethod.GetSelfAndChildrenRecursive<ILExpression>().Select(e => e.Operand as ILVariable)
.Where(v => v != null && !v.IsParameter).Distinct();
foreach (ILVariable v in allVariables) {
output.WriteDefinition(v.Name, v);
if (v.Type != null) {

Loading…
Cancel
Save