Browse Source

Fix handling of recombined variables and nested functions in IntroduceNativeIntTypeOnLocals and IntroduceDynamicTypeOnLocals.

pull/2971/head
Siegfried Pammer 2 years ago
parent
commit
29ca38d338
  1. 49
      ICSharpCode.Decompiler/IL/Transforms/IntroduceDynamicTypeOnLocals.cs
  2. 40
      ICSharpCode.Decompiler/IL/Transforms/IntroduceNativeIntTypeOnLocals.cs

49
ICSharpCode.Decompiler/IL/Transforms/IntroduceDynamicTypeOnLocals.cs

@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ICSharpCode.Decompiler.IL.Transforms;
@ -29,28 +30,46 @@ namespace ICSharpCode.Decompiler.IL @@ -29,28 +30,46 @@ namespace ICSharpCode.Decompiler.IL
{
public void Run(ILFunction function, ILTransformContext context)
{
foreach (var variable in function.Variables)
foreach (var nestedFunction in function.Descendants.OfType<ILFunction>())
{
if (variable.Kind != VariableKind.Local &&
variable.Kind != VariableKind.StackSlot &&
variable.Kind != VariableKind.ForeachLocal &&
variable.Kind != VariableKind.UsingLocal)
HashSet<int> dynamicVariables = new();
foreach (var variable in nestedFunction.Variables)
{
continue;
}
if (!variable.Type.IsKnownType(KnownTypeCode.Object) || variable.LoadCount == 0)
continue;
foreach (var load in variable.LoadInstructions)
{
if (load.Parent is DynamicInstruction dynamicInstruction)
if (variable.Kind != VariableKind.Local &&
variable.Kind != VariableKind.StackSlot &&
variable.Kind != VariableKind.ForeachLocal &&
variable.Kind != VariableKind.UsingLocal)
{
continue;
}
if (!variable.Type.IsKnownType(KnownTypeCode.Object) || variable.LoadCount == 0)
continue;
foreach (var load in variable.LoadInstructions)
{
var argumentInfo = dynamicInstruction.GetArgumentInfoOfChild(load.ChildIndex);
if (!argumentInfo.HasFlag(CSharpArgumentInfoFlags.UseCompileTimeType))
if (load.Parent is DynamicInstruction dynamicInstruction)
{
variable.Type = SpecialType.Dynamic;
var argumentInfo = dynamicInstruction.GetArgumentInfoOfChild(load.ChildIndex);
if (!argumentInfo.HasFlag(CSharpArgumentInfoFlags.UseCompileTimeType))
{
variable.Type = SpecialType.Dynamic;
if (variable.Index.HasValue && variable.Kind == VariableKind.Local)
{
dynamicVariables.Add(variable.Index.Value);
}
break;
}
}
}
}
foreach (var variable in nestedFunction.Variables)
{
if (variable.Index.HasValue && variable.Kind == VariableKind.Local
&& dynamicVariables.Contains(variable.Index.Value))
{
variable.Type = SpecialType.Dynamic;
continue;
}
}
}
}
}

40
ICSharpCode.Decompiler/IL/Transforms/IntroduceNativeIntTypeOnLocals.cs

@ -32,23 +32,37 @@ namespace ICSharpCode.Decompiler.IL @@ -32,23 +32,37 @@ namespace ICSharpCode.Decompiler.IL
{
if (!context.Settings.NativeIntegers)
return;
foreach (var variable in function.Variables)
foreach (var nestedFunction in function.Descendants.OfType<ILFunction>())
{
if (variable.Kind != VariableKind.Local &&
variable.Kind != VariableKind.StackSlot &&
variable.Kind != VariableKind.PatternLocal &&
variable.Kind != VariableKind.ForeachLocal &&
variable.Kind != VariableKind.UsingLocal)
Dictionary<int, IType> variableTypeMapping = new();
foreach (var variable in nestedFunction.Variables)
{
continue;
if (variable.Kind != VariableKind.Local &&
variable.Kind != VariableKind.StackSlot &&
variable.Kind != VariableKind.PatternLocal &&
variable.Kind != VariableKind.ForeachLocal &&
variable.Kind != VariableKind.UsingLocal)
{
continue;
}
if (!(variable.Type.IsKnownType(KnownTypeCode.IntPtr) || variable.Type.IsKnownType(KnownTypeCode.UIntPtr)))
continue;
bool isUsedAsNativeInt = variable.LoadInstructions.Any(IsUsedAsNativeInt);
bool isAssignedNativeInt = variable.StoreInstructions.Any(store => IsNativeIntStore(store, context.TypeSystem));
if (isUsedAsNativeInt || isAssignedNativeInt)
{
variable.Type = variable.Type.GetSign() == Sign.Unsigned ? SpecialType.NUInt : SpecialType.NInt;
if (variable.Kind == VariableKind.Local && variable.Index.HasValue)
variableTypeMapping[variable.Index.Value] = variable.Type;
}
}
if (!(variable.Type.IsKnownType(KnownTypeCode.IntPtr) || variable.Type.IsKnownType(KnownTypeCode.UIntPtr)))
continue;
bool isUsedAsNativeInt = variable.LoadInstructions.Any(IsUsedAsNativeInt);
bool isAssignedNativeInt = variable.StoreInstructions.Any(store => IsNativeIntStore(store, context.TypeSystem));
if (isUsedAsNativeInt || isAssignedNativeInt)
foreach (var variable in nestedFunction.Variables)
{
variable.Type = variable.Type.GetSign() == Sign.Unsigned ? SpecialType.NUInt : SpecialType.NInt;
if (variable.Kind == VariableKind.Local && variable.Index.HasValue
&& variableTypeMapping.TryGetValue(variable.Index.Value, out var type))
{
variable.Type = type;
}
}
}
}

Loading…
Cancel
Save