Browse Source

Infer types for the temporary variables introduced in ILAst.

pull/37/head
Daniel Grunwald 16 years ago
parent
commit
a61a4c2245
  1. 58
      ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs

58
ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs

@ -20,40 +20,69 @@ namespace Decompiler @@ -20,40 +20,69 @@ namespace Decompiler
/// </remarks>
public class TypeAnalysis
{
public static void Run(DecompilerContext context, ILNode node)
public static void Run(DecompilerContext context, ILBlock method)
{
TypeAnalysis ta = new TypeAnalysis();
ta.context = context;
ta.module = context.CurrentMethod.Module;
ta.typeSystem = ta.module.TypeSystem;
ta.InferTypes(node);
ta.method = method;
ta.InferTypes(method);
ta.InferRemainingStores();
}
DecompilerContext context;
TypeSystem typeSystem;
ILBlock method;
ModuleDefinition module;
List<ILExpression> storedToGeneratedVariables = new List<ILExpression>();
void InferTypes(ILNode node)
{
foreach (ILNode child in node.GetChildren()) {
ILExpression expr = child as ILExpression;
ILExpression expr = node as ILExpression;
if (expr != null) {
ILVariable v = expr.Operand as ILVariable;
if (v != null && v.IsGenerated && v.Type == null && expr.Code == ILCode.Stloc) {
if (v != null && v.IsGenerated && v.Type == null && expr.Code == ILCode.Stloc && HasSingleLoad(v)) {
// don't deal with this node or its children yet,
// wait for the expected type to be inferred first
storedToGeneratedVariables.Add(expr);
continue;
return;
}
bool anyArgumentIsMissingType = expr.Arguments.Any(a => a.InferredType == null);
if (expr.InferredType == null || anyArgumentIsMissingType)
expr.InferredType = InferTypeForExpression(expr, null, forceInferChildren: anyArgumentIsMissingType);
}
foreach (ILNode child in node.GetChildren()) {
InferTypes(child);
}
}
bool HasSingleLoad(ILVariable v)
{
int loads = 0;
foreach (ILExpression expr in method.GetSelfAndChildrenRecursive<ILExpression>()) {
if (expr.Operand == v) {
if (expr.Code == ILCode.Ldloc)
loads++;
else if (expr.Code != ILCode.Stloc)
return false;
}
}
return loads == 1;
}
void InferRemainingStores()
{
while (storedToGeneratedVariables.Count > 0) {
List<ILExpression> stored = storedToGeneratedVariables;
storedToGeneratedVariables = new List<ILExpression>();
foreach (ILExpression expr in stored)
InferTypes(expr);
if (!(storedToGeneratedVariables.Count < stored.Count))
throw new InvalidOperationException("Infinite loop in type analysis detected.");
}
}
/// <summary>
/// Infers the C# type of <paramref name="expr"/>.
/// </summary>
@ -73,11 +102,22 @@ namespace Decompiler @@ -73,11 +102,22 @@ namespace Decompiler
switch ((Code)expr.Code) {
#region Variable load/store
case Code.Stloc:
if (forceInferChildren)
InferTypeForExpression(expr.Arguments.Single(), ((ILVariable)expr.Operand).Type);
{
ILVariable v = (ILVariable)expr.Operand;
if (forceInferChildren || v.Type == null) {
TypeReference t = InferTypeForExpression(expr.Arguments.Single(), ((ILVariable)expr.Operand).Type);
if (v.Type == null)
v.Type = t;
}
}
return null;
case Code.Ldloc:
return ((ILVariable)expr.Operand).Type;
{
ILVariable v = (ILVariable)expr.Operand;
if (v.Type == null)
v.Type = expectedType;
return v.Type;
}
case Code.Starg:
if (forceInferChildren)
InferTypeForExpression(expr.Arguments.Single(), ((ParameterReference)expr.Operand).ParameterType);

Loading…
Cancel
Save