Browse Source

Merge branch 'master' of git://github.com/icsharpcode/ILSpy into Debugger

pull/191/merge
Eusebiu Marcu 15 years ago
parent
commit
5b530035ad
  1. 58
      ICSharpCode.Decompiler/Ast/AstBuilder.cs
  2. 473
      ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs
  3. 2
      ICSharpCode.Decompiler/Ast/NRefactoryExtensions.cs
  4. 142
      ICSharpCode.Decompiler/Ast/NameVariables.cs
  5. 39
      ICSharpCode.Decompiler/Ast/Transforms/DelegateConstruction.cs
  6. 50
      ICSharpCode.Decompiler/Ast/Transforms/IntroduceUnsafeModifier.cs
  7. 1
      ICSharpCode.Decompiler/Ast/Transforms/TransformationPipeline.cs
  8. 1
      ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
  9. 42
      ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs
  10. 1
      ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs
  11. 5
      ICSharpCode.Decompiler/ILAst/ILAstTypes.cs
  12. 141
      ICSharpCode.Decompiler/ILAst/ILCodes.cs
  13. 58
      ICSharpCode.Decompiler/ILAst/ILInlining.cs
  14. 4
      ICSharpCode.Decompiler/ILAst/PatternMatching.cs
  15. 4
      ICSharpCode.Decompiler/ILAst/PeepholeTransform.cs
  16. 80
      ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs
  17. 52
      ICSharpCode.Decompiler/ILAst/YieldReturnDecompiler.cs
  18. 26
      ICSharpCode.Decompiler/Tests/CustomAttributes/S_CustomAttributes.cs
  19. 3
      ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj
  20. 29
      ICSharpCode.Decompiler/Tests/UnsafeCode.cs
  21. 3
      ILSpy/ILAstLanguage.cs
  22. 56
      NRefactory/ICSharpCode.NRefactory/CSharp/Ast/AstNode.cs

58
ICSharpCode.Decompiler/Ast/AstBuilder.cs

@ -610,9 +610,16 @@ namespace ICSharpCode.Decompiler.Ast @@ -610,9 +610,16 @@ namespace ICSharpCode.Decompiler.Ast
astMethod.Modifiers = ConvertModifiers(methodDef);
else
astMethod.PrivateImplementationType = ConvertType(methodDef.Overrides.First().DeclaringType);
astMethod.Body = AstMethodBodyBuilder.CreateMethodBody(methodDef, context);
astMethod.Body = AstMethodBodyBuilder.CreateMethodBody(methodDef, context, astMethod.Parameters);
}
ConvertAttributes(astMethod, methodDef);
if (methodDef.HasCustomAttributes && astMethod.Parameters.Count > 0) {
foreach (CustomAttribute ca in methodDef.CustomAttributes) {
if (ca.AttributeType.Name == "ExtensionAttribute" && ca.AttributeType.Namespace == "System.Runtime.CompilerServices") {
astMethod.Parameters.First().ParameterModifier = ParameterModifier.This;
}
}
}
astMethod.WithAnnotation(methodMapping);
return astMethod;
}
@ -669,7 +676,7 @@ namespace ICSharpCode.Decompiler.Ast @@ -669,7 +676,7 @@ namespace ICSharpCode.Decompiler.Ast
}
astMethod.Name = CleanName(methodDef.DeclaringType.Name);
astMethod.Parameters.AddRange(MakeParameters(methodDef.Parameters));
astMethod.Body = AstMethodBodyBuilder.CreateMethodBody(methodDef, context);
astMethod.Body = AstMethodBodyBuilder.CreateMethodBody(methodDef, context, astMethod.Parameters);
ConvertAttributes(astMethod, methodDef);
astMethod.WithAnnotation(methodMapping);
return astMethod;
@ -837,13 +844,19 @@ namespace ICSharpCode.Decompiler.Ast @@ -837,13 +844,19 @@ namespace ICSharpCode.Decompiler.Ast
{
foreach(ParameterDefinition paramDef in paramCol) {
ParameterDeclaration astParam = new ParameterDeclaration();
astParam.AddAnnotation(paramDef);
astParam.Type = ConvertType(paramDef.ParameterType, paramDef);
astParam.Name = paramDef.Name;
if (paramDef.ParameterType is ByReferenceType) {
astParam.ParameterModifier = (!paramDef.IsIn && paramDef.IsOut) ? ParameterModifier.Out : ParameterModifier.Ref;
}
// TODO: params, this
if (paramDef.HasCustomAttributes) {
foreach (CustomAttribute ca in paramDef.CustomAttributes) {
if (ca.AttributeType.Name == "ParamArrayAttribute" && ca.AttributeType.Namespace == "System")
astParam.ParameterModifier = ParameterModifier.Params;
}
}
ConvertCustomAttributes(astParam, paramDef);
ModuleDefinition module = ((MethodDefinition)paramDef.Method).Module;
@ -1070,6 +1083,15 @@ namespace ICSharpCode.Decompiler.Ast @@ -1070,6 +1083,15 @@ namespace ICSharpCode.Decompiler.Ast
if (customAttributeProvider.HasCustomAttributes) {
var attributes = new List<ICSharpCode.NRefactory.CSharp.Attribute>();
foreach (var customAttribute in customAttributeProvider.CustomAttributes) {
if (customAttribute.AttributeType.Name == "ExtensionAttribute" && customAttribute.AttributeType.Namespace == "System.Runtime.CompilerServices") {
// don't show the ExtensionAttribute (it's converted to the 'this' modifier)
continue;
}
if (customAttribute.AttributeType.Name == "ParamArrayAttribute" && customAttribute.AttributeType.Namespace == "System") {
// don't show the ParamArrayAttribute (it's converted to the 'params' modifier)
continue;
}
var attribute = new ICSharpCode.NRefactory.CSharp.Attribute();
attribute.AddAnnotation(customAttribute);
attribute.Type = ConvertType(customAttribute.AttributeType);
@ -1115,7 +1137,7 @@ namespace ICSharpCode.Decompiler.Ast @@ -1115,7 +1137,7 @@ namespace ICSharpCode.Decompiler.Ast
section.Attributes.Add(attribute);
attributedNode.AddChild(section, AttributedNode.AttributeRole);
}
} else {
} else if (attributes.Count > 0) {
// use single section for all attributes
var section = new AttributeSection();
section.AttributeTarget = target;
@ -1125,17 +1147,31 @@ namespace ICSharpCode.Decompiler.Ast @@ -1125,17 +1147,31 @@ namespace ICSharpCode.Decompiler.Ast
}
}
private static Expression ConvertArgumentValue(CustomAttributeArgument parameter)
private static Expression ConvertArgumentValue(CustomAttributeArgument argument)
{
var type = parameter.Type.Resolve();
if (argument.Value is CustomAttributeArgument[]) {
ArrayInitializerExpression arrayInit = new ArrayInitializerExpression();
foreach (CustomAttributeArgument element in (CustomAttributeArgument[])argument.Value) {
arrayInit.Elements.Add(ConvertArgumentValue(element));
}
ArrayType arrayType = argument.Type as ArrayType;
return new ArrayCreateExpression {
Type = ConvertType(arrayType != null ? arrayType.ElementType : argument.Type),
Initializer = arrayInit
};
} else if (argument.Value is CustomAttributeArgument) {
// occurs with boxed arguments
return ConvertArgumentValue((CustomAttributeArgument)argument.Value);
}
var type = argument.Type.Resolve();
if (type != null && type.IsEnum) {
return MakePrimitive(Convert.ToInt64(parameter.Value), type);
} else if (parameter.Value is TypeReference) {
return MakePrimitive(Convert.ToInt64(argument.Value), type);
} else if (argument.Value is TypeReference) {
return new TypeOfExpression() {
Type = ConvertType((TypeReference)parameter.Value),
Type = ConvertType((TypeReference)argument.Value),
};
} else {
return new PrimitiveExpression(parameter.Value);
return new PrimitiveExpression(argument.Value);
}
}
#endregion
@ -1146,6 +1182,8 @@ namespace ICSharpCode.Decompiler.Ast @@ -1146,6 +1182,8 @@ namespace ICSharpCode.Decompiler.Ast
return new Ast.PrimitiveExpression(false);
else if (TypeAnalysis.IsBoolean(type) && val == 1)
return new Ast.PrimitiveExpression(true);
else if (val == 0 && type is PointerType)
return new Ast.NullReferenceExpression();
if (type != null)
{ // cannot rely on type.IsValueType, it's not set for typerefs (but is set for typespecs)
TypeDefinition enumDefinition = type.Resolve();

473
ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs

@ -24,7 +24,15 @@ namespace ICSharpCode.Decompiler.Ast @@ -24,7 +24,15 @@ namespace ICSharpCode.Decompiler.Ast
HashSet<ILVariable> localVariablesToDefine = new HashSet<ILVariable>(); // local variables that are missing a definition
HashSet<ILVariable> implicitlyDefinedVariables = new HashSet<ILVariable>(); // local variables that are implicitly defined (e.g. catch handler)
public static BlockStatement CreateMethodBody(MethodDefinition methodDef, DecompilerContext context)
/// <summary>
/// Creates the body for the method definition.
/// </summary>
/// <param name="methodDef">Method definition to decompile.</param>
/// <param name="context">Decompilation context.</param>
/// <param name="parameters">Parameter declarations of the method being decompiled.
/// These are used to update the parameter names when the decompiler generates names for the parameters.</param>
/// <returns>Block for the method body</returns>
public static BlockStatement CreateMethodBody(MethodDefinition methodDef, DecompilerContext context, IEnumerable<ParameterDeclaration> parameters = null)
{
MethodDefinition oldCurrentMethod = context.CurrentMethod;
Debug.Assert(oldCurrentMethod == null || oldCurrentMethod == methodDef);
@ -35,10 +43,10 @@ namespace ICSharpCode.Decompiler.Ast @@ -35,10 +43,10 @@ namespace ICSharpCode.Decompiler.Ast
builder.context = context;
builder.typeSystem = methodDef.Module.TypeSystem;
if (Debugger.IsAttached) {
return builder.CreateMethodBody();
return builder.CreateMethodBody(parameters);
} else {
try {
return builder.CreateMethodBody();
return builder.CreateMethodBody(parameters);
} catch (OperationCanceledException) {
throw;
} catch (Exception ex) {
@ -50,7 +58,7 @@ namespace ICSharpCode.Decompiler.Ast @@ -50,7 +58,7 @@ namespace ICSharpCode.Decompiler.Ast
}
}
public BlockStatement CreateMethodBody()
public BlockStatement CreateMethodBody(IEnumerable<ParameterDeclaration> parameters)
{
if (methodDef.Body == null) return null;
@ -64,8 +72,19 @@ namespace ICSharpCode.Decompiler.Ast @@ -64,8 +72,19 @@ 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).Where(v => !v.IsGenerated).Distinct();
NameVariables.AssignNamesToVariables(methodDef.Parameters.Select(p => p.Name), allVariables, ilMethod);
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, astBuilder.Parameters, allVariables, ilMethod);
if (parameters != null) {
foreach (var pair in (from p in parameters
join v in astBuilder.Parameters on p.Annotation<ParameterDefinition>() equals v.OriginalParameter
select new { p, v.Name }))
{
pair.p.Name = pair.Name;
}
}
context.CancellationToken.ThrowIfCancellationRequested();
Ast.BlockStatement astBlock = TransformBlock(ilMethod);
@ -205,48 +224,48 @@ namespace ICSharpCode.Decompiler.Ast @@ -205,48 +224,48 @@ namespace ICSharpCode.Decompiler.Ast
Ast.Expression arg3 = args.Count >= 3 ? args[2] : null;
switch(byteCode.Code) {
#region Arithmetic
case ILCode.Add: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Add, arg2);
case ILCode.Add_Ovf: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Add, arg2);
case ILCode.Add_Ovf_Un: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Add, arg2);
case ILCode.Div: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Divide, arg2);
case ILCode.Div_Un: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Divide, arg2);
case ILCode.Mul: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Multiply, arg2);
case ILCode.Mul_Ovf: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Multiply, arg2);
case ILCode.Mul_Ovf_Un: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Multiply, arg2);
case ILCode.Rem: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Modulus, arg2);
case ILCode.Rem_Un: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Modulus, arg2);
case ILCode.Sub: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Subtract, arg2);
case ILCode.Sub_Ovf: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Subtract, arg2);
case ILCode.Sub_Ovf_Un: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Subtract, arg2);
case ILCode.And: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.BitwiseAnd, arg2);
case ILCode.Or: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.BitwiseOr, arg2);
case ILCode.Xor: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.ExclusiveOr, arg2);
case ILCode.Shl: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.ShiftLeft, arg2);
case ILCode.Shr: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.ShiftRight, arg2);
case ILCode.Shr_Un: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.ShiftRight, arg2);
case ILCode.Neg: return new Ast.UnaryOperatorExpression(UnaryOperatorType.Minus, arg1);
case ILCode.Not: return new Ast.UnaryOperatorExpression(UnaryOperatorType.BitNot, arg1);
#endregion
#region Arrays
#region Arithmetic
case ILCode.Add: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Add, arg2);
case ILCode.Add_Ovf: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Add, arg2);
case ILCode.Add_Ovf_Un: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Add, arg2);
case ILCode.Div: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Divide, arg2);
case ILCode.Div_Un: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Divide, arg2);
case ILCode.Mul: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Multiply, arg2);
case ILCode.Mul_Ovf: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Multiply, arg2);
case ILCode.Mul_Ovf_Un: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Multiply, arg2);
case ILCode.Rem: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Modulus, arg2);
case ILCode.Rem_Un: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Modulus, arg2);
case ILCode.Sub: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Subtract, arg2);
case ILCode.Sub_Ovf: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Subtract, arg2);
case ILCode.Sub_Ovf_Un: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Subtract, arg2);
case ILCode.And: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.BitwiseAnd, arg2);
case ILCode.Or: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.BitwiseOr, arg2);
case ILCode.Xor: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.ExclusiveOr, arg2);
case ILCode.Shl: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.ShiftLeft, arg2);
case ILCode.Shr: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.ShiftRight, arg2);
case ILCode.Shr_Un: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.ShiftRight, arg2);
case ILCode.Neg: return new Ast.UnaryOperatorExpression(UnaryOperatorType.Minus, arg1);
case ILCode.Not: return new Ast.UnaryOperatorExpression(UnaryOperatorType.BitNot, arg1);
#endregion
#region Arrays
case ILCode.Newarr:
case ILCode.InitArray: {
var ace = new Ast.ArrayCreateExpression();
ace.Type = operandAsTypeRef;
ComposedType ct = operandAsTypeRef as ComposedType;
if (ct != null) {
// change "new (int[,])[10] to new int[10][,]"
ct.ArraySpecifiers.MoveTo(ace.AdditionalArraySpecifiers);
}
if (byteCode.Code == ILCode.InitArray) {
ace.Initializer = new ArrayInitializerExpression();
ace.Initializer.Elements.AddRange(args);
} else {
ace.Arguments.Add(arg1);
case ILCode.InitArray: {
var ace = new Ast.ArrayCreateExpression();
ace.Type = operandAsTypeRef;
ComposedType ct = operandAsTypeRef as ComposedType;
if (ct != null) {
// change "new (int[,])[10] to new int[10][,]"
ct.ArraySpecifiers.MoveTo(ace.AdditionalArraySpecifiers);
}
if (byteCode.Code == ILCode.InitArray) {
ace.Initializer = new ArrayInitializerExpression();
ace.Initializer.Elements.AddRange(args);
} else {
ace.Arguments.Add(arg1);
}
return ace;
}
return ace;
}
case ILCode.Ldlen: return arg1.Member("Length");
case ILCode.Ldlen: return arg1.Member("Length");
case ILCode.Ldelem_I:
case ILCode.Ldelem_I1:
case ILCode.Ldelem_I2:
@ -260,7 +279,7 @@ namespace ICSharpCode.Decompiler.Ast @@ -260,7 +279,7 @@ namespace ICSharpCode.Decompiler.Ast
case ILCode.Ldelem_Ref:
case ILCode.Ldelem_Any:
return arg1.Indexer(arg2);
case ILCode.Ldelema: return MakeRef(arg1.Indexer(arg2));
case ILCode.Ldelema: return MakeRef(arg1.Indexer(arg2));
case ILCode.Stelem_I:
case ILCode.Stelem_I1:
case ILCode.Stelem_I2:
@ -271,30 +290,30 @@ namespace ICSharpCode.Decompiler.Ast @@ -271,30 +290,30 @@ namespace ICSharpCode.Decompiler.Ast
case ILCode.Stelem_Ref:
case ILCode.Stelem_Any:
return new Ast.AssignmentExpression(arg1.Indexer(arg2), arg3);
#endregion
#region Comparison
case ILCode.Ceq: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Equality, arg2);
case ILCode.Cgt: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.GreaterThan, arg2);
case ILCode.Cgt_Un: {
// can also mean Inequality, when used with object references
TypeReference arg1Type = byteCode.Arguments[0].InferredType;
if (arg1Type != null && !arg1Type.IsValueType)
return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.InEquality, arg2);
else
return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.GreaterThan, arg2);
}
case ILCode.Clt: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.LessThan, arg2);
case ILCode.Clt_Un: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.LessThan, arg2);
#endregion
#region Logical
case ILCode.LogicNot: return new Ast.UnaryOperatorExpression(UnaryOperatorType.Not, arg1);
case ILCode.LogicAnd: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.ConditionalAnd, arg2);
case ILCode.LogicOr: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.ConditionalOr, arg2);
case ILCode.TernaryOp: return new Ast.ConditionalExpression() { Condition = arg1, TrueExpression = arg2, FalseExpression = arg3 };
case ILCode.NullCoalescing: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.NullCoalescing, arg2);
#endregion
#region Branch
case ILCode.Br: return new Ast.GotoStatement(((ILLabel)byteCode.Operand).Name);
#endregion
#region Comparison
case ILCode.Ceq: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Equality, arg2);
case ILCode.Cgt: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.GreaterThan, arg2);
case ILCode.Cgt_Un: {
// can also mean Inequality, when used with object references
TypeReference arg1Type = byteCode.Arguments[0].InferredType;
if (arg1Type != null && !arg1Type.IsValueType)
return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.InEquality, arg2);
else
return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.GreaterThan, arg2);
}
case ILCode.Clt: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.LessThan, arg2);
case ILCode.Clt_Un: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.LessThan, arg2);
#endregion
#region Logical
case ILCode.LogicNot: return new Ast.UnaryOperatorExpression(UnaryOperatorType.Not, arg1);
case ILCode.LogicAnd: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.ConditionalAnd, arg2);
case ILCode.LogicOr: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.ConditionalOr, arg2);
case ILCode.TernaryOp: return new Ast.ConditionalExpression() { Condition = arg1, TrueExpression = arg2, FalseExpression = arg3 };
case ILCode.NullCoalescing: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.NullCoalescing, arg2);
#endregion
#region Branch
case ILCode.Br: return new Ast.GotoStatement(((ILLabel)byteCode.Operand).Name);
case ILCode.Brtrue:
return new Ast.IfElseStatement() {
Condition = arg1,
@ -302,10 +321,10 @@ namespace ICSharpCode.Decompiler.Ast @@ -302,10 +321,10 @@ namespace ICSharpCode.Decompiler.Ast
new Ast.GotoStatement(((ILLabel)byteCode.Operand).Name)
}
};
case ILCode.LoopOrSwitchBreak: return new Ast.BreakStatement();
case ILCode.LoopContinue: return new Ast.ContinueStatement();
#endregion
#region Conversions
case ILCode.LoopOrSwitchBreak: return new Ast.BreakStatement();
case ILCode.LoopContinue: return new Ast.ContinueStatement();
#endregion
#region Conversions
case ILCode.Conv_I1:
case ILCode.Conv_I2:
case ILCode.Conv_I4:
@ -314,12 +333,12 @@ namespace ICSharpCode.Decompiler.Ast @@ -314,12 +333,12 @@ namespace ICSharpCode.Decompiler.Ast
case ILCode.Conv_U2:
case ILCode.Conv_U4:
case ILCode.Conv_U8:
case ILCode.Conv_I:
case ILCode.Conv_U:
return arg1; // conversion is handled by Convert() function using the info from type analysis
case ILCode.Conv_I: return arg1.CastTo(typeof(IntPtr)); // TODO
case ILCode.Conv_U: return arg1.CastTo(typeof(UIntPtr)); // TODO
case ILCode.Conv_R4: return arg1.CastTo(typeof(float));
case ILCode.Conv_R8: return arg1.CastTo(typeof(double));
case ILCode.Conv_R_Un: return arg1.CastTo(typeof(double)); // TODO
case ILCode.Conv_R4: return arg1.CastTo(typeof(float));
case ILCode.Conv_R8: return arg1.CastTo(typeof(double));
case ILCode.Conv_R_Un: return arg1.CastTo(typeof(double)); // TODO
case ILCode.Conv_Ovf_I1:
case ILCode.Conv_Ovf_I2:
case ILCode.Conv_Ovf_I4:
@ -337,76 +356,59 @@ namespace ICSharpCode.Decompiler.Ast @@ -337,76 +356,59 @@ namespace ICSharpCode.Decompiler.Ast
case ILCode.Conv_Ovf_U4_Un:
case ILCode.Conv_Ovf_U8_Un:
return arg1; // conversion was handled by Convert() function using the info from type analysis
case ILCode.Conv_Ovf_I: return arg1.CastTo(typeof(IntPtr)); // TODO
case ILCode.Conv_Ovf_U: return arg1.CastTo(typeof(UIntPtr));
case ILCode.Conv_Ovf_I_Un: return arg1.CastTo(typeof(IntPtr));
case ILCode.Conv_Ovf_U_Un: return arg1.CastTo(typeof(UIntPtr));
case ILCode.Castclass: return arg1.CastTo(operandAsTypeRef);
case ILCode.Unbox_Any: return arg1.CastTo(operandAsTypeRef);
case ILCode.Isinst: return arg1.CastAs(operandAsTypeRef);
case ILCode.Box: return arg1;
case ILCode.Unbox: return InlineAssembly(byteCode, args);
#endregion
#region Indirect
case ILCode.Ldind_I:
case ILCode.Ldind_I1:
case ILCode.Ldind_I2:
case ILCode.Ldind_I4:
case ILCode.Ldind_I8:
case ILCode.Ldind_U1:
case ILCode.Ldind_U2:
case ILCode.Ldind_U4:
case ILCode.Ldind_R4:
case ILCode.Ldind_R8:
case ILCode.Conv_Ovf_I: return arg1.CastTo(typeof(IntPtr)); // TODO
case ILCode.Conv_Ovf_U: return arg1.CastTo(typeof(UIntPtr));
case ILCode.Conv_Ovf_I_Un: return arg1.CastTo(typeof(IntPtr));
case ILCode.Conv_Ovf_U_Un: return arg1.CastTo(typeof(UIntPtr));
case ILCode.Castclass: return arg1.CastTo(operandAsTypeRef);
case ILCode.Unbox_Any: return arg1.CastTo(operandAsTypeRef);
case ILCode.Isinst: return arg1.CastAs(operandAsTypeRef);
case ILCode.Box: return arg1;
case ILCode.Unbox: return InlineAssembly(byteCode, args);
#endregion
#region Indirect
case ILCode.Ldind_Ref:
case ILCode.Ldobj:
if (args[0] is DirectionExpression)
return ((DirectionExpression)args[0]).Expression.Detach();
if (arg1 is DirectionExpression)
return ((DirectionExpression)arg1).Expression.Detach();
else
return InlineAssembly(byteCode, args);
case ILCode.Stind_I:
case ILCode.Stind_I1:
case ILCode.Stind_I2:
case ILCode.Stind_I4:
case ILCode.Stind_I8:
case ILCode.Stind_R4:
case ILCode.Stind_R8:
return new UnaryOperatorExpression(UnaryOperatorType.Dereference, arg1);
case ILCode.Stind_Ref:
case ILCode.Stobj:
if (args[0] is DirectionExpression)
return new AssignmentExpression(((DirectionExpression)args[0]).Expression.Detach(), args[1]);
if (arg1 is DirectionExpression)
return new AssignmentExpression(((DirectionExpression)arg1).Expression.Detach(), arg2);
else
return InlineAssembly(byteCode, args);
#endregion
case ILCode.Arglist: return InlineAssembly(byteCode, args);
case ILCode.Break: return InlineAssembly(byteCode, args);
case ILCode.Call: return TransformCall(false, operand, methodDef, args);
case ILCode.Callvirt: return TransformCall(true, operand, methodDef, args);
case ILCode.Ldftn: {
Cecil.MethodReference cecilMethod = ((MethodReference)operand);
var expr = new Ast.IdentifierExpression(cecilMethod.Name);
expr.TypeArguments.AddRange(ConvertTypeArguments(cecilMethod));
expr.AddAnnotation(cecilMethod);
return new IdentifierExpression("ldftn").Invoke(expr)
.WithAnnotation(new Transforms.DelegateConstruction.Annotation(false));
}
case ILCode.Ldvirtftn: {
Cecil.MethodReference cecilMethod = ((MethodReference)operand);
var expr = new Ast.IdentifierExpression(cecilMethod.Name);
expr.TypeArguments.AddRange(ConvertTypeArguments(cecilMethod));
expr.AddAnnotation(cecilMethod);
return new IdentifierExpression("ldvirtftn").Invoke(expr)
.WithAnnotation(new Transforms.DelegateConstruction.Annotation(true));
}
case ILCode.Calli: return InlineAssembly(byteCode, args);
case ILCode.Ckfinite: return InlineAssembly(byteCode, args);
case ILCode.Constrained: return InlineAssembly(byteCode, args);
case ILCode.Cpblk: return InlineAssembly(byteCode, args);
case ILCode.Cpobj: return InlineAssembly(byteCode, args);
case ILCode.Dup: return arg1;
case ILCode.Endfilter: return InlineAssembly(byteCode, args);
case ILCode.Endfinally: return null;
case ILCode.Initblk: return InlineAssembly(byteCode, args);
return new AssignmentExpression(new UnaryOperatorExpression(UnaryOperatorType.Dereference, arg1), arg2);
#endregion
case ILCode.Arglist: return InlineAssembly(byteCode, args);
case ILCode.Break: return InlineAssembly(byteCode, args);
case ILCode.Call: return TransformCall(false, operand, methodDef, args);
case ILCode.Callvirt: return TransformCall(true, operand, methodDef, args);
case ILCode.Ldftn: {
Cecil.MethodReference cecilMethod = ((MethodReference)operand);
var expr = new Ast.IdentifierExpression(cecilMethod.Name);
expr.TypeArguments.AddRange(ConvertTypeArguments(cecilMethod));
expr.AddAnnotation(cecilMethod);
return new IdentifierExpression("ldftn").Invoke(expr)
.WithAnnotation(new Transforms.DelegateConstruction.Annotation(false));
}
case ILCode.Ldvirtftn: {
Cecil.MethodReference cecilMethod = ((MethodReference)operand);
var expr = new Ast.IdentifierExpression(cecilMethod.Name);
expr.TypeArguments.AddRange(ConvertTypeArguments(cecilMethod));
expr.AddAnnotation(cecilMethod);
return new IdentifierExpression("ldvirtftn").Invoke(expr)
.WithAnnotation(new Transforms.DelegateConstruction.Annotation(true));
}
case ILCode.Calli: return InlineAssembly(byteCode, args);
case ILCode.Ckfinite: return InlineAssembly(byteCode, args);
case ILCode.Constrained: return InlineAssembly(byteCode, args);
case ILCode.Cpblk: return InlineAssembly(byteCode, args);
case ILCode.Cpobj: return InlineAssembly(byteCode, args);
case ILCode.Dup: return arg1;
case ILCode.Endfilter: return InlineAssembly(byteCode, args);
case ILCode.Endfinally: return null;
case ILCode.Initblk: return InlineAssembly(byteCode, args);
case ILCode.Initobj:
if (args[0] is DirectionExpression)
return new AssignmentExpression(((DirectionExpression)args[0]).Expression.Detach(), MakeDefaultValue((TypeReference)operand));
@ -414,29 +416,9 @@ namespace ICSharpCode.Decompiler.Ast @@ -414,29 +416,9 @@ namespace ICSharpCode.Decompiler.Ast
return InlineAssembly(byteCode, args);
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.Jmp: return InlineAssembly(byteCode, args);
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:
case ILCode.Ldc_R8:
case ILCode.Ldc_Decimal:
@ -457,93 +439,106 @@ namespace ICSharpCode.Decompiler.Ast @@ -457,93 +439,106 @@ namespace ICSharpCode.Decompiler.Ast
AstBuilder.ConvertType(((FieldReference)operand).DeclaringType)
.Member(((FieldReference)operand).Name).WithAnnotation(operand),
arg1);
case ILCode.Ldflda: return MakeRef(arg1.Member(((FieldReference) operand).Name).WithAnnotation(operand));
case ILCode.Ldflda: return MakeRef(arg1.Member(((FieldReference) operand).Name).WithAnnotation(operand));
case ILCode.Ldsflda:
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);
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.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:
if (operand is Cecil.TypeReference) {
return new Ast.TypeOfExpression { Type = operandAsTypeRef }.Member("TypeHandle");
} else {
return InlineAssembly(byteCode, args);
}
case ILCode.Leave: return new GotoStatement() { Label = ((ILLabel)operand).Name };
case ILCode.Localloc: return InlineAssembly(byteCode, args);
case ILCode.Mkrefany: return InlineAssembly(byteCode, args);
case ILCode.Newobj: {
Cecil.TypeReference declaringType = ((MethodReference)operand).DeclaringType;
if (declaringType is ArrayType) {
ComposedType ct = AstBuilder.ConvertType((ArrayType)declaringType) as ComposedType;
if (ct != null && ct.ArraySpecifiers.Count >= 1) {
var ace = new Ast.ArrayCreateExpression();
ct.ArraySpecifiers.First().Remove();
ct.ArraySpecifiers.MoveTo(ace.AdditionalArraySpecifiers);
ace.Type = ct;
ace.Arguments.AddRange(args);
return ace;
case ILCode.Leave: return new GotoStatement() { Label = ((ILLabel)operand).Name };
case ILCode.Localloc: return InlineAssembly(byteCode, args);
case ILCode.Mkrefany: return InlineAssembly(byteCode, args);
case ILCode.Newobj: {
Cecil.TypeReference declaringType = ((MethodReference)operand).DeclaringType;
if (declaringType is ArrayType) {
ComposedType ct = AstBuilder.ConvertType((ArrayType)declaringType) as ComposedType;
if (ct != null && ct.ArraySpecifiers.Count >= 1) {
var ace = new Ast.ArrayCreateExpression();
ct.ArraySpecifiers.First().Remove();
ct.ArraySpecifiers.MoveTo(ace.AdditionalArraySpecifiers);
ace.Type = ct;
ace.Arguments.AddRange(args);
return ace;
}
}
var oce = new Ast.ObjectCreateExpression();
oce.Type = AstBuilder.ConvertType(declaringType);
oce.Arguments.AddRange(args);
return oce.WithAnnotation(operand);
}
var oce = new Ast.ObjectCreateExpression();
oce.Type = AstBuilder.ConvertType(declaringType);
oce.Arguments.AddRange(args);
return oce.WithAnnotation(operand);
}
case ILCode.No: return InlineAssembly(byteCode, args);
case ILCode.Nop: return null;
case ILCode.Pop: return arg1;
case ILCode.Readonly: return InlineAssembly(byteCode, args);
case ILCode.Refanytype: return InlineAssembly(byteCode, args);
case ILCode.Refanyval: return InlineAssembly(byteCode, args);
case ILCode.No: return InlineAssembly(byteCode, args);
case ILCode.Nop: return null;
case ILCode.Pop: return arg1;
case ILCode.Readonly: return InlineAssembly(byteCode, args);
case ILCode.Refanytype: return InlineAssembly(byteCode, args);
case ILCode.Refanyval: return InlineAssembly(byteCode, args);
case ILCode.Ret:
if (methodDef.ReturnType.FullName != "System.Void") {
return new Ast.ReturnStatement { Expression = arg1 };
} else {
return new Ast.ReturnStatement();
}
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);
return new Ast.AssignmentExpression(new Ast.IdentifierExpression(locVar.Name).WithAnnotation(locVar), arg1);
}
case ILCode.Switch: return InlineAssembly(byteCode, args);
case ILCode.Tail: return InlineAssembly(byteCode, args);
case ILCode.Throw: return new Ast.ThrowStatement { Expression = arg1 };
case ILCode.Unaligned: return InlineAssembly(byteCode, args);
case ILCode.Volatile: return InlineAssembly(byteCode, args);
case ILCode.Rethrow: return new Ast.ThrowStatement();
case ILCode.Sizeof: return new Ast.SizeOfExpression { Type = operandAsTypeRef };
case ILCode.Stloc: {
ILVariable locVar = (ILVariable)operand;
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);
case ILCode.Tail: return InlineAssembly(byteCode, args);
case ILCode.Throw: return new Ast.ThrowStatement { Expression = arg1 };
case ILCode.Unaligned: return InlineAssembly(byteCode, args);
case ILCode.Volatile: return InlineAssembly(byteCode, args);
case ILCode.YieldBreak:
return new Ast.YieldBreakStatement();
case ILCode.YieldReturn:
return new Ast.YieldStatement { Expression = arg1 };
case ILCode.InitCollection: {
ObjectCreateExpression oce = (ObjectCreateExpression)arg1;
oce.Initializer = new ArrayInitializerExpression();
for (int i = 1; i < args.Count; i++) {
ArrayInitializerExpression aie = args[i] as ArrayInitializerExpression;
if (aie != null && aie.Elements.Count == 1)
oce.Initializer.Elements.Add(aie.Elements.Single().Detach());
else
oce.Initializer.Elements.Add(args[i]);
case ILCode.InitCollection: {
ObjectCreateExpression oce = (ObjectCreateExpression)arg1;
oce.Initializer = new ArrayInitializerExpression();
for (int i = 1; i < args.Count; i++) {
ArrayInitializerExpression aie = args[i] as ArrayInitializerExpression;
if (aie != null && aie.Elements.Count == 1)
oce.Initializer.Elements.Add(aie.Elements.Single().Detach());
else
oce.Initializer.Elements.Add(args[i]);
}
return oce;
}
return oce;
}
case ILCode.InitCollectionAddMethod: {
var collectionInit = new ArrayInitializerExpression();
collectionInit.Elements.AddRange(args);
return collectionInit;
}
default: throw new Exception("Unknown OpCode: " + byteCode.Code);
case ILCode.InitCollectionAddMethod: {
var collectionInit = new ArrayInitializerExpression();
collectionInit.Elements.AddRange(args);
return collectionInit;
}
default: throw new Exception("Unknown OpCode: " + byteCode.Code);
}
}
@ -772,6 +767,22 @@ namespace ICSharpCode.Decompiler.Ast @@ -772,6 +767,22 @@ namespace ICSharpCode.Decompiler.Ast
{
if (reqType == null || actualType == reqType) {
return expr;
} else if (actualType is ByReferenceType && reqType is PointerType && expr is DirectionExpression) {
return Convert(
new UnaryOperatorExpression(UnaryOperatorType.AddressOf, ((DirectionExpression)expr).Expression.Detach()),
new PointerType(((ByReferenceType)actualType).ElementType),
reqType);
} else if (actualType is PointerType && reqType is ByReferenceType) {
expr = Convert(expr, actualType, new PointerType(((ByReferenceType)reqType).ElementType));
return new DirectionExpression {
FieldDirection = FieldDirection.Ref,
Expression = new UnaryOperatorExpression(UnaryOperatorType.Dereference, expr)
};
} else if (actualType is PointerType && reqType is PointerType) {
if (actualType.FullName != reqType.FullName)
return expr.CastTo(AstBuilder.ConvertType(reqType));
else
return expr;
} else {
bool actualIsIntegerOrEnum = TypeAnalysis.IsIntegerOrEnum(actualType);
bool requiredIsIntegerOrEnum = TypeAnalysis.IsIntegerOrEnum(reqType);

2
ICSharpCode.Decompiler/Ast/NRefactoryExtensions.cs

@ -17,7 +17,7 @@ namespace ICSharpCode.Decompiler.Ast @@ -17,7 +17,7 @@ namespace ICSharpCode.Decompiler.Ast
public static T CopyAnnotationsFrom<T>(this T node, AstNode other) where T : AstNode
{
foreach (var annotation in other.Annotations<object>()) {
foreach (object annotation in other.Annotations) {
node.AddAnnotation(annotation);
}
return node;

142
ICSharpCode.Decompiler/Ast/NameVariables.cs

@ -31,15 +31,26 @@ namespace ICSharpCode.Decompiler.Ast @@ -31,15 +31,26 @@ namespace ICSharpCode.Decompiler.Ast
};
public static void AssignNamesToVariables(IEnumerable<string> existingNames, IEnumerable<ILVariable> variables, ILBlock methodBody)
public static void AssignNamesToVariables(DecompilerContext context, IEnumerable<ILVariable> parameters, IEnumerable<ILVariable> variables, ILBlock methodBody)
{
NameVariables nv = new NameVariables();
nv.AddExistingNames(existingNames);
nv.context = context;
nv.fieldNamesInCurrentType = context.CurrentType.Fields.Select(f => f.Name).ToList();
nv.AddExistingNames(parameters.Select(p => p.Name));
nv.AddExistingNames(variables.Where(v => v.IsGenerated).Select(v => v.Name));
foreach (ILVariable p in parameters) {
if (string.IsNullOrEmpty(p.Name))
p.Name = nv.GenerateNameForVariable(p, methodBody);
}
foreach (ILVariable varDef in variables) {
nv.AssignNameToVariable(varDef, methodBody.GetSelfAndChildrenRecursive<ILExpression>());
if (!varDef.IsGenerated) {
varDef.Name = nv.GenerateNameForVariable(varDef, methodBody);
}
}
}
DecompilerContext context;
List<string> fieldNamesInCurrentType;
Dictionary<string, int> typeNames = new Dictionary<string, int>();
void AddExistingNames(IEnumerable<string> existingNames)
@ -69,29 +80,74 @@ namespace ICSharpCode.Decompiler.Ast @@ -69,29 +80,74 @@ namespace ICSharpCode.Decompiler.Ast
}
}
void AssignNameToVariable(ILVariable varDef, IEnumerable<ILExpression> allExpressions)
string GenerateNameForVariable(ILVariable variable, ILBlock methodBody)
{
string proposedName = null;
foreach (ILExpression expr in allExpressions) {
if (expr.Operand != varDef)
continue;
if (expr.Code == ILCode.Stloc) {
proposedName = GetNameFromExpression(expr.Arguments.Single());
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>()) {
ILExpression expr = loop.Condition;
while (expr != null && expr.Code == ILCode.LogicNot)
expr = expr.Arguments[0];
if (expr != null) {
switch (expr.Code) {
case ILCode.Clt:
case ILCode.Clt_Un:
case ILCode.Cgt:
case ILCode.Cgt_Un:
ILVariable loadVar;
if (expr.Arguments[0].Match(ILCode.Ldloc, out loadVar) && loadVar == variable) {
isLoopCounter = true;
}
break;
}
}
}
if (isLoopCounter) {
// For loop variables, use i,j,k,l,m,n
for (char c = 'i'; c <= 'n'; c++) {
if (!typeNames.ContainsKey(c.ToString())) {
proposedName = c.ToString();
break;
}
}
}
}
if (string.IsNullOrEmpty(proposedName)) {
var proposedNameForStores =
(from expr in methodBody.GetSelfAndChildrenRecursive<ILExpression>()
where expr.Code == ILCode.Stloc && expr.Operand == variable
select GetNameFromExpression(expr.Arguments.Single())
).Except(fieldNamesInCurrentType).ToList();
if (proposedNameForStores.Count == 1) {
proposedName = proposedNameForStores[0];
}
if (proposedName != null)
break;
}
if (proposedName == null)
proposedName = GetNameByType(varDef.Type);
if (string.IsNullOrEmpty(proposedName)) {
var proposedNameForLoads =
(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.Operand == variable
select GetNameForArgument(expr, i)
).Except(fieldNamesInCurrentType).ToList();
if (proposedNameForLoads.Count == 1) {
proposedName = proposedNameForLoads[0];
}
}
if (string.IsNullOrEmpty(proposedName)) {
proposedName = GetNameByType(variable.Type);
}
if (!typeNames.ContainsKey(proposedName)) {
typeNames.Add(proposedName, 0);
}
int count = ++typeNames[proposedName];
if (count > 1) {
varDef.Name = proposedName + count.ToString();
return proposedName + count.ToString();
} else {
varDef.Name = proposedName;
return proposedName;
}
}
@ -99,19 +155,15 @@ namespace ICSharpCode.Decompiler.Ast @@ -99,19 +155,15 @@ namespace ICSharpCode.Decompiler.Ast
{
switch (expr.Code) {
case ILCode.Ldfld:
// Use the field name only if it's not a field on this (avoid confusion between local variables and fields)
if (!(expr.Arguments[0].Code == ILCode.Ldarg && ((ParameterDefinition)expr.Arguments[0].Operand).Index < 0))
return CleanUpVariableName(((FieldReference)expr.Operand).Name);
break;
case ILCode.Ldsfld:
return CleanUpVariableName(((FieldReference)expr.Operand).Name);
case ILCode.Call:
case ILCode.Callvirt:
MethodReference mr = (MethodReference)expr.Operand;
if (mr.Name.StartsWith("get_", StringComparison.Ordinal) && mr.Parameters.Count == 0) {
if (mr.Name.StartsWith("get_", StringComparison.OrdinalIgnoreCase) && mr.Parameters.Count == 0) {
// use name from properties, but not from indexers
return CleanUpVariableName(mr.Name.Substring(4));
} else if (mr.Name.StartsWith("Get", StringComparison.Ordinal) && mr.Name.Length >= 4 && char.IsUpper(mr.Name[3])) {
} else if (mr.Name.StartsWith("Get", StringComparison.OrdinalIgnoreCase) && mr.Name.Length >= 4 && char.IsUpper(mr.Name[3])) {
// use name from Get-methods
return CleanUpVariableName(mr.Name.Substring(3));
}
@ -120,6 +172,40 @@ namespace ICSharpCode.Decompiler.Ast @@ -120,6 +172,40 @@ namespace ICSharpCode.Decompiler.Ast
return null;
}
static string GetNameForArgument(ILExpression parent, int i)
{
switch (parent.Code) {
case ILCode.Stfld:
case ILCode.Stsfld:
if (i == parent.Arguments.Count - 1) // last argument is stored value
return CleanUpVariableName(((FieldReference)parent.Operand).Name);
else
break;
case ILCode.Call:
case ILCode.Callvirt:
case ILCode.Newobj:
MethodReference methodRef = (MethodReference)parent.Operand;
if (methodRef.Parameters.Count == 1 && i == parent.Arguments.Count - 1) {
// argument might be value of a setter
if (methodRef.Name.StartsWith("set_", StringComparison.OrdinalIgnoreCase)) {
return CleanUpVariableName(methodRef.Name.Substring(4));
} else if (methodRef.Name.StartsWith("Set", StringComparison.OrdinalIgnoreCase) && methodRef.Name.Length >= 4 && char.IsUpper(methodRef.Name[3])) {
return CleanUpVariableName(methodRef.Name.Substring(3));
}
}
MethodDefinition methodDef = methodRef.Resolve();
if (methodDef != null) {
var p = methodDef.Parameters.ElementAtOrDefault((parent.Code != ILCode.Newobj && methodDef.HasThis) ? i - 1 : i);
if (p != null && !string.IsNullOrEmpty(p.Name))
return CleanUpVariableName(p.Name);
}
break;
case ILCode.Ret:
return "result";
}
return null;
}
string GetNameByType(TypeReference type)
{
GenericInstanceType git = type as GenericInstanceType;
@ -127,13 +213,6 @@ namespace ICSharpCode.Decompiler.Ast @@ -127,13 +213,6 @@ namespace ICSharpCode.Decompiler.Ast
type = ((GenericInstanceType)type).GenericArguments[0];
}
if (type.FullName == "System.Int32") {
// try i,j,k, etc.
for (char c = 'i'; c <= 'n'; c++) {
if (!typeNames.ContainsKey(c.ToString()))
return c.ToString();
}
}
string name;
if (type.IsArray) {
name = "array";
@ -155,6 +234,13 @@ namespace ICSharpCode.Decompiler.Ast @@ -155,6 +234,13 @@ namespace ICSharpCode.Decompiler.Ast
int pos = name.IndexOf('`');
if (pos >= 0)
name = name.Substring(0, pos);
// remove field prefix:
if (name.Length > 2 && name.StartsWith("m_", StringComparison.Ordinal))
name = name.Substring(2);
else if (name.Length > 1 && name[0] == '_')
name = name.Substring(1);
if (name.Length == 0)
return "obj";
else

39
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;
@ -113,23 +114,35 @@ namespace ICSharpCode.Decompiler.Ast.Transforms @@ -113,23 +114,35 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
if (!IsAnonymousMethod(context, method))
return false;
// Create AnonymousMethodExpression and prepare parameters
AnonymousMethodExpression ame = new AnonymousMethodExpression();
ame.Parameters.AddRange(AstBuilder.MakeParameters(method.Parameters));
ame.HasParameterList = true;
// Decompile the anonymous method:
DecompilerContext subContext = context.Clone();
subContext.CurrentMethod = method;
BlockStatement body = AstMethodBodyBuilder.CreateMethodBody(method, subContext);
BlockStatement body = AstMethodBodyBuilder.CreateMethodBody(method, subContext, ame.Parameters);
TransformationPipeline.RunTransformationsUntil(body, v => v is DelegateConstruction, subContext);
body.AcceptVisitor(this, null);
AnonymousMethodExpression ame = new AnonymousMethodExpression();
bool isLambda = false;
if (method.Parameters.All(p => string.IsNullOrEmpty(p.Name))) {
ame.HasParameterList = false;
} else {
ame.HasParameterList = true;
ame.Parameters.AddRange(AstBuilder.MakeParameters(method.Parameters));
if (ame.Parameters.All(p => p.ParameterModifier == ParameterModifier.None)) {
isLambda = (body.Statements.Count == 1 && body.Statements.Single() is ReturnStatement);
if (ame.Parameters.All(p => p.ParameterModifier == ParameterModifier.None)) {
isLambda = (body.Statements.Count == 1 && body.Statements.Single() is ReturnStatement);
}
// Remove the parameter list from an AnonymousMethodExpression if the original method had no names,
// and the parameters are not used in the method body
if (!isLambda && method.Parameters.All(p => string.IsNullOrEmpty(p.Name))) {
var parameterReferencingIdentifiers =
from ident in body.Descendants.OfType<IdentifierExpression>()
let v = ident.Annotation<ILVariable>()
where v != null && v.IsParameter && method.Parameters.Contains(v.OriginalParameter)
select ident;
if (!parameterReferencingIdentifiers.Any()) {
ame.Parameters.Clear();
ame.HasParameterList = false;
}
}
@ -196,8 +209,8 @@ namespace ICSharpCode.Decompiler.Ast.Transforms @@ -196,8 +209,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 +231,8 @@ namespace ICSharpCode.Decompiler.Ast.Transforms @@ -218,8 +231,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;

50
ICSharpCode.Decompiler/Ast/Transforms/IntroduceUnsafeModifier.cs

@ -0,0 +1,50 @@ @@ -0,0 +1,50 @@
// 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 ICSharpCode.NRefactory.CSharp;
namespace ICSharpCode.Decompiler.Ast.Transforms
{
public class IntroduceUnsafeModifier : DepthFirstAstVisitor<object, bool>, IAstTransform
{
public void Run(AstNode compilationUnit)
{
compilationUnit.AcceptVisitor(this, null);
}
protected override bool VisitChildren(AstNode node, object data)
{
bool result = false;
for (AstNode child = node.FirstChild; child != null; child = child.NextSibling) {
result |= child.AcceptVisitor(this, data);
}
if (result && node is AttributedNode && !(node is Accessor)) {
((AttributedNode)node).Modifiers |= Modifiers.Unsafe;
return false;
}
return result;
}
public override bool VisitPointerReferenceExpression(PointerReferenceExpression pointerReferenceExpression, object data)
{
return true;
}
public override bool VisitComposedType(ComposedType composedType, object data)
{
if (composedType.PointerRank > 0)
return true;
else
return base.VisitComposedType(composedType, data);
}
public override bool VisitUnaryOperatorExpression(UnaryOperatorExpression unaryOperatorExpression, object data)
{
if (unaryOperatorExpression.Operator == UnaryOperatorType.Dereference || unaryOperatorExpression.Operator == UnaryOperatorType.AddressOf)
return true;
else
return base.VisitUnaryOperatorExpression(unaryOperatorExpression, data);
}
}
}

1
ICSharpCode.Decompiler/Ast/Transforms/TransformationPipeline.cs

@ -22,6 +22,7 @@ namespace ICSharpCode.Decompiler.Ast.Transforms @@ -22,6 +22,7 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
new PatternStatementTransform(context),
new ConvertConstructorCallIntoInitializer(),
new ReplaceMethodCallsWithOperators(),
new IntroduceUnsafeModifier(),
};
}

1
ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj

@ -61,6 +61,7 @@ @@ -61,6 +61,7 @@
<Compile Include="Ast\Transforms\ContextTrackingVisitor.cs" />
<Compile Include="Ast\Transforms\ConvertConstructorCallIntoInitializer.cs" />
<Compile Include="Ast\Transforms\DelegateConstruction.cs" />
<Compile Include="Ast\Transforms\IntroduceUnsafeModifier.cs" />
<Compile Include="Ast\Transforms\ReplaceMethodCallsWithOperators.cs" />
<Compile Include="Ast\Transforms\PushNegation.cs" />
<Compile Include="Ast\Transforms\TransformationPipeline.cs" />

42
ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs

@ -457,6 +457,9 @@ namespace ICSharpCode.Decompiler.ILAst @@ -457,6 +457,9 @@ namespace ICSharpCode.Decompiler.ILAst
}
}
// Convert parameters to ILVariables
ConvertParameters(body);
return body;
}
@ -551,6 +554,45 @@ namespace ICSharpCode.Decompiler.ILAst @@ -551,6 +554,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()
{

141
ICSharpCode.Decompiler/ILAst/ILCodes.cs

@ -102,24 +102,24 @@ namespace ICSharpCode.Decompiler.ILAst @@ -102,24 +102,24 @@ namespace ICSharpCode.Decompiler.ILAst
__Ble_Un,
__Blt_Un,
Switch,
Ldind_I1,
Ldind_U1,
Ldind_I2,
Ldind_U2,
Ldind_I4,
Ldind_U4,
Ldind_I8,
Ldind_I,
Ldind_R4,
Ldind_R8,
__Ldind_I1,
__Ldind_U1,
__Ldind_I2,
__Ldind_U2,
__Ldind_I4,
__Ldind_U4,
__Ldind_I8,
__Ldind_I,
__Ldind_R4,
__Ldind_R8,
Ldind_Ref,
Stind_Ref,
Stind_I1,
Stind_I2,
Stind_I4,
Stind_I8,
Stind_R4,
Stind_R8,
__Stind_I1,
__Stind_I2,
__Stind_I4,
__Stind_I8,
__Stind_R4,
__Stind_R8,
Add,
Sub,
Mul,
@ -222,7 +222,7 @@ namespace ICSharpCode.Decompiler.ILAst @@ -222,7 +222,7 @@ namespace ICSharpCode.Decompiler.ILAst
Endfinally,
Leave,
__Leave_S,
Stind_I,
__Stind_I,
Conv_U,
Arglist,
Ceq,
@ -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,49 +375,64 @@ namespace ICSharpCode.Decompiler.ILAst @@ -375,49 +375,64 @@ 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.__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;
case ILCode.__Ldloc_3: code = ILCode.Ldloc; operand = methodBody.Variables[3]; break;
case ILCode.__Stloc_0: code = ILCode.Stloc; operand = methodBody.Variables[0]; break;
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.__Ldloc_S: code = ILCode.Ldloc; break;
case ILCode.__Ldloca_S: code = ILCode.Ldloca; break;
case ILCode.__Stloc_S: code = ILCode.Stloc; break;
case ILCode.__Ldc_I4_M1: code = ILCode.Ldc_I4; operand = -1; break;
case ILCode.__Ldc_I4_0: code = ILCode.Ldc_I4; operand = 0; break;
case ILCode.__Ldc_I4_1: code = ILCode.Ldc_I4; operand = 1; break;
case ILCode.__Ldc_I4_2: code = ILCode.Ldc_I4; operand = 2; break;
case ILCode.__Ldc_I4_3: code = ILCode.Ldc_I4; operand = 3; break;
case ILCode.__Ldc_I4_4: code = ILCode.Ldc_I4; operand = 4; break;
case ILCode.__Ldc_I4_5: code = ILCode.Ldc_I4; operand = 5; break;
case ILCode.__Ldc_I4_6: code = ILCode.Ldc_I4; operand = 6; break;
case ILCode.__Ldc_I4_7: code = ILCode.Ldc_I4; operand = 7; break;
case ILCode.__Ldc_I4_8: code = ILCode.Ldc_I4; operand = 8; break;
case ILCode.__Ldc_I4_S: code = ILCode.Ldc_I4; operand = (int) (sbyte) operand; break;
case ILCode.__Br_S: code = ILCode.Br; break;
case ILCode.__Brfalse_S: code = ILCode.__Brfalse; break;
case ILCode.__Brtrue_S: code = ILCode.Brtrue; break;
case ILCode.__Beq_S: code = ILCode.__Beq; break;
case ILCode.__Bge_S: code = ILCode.__Bge; break;
case ILCode.__Bgt_S: code = ILCode.__Bgt; break;
case ILCode.__Ble_S: code = ILCode.__Ble; break;
case ILCode.__Blt_S: code = ILCode.__Blt; break;
case ILCode.__Bne_Un_S: code = ILCode.__Bne_Un; break;
case ILCode.__Bge_Un_S: code = ILCode.__Bge_Un; break;
case ILCode.__Bgt_Un_S: code = ILCode.__Bgt_Un; break;
case ILCode.__Ble_Un_S: code = ILCode.__Ble_Un; break;
case ILCode.__Blt_Un_S: code = ILCode.__Blt_Un; break;
case ILCode.__Leave_S: code = ILCode.Leave; 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;
case ILCode.__Ldloc_3: code = ILCode.Ldloc; operand = methodBody.Variables[3]; break;
case ILCode.__Stloc_0: code = ILCode.Stloc; operand = methodBody.Variables[0]; break;
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.__Ldloc_S: code = ILCode.Ldloc; break;
case ILCode.__Ldloca_S: code = ILCode.Ldloca; break;
case ILCode.__Stloc_S: code = ILCode.Stloc; break;
case ILCode.__Ldc_I4_M1: code = ILCode.Ldc_I4; operand = -1; break;
case ILCode.__Ldc_I4_0: code = ILCode.Ldc_I4; operand = 0; break;
case ILCode.__Ldc_I4_1: code = ILCode.Ldc_I4; operand = 1; break;
case ILCode.__Ldc_I4_2: code = ILCode.Ldc_I4; operand = 2; break;
case ILCode.__Ldc_I4_3: code = ILCode.Ldc_I4; operand = 3; break;
case ILCode.__Ldc_I4_4: code = ILCode.Ldc_I4; operand = 4; break;
case ILCode.__Ldc_I4_5: code = ILCode.Ldc_I4; operand = 5; break;
case ILCode.__Ldc_I4_6: code = ILCode.Ldc_I4; operand = 6; break;
case ILCode.__Ldc_I4_7: code = ILCode.Ldc_I4; operand = 7; break;
case ILCode.__Ldc_I4_8: code = ILCode.Ldc_I4; operand = 8; break;
case ILCode.__Ldc_I4_S: code = ILCode.Ldc_I4; operand = (int) (sbyte) operand; break;
case ILCode.__Br_S: code = ILCode.Br; break;
case ILCode.__Brfalse_S: code = ILCode.__Brfalse; break;
case ILCode.__Brtrue_S: code = ILCode.Brtrue; break;
case ILCode.__Beq_S: code = ILCode.__Beq; break;
case ILCode.__Bge_S: code = ILCode.__Bge; break;
case ILCode.__Bgt_S: code = ILCode.__Bgt; break;
case ILCode.__Ble_S: code = ILCode.__Ble; break;
case ILCode.__Blt_S: code = ILCode.__Blt; break;
case ILCode.__Bne_Un_S: code = ILCode.__Bne_Un; break;
case ILCode.__Bge_Un_S: code = ILCode.__Bge_Un; break;
case ILCode.__Bgt_Un_S: code = ILCode.__Bgt_Un; break;
case ILCode.__Ble_Un_S: code = ILCode.__Ble_Un; break;
case ILCode.__Blt_Un_S: code = ILCode.__Blt_Un; break;
case ILCode.__Leave_S: code = ILCode.Leave; break;
case ILCode.__Ldind_I: code = ILCode.Ldobj; operand = methodBody.Method.Module.TypeSystem.IntPtr; break;
case ILCode.__Ldind_I1: code = ILCode.Ldobj; operand = methodBody.Method.Module.TypeSystem.SByte; break;
case ILCode.__Ldind_I2: code = ILCode.Ldobj; operand = methodBody.Method.Module.TypeSystem.Int16; break;
case ILCode.__Ldind_I4: code = ILCode.Ldobj; operand = methodBody.Method.Module.TypeSystem.Int32; break;
case ILCode.__Ldind_I8: code = ILCode.Ldobj; operand = methodBody.Method.Module.TypeSystem.Int64; break;
case ILCode.__Ldind_U1: code = ILCode.Ldobj; operand = methodBody.Method.Module.TypeSystem.Byte; break;
case ILCode.__Ldind_U2: code = ILCode.Ldobj; operand = methodBody.Method.Module.TypeSystem.UInt16; break;
case ILCode.__Ldind_U4: code = ILCode.Ldobj; operand = methodBody.Method.Module.TypeSystem.UInt32; break;
case ILCode.__Ldind_R4: code = ILCode.Ldobj; operand = methodBody.Method.Module.TypeSystem.Single; break;
case ILCode.__Ldind_R8: code = ILCode.Ldobj; operand = methodBody.Method.Module.TypeSystem.Double; break;
case ILCode.__Stind_I: code = ILCode.Stobj; operand = methodBody.Method.Module.TypeSystem.IntPtr; break;
case ILCode.__Stind_I1: code = ILCode.Stobj; operand = methodBody.Method.Module.TypeSystem.Byte; break;
case ILCode.__Stind_I2: code = ILCode.Stobj; operand = methodBody.Method.Module.TypeSystem.Int16; break;
case ILCode.__Stind_I4: code = ILCode.Stobj; operand = methodBody.Method.Module.TypeSystem.Int32; break;
case ILCode.__Stind_I8: code = ILCode.Stobj; operand = methodBody.Method.Module.TypeSystem.Int64; 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:

80
ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs

@ -108,7 +108,10 @@ namespace ICSharpCode.Decompiler.ILAst @@ -108,7 +108,10 @@ namespace ICSharpCode.Decompiler.ILAst
/// <returns>The inferred type</returns>
TypeReference InferTypeForExpression(ILExpression expr, TypeReference expectedType, bool forceInferChildren = false)
{
expr.ExpectedType = expectedType;
if (expectedType != null && expr.ExpectedType != expectedType) {
expr.ExpectedType = expectedType;
forceInferChildren = true;
}
if (forceInferChildren || expr.InferredType == null)
expr.InferredType = DoInferTypeForExpression(expr, expectedType, forceInferChildren);
return expr.InferredType;
@ -167,16 +170,8 @@ namespace ICSharpCode.Decompiler.ILAst @@ -167,16 +170,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:
@ -243,25 +238,8 @@ namespace ICSharpCode.Decompiler.ILAst @@ -243,25 +238,8 @@ namespace ICSharpCode.Decompiler.ILAst
return GetFieldType((FieldReference)expr.Operand);
#endregion
#region Reference/Pointer instructions
case ILCode.Ldind_I:
case ILCode.Ldind_I1:
case ILCode.Ldind_I2:
case ILCode.Ldind_I4:
case ILCode.Ldind_I8:
case ILCode.Ldind_U1:
case ILCode.Ldind_U2:
case ILCode.Ldind_U4:
case ILCode.Ldind_R4:
case ILCode.Ldind_R8:
case ILCode.Ldind_Ref:
return UnpackPointer(InferTypeForExpression(expr.Arguments[0], null));
case ILCode.Stind_I1:
case ILCode.Stind_I2:
case ILCode.Stind_I4:
case ILCode.Stind_I8:
case ILCode.Stind_R4:
case ILCode.Stind_R8:
case ILCode.Stind_I:
case ILCode.Stind_Ref:
if (forceInferChildren) {
TypeReference elementType = UnpackPointer(InferTypeForExpression(expr.Arguments[0], null));
@ -269,12 +247,18 @@ namespace ICSharpCode.Decompiler.ILAst @@ -269,12 +247,18 @@ namespace ICSharpCode.Decompiler.ILAst
}
return null;
case ILCode.Ldobj:
if (forceInferChildren) {
if (InferTypeForExpression(expr.Arguments[0], new ByReferenceType((TypeReference)expr.Operand)) is PointerType)
InferTypeForExpression(expr.Arguments[0], new PointerType((TypeReference)expr.Operand));
}
return (TypeReference)expr.Operand;
case ILCode.Stobj:
if (forceInferChildren) {
if (InferTypeForExpression(expr.Arguments[0], new ByReferenceType((TypeReference)expr.Operand)) is PointerType)
InferTypeForExpression(expr.Arguments[0], new PointerType((TypeReference)expr.Operand));
InferTypeForExpression(expr.Arguments[1], (TypeReference)expr.Operand);
}
return null;
return (TypeReference)expr.Operand;
case ILCode.Initobj:
return null;
case ILCode.DefaultValue:
@ -334,9 +318,9 @@ namespace ICSharpCode.Decompiler.ILAst @@ -334,9 +318,9 @@ namespace ICSharpCode.Decompiler.ILAst
case ILCode.Ldc_I4:
if (IsBoolean(expectedType) && ((int)expr.Operand == 0 || (int)expr.Operand == 1))
return typeSystem.Boolean;
return IsIntegerOrEnum(expectedType) ? expectedType : typeSystem.Int32;
return (IsIntegerOrEnum(expectedType) || expectedType is PointerType) ? expectedType : typeSystem.Int32;
case ILCode.Ldc_I8:
return (IsIntegerOrEnum(expectedType)) ? expectedType : typeSystem.Int64;
return (IsIntegerOrEnum(expectedType) || expectedType is PointerType) ? expectedType : typeSystem.Int64;
case ILCode.Ldc_R4:
return typeSystem.Single;
case ILCode.Ldc_R8:
@ -419,43 +403,43 @@ namespace ICSharpCode.Decompiler.ILAst @@ -419,43 +403,43 @@ namespace ICSharpCode.Decompiler.ILAst
case ILCode.Conv_I1:
case ILCode.Conv_Ovf_I1:
case ILCode.Conv_Ovf_I1_Un:
return (GetInformationAmount(expectedType) == 8 && IsSigned(expectedType) == true) ? expectedType : typeSystem.SByte;
return HandleConversion(8, true, expr.Arguments[0], expectedType, typeSystem.Byte);
case ILCode.Conv_I2:
case ILCode.Conv_Ovf_I2:
case ILCode.Conv_Ovf_I2_Un:
return (GetInformationAmount(expectedType) == 16 && IsSigned(expectedType) == true) ? expectedType : typeSystem.Int16;
return HandleConversion(16, true, expr.Arguments[0], expectedType, typeSystem.UInt16);
case ILCode.Conv_I4:
case ILCode.Conv_Ovf_I4:
case ILCode.Conv_Ovf_I4_Un:
return (GetInformationAmount(expectedType) == 32 && IsSigned(expectedType) == true) ? expectedType : typeSystem.Int32;
return HandleConversion(32, true, expr.Arguments[0], expectedType, typeSystem.UInt32);
case ILCode.Conv_I8:
case ILCode.Conv_Ovf_I8:
case ILCode.Conv_Ovf_I8_Un:
return (GetInformationAmount(expectedType) == 64 && IsSigned(expectedType) == true) ? expectedType : typeSystem.Int64;
return HandleConversion(64, true, expr.Arguments[0], expectedType, typeSystem.UInt64);
case ILCode.Conv_U1:
case ILCode.Conv_Ovf_U1:
case ILCode.Conv_Ovf_U1_Un:
return (GetInformationAmount(expectedType) == 8 && IsSigned(expectedType) == false) ? expectedType : typeSystem.Byte;
return HandleConversion(8, false, expr.Arguments[0], expectedType, typeSystem.SByte);
case ILCode.Conv_U2:
case ILCode.Conv_Ovf_U2:
case ILCode.Conv_Ovf_U2_Un:
return (GetInformationAmount(expectedType) == 16 && IsSigned(expectedType) == false) ? expectedType : typeSystem.UInt16;
return HandleConversion(16, false, expr.Arguments[0], expectedType, typeSystem.Int16);
case ILCode.Conv_U4:
case ILCode.Conv_Ovf_U4:
case ILCode.Conv_Ovf_U4_Un:
return (GetInformationAmount(expectedType) == 32 && IsSigned(expectedType) == false) ? expectedType : typeSystem.UInt32;
return HandleConversion(32, false, expr.Arguments[0], expectedType, typeSystem.Int32);
case ILCode.Conv_U8:
case ILCode.Conv_Ovf_U8:
case ILCode.Conv_Ovf_U8_Un:
return (GetInformationAmount(expectedType) == 64 && IsSigned(expectedType) == false) ? expectedType : typeSystem.UInt64;
return HandleConversion(64, false, expr.Arguments[0], expectedType, typeSystem.UInt64);
case ILCode.Conv_I:
case ILCode.Conv_Ovf_I:
case ILCode.Conv_Ovf_I_Un:
return (GetInformationAmount(expectedType) == nativeInt && IsSigned(expectedType) == true) ? expectedType : typeSystem.IntPtr;
return HandleConversion(nativeInt, true, expr.Arguments[0], expectedType, typeSystem.IntPtr);
case ILCode.Conv_U:
case ILCode.Conv_Ovf_U:
case ILCode.Conv_Ovf_U_Un:
return (GetInformationAmount(expectedType) == nativeInt && IsSigned(expectedType) == false) ? expectedType : typeSystem.UIntPtr;
return HandleConversion(nativeInt, false, expr.Arguments[0], expectedType, typeSystem.UIntPtr);
case ILCode.Conv_R4:
return typeSystem.Single;
case ILCode.Conv_R8:
@ -527,6 +511,24 @@ namespace ICSharpCode.Decompiler.ILAst @@ -527,6 +511,24 @@ namespace ICSharpCode.Decompiler.ILAst
}
}
TypeReference HandleConversion(int targetBitSize, bool targetSigned, ILExpression arg, TypeReference expectedType, TypeReference targetType)
{
if (targetBitSize >= nativeInt && expectedType is PointerType) {
InferTypeForExpression(arg, expectedType);
return expectedType;
}
TypeReference argType = InferTypeForExpression(arg, null);
if (targetBitSize >= nativeInt && argType is ByReferenceType) {
// conv instructions on managed references mean that the GC should stop tracking them, so they become pointers:
PointerType ptrType = new PointerType(((ByReferenceType)argType).ElementType);
InferTypeForExpression(arg, ptrType);
return ptrType;
} else if (targetBitSize >= nativeInt && argType is PointerType) {
return argType;
}
return (GetInformationAmount(expectedType) == targetBitSize && IsSigned(expectedType) == targetSigned) ? expectedType : targetType;
}
static TypeReference GetFieldType(FieldReference fieldReference)
{
return SubstituteTypeArgs(UnpackModifiers(fieldReference.FieldType), fieldReference);

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;
}
}

26
ICSharpCode.Decompiler/Tests/CustomAttributes/S_CustomAttributes.cs

@ -5,7 +5,7 @@ using System; @@ -5,7 +5,7 @@ using System;
namespace aa
{
public static class CustomAtributes
public static class CustomAttributes
{
[Flags]
public enum EnumWithFlag
@ -20,13 +20,13 @@ namespace aa @@ -20,13 +20,13 @@ namespace aa
[AttributeUsage(AttributeTargets.All)]
public class MyAttribute : Attribute
{
public MyAttribute(CustomAtributes.EnumWithFlag en)
public MyAttribute(object val)
{
}
}
[CustomAtributes.MyAttribute(CustomAtributes.EnumWithFlag.Item1 | CustomAtributes.EnumWithFlag.Item2)]
[CustomAttributes.MyAttribute(CustomAttributes.EnumWithFlag.Item1 | CustomAttributes.EnumWithFlag.Item2)]
private static int field;
[CustomAtributes.MyAttribute(CustomAtributes.EnumWithFlag.All)]
[CustomAttributes.MyAttribute(CustomAttributes.EnumWithFlag.All)]
public static string Property
{
get
@ -42,5 +42,23 @@ namespace aa @@ -42,5 +42,23 @@ namespace aa
AttributeTargets attributeTargets = AttributeTargets.Property | AttributeTargets.Field;
Console.WriteLine("{0} $$$ {1}", AttributeTargets.Interface, attributeTargets);
}
// No Boxing
[CustomAttributes.MyAttribute(new StringComparison[]
{
StringComparison.Ordinal,
StringComparison.CurrentCulture
})]
public static void ArrayAsAttribute1()
{
}
// Boxing of each array element
[CustomAttributes.MyAttribute(new object[]
{
StringComparison.Ordinal,
StringComparison.CurrentCulture
})]
public static void ArrayAsAttribute2()
{
}
}
}

3
ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj

@ -9,7 +9,7 @@ @@ -9,7 +9,7 @@
<AssemblyName>ICSharpCode.Decompiler.Tests</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<AppDesignerFolder>Properties</AppDesignerFolder>
<AllowUnsafeBlocks>False</AllowUnsafeBlocks>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
<NoStdLib>False</NoStdLib>
<WarningLevel>4</WarningLevel>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
@ -54,6 +54,7 @@ @@ -54,6 +54,7 @@
</ItemGroup>
<ItemGroup>
<Compile Include="Switch.cs" />
<Compile Include="UnsafeCode.cs" />
<Compile Include="YieldReturn.cs" />
<None Include="Types\S_EnumSamples.cs" />
<None Include="CustomAttributes\S_AssemblyCustomAttribute.cs" />

29
ICSharpCode.Decompiler/Tests/UnsafeCode.cs

@ -0,0 +1,29 @@ @@ -0,0 +1,29 @@
// 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 UnsafeCode
{
public unsafe long ConvertDoubleToLong(double d)
{
return *(long*)&d;
}
public unsafe int* NullPointer {
get {
return null;
}
}
public unsafe void PassRefParameterAsPointer(ref int p)
{
fixed (int* ptr = &p)
PassPointerAsRefParameter(ptr);
}
public unsafe void PassPointerAsRefParameter(int* p)
{
PassRefParameterAsPointer(ref *p);
}
}

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) {

56
NRefactory/ICSharpCode.NRefactory/CSharp/Ast/AstNode.cs

@ -537,49 +537,23 @@ namespace ICSharpCode.NRefactory.CSharp @@ -537,49 +537,23 @@ namespace ICSharpCode.NRefactory.CSharp
return null;
}
public IEnumerable<T> Annotations<T>() where T: class
{
object annotations = this.annotations;
AnnotationList list = annotations as AnnotationList;
if (list != null) {
List<T> result = new List<T>();
lock (list) {
foreach (object obj in list) {
T t = obj as T;
if (t != null)
result.Add(t);
}
}
return result;
} else {
T t = annotations as T;
if (t != null)
return new T[] { t };
else
return Enumerable.Empty<T>();
}
}
public IEnumerable<object> Annotations(Type type)
{
if (type == null)
throw new ArgumentNullException("type");
object annotations = this.annotations;
AnnotationList list = annotations as AnnotationList;
if (list != null) {
List<object> result = new List<object>();
lock (list) {
foreach (object obj in list) {
if (type.IsInstanceOfType(obj))
result.Add(obj);
/// <summary>
/// Gets all annotations stored on this AstNode.
/// </summary>
public IEnumerable<object> Annotations {
get {
object annotations = this.annotations;
AnnotationList list = annotations as AnnotationList;
if (list != null) {
lock (list) {
return list.ToArray();
}
} else {
if (annotations != null)
return new object[] { annotations };
else
return Enumerable.Empty<object>();
}
return result;
} else {
if (type.IsInstanceOfType(annotations))
return new object[] { annotations };
else
return Enumerable.Empty<object>();
}
}
#endregion

Loading…
Cancel
Save