Browse Source

Fix #562: Update ILSpy to version 2.2

pull/567/head
Daniel Grunwald 11 years ago
parent
commit
72c23cdbad
  1. 23
      src/Libraries/ICSharpCode.Decompiler/Ast/AstBuilder.cs
  2. 16
      src/Libraries/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs
  3. 2
      src/Libraries/ICSharpCode.Decompiler/Ast/Transforms/ExpressionTreeConverter.cs
  4. 15
      src/Libraries/ICSharpCode.Decompiler/DecompilerSettings.cs
  5. 8
      src/Libraries/ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs
  6. 4
      src/Libraries/ICSharpCode.Decompiler/Disassembler/MethodBodyDisassembler.cs
  7. 97
      src/Libraries/ICSharpCode.Decompiler/ILAst/AsyncDecompiler.cs
  8. 8
      src/Libraries/ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs
  9. 20
      src/Libraries/ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs
  10. 20
      src/Libraries/ICSharpCode.Decompiler/ILAst/ILInlining.cs
  11. 6
      src/Libraries/ICSharpCode.Decompiler/ILAst/PatternMatching.cs
  12. 14
      src/Libraries/ICSharpCode.Decompiler/ILAst/StateRange.cs
  13. 15
      src/Libraries/ICSharpCode.Decompiler/ILAst/SymbolicExecution.cs
  14. 4
      src/Libraries/ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs
  15. 30
      src/Libraries/ICSharpCode.Decompiler/ILAst/YieldReturnDecompiler.cs
  16. 26
      src/Libraries/ICSharpCode.Decompiler/Properties/AssemblyInfo.cs
  17. 11
      src/Libraries/ICSharpCode.Decompiler/Tests/Async.cs
  18. 16
      src/Libraries/ICSharpCode.Decompiler/Tests/DelegateConstruction.cs
  19. 28
      src/Libraries/ICSharpCode.Decompiler/Tests/DoubleConstants.cs
  20. 1
      src/Libraries/ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj
  21. 6
      src/Libraries/ICSharpCode.Decompiler/Tests/TestRunner.cs

23
src/Libraries/ICSharpCode.Decompiler/Ast/AstBuilder.cs

@ -167,7 +167,12 @@ namespace ICSharpCode.Decompiler.Ast
public void AddAssembly(AssemblyDefinition assemblyDefinition, bool onlyAssemblyLevel = false) public void AddAssembly(AssemblyDefinition assemblyDefinition, bool onlyAssemblyLevel = false)
{ {
if (assemblyDefinition.Name.Version != null) { AddAssembly(assemblyDefinition.MainModule, onlyAssemblyLevel);
}
public void AddAssembly(ModuleDefinition moduleDefinition, bool onlyAssemblyLevel = false)
{
if (moduleDefinition.Assembly != null && moduleDefinition.Assembly.Name.Version != null) {
syntaxTree.AddChild( syntaxTree.AddChild(
new AttributeSection { new AttributeSection {
AttributeTarget = "assembly", AttributeTarget = "assembly",
@ -176,22 +181,24 @@ namespace ICSharpCode.Decompiler.Ast
Type = new SimpleType("AssemblyVersion") Type = new SimpleType("AssemblyVersion")
.WithAnnotation(new TypeReference( .WithAnnotation(new TypeReference(
"System.Reflection", "AssemblyVersionAttribute", "System.Reflection", "AssemblyVersionAttribute",
assemblyDefinition.MainModule, assemblyDefinition.MainModule.TypeSystem.Corlib)), moduleDefinition, moduleDefinition.TypeSystem.Corlib)),
Arguments = { Arguments = {
new PrimitiveExpression(assemblyDefinition.Name.Version.ToString()) new PrimitiveExpression(moduleDefinition.Assembly.Name.Version.ToString())
} }
} }
} }
}, EntityDeclaration.AttributeRole); }, EntityDeclaration.AttributeRole);
} }
ConvertCustomAttributes(syntaxTree, assemblyDefinition, "assembly"); if (moduleDefinition.Assembly != null) {
ConvertSecurityAttributes(syntaxTree, assemblyDefinition, "assembly"); ConvertCustomAttributes(syntaxTree, moduleDefinition.Assembly, "assembly");
ConvertCustomAttributes(syntaxTree, assemblyDefinition.MainModule, "module"); ConvertSecurityAttributes(syntaxTree, moduleDefinition.Assembly, "assembly");
AddTypeForwarderAttributes(syntaxTree, assemblyDefinition.MainModule, "assembly"); }
ConvertCustomAttributes(syntaxTree, moduleDefinition, "module");
AddTypeForwarderAttributes(syntaxTree, moduleDefinition, "assembly");
if (!onlyAssemblyLevel) { if (!onlyAssemblyLevel) {
foreach (TypeDefinition typeDef in assemblyDefinition.MainModule.Types) { foreach (TypeDefinition typeDef in moduleDefinition.Types) {
// Skip the <Module> class // Skip the <Module> class
if (typeDef.Name == "<Module>") continue; if (typeDef.Name == "<Module>") continue;
// Skip any hidden types // Skip any hidden types

16
src/Libraries/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs

@ -849,7 +849,7 @@ namespace ICSharpCode.Decompiler.Ast
args[args.Count - 1].AddAnnotation(new ParameterDeclarationAnnotation(byteCode)); args[args.Count - 1].AddAnnotation(new ParameterDeclarationAnnotation(byteCode));
return args[args.Count - 1]; return args[args.Count - 1];
case ILCode.Await: case ILCode.Await:
return new UnaryOperatorExpression(UnaryOperatorType.Await, arg1); return new UnaryOperatorExpression(UnaryOperatorType.Await, UnpackDirectionExpression(arg1));
case ILCode.NullableOf: case ILCode.NullableOf:
case ILCode.ValueOf: case ILCode.ValueOf:
return arg1; return arg1;
@ -975,10 +975,7 @@ namespace ICSharpCode.Decompiler.Ast
// Unpack any DirectionExpression that is used as target for the call // Unpack any DirectionExpression that is used as target for the call
// (calling methods on value types implicitly passes the first argument by reference) // (calling methods on value types implicitly passes the first argument by reference)
if (target is DirectionExpression) { target = UnpackDirectionExpression(target);
target = ((DirectionExpression)target).Expression;
target.Remove(); // detach from DirectionExpression
}
if (cecilMethodDef != null) { if (cecilMethodDef != null) {
// convert null.ToLower() to ((string)null).ToLower() // convert null.ToLower() to ((string)null).ToLower()
@ -1078,6 +1075,15 @@ namespace ICSharpCode.Decompiler.Ast
return target.Invoke(cecilMethod.Name, ConvertTypeArguments(cecilMethod), methodArgs).WithAnnotation(cecilMethod); return target.Invoke(cecilMethod.Name, ConvertTypeArguments(cecilMethod), methodArgs).WithAnnotation(cecilMethod);
} }
static Expression UnpackDirectionExpression(Expression target)
{
if (target is DirectionExpression) {
return ((DirectionExpression)target).Expression.Detach();
} else {
return target;
}
}
static void AdjustArgumentsForMethodCall(MethodReference cecilMethod, List<Expression> methodArgs) static void AdjustArgumentsForMethodCall(MethodReference cecilMethod, List<Expression> methodArgs)
{ {
// Convert 'ref' into 'out' where necessary // Convert 'ref' into 'out' where necessary

2
src/Libraries/ICSharpCode.Decompiler/Ast/Transforms/ExpressionTreeConverter.cs

@ -804,7 +804,7 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
return new IndexerExpression(targetConverted, indexConverted); return new IndexerExpression(targetConverted, indexConverted);
} }
IList<Expression> indexesConverted = ConvertExpressionsArray(index); IList<Expression> indexesConverted = ConvertExpressionsArray(index);
if (indexConverted != null) { if (indexesConverted != null) {
return new IndexerExpression(targetConverted, indexesConverted); return new IndexerExpression(targetConverted, indexesConverted);
} }
return null; return null;

15
src/Libraries/ICSharpCode.Decompiler/DecompilerSettings.cs

@ -283,6 +283,21 @@ namespace ICSharpCode.Decompiler
} }
} }
bool makeAssignmentExpressions = true;
/// <summary>
/// Gets/Sets whether to use assignment expressions such as in while ((count = Do()) != 0) ;
/// </summary>
public bool MakeAssignmentExpressions {
get { return makeAssignmentExpressions; }
set {
if (makeAssignmentExpressions != value) {
makeAssignmentExpressions = value;
OnPropertyChanged("MakeAssignmentExpressions");
}
}
}
bool alwaysGenerateExceptionVariableForCatchBlocks = false; bool alwaysGenerateExceptionVariableForCatchBlocks = false;
/// <summary> /// <summary>

8
src/Libraries/ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs

@ -359,6 +359,10 @@ namespace ICSharpCode.Decompiler.Disassembler
} else if (operand is float) { } else if (operand is float) {
float val = (float)operand; float val = (float)operand;
if (val == 0) { if (val == 0) {
if (1 / val == float.NegativeInfinity) {
// negative zero is a special case
writer.Write('-');
}
writer.Write("0.0"); writer.Write("0.0");
} else if (float.IsInfinity(val) || float.IsNaN(val)) { } else if (float.IsInfinity(val) || float.IsNaN(val)) {
byte[] data = BitConverter.GetBytes(val); byte[] data = BitConverter.GetBytes(val);
@ -375,6 +379,10 @@ namespace ICSharpCode.Decompiler.Disassembler
} else if (operand is double) { } else if (operand is double) {
double val = (double)operand; double val = (double)operand;
if (val == 0) { if (val == 0) {
if (1 / val == double.NegativeInfinity) {
// negative zero is a special case
writer.Write('-');
}
writer.Write("0.0"); writer.Write("0.0");
} else if (double.IsInfinity(val) || double.IsNaN(val)) { } else if (double.IsInfinity(val) || double.IsNaN(val)) {
byte[] data = BitConverter.GetBytes(val); byte[] data = BitConverter.GetBytes(val);

4
src/Libraries/ICSharpCode.Decompiler/Disassembler/MethodBodyDisassembler.cs

@ -54,8 +54,8 @@ namespace ICSharpCode.Decompiler.Disassembler
output.WriteLine("// Method begins at RVA 0x{0:x4}", method.RVA); output.WriteLine("// Method begins at RVA 0x{0:x4}", method.RVA);
output.WriteLine("// Code size {0} (0x{0:x})", body.CodeSize); output.WriteLine("// Code size {0} (0x{0:x})", body.CodeSize);
output.WriteLine(".maxstack {0}", body.MaxStackSize); output.WriteLine(".maxstack {0}", body.MaxStackSize);
if (method.DeclaringType.Module.Assembly.EntryPoint == method) if (method.DeclaringType.Module.Assembly != null && method.DeclaringType.Module.Assembly.EntryPoint == method)
output.WriteLine (".entrypoint"); output.WriteLine (".entrypoint");
if (method.Body.HasVariables) { if (method.Body.HasVariables) {
output.Write(".locals "); output.Write(".locals ");

97
src/Libraries/ICSharpCode.Decompiler/ILAst/AsyncDecompiler.cs

@ -58,6 +58,7 @@ namespace ICSharpCode.Decompiler.ILAst
FieldDefinition builderField; FieldDefinition builderField;
FieldDefinition stateField; FieldDefinition stateField;
Dictionary<FieldDefinition, ILVariable> fieldToParameterMap = new Dictionary<FieldDefinition, ILVariable>(); Dictionary<FieldDefinition, ILVariable> fieldToParameterMap = new Dictionary<FieldDefinition, ILVariable>();
ILVariable cachedStateVar;
// These fields are set by AnalyzeMoveNext() // These fields are set by AnalyzeMoveNext()
int finalState = -2; int finalState = -2;
@ -155,7 +156,7 @@ namespace ICSharpCode.Decompiler.ILAst
ILExpression loadStateMachineForBuilderExpr; ILExpression loadStateMachineForBuilderExpr;
if (!loadBuilderExpr.Match(ILCode.Ldfld, out builderFieldRef, out loadStateMachineForBuilderExpr)) if (!loadBuilderExpr.Match(ILCode.Ldfld, out builderFieldRef, out loadStateMachineForBuilderExpr))
return false; return false;
if (!loadStateMachineForBuilderExpr.MatchLdloca(stateMachineVar)) if (!(loadStateMachineForBuilderExpr.MatchLdloca(stateMachineVar) || loadStateMachineForBuilderExpr.MatchLdloc(stateMachineVar)))
return false; return false;
builderField = builderFieldRef.ResolveWithinSameModule(); builderField = builderFieldRef.ResolveWithinSameModule();
if (builderField == null) if (builderField == null)
@ -235,36 +236,50 @@ namespace ICSharpCode.Decompiler.ILAst
{ {
ILBlock ilMethod = CreateILAst(moveNextMethod); ILBlock ilMethod = CreateILAst(moveNextMethod);
if (ilMethod.Body.Count != 6) int startIndex;
if (ilMethod.Body.Count == 6) {
startIndex = 0;
} else if (ilMethod.Body.Count == 7) {
// stloc(cachedState, ldfld(valuetype StateMachineStruct::<>1__state, ldloc(this)))
ILExpression cachedStateInit;
if (!ilMethod.Body[0].Match(ILCode.Stloc, out cachedStateVar, out cachedStateInit))
throw new SymbolicAnalysisFailedException();
ILExpression instanceExpr;
FieldReference loadedField;
if (!cachedStateInit.Match(ILCode.Ldfld, out loadedField, out instanceExpr) || loadedField.ResolveWithinSameModule() != stateField || !instanceExpr.MatchThis())
throw new SymbolicAnalysisFailedException();
startIndex = 1;
} else {
throw new SymbolicAnalysisFailedException(); throw new SymbolicAnalysisFailedException();
}
mainTryCatch = ilMethod.Body[0] as ILTryCatchBlock; mainTryCatch = ilMethod.Body[startIndex + 0] as ILTryCatchBlock;
if (mainTryCatch == null || mainTryCatch.CatchBlocks.Count != 1) if (mainTryCatch == null || mainTryCatch.CatchBlocks.Count != 1)
throw new SymbolicAnalysisFailedException(); throw new SymbolicAnalysisFailedException();
if (mainTryCatch.FaultBlock != null || mainTryCatch.FinallyBlock != null) if (mainTryCatch.FaultBlock != null || mainTryCatch.FinallyBlock != null)
throw new SymbolicAnalysisFailedException(); throw new SymbolicAnalysisFailedException();
setResultAndExitLabel = ilMethod.Body[1] as ILLabel; setResultAndExitLabel = ilMethod.Body[startIndex + 1] as ILLabel;
if (setResultAndExitLabel == null) if (setResultAndExitLabel == null)
throw new SymbolicAnalysisFailedException(); throw new SymbolicAnalysisFailedException();
if (!MatchStateAssignment(ilMethod.Body[2], out finalState)) if (!MatchStateAssignment(ilMethod.Body[startIndex + 2], out finalState))
throw new SymbolicAnalysisFailedException(); throw new SymbolicAnalysisFailedException();
// call(AsyncTaskMethodBuilder`1::SetResult, ldflda(StateMachine::<>t__builder, ldloc(this)), ldloc(<>t__result)) // call(AsyncTaskMethodBuilder`1::SetResult, ldflda(StateMachine::<>t__builder, ldloc(this)), ldloc(<>t__result))
MethodReference setResultMethod; MethodReference setResultMethod;
ILExpression builderExpr; ILExpression builderExpr;
if (methodType == AsyncMethodType.TaskOfT) { if (methodType == AsyncMethodType.TaskOfT) {
if (!ilMethod.Body[3].Match(ILCode.Call, out setResultMethod, out builderExpr, out resultExpr)) if (!ilMethod.Body[startIndex + 3].Match(ILCode.Call, out setResultMethod, out builderExpr, out resultExpr))
throw new SymbolicAnalysisFailedException(); throw new SymbolicAnalysisFailedException();
} else { } else {
if (!ilMethod.Body[3].Match(ILCode.Call, out setResultMethod, out builderExpr)) if (!ilMethod.Body[startIndex + 3].Match(ILCode.Call, out setResultMethod, out builderExpr))
throw new SymbolicAnalysisFailedException(); throw new SymbolicAnalysisFailedException();
} }
if (!(setResultMethod.Name == "SetResult" && IsBuilderFieldOnThis(builderExpr))) if (!(setResultMethod.Name == "SetResult" && IsBuilderFieldOnThis(builderExpr)))
throw new SymbolicAnalysisFailedException(); throw new SymbolicAnalysisFailedException();
exitLabel = ilMethod.Body[4] as ILLabel; exitLabel = ilMethod.Body[startIndex + 4] as ILLabel;
if (exitLabel == null) if (exitLabel == null)
throw new SymbolicAnalysisFailedException(); throw new SymbolicAnalysisFailedException();
} }
@ -318,7 +333,7 @@ namespace ICSharpCode.Decompiler.ILAst
bool MatchStateAssignment(ILNode stfld, out int stateID) bool MatchStateAssignment(ILNode stfld, out int stateID)
{ {
// stfld(StateMachine::<>1__state, ldloc(this), ldc.i4(-2)) // stfld(StateMachine::<>1__state, ldloc(this), ldc.i4(stateId))
stateID = 0; stateID = 0;
FieldReference fieldRef; FieldReference fieldRef;
ILExpression target, val; ILExpression target, val;
@ -329,6 +344,31 @@ namespace ICSharpCode.Decompiler.ILAst
} }
return false; return false;
} }
bool MatchRoslynStateAssignment(List<ILNode> block, int index, out int stateID)
{
// v = ldc.i4(stateId)
// stloc(cachedState, v)
// stfld(StateMachine::<>1__state, ldloc(this), v)
stateID = 0;
if (index < 0)
return false;
ILVariable v;
ILExpression val;
if (!block[index].Match(ILCode.Stloc, out v, out val) || !val.Match(ILCode.Ldc_I4, out stateID))
return false;
ILExpression loadV;
if (!block[index + 1].MatchStloc(cachedStateVar, out loadV) || !loadV.MatchLdloc(v))
return false;
ILExpression target;
FieldReference fieldRef;
if (block[index + 2].Match(ILCode.Stfld, out fieldRef, out target, out loadV)) {
return fieldRef.ResolveWithinSameModule() == stateField
&& target.MatchThis()
&& loadV.MatchLdloc(v);
}
return false;
}
#endregion #endregion
#region AnalyzeStateMachine #region AnalyzeStateMachine
@ -345,7 +385,7 @@ namespace ICSharpCode.Decompiler.ILAst
if (body.Count == 0) if (body.Count == 0)
throw new SymbolicAnalysisFailedException(); throw new SymbolicAnalysisFailedException();
} }
StateRangeAnalysis rangeAnalysis = new StateRangeAnalysis(body[0], StateRangeAnalysisMode.AsyncMoveNext, stateField); StateRangeAnalysis rangeAnalysis = new StateRangeAnalysis(body[0], StateRangeAnalysisMode.AsyncMoveNext, stateField, cachedStateVar);
int bodyLength = block.Body.Count; int bodyLength = block.Body.Count;
int pos = rangeAnalysis.AssignStateRanges(body, bodyLength); int pos = rangeAnalysis.AssignStateRanges(body, bodyLength);
rangeAnalysis.EnsureLabelAtPos(body, ref pos, ref bodyLength); rangeAnalysis.EnsureLabelAtPos(body, ref pos, ref bodyLength);
@ -435,18 +475,16 @@ namespace ICSharpCode.Decompiler.ILAst
List<ILNode> ConvertFinally(List<ILNode> body) List<ILNode> ConvertFinally(List<ILNode> body)
{ {
List<ILNode> newBody = new List<ILNode>(body); List<ILNode> newBody = new List<ILNode>(body);
if (newBody.Count == 0)
return newBody;
ILLabel endFinallyLabel; ILLabel endFinallyLabel;
ILExpression ceqExpr; ILExpression ceqExpr;
if (newBody.Count > 0 && newBody[0].Match(ILCode.Brtrue, out endFinallyLabel, out ceqExpr)) { if (newBody[0].Match(ILCode.Brtrue, out endFinallyLabel, out ceqExpr)) {
ILExpression loadDoFinallyBodies, loadZero; ILExpression condition;
object unused; if (MatchLogicNot(ceqExpr, out condition)) {
if (ceqExpr.Match(ILCode.Ceq, out unused, out loadDoFinallyBodies, out loadZero)) { if (condition.MatchLdloc(doFinallyBodies)) {
int num;
if (loadDoFinallyBodies.MatchLdloc(doFinallyBodies) && loadZero.Match(ILCode.Ldc_I4, out num) && num == 0) {
newBody.RemoveAt(0); newBody.RemoveAt(0);
} } else if (condition.Code == ILCode.Clt && condition.Arguments[0].MatchLdloc(cachedStateVar) && condition.Arguments[1].MatchLdcI4(0)) {
} else if (ceqExpr.Match(ILCode.LogicNot, out loadDoFinallyBodies)) {
if (loadDoFinallyBodies.MatchLdloc(doFinallyBodies)) {
newBody.RemoveAt(0); newBody.RemoveAt(0);
} }
} }
@ -454,6 +492,17 @@ namespace ICSharpCode.Decompiler.ILAst
return newBody; return newBody;
} }
bool MatchLogicNot(ILExpression expr, out ILExpression arg)
{
ILExpression loadZero;
object unused;
if (expr.Match(ILCode.Ceq, out unused, out arg, out loadZero)) {
int num;
return loadZero.Match(ILCode.Ldc_I4, out num) && num == 0;
}
return expr.Match(ILCode.LogicNot, out arg);
}
void HandleAwait(List<ILNode> newBody, out ILVariable awaiterVar, out FieldDefinition awaiterField, out int targetStateID) void HandleAwait(List<ILNode> newBody, out ILVariable awaiterVar, out FieldDefinition awaiterField, out int targetStateID)
{ {
// Handle the instructions prior to the exit out of the method to detect what is being awaited. // Handle the instructions prior to the exit out of the method to detect what is being awaited.
@ -475,7 +524,8 @@ namespace ICSharpCode.Decompiler.ILAst
newBody.RemoveAt(newBody.Count - 1); // remove AwaitUnsafeOnCompleted call newBody.RemoveAt(newBody.Count - 1); // remove AwaitUnsafeOnCompleted call
if (callAwaitUnsafeOnCompleted == null || callAwaitUnsafeOnCompleted.Code != ILCode.Call) if (callAwaitUnsafeOnCompleted == null || callAwaitUnsafeOnCompleted.Code != ILCode.Call)
throw new SymbolicAnalysisFailedException(); throw new SymbolicAnalysisFailedException();
if (((MethodReference)callAwaitUnsafeOnCompleted.Operand).Name != "AwaitUnsafeOnCompleted") string methodName = ((MethodReference)callAwaitUnsafeOnCompleted.Operand).Name;
if (methodName != "AwaitUnsafeOnCompleted" && methodName != "AwaitOnCompleted")
throw new SymbolicAnalysisFailedException(); throw new SymbolicAnalysisFailedException();
if (callAwaitUnsafeOnCompleted.Arguments.Count != 3) if (callAwaitUnsafeOnCompleted.Arguments.Count != 3)
throw new SymbolicAnalysisFailedException(); throw new SymbolicAnalysisFailedException();
@ -493,9 +543,10 @@ namespace ICSharpCode.Decompiler.ILAst
throw new SymbolicAnalysisFailedException(); throw new SymbolicAnalysisFailedException();
// stfld(StateMachine::<>1__state, ldloc(this), ldc.i4(0)) // stfld(StateMachine::<>1__state, ldloc(this), ldc.i4(0))
if (!MatchStateAssignment(newBody.LastOrDefault(), out targetStateID)) if (MatchStateAssignment(newBody.LastOrDefault(), out targetStateID))
throw new SymbolicAnalysisFailedException(); newBody.RemoveAt(newBody.Count - 1); // remove awaiter field assignment
newBody.RemoveAt(newBody.Count - 1); // remove awaiter field assignment else if (MatchRoslynStateAssignment(newBody, newBody.Count - 3, out targetStateID))
newBody.RemoveRange(newBody.Count - 3, 3); // remove awaiter field assignment
} }
#endregion #endregion

8
src/Libraries/ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs

@ -413,11 +413,11 @@ namespace ICSharpCode.Decompiler.ILAst
} }
} }
// Occasionally the compilers or obfuscators generate unreachable code (which might be intentonally invalid) // Occasionally the compilers or obfuscators generate unreachable code (which might be intentionally invalid)
// I belive it is safe to just remove it // I believe it is safe to just remove it
body.RemoveAll(b => b.StackBefore == null); body.RemoveAll(b => b.StackBefore == null);
// Genertate temporary variables to replace stack // Generate temporary variables to replace stack
foreach(ByteCode byteCode in body) { foreach(ByteCode byteCode in body) {
int argIdx = 0; int argIdx = 0;
int popCount = byteCode.PopCount ?? byteCode.StackBefore.Length; int popCount = byteCode.PopCount ?? byteCode.StackBefore.Length;
@ -652,7 +652,7 @@ namespace ICSharpCode.Decompiler.ILAst
// Find the first and widest scope // Find the first and widest scope
int tryStart = ehs.Min(eh => eh.TryStart.Offset); int tryStart = ehs.Min(eh => eh.TryStart.Offset);
int tryEnd = ehs.Where(eh => eh.TryStart.Offset == tryStart).Max(eh => eh.TryEnd.Offset); int tryEnd = ehs.Where(eh => eh.TryStart.Offset == tryStart).Max(eh => eh.TryEnd.Offset);
var handlers = ehs.Where(eh => eh.TryStart.Offset == tryStart && eh.TryEnd.Offset == tryEnd).OrderBy(eh => eh.TryStart.Offset).ToList(); var handlers = ehs.Where(eh => eh.TryStart.Offset == tryStart && eh.TryEnd.Offset == tryEnd).ToList();
// Remember that any part of the body migt have been removed due to unreachability // Remember that any part of the body migt have been removed due to unreachability

20
src/Libraries/ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs

@ -170,11 +170,15 @@ namespace ICSharpCode.Decompiler.ILAst
modified |= block.RunOptimization(TransformObjectInitializers); modified |= block.RunOptimization(TransformObjectInitializers);
if (abortBeforeStep == ILAstOptimizationStep.MakeAssignmentExpression) return; if (abortBeforeStep == ILAstOptimizationStep.MakeAssignmentExpression) return;
modified |= block.RunOptimization(MakeAssignmentExpression); if (context.Settings.MakeAssignmentExpressions) {
modified |= block.RunOptimization(MakeAssignmentExpression);
}
modified |= block.RunOptimization(MakeCompoundAssignments); modified |= block.RunOptimization(MakeCompoundAssignments);
if (abortBeforeStep == ILAstOptimizationStep.IntroducePostIncrement) return; if (abortBeforeStep == ILAstOptimizationStep.IntroducePostIncrement) return;
modified |= block.RunOptimization(IntroducePostIncrement); if (context.Settings.IntroduceIncrementAndDecrement) {
modified |= block.RunOptimization(IntroducePostIncrement);
}
if (abortBeforeStep == ILAstOptimizationStep.InlineExpressionTreeParameterDeclarations) return; if (abortBeforeStep == ILAstOptimizationStep.InlineExpressionTreeParameterDeclarations) return;
if (context.Settings.ExpressionTrees) { if (context.Settings.ExpressionTrees) {
@ -225,11 +229,13 @@ namespace ICSharpCode.Decompiler.ILAst
new ILInlining(method).InlineAllVariables(); new ILInlining(method).InlineAllVariables();
if (abortBeforeStep == ILAstOptimizationStep.CachedDelegateInitialization) return; if (abortBeforeStep == ILAstOptimizationStep.CachedDelegateInitialization) return;
foreach(ILBlock block in method.GetSelfAndChildrenRecursive<ILBlock>()) { if (context.Settings.AnonymousMethods) {
for (int i = 0; i < block.Body.Count; i++) { foreach(ILBlock block in method.GetSelfAndChildrenRecursive<ILBlock>()) {
// TODO: Move before loops for (int i = 0; i < block.Body.Count; i++) {
CachedDelegateInitializationWithField(block, ref i); // TODO: Move before loops
CachedDelegateInitializationWithLocal(block, ref i); CachedDelegateInitializationWithField(block, ref i);
CachedDelegateInitializationWithLocal(block, ref i);
}
} }
} }

20
src/Libraries/ICSharpCode.Decompiler/ILAst/ILInlining.cs

@ -50,32 +50,36 @@ namespace ICSharpCode.Decompiler.ILAst
AnalyzeNode(method); AnalyzeNode(method);
} }
void AnalyzeNode(ILNode node) /// <summary>
/// For each variable reference, adds <paramref name="direction"/> to the num* dicts.
/// Direction will be 1 for analysis, and -1 when removing a node from analysis.
/// </summary>
void AnalyzeNode(ILNode node, int direction = 1)
{ {
ILExpression expr = node as ILExpression; ILExpression expr = node as ILExpression;
if (expr != null) { if (expr != null) {
ILVariable locVar = expr.Operand as ILVariable; ILVariable locVar = expr.Operand as ILVariable;
if (locVar != null) { if (locVar != null) {
if (expr.Code == ILCode.Stloc) { if (expr.Code == ILCode.Stloc) {
numStloc[locVar] = numStloc.GetOrDefault(locVar) + 1; numStloc[locVar] = numStloc.GetOrDefault(locVar) + direction;
} else if (expr.Code == ILCode.Ldloc) { } else if (expr.Code == ILCode.Ldloc) {
numLdloc[locVar] = numLdloc.GetOrDefault(locVar) + 1; numLdloc[locVar] = numLdloc.GetOrDefault(locVar) + direction;
} else if (expr.Code == ILCode.Ldloca) { } else if (expr.Code == ILCode.Ldloca) {
numLdloca[locVar] = numLdloca.GetOrDefault(locVar) + 1; numLdloca[locVar] = numLdloca.GetOrDefault(locVar) + direction;
} else { } else {
throw new NotSupportedException(expr.Code.ToString()); throw new NotSupportedException(expr.Code.ToString());
} }
} }
foreach (ILExpression child in expr.Arguments) foreach (ILExpression child in expr.Arguments)
AnalyzeNode(child); AnalyzeNode(child, direction);
} else { } else {
var catchBlock = node as ILTryCatchBlock.CatchBlock; var catchBlock = node as ILTryCatchBlock.CatchBlock;
if (catchBlock != null && catchBlock.ExceptionVariable != null) { if (catchBlock != null && catchBlock.ExceptionVariable != null) {
numStloc[catchBlock.ExceptionVariable] = numStloc.GetOrDefault(catchBlock.ExceptionVariable) + 1; numStloc[catchBlock.ExceptionVariable] = numStloc.GetOrDefault(catchBlock.ExceptionVariable) + direction;
} }
foreach (ILNode child in node.GetChildren()) foreach (ILNode child in node.GetChildren())
AnalyzeNode(child); AnalyzeNode(child, direction);
} }
} }
@ -194,6 +198,7 @@ namespace ICSharpCode.Decompiler.ILAst
// The variable is never loaded // The variable is never loaded
if (inlinedExpression.HasNoSideEffects()) { if (inlinedExpression.HasNoSideEffects()) {
// Remove completely // Remove completely
AnalyzeNode(body[pos], -1);
body.RemoveAt(pos); body.RemoveAt(pos);
return true; return true;
} else if (inlinedExpression.CanBeExpressionStatement() && v.IsGenerated) { } else if (inlinedExpression.CanBeExpressionStatement() && v.IsGenerated) {
@ -334,6 +339,7 @@ namespace ICSharpCode.Decompiler.ILAst
case ILCode.Stfld: case ILCode.Stfld:
case ILCode.Ldfld: case ILCode.Ldfld:
case ILCode.Ldflda: case ILCode.Ldflda:
case ILCode.Await:
return true; return true;
} }
} }

6
src/Libraries/ICSharpCode.Decompiler/ILAst/PatternMatching.cs

@ -167,5 +167,11 @@ namespace ICSharpCode.Decompiler.ILAst
ILVariable v; ILVariable v;
return node.Match(ILCode.Stloc, out v, out expr) && v == expectedVar; return node.Match(ILCode.Stloc, out v, out expr) && v == expectedVar;
} }
public static bool MatchLdcI4(this ILNode node, int expectedValue)
{
int v;
return node.Match(ILCode.Ldc_I4, out v) && v == expectedValue;
}
} }
} }

14
src/Libraries/ICSharpCode.Decompiler/ILAst/StateRange.cs

@ -137,23 +137,25 @@ namespace ICSharpCode.Decompiler.ILAst
internal DefaultDictionary<ILNode, StateRange> ranges; internal DefaultDictionary<ILNode, StateRange> ranges;
SymbolicEvaluationContext evalContext; SymbolicEvaluationContext evalContext;
internal Dictionary<MethodDefinition, Interval> finallyMethodToStateInterval; // used only for IteratorDispose internal Dictionary<MethodDefinition, StateRange> finallyMethodToStateRange; // used only for IteratorDispose
/// <summary> /// <summary>
/// Initializes the state range logic: /// Initializes the state range logic:
/// Clears 'ranges' and sets 'ranges[entryPoint]' to the full range (int.MinValue to int.MaxValue) /// Clears 'ranges' and sets 'ranges[entryPoint]' to the full range (int.MinValue to int.MaxValue)
/// </summary> /// </summary>
public StateRangeAnalysis(ILNode entryPoint, StateRangeAnalysisMode mode, FieldDefinition stateField) public StateRangeAnalysis(ILNode entryPoint, StateRangeAnalysisMode mode, FieldDefinition stateField, ILVariable cachedStateVar = null)
{ {
this.mode = mode; this.mode = mode;
this.stateField = stateField; this.stateField = stateField;
if (mode == StateRangeAnalysisMode.IteratorDispose) { if (mode == StateRangeAnalysisMode.IteratorDispose) {
finallyMethodToStateInterval = new Dictionary<MethodDefinition, Interval>(); finallyMethodToStateRange = new Dictionary<MethodDefinition, StateRange>();
} }
ranges = new DefaultDictionary<ILNode, StateRange>(n => new StateRange()); ranges = new DefaultDictionary<ILNode, StateRange>(n => new StateRange());
ranges[entryPoint] = new StateRange(int.MinValue, int.MaxValue); ranges[entryPoint] = new StateRange(int.MinValue, int.MaxValue);
evalContext = new SymbolicEvaluationContext(stateField); evalContext = new SymbolicEvaluationContext(stateField);
if (cachedStateVar != null)
evalContext.AddStateVariable(cachedStateVar);
} }
public int AssignStateRanges(List<ILNode> body, int bodyLength) public int AssignStateRanges(List<ILNode> body, int bodyLength)
@ -213,7 +215,7 @@ namespace ICSharpCode.Decompiler.ILAst
break; break;
case ILCode.Brtrue: case ILCode.Brtrue:
{ {
SymbolicValue val = evalContext.Eval(expr.Arguments[0]); SymbolicValue val = evalContext.Eval(expr.Arguments[0]).AsBool();
if (val.Type == SymbolicValueType.StateEquals) { if (val.Type == SymbolicValueType.StateEquals) {
ranges[(ILLabel)expr.Operand].UnionWith(nodeRange, val.Constant, val.Constant); ranges[(ILLabel)expr.Operand].UnionWith(nodeRange, val.Constant, val.Constant);
StateRange nextRange = ranges[body[i + 1]]; StateRange nextRange = ranges[body[i + 1]];
@ -249,9 +251,9 @@ namespace ICSharpCode.Decompiler.ILAst
// in some cases (e.g. foreach over array) the C# compiler produces a finally method outside of try-finally blocks // in some cases (e.g. foreach over array) the C# compiler produces a finally method outside of try-finally blocks
if (mode == StateRangeAnalysisMode.IteratorDispose) { if (mode == StateRangeAnalysisMode.IteratorDispose) {
MethodDefinition mdef = (expr.Operand as MethodReference).ResolveWithinSameModule(); MethodDefinition mdef = (expr.Operand as MethodReference).ResolveWithinSameModule();
if (mdef == null || finallyMethodToStateInterval.ContainsKey(mdef)) if (mdef == null || finallyMethodToStateRange.ContainsKey(mdef))
throw new SymbolicAnalysisFailedException(); throw new SymbolicAnalysisFailedException();
finallyMethodToStateInterval.Add(mdef, nodeRange.ToEnclosingInterval()); finallyMethodToStateRange.Add(mdef, nodeRange);
break; break;
} else { } else {
goto default; goto default;

15
src/Libraries/ICSharpCode.Decompiler/ILAst/SymbolicExecution.cs

@ -67,7 +67,16 @@ namespace ICSharpCode.Decompiler.ILAst
this.Type = type; this.Type = type;
this.Constant = constant; this.Constant = constant;
} }
public SymbolicValue AsBool()
{
if (Type == SymbolicValueType.State) {
// convert state integer to bool:
// if (state + c) = if (state + c != 0) = if (state != -c)
return new SymbolicValue(SymbolicValueType.StateInEquals, unchecked(-Constant));
}
return this;
}
public override string ToString() public override string ToString()
{ {
return string.Format("[SymbolicValue {0}: {1}]", this.Type, this.Constant); return string.Format("[SymbolicValue {0}: {1}]", this.Type, this.Constant);
@ -133,7 +142,7 @@ namespace ICSharpCode.Decompiler.ILAst
// bool: (state == right.Constant - left.Constant) // bool: (state == right.Constant - left.Constant)
return new SymbolicValue(expr.Code == ILCode.Ceq ? SymbolicValueType.StateEquals : SymbolicValueType.StateInEquals, unchecked(right.Constant - left.Constant)); return new SymbolicValue(expr.Code == ILCode.Ceq ? SymbolicValueType.StateEquals : SymbolicValueType.StateInEquals, unchecked(right.Constant - left.Constant));
case ILCode.LogicNot: case ILCode.LogicNot:
SymbolicValue val = Eval(expr.Arguments[0]); SymbolicValue val = Eval(expr.Arguments[0]).AsBool();
if (val.Type == SymbolicValueType.StateEquals) if (val.Type == SymbolicValueType.StateEquals)
return new SymbolicValue(SymbolicValueType.StateInEquals, val.Constant); return new SymbolicValue(SymbolicValueType.StateInEquals, val.Constant);
else if (val.Type == SymbolicValueType.StateInEquals) else if (val.Type == SymbolicValueType.StateInEquals)
@ -141,7 +150,7 @@ namespace ICSharpCode.Decompiler.ILAst
else else
return Failed(); return Failed();
default: default:
return Failed(); return Failed();
} }
} }
} }

4
src/Libraries/ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs

@ -539,6 +539,8 @@ namespace ICSharpCode.Decompiler.ILAst
if (forceInferChildren) if (forceInferChildren)
InferTypeForExpression(expr.Arguments[1], typeSystem.Int32); InferTypeForExpression(expr.Arguments[1], typeSystem.Int32);
TypeReference type = NumericPromotion(InferTypeForExpression(expr.Arguments[0], null)); TypeReference type = NumericPromotion(InferTypeForExpression(expr.Arguments[0], null));
if (type == null)
return null;
TypeReference expectedInputType = null; TypeReference expectedInputType = null;
switch (type.MetadataType) { switch (type.MetadataType) {
case MetadataType.Int32: case MetadataType.Int32:
@ -827,7 +829,7 @@ namespace ICSharpCode.Decompiler.ILAst
case ILCode.Await: case ILCode.Await:
{ {
TypeReference taskType = InferTypeForExpression(expr.Arguments[0], null); TypeReference taskType = InferTypeForExpression(expr.Arguments[0], null);
if (taskType.Name == "Task`1" && taskType.IsGenericInstance && taskType.Namespace == "System.Threading.Tasks") { if (taskType != null && taskType.Name == "Task`1" && taskType.IsGenericInstance && taskType.Namespace == "System.Threading.Tasks") {
return ((GenericInstanceType)taskType).GenericArguments[0]; return ((GenericInstanceType)taskType).GenericArguments[0];
} }
return null; return null;

30
src/Libraries/ICSharpCode.Decompiler/ILAst/YieldReturnDecompiler.cs

@ -312,7 +312,7 @@ namespace ICSharpCode.Decompiler.ILAst
// This is (int.MinValue, int.MaxValue) for the first instruction. // This is (int.MinValue, int.MaxValue) for the first instruction.
// These ranges are propagated depending on the conditional jumps performed by the code. // These ranges are propagated depending on the conditional jumps performed by the code.
Dictionary<MethodDefinition, Interval> finallyMethodToStateInterval; Dictionary<MethodDefinition, StateRange> finallyMethodToStateRange;
void ConstructExceptionTable() void ConstructExceptionTable()
{ {
@ -321,11 +321,11 @@ namespace ICSharpCode.Decompiler.ILAst
var rangeAnalysis = new StateRangeAnalysis(ilMethod.Body[0], StateRangeAnalysisMode.IteratorDispose, stateField); var rangeAnalysis = new StateRangeAnalysis(ilMethod.Body[0], StateRangeAnalysisMode.IteratorDispose, stateField);
rangeAnalysis.AssignStateRanges(ilMethod.Body, ilMethod.Body.Count); rangeAnalysis.AssignStateRanges(ilMethod.Body, ilMethod.Body.Count);
finallyMethodToStateInterval = rangeAnalysis.finallyMethodToStateInterval; finallyMethodToStateRange = rangeAnalysis.finallyMethodToStateRange;
// Now look at the finally blocks: // Now look at the finally blocks:
foreach (var tryFinally in ilMethod.GetSelfAndChildrenRecursive<ILTryCatchBlock>()) { foreach (var tryFinally in ilMethod.GetSelfAndChildrenRecursive<ILTryCatchBlock>()) {
Interval interval = rangeAnalysis.ranges[tryFinally.TryBlock.Body[0]].ToEnclosingInterval(); var range = rangeAnalysis.ranges[tryFinally.TryBlock.Body[0]];
var finallyBody = tryFinally.FinallyBlock.Body; var finallyBody = tryFinally.FinallyBlock.Body;
if (finallyBody.Count != 2) if (finallyBody.Count != 2)
throw new SymbolicAnalysisFailedException(); throw new SymbolicAnalysisFailedException();
@ -338,9 +338,9 @@ namespace ICSharpCode.Decompiler.ILAst
throw new SymbolicAnalysisFailedException(); throw new SymbolicAnalysisFailedException();
MethodDefinition mdef = GetMethodDefinition(call.Operand as MethodReference); MethodDefinition mdef = GetMethodDefinition(call.Operand as MethodReference);
if (mdef == null || finallyMethodToStateInterval.ContainsKey(mdef)) if (mdef == null || finallyMethodToStateRange.ContainsKey(mdef))
throw new SymbolicAnalysisFailedException(); throw new SymbolicAnalysisFailedException();
finallyMethodToStateInterval.Add(mdef, interval); finallyMethodToStateRange.Add(mdef, range);
} }
rangeAnalysis = null; rangeAnalysis = null;
} }
@ -430,10 +430,9 @@ namespace ICSharpCode.Decompiler.ILAst
bodyLength--; // don't conside the stloc instruction to be part of the body bodyLength--; // don't conside the stloc instruction to be part of the body
} }
// verify that the last element in the body is a label pointing to the 'ret(false)' // The last element in the body usually is a label pointing to the 'ret(false)'
returnFalseLabel = body.ElementAtOrDefault(bodyLength - 1) as ILLabel; returnFalseLabel = body.ElementAtOrDefault(bodyLength - 1) as ILLabel;
if (returnFalseLabel == null) // Note: in Roslyn-compiled code, returnFalseLabel may be null.
throw new SymbolicAnalysisFailedException();
var rangeAnalysis = new StateRangeAnalysis(body[0], StateRangeAnalysisMode.IteratorMoveNext, stateField); var rangeAnalysis = new StateRangeAnalysis(body[0], StateRangeAnalysisMode.IteratorMoveNext, stateField);
int pos = rangeAnalysis.AssignStateRanges(body, bodyLength); int pos = rangeAnalysis.AssignStateRanges(body, bodyLength);
@ -485,7 +484,7 @@ namespace ICSharpCode.Decompiler.ILAst
throw new SymbolicAnalysisFailedException(); throw new SymbolicAnalysisFailedException();
int val = (int)expr.Arguments[0].Operand; int val = (int)expr.Arguments[0].Operand;
if (val == 0) { if (val == 0) {
newBody.Add(MakeGoTo(returnFalseLabel)); newBody.Add(new ILExpression(ILCode.YieldBreak, null));
} else if (val == 1) { } else if (val == 1) {
newBody.Add(MakeGoTo(labels, currentState)); newBody.Add(MakeGoTo(labels, currentState));
} else { } else {
@ -497,7 +496,7 @@ namespace ICSharpCode.Decompiler.ILAst
// handle direct return (e.g. in release builds) // handle direct return (e.g. in release builds)
int val = (int)expr.Arguments[0].Operand; int val = (int)expr.Arguments[0].Operand;
if (val == 0) { if (val == 0) {
newBody.Add(MakeGoTo(returnFalseLabel)); newBody.Add(new ILExpression(ILCode.YieldBreak, null));
} else if (val == 1) { } else if (val == 1) {
newBody.Add(MakeGoTo(labels, currentState)); newBody.Add(MakeGoTo(labels, currentState));
} else { } else {
@ -507,21 +506,21 @@ namespace ICSharpCode.Decompiler.ILAst
MethodDefinition method = GetMethodDefinition(expr.Operand as MethodReference); MethodDefinition method = GetMethodDefinition(expr.Operand as MethodReference);
if (method == null) if (method == null)
throw new SymbolicAnalysisFailedException(); throw new SymbolicAnalysisFailedException();
Interval interval; StateRange stateRange;
if (method == disposeMethod) { if (method == disposeMethod) {
// Explicit call to dispose is used for "yield break;" within the method. // Explicit call to dispose is used for "yield break;" within the method.
ILExpression br = body.ElementAtOrDefault(++pos) as ILExpression; ILExpression br = body.ElementAtOrDefault(++pos) as ILExpression;
if (br == null || !(br.Code == ILCode.Br || br.Code == ILCode.Leave) || br.Operand != returnFalseLabel) if (br == null || !(br.Code == ILCode.Br || br.Code == ILCode.Leave) || br.Operand != returnFalseLabel)
throw new SymbolicAnalysisFailedException(); throw new SymbolicAnalysisFailedException();
newBody.Add(MakeGoTo(returnFalseLabel)); newBody.Add(new ILExpression(ILCode.YieldBreak, null));
} else if (finallyMethodToStateInterval.TryGetValue(method, out interval)) { } else if (finallyMethodToStateRange.TryGetValue(method, out stateRange)) {
// Call to Finally-method // Call to Finally-method
int index = stateChanges.FindIndex(ss => ss.NewState >= interval.Start && ss.NewState <= interval.End); int index = stateChanges.FindIndex(ss => stateRange.Contains(ss.NewState));
if (index < 0) if (index < 0)
throw new SymbolicAnalysisFailedException(); throw new SymbolicAnalysisFailedException();
ILLabel label = new ILLabel(); ILLabel label = new ILLabel();
label.Name = "JumpOutOfTryFinally" + interval.Start + "_" + interval.End; label.Name = "JumpOutOfTryFinally" + stateChanges[index].NewState;
newBody.Add(new ILExpression(ILCode.Leave, label)); newBody.Add(new ILExpression(ILCode.Leave, label));
SetState stateChange = stateChanges[index]; SetState stateChange = stateChanges[index];
@ -544,6 +543,7 @@ namespace ICSharpCode.Decompiler.ILAst
ILExpression MakeGoTo(ILLabel targetLabel) ILExpression MakeGoTo(ILLabel targetLabel)
{ {
Debug.Assert(targetLabel != null);
if (targetLabel == returnFalseLabel) if (targetLabel == returnFalseLabel)
return new ILExpression(ILCode.YieldBreak, null); return new ILExpression(ILCode.YieldBreak, null);
else else

26
src/Libraries/ICSharpCode.Decompiler/Properties/AssemblyInfo.cs

@ -1,31 +1,17 @@
// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team #region Using directives
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System; using System;
using System.Resources; using System.Resources;
using System.Reflection; using System.Reflection;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
#endregion
[assembly: AssemblyTitle("ICSharpCode.Decompiler")] [assembly: AssemblyTitle("ICSharpCode.Decompiler")]
[assembly: AssemblyDescription("IL decompiler engine")] [assembly: AssemblyDescription("IL decompiler engine")]
[assembly: AssemblyCompany("ic#code")] [assembly: AssemblyCompany("ic#code")]
[assembly: AssemblyProduct("ILSpy")] [assembly: AssemblyProduct("ILSpy")]
[assembly: AssemblyCopyright("Copyright 2011 AlphaSierraPapa for the SharpDevelop Team")] [assembly: AssemblyCopyright("Copyright 2011-2014 AlphaSierraPapa for the SharpDevelop Team")]
[assembly: AssemblyTrademark("")] [assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")] [assembly: AssemblyCulture("")]
@ -33,8 +19,8 @@ using System.Runtime.InteropServices;
// If you need to expose a type to COM, use [ComVisible(true)] on that type. // If you need to expose a type to COM, use [ComVisible(true)] on that type.
[assembly: ComVisible(false)] [assembly: ComVisible(false)]
[assembly: AssemblyVersion("2.1.0.1619")] [assembly: AssemblyVersion("2.2.0.1706")]
[assembly: AssemblyInformationalVersion("2.1.0.1619-214c1f73")] [assembly: AssemblyInformationalVersion("2.2.0.1706-cc270c8f")]
[assembly: NeutralResourcesLanguage("en-US")] [assembly: NeutralResourcesLanguage("en-US")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2243:AttributeStringLiteralsShouldParseCorrectly", [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2243:AttributeStringLiteralsShouldParseCorrectly",

11
src/Libraries/ICSharpCode.Decompiler/Tests/Async.cs

@ -20,6 +20,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Runtime.CompilerServices;
using System.Threading.Tasks; using System.Threading.Tasks;
public class Async public class Async
@ -36,6 +37,16 @@ public class Async
Console.WriteLine("No Await"); Console.WriteLine("No Await");
} }
public async void AwaitYield()
{
await Task.Yield();
}
public async void AwaitDefaultYieldAwaitable()
{
await default(YieldAwaitable);
}
public async Task SimpleVoidTaskMethod() public async Task SimpleVoidTaskMethod()
{ {
Console.WriteLine("Before"); Console.WriteLine("Before");

16
src/Libraries/ICSharpCode.Decompiler/Tests/DelegateConstruction.cs

@ -62,6 +62,22 @@ public static class DelegateConstruction
} }
return null; return null;
} }
public void LambdaInForLoop()
{
for (int i = 0; i < 100000; i++) {
Bar(() => Foo());
}
}
public int Foo()
{
return 0;
}
public void Bar(Func<int> f)
{
}
} }
public static void Test(this string a) public static void Test(this string a)

28
src/Libraries/ICSharpCode.Decompiler/Tests/DoubleConstants.cs

@ -0,0 +1,28 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
public class DoubleConstants
{
public const double Zero = 0.0;
public const double MinusZero = -0.0;
public const double NaN = double.NaN;
public const double PositiveInfinity = double.PositiveInfinity;
public const double NegativeInfinity = double.NegativeInfinity;
}

1
src/Libraries/ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj

@ -67,6 +67,7 @@
<Compile Include="CallOverloadedMethod.cs" /> <Compile Include="CallOverloadedMethod.cs" />
<Compile Include="CheckedUnchecked.cs" /> <Compile Include="CheckedUnchecked.cs" />
<Compile Include="ControlFlow.cs" /> <Compile Include="ControlFlow.cs" />
<Compile Include="DoubleConstants.cs" />
<Compile Include="ExpressionTrees.cs" /> <Compile Include="ExpressionTrees.cs" />
<None Include="IL\SequenceOfNestedIfs.Output.cs" /> <None Include="IL\SequenceOfNestedIfs.Output.cs" />
<Compile Include="IL\ILTests.cs" /> <Compile Include="IL\ILTests.cs" />

6
src/Libraries/ICSharpCode.Decompiler/Tests/TestRunner.cs

@ -88,6 +88,12 @@ namespace ICSharpCode.Decompiler.Tests
TestFile(@"..\..\Tests\ControlFlow.cs", optimize: false, useDebug: true); TestFile(@"..\..\Tests\ControlFlow.cs", optimize: false, useDebug: true);
} }
[Test]
public void DoubleConstants()
{
TestFile(@"..\..\Tests\DoubleConstants.cs");
}
[Test] [Test]
public void IncrementDecrement() public void IncrementDecrement()
{ {

Loading…
Cancel
Save