From aeddcf4b80bb4a5568e9fcdeaa528a0a204c8d1a Mon Sep 17 00:00:00 2001 From: LordJZ Date: Sun, 29 Mar 2015 16:26:24 +0300 Subject: [PATCH 1/5] Enhanced point arithmetic handling This fixes more complex pointer addition/subtraction examples, like PointerArithmetic3 and 4 test cases. Test case 2 is still failing. Fixes #565 Fixes #400 --- .../ILAst/ILAstOptimizer.cs | 143 +++++++++++++----- ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs | 5 +- ICSharpCode.Decompiler/Tests/UnsafeCode.cs | 22 ++- 3 files changed, 131 insertions(+), 39 deletions(-) diff --git a/ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs b/ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs index bd8543cf5..95e615875 100644 --- a/ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs +++ b/ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs @@ -669,33 +669,84 @@ namespace ICSharpCode.Decompiler.ILAst }); } - static void HandlePointerArithmetic(ILNode method) + void HandlePointerArithmetic(ILNode method) { foreach (ILExpression expr in method.GetSelfAndChildrenRecursive()) { List args = expr.Arguments; switch (expr.Code) { case ILCode.Localloc: - args[0] = DivideBySize(args[0], ((PointerType)expr.InferredType).ElementType); - break; - case ILCode.Add: + { + ILExpression arg0 = args[0]; + ILExpression expr2 = expr; + DivideOrMultiplyBySize(ref expr2, ref arg0, ((PointerType)expr.InferredType).ElementType, true); + // expr shouldn't change + if (expr2 != expr) + throw new InvalidOperationException(); + args[0] = arg0; + break; + } + case ILCode.Add: case ILCode.Add_Ovf: case ILCode.Add_Ovf_Un: - if (expr.InferredType is PointerType) { - if (args[0].ExpectedType is PointerType) - args[1] = DivideBySize(args[1], ((PointerType)expr.InferredType).ElementType); - else if (args[1].ExpectedType is PointerType) - args[0] = DivideBySize(args[0], ((PointerType)expr.InferredType).ElementType); - } - break; - case ILCode.Sub: + { + ILExpression arg0 = args[0]; + ILExpression arg1 = args[1]; + if (expr.InferredType is PointerType) { + if (arg0.ExpectedType is PointerType) { + DivideOrMultiplyBySize(ref arg0, ref arg1, ((PointerType)expr.InferredType).ElementType, true); + } else if (arg1.ExpectedType is PointerType) + DivideOrMultiplyBySize(ref arg1, ref arg0, ((PointerType)expr.InferredType).ElementType, true); + } + args[0] = arg0; + args[1] = arg1; + break; + } + case ILCode.Sub: case ILCode.Sub_Ovf: case ILCode.Sub_Ovf_Un: + { + ILExpression arg0 = args[0]; + ILExpression arg1 = args[1]; if (expr.InferredType is PointerType) { - if (args[0].ExpectedType is PointerType) - args[1] = DivideBySize(args[1], ((PointerType)expr.InferredType).ElementType); + if (arg0.ExpectedType is PointerType && !(arg1.InferredType is PointerType)) + DivideOrMultiplyBySize(ref arg0, ref arg1, ((PointerType)expr.InferredType).ElementType, true); } - break; - } + args[0] = arg0; + args[1] = arg1; + break; + } + case ILCode.Conv_I8: + { + ILExpression arg0 = args[0]; + // conv.i8(div:intptr(p0 - p1)) + if (arg0.Code == ILCode.Div && arg0.InferredType.FullName == "System.IntPtr") + { + ILExpression dividend = arg0.Arguments[0]; + if (dividend.InferredType.FullName == "System.IntPtr" && + (dividend.Code == ILCode.Sub || dividend.Code == ILCode.Sub_Ovf || dividend.Code == ILCode.Sub_Ovf_Un)) + { + PointerType pointerType0 = dividend.Arguments[0].InferredType as PointerType; + PointerType pointerType1 = dividend.Arguments[1].InferredType as PointerType; + + if (pointerType0 != null && pointerType1 != null) { + if (pointerType0.ElementType.FullName == "System.Void" || + pointerType0.ElementType.FullName != pointerType1.ElementType.FullName) { + pointerType0 = pointerType1 = new PointerType(typeSystem.Byte); + dividend.Arguments[0] = Cast(dividend.Arguments[0], pointerType0); + dividend.Arguments[1] = Cast(dividend.Arguments[1], pointerType1); + } + + DivideOrMultiplyBySize(ref dividend, ref arg0, pointerType0.ElementType, false); + // dividend shouldn't change + if (args[0].Arguments[0] != dividend) + throw new InvalidOperationException(); + } + } + } + args[0] = arg0; + break; + } + } } } @@ -720,12 +771,24 @@ namespace ICSharpCode.Decompiler.ILAst return expr; } - static ILExpression DivideBySize(ILExpression expr, TypeReference type) + static ILExpression Cast(ILExpression expr, TypeReference type) + { + return new ILExpression(ILCode.Castclass, type, expr) + { + InferredType = type, + ExpectedType = type + }; + } + + void DivideOrMultiplyBySize(ref ILExpression pointerExpr, ref ILExpression adjustmentExpr, TypeReference elementType, bool divide) { - expr = UnwrapIntPtrCast(expr); + adjustmentExpr = UnwrapIntPtrCast(adjustmentExpr); ILExpression sizeOfExpression; - switch (TypeAnalysis.GetInformationAmount(type)) { + switch (TypeAnalysis.GetInformationAmount(elementType)) { + case 0: // System.Void + pointerExpr = Cast(pointerExpr, new PointerType(typeSystem.Byte)); + goto case 1; case 1: case 8: sizeOfExpression = new ILExpression(ILCode.Ldc_I4, 1); @@ -740,34 +803,40 @@ namespace ICSharpCode.Decompiler.ILAst sizeOfExpression = new ILExpression(ILCode.Ldc_I4, 8); break; default: - sizeOfExpression = new ILExpression(ILCode.Sizeof, type); + sizeOfExpression = new ILExpression(ILCode.Sizeof, elementType); break; } - if (expr.Code == ILCode.Mul || expr.Code == ILCode.Mul_Ovf || expr.Code == ILCode.Mul_Ovf_Un) { - ILExpression mulArg = expr.Arguments[1]; - if (mulArg.Code == sizeOfExpression.Code && sizeOfExpression.Operand.Equals(mulArg.Operand)) - return UnwrapIntPtrCast(expr.Arguments[0]); + if (divide && (adjustmentExpr.Code == ILCode.Mul || adjustmentExpr.Code == ILCode.Mul_Ovf || adjustmentExpr.Code == ILCode.Mul_Ovf_Un) || + !divide && (adjustmentExpr.Code == ILCode.Div || adjustmentExpr.Code == ILCode.Div_Un)) { + ILExpression mulArg = adjustmentExpr.Arguments[1]; + if (mulArg.Code == sizeOfExpression.Code && sizeOfExpression.Operand.Equals(mulArg.Operand)) { + adjustmentExpr = UnwrapIntPtrCast(adjustmentExpr.Arguments[0]); + return; + } } - if (expr.Code == sizeOfExpression.Code) { - if (sizeOfExpression.Operand.Equals(expr.Operand)) - return new ILExpression(ILCode.Ldc_I4, 1); + if (adjustmentExpr.Code == sizeOfExpression.Code) { + if (sizeOfExpression.Operand.Equals(adjustmentExpr.Operand)) { + adjustmentExpr = new ILExpression(ILCode.Ldc_I4, 1); + return; + } - if (expr.Code == ILCode.Ldc_I4) { - int offsetInBytes = (int)expr.Operand; + if (adjustmentExpr.Code == ILCode.Ldc_I4) { + int offsetInBytes = (int)adjustmentExpr.Operand; int elementSize = (int)sizeOfExpression.Operand; - int offsetInElements = offsetInBytes / elementSize; - // ensure integer division - if (offsetInElements * elementSize == offsetInBytes) { - expr.Operand = offsetInElements; - return expr; - } - } + if (offsetInBytes % elementSize != 0) { + pointerExpr = Cast(pointerExpr, new PointerType(typeSystem.Byte)); + return; + } + + adjustmentExpr.Operand = offsetInBytes / elementSize; + return; + } } - return new ILExpression(ILCode.Div_Un, null, expr, sizeOfExpression); + adjustmentExpr = new ILExpression(divide ? ILCode.Div_Un : ILCode.Mul, null, adjustmentExpr, sizeOfExpression); } public static void ReplaceVariables(ILNode node, Func variableMapping) diff --git a/ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs b/ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs index 1931d390d..6ed1f4dc0 100644 --- a/ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs +++ b/ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs @@ -1044,7 +1044,10 @@ namespace ICSharpCode.Decompiler.ILAst TypeReference leftPreferred = DoInferTypeForExpression(left, expectedType); if (leftPreferred is PointerType) { left.InferredType = left.ExpectedType = leftPreferred; - InferTypeForExpression(right, null); + TypeReference rightPreferred = InferTypeForExpression(right, null); + // subtracting two pointers is not a pointer + if (rightPreferred is PointerType) + return typeSystem.IntPtr; return leftPreferred; } if (IsEnum(leftPreferred)) { diff --git a/ICSharpCode.Decompiler/Tests/UnsafeCode.cs b/ICSharpCode.Decompiler/Tests/UnsafeCode.cs index 1a3bd6a0f..7a40389f4 100644 --- a/ICSharpCode.Decompiler/Tests/UnsafeCode.cs +++ b/ICSharpCode.Decompiler/Tests/UnsafeCode.cs @@ -130,7 +130,7 @@ public class UnsafeCode public unsafe byte* PointerArithmetic2(long* p, int y, int x) { - return (byte*)p + (y * x); + return (byte*)((short*)p + (y * x)); } public unsafe long* PointerArithmetic3(long* p) @@ -138,6 +138,26 @@ public class UnsafeCode return (long*)((byte*)p + 3); } + public unsafe long* PointerArithmetic4(void* p) + { + return (long*)((byte*)p + 3); + } + + public unsafe int PointerSubtraction(long* p, long* q) + { + return (int)((long)(p - q)); + } + + public unsafe int PointerSubtraction2(long* p, short* q) + { + return (int)((long)((byte*)p - (byte*)q)); + } + + public unsafe int PointerSubtraction3(void* p, void* q) + { + return (int)((long)((byte*)p - (byte*)q)); + } + unsafe ~UnsafeCode() { this.PassPointerAsRefParameter(this.NullPointer); From 5f2097ade646061a374e499d48ec7eda0bef75a3 Mon Sep 17 00:00:00 2001 From: LordJZ Date: Thu, 9 Apr 2015 06:30:39 +0300 Subject: [PATCH 2/5] Fixed C++/CLI generated stackalloc fixed #592 partially fixes #569 --- ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs b/ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs index 95e615875..e6277dee2 100644 --- a/ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs +++ b/ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs @@ -676,13 +676,16 @@ namespace ICSharpCode.Decompiler.ILAst switch (expr.Code) { case ILCode.Localloc: { - ILExpression arg0 = args[0]; - ILExpression expr2 = expr; - DivideOrMultiplyBySize(ref expr2, ref arg0, ((PointerType)expr.InferredType).ElementType, true); - // expr shouldn't change - if (expr2 != expr) - throw new InvalidOperationException(); - args[0] = arg0; + PointerType type = expr.InferredType as PointerType; + if (type != null) { + ILExpression arg0 = args[0]; + ILExpression expr2 = expr; + DivideOrMultiplyBySize(ref expr2, ref arg0, type.ElementType, true); + // expr shouldn't change + if (expr2 != expr) + throw new InvalidOperationException(); + args[0] = arg0; + } break; } case ILCode.Add: From e6058e819ab295d45486ae7a5145c56f54a22f46 Mon Sep 17 00:00:00 2001 From: LordJZ Date: Thu, 9 Apr 2015 06:32:11 +0300 Subject: [PATCH 3/5] Spaces to tabs in pointer handling code --- .../ILAst/ILAstOptimizer.cs | 182 +++++++++--------- 1 file changed, 91 insertions(+), 91 deletions(-) diff --git a/ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs b/ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs index e6277dee2..8d01fb819 100644 --- a/ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs +++ b/ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs @@ -349,15 +349,15 @@ namespace ICSharpCode.Decompiler.ILAst expr.ILRanges.Clear(); continue; case ILCode.__Brfalse: op = ILCode.LogicNot; break; - case ILCode.__Beq: op = ILCode.Ceq; break; + case ILCode.__Beq: op = ILCode.Ceq; break; case ILCode.__Bne_Un: op = ILCode.Cne; break; - case ILCode.__Bgt: op = ILCode.Cgt; break; + case ILCode.__Bgt: op = ILCode.Cgt; break; case ILCode.__Bgt_Un: op = ILCode.Cgt_Un; break; - case ILCode.__Ble: op = ILCode.Cle; break; + case ILCode.__Ble: op = ILCode.Cle; break; case ILCode.__Ble_Un: op = ILCode.Cle_Un; break; - case ILCode.__Blt: op = ILCode.Clt; break; + case ILCode.__Blt: op = ILCode.Clt; break; case ILCode.__Blt_Un: op = ILCode.Clt_Un; break; - case ILCode.__Bge: op = ILCode.Cge; break; + case ILCode.__Bge: op = ILCode.Cge; break; case ILCode.__Bge_Un: op = ILCode.Cge_Un; break; default: continue; @@ -436,9 +436,9 @@ namespace ICSharpCode.Decompiler.ILAst // Might be 'newobj(SomeDelegate, target, ldvirtftn(F, target))'. ILVariable target; if (expr.Arguments[0].Match(ILCode.Ldloc, out target) - && expr.Arguments[1].Code == ILCode.Ldvirtftn - && expr.Arguments[1].Arguments.Count == 1 - && expr.Arguments[1].Arguments[0].MatchLdloc(target)) + && expr.Arguments[1].Code == ILCode.Ldvirtftn + && expr.Arguments[1].Arguments.Count == 1 + && expr.Arguments[1].Arguments[0].MatchLdloc(target)) { // Remove the 'target' argument from the ldvirtftn instruction. // It's not needed in the translation to C#, and needs to be eliminated so that the target expression @@ -473,9 +473,9 @@ namespace ICSharpCode.Decompiler.ILAst // Start a new basic block if necessary if (currNode is ILLabel || - currNode is ILTryCatchBlock || // Counts as label - lastNode.IsConditionalControlFlow() || - lastNode.IsUnconditionalControlFlow()) + currNode is ILTryCatchBlock || // Counts as label + lastNode.IsConditionalControlFlow() || + lastNode.IsUnconditionalControlFlow()) { // Try to reuse the label ILLabel label = currNode as ILLabel ?? new ILLabel() { Name = "Block_" + (nextLabelIndex++).ToString() }; @@ -675,53 +675,53 @@ namespace ICSharpCode.Decompiler.ILAst List args = expr.Arguments; switch (expr.Code) { case ILCode.Localloc: - { - PointerType type = expr.InferredType as PointerType; - if (type != null) { - ILExpression arg0 = args[0]; - ILExpression expr2 = expr; - DivideOrMultiplyBySize(ref expr2, ref arg0, type.ElementType, true); - // expr shouldn't change - if (expr2 != expr) - throw new InvalidOperationException(); - args[0] = arg0; - } - break; - } - case ILCode.Add: + { + PointerType type = expr.InferredType as PointerType; + if (type != null) { + ILExpression arg0 = args[0]; + ILExpression expr2 = expr; + DivideOrMultiplyBySize(ref expr2, ref arg0, type.ElementType, true); + // expr shouldn't change + if (expr2 != expr) + throw new InvalidOperationException(); + args[0] = arg0; + } + break; + } + case ILCode.Add: case ILCode.Add_Ovf: case ILCode.Add_Ovf_Un: - { - ILExpression arg0 = args[0]; - ILExpression arg1 = args[1]; - if (expr.InferredType is PointerType) { - if (arg0.ExpectedType is PointerType) { - DivideOrMultiplyBySize(ref arg0, ref arg1, ((PointerType)expr.InferredType).ElementType, true); - } else if (arg1.ExpectedType is PointerType) - DivideOrMultiplyBySize(ref arg1, ref arg0, ((PointerType)expr.InferredType).ElementType, true); - } - args[0] = arg0; - args[1] = arg1; - break; - } - case ILCode.Sub: + { + ILExpression arg0 = args[0]; + ILExpression arg1 = args[1]; + if (expr.InferredType is PointerType) { + if (arg0.ExpectedType is PointerType) { + DivideOrMultiplyBySize(ref arg0, ref arg1, ((PointerType)expr.InferredType).ElementType, true); + } else if (arg1.ExpectedType is PointerType) + DivideOrMultiplyBySize(ref arg1, ref arg0, ((PointerType)expr.InferredType).ElementType, true); + } + args[0] = arg0; + args[1] = arg1; + break; + } + case ILCode.Sub: case ILCode.Sub_Ovf: case ILCode.Sub_Ovf_Un: - { - ILExpression arg0 = args[0]; - ILExpression arg1 = args[1]; + { + ILExpression arg0 = args[0]; + ILExpression arg1 = args[1]; if (expr.InferredType is PointerType) { if (arg0.ExpectedType is PointerType && !(arg1.InferredType is PointerType)) DivideOrMultiplyBySize(ref arg0, ref arg1, ((PointerType)expr.InferredType).ElementType, true); } - args[0] = arg0; - args[1] = arg1; - break; - } - case ILCode.Conv_I8: - { - ILExpression arg0 = args[0]; - // conv.i8(div:intptr(p0 - p1)) + args[0] = arg0; + args[1] = arg1; + break; + } + case ILCode.Conv_I8: + { + ILExpression arg0 = args[0]; + // conv.i8(div:intptr(p0 - p1)) if (arg0.Code == ILCode.Div && arg0.InferredType.FullName == "System.IntPtr") { ILExpression dividend = arg0.Arguments[0]; @@ -732,24 +732,24 @@ namespace ICSharpCode.Decompiler.ILAst PointerType pointerType1 = dividend.Arguments[1].InferredType as PointerType; if (pointerType0 != null && pointerType1 != null) { - if (pointerType0.ElementType.FullName == "System.Void" || - pointerType0.ElementType.FullName != pointerType1.ElementType.FullName) { - pointerType0 = pointerType1 = new PointerType(typeSystem.Byte); - dividend.Arguments[0] = Cast(dividend.Arguments[0], pointerType0); - dividend.Arguments[1] = Cast(dividend.Arguments[1], pointerType1); - } + if (pointerType0.ElementType.FullName == "System.Void" || + pointerType0.ElementType.FullName != pointerType1.ElementType.FullName) { + pointerType0 = pointerType1 = new PointerType(typeSystem.Byte); + dividend.Arguments[0] = Cast(dividend.Arguments[0], pointerType0); + dividend.Arguments[1] = Cast(dividend.Arguments[1], pointerType1); + } - DivideOrMultiplyBySize(ref dividend, ref arg0, pointerType0.ElementType, false); - // dividend shouldn't change - if (args[0].Arguments[0] != dividend) - throw new InvalidOperationException(); + DivideOrMultiplyBySize(ref dividend, ref arg0, pointerType0.ElementType, false); + // dividend shouldn't change + if (args[0].Arguments[0] != dividend) + throw new InvalidOperationException(); } } } - args[0] = arg0; - break; - } - } + args[0] = arg0; + break; + } + } } } @@ -774,14 +774,14 @@ namespace ICSharpCode.Decompiler.ILAst return expr; } - static ILExpression Cast(ILExpression expr, TypeReference type) - { - return new ILExpression(ILCode.Castclass, type, expr) - { - InferredType = type, - ExpectedType = type - }; - } + static ILExpression Cast(ILExpression expr, TypeReference type) + { + return new ILExpression(ILCode.Castclass, type, expr) + { + InferredType = type, + ExpectedType = type + }; + } void DivideOrMultiplyBySize(ref ILExpression pointerExpr, ref ILExpression adjustmentExpr, TypeReference elementType, bool divide) { @@ -789,9 +789,9 @@ namespace ICSharpCode.Decompiler.ILAst ILExpression sizeOfExpression; switch (TypeAnalysis.GetInformationAmount(elementType)) { - case 0: // System.Void - pointerExpr = Cast(pointerExpr, new PointerType(typeSystem.Byte)); - goto case 1; + case 0: // System.Void + pointerExpr = Cast(pointerExpr, new PointerType(typeSystem.Byte)); + goto case 1; case 1: case 8: sizeOfExpression = new ILExpression(ILCode.Ldc_I4, 1); @@ -813,30 +813,30 @@ namespace ICSharpCode.Decompiler.ILAst if (divide && (adjustmentExpr.Code == ILCode.Mul || adjustmentExpr.Code == ILCode.Mul_Ovf || adjustmentExpr.Code == ILCode.Mul_Ovf_Un) || !divide && (adjustmentExpr.Code == ILCode.Div || adjustmentExpr.Code == ILCode.Div_Un)) { ILExpression mulArg = adjustmentExpr.Arguments[1]; - if (mulArg.Code == sizeOfExpression.Code && sizeOfExpression.Operand.Equals(mulArg.Operand)) { - adjustmentExpr = UnwrapIntPtrCast(adjustmentExpr.Arguments[0]); - return; - } + if (mulArg.Code == sizeOfExpression.Code && sizeOfExpression.Operand.Equals(mulArg.Operand)) { + adjustmentExpr = UnwrapIntPtrCast(adjustmentExpr.Arguments[0]); + return; + } } if (adjustmentExpr.Code == sizeOfExpression.Code) { - if (sizeOfExpression.Operand.Equals(adjustmentExpr.Operand)) { - adjustmentExpr = new ILExpression(ILCode.Ldc_I4, 1); - return; - } + if (sizeOfExpression.Operand.Equals(adjustmentExpr.Operand)) { + adjustmentExpr = new ILExpression(ILCode.Ldc_I4, 1); + return; + } - if (adjustmentExpr.Code == ILCode.Ldc_I4) { + if (adjustmentExpr.Code == ILCode.Ldc_I4) { int offsetInBytes = (int)adjustmentExpr.Operand; int elementSize = (int)sizeOfExpression.Operand; - if (offsetInBytes % elementSize != 0) { - pointerExpr = Cast(pointerExpr, new PointerType(typeSystem.Byte)); - return; - } + if (offsetInBytes % elementSize != 0) { + pointerExpr = Cast(pointerExpr, new PointerType(typeSystem.Byte)); + return; + } - adjustmentExpr.Operand = offsetInBytes / elementSize; - return; - } + adjustmentExpr.Operand = offsetInBytes / elementSize; + return; + } } adjustmentExpr = new ILExpression(divide ? ILCode.Div_Un : ILCode.Mul, null, adjustmentExpr, sizeOfExpression); From a1d2b812a32d3817cd472d5aab57423c84e19d2b Mon Sep 17 00:00:00 2001 From: LordJZ Date: Sun, 19 Apr 2015 15:50:29 +0300 Subject: [PATCH 4/5] Fixed tree traversal in IntroduceUnsafeModifier --- .../Ast/Transforms/IntroduceUnsafeModifier.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ICSharpCode.Decompiler/Ast/Transforms/IntroduceUnsafeModifier.cs b/ICSharpCode.Decompiler/Ast/Transforms/IntroduceUnsafeModifier.cs index 43548e38d..a9e72564f 100644 --- a/ICSharpCode.Decompiler/Ast/Transforms/IntroduceUnsafeModifier.cs +++ b/ICSharpCode.Decompiler/Ast/Transforms/IntroduceUnsafeModifier.cs @@ -35,7 +35,11 @@ namespace ICSharpCode.Decompiler.Ast.Transforms protected override bool VisitChildren(AstNode node, object data) { bool result = false; - for (AstNode child = node.FirstChild; child != null; child = child.NextSibling) { + AstNode next; + for (AstNode child = node.FirstChild; child != null; child = next) { + // Store next to allow the loop to continue + // if the visitor removes/replaces child. + next = child.NextSibling; result |= child.AcceptVisitor(this, data); } if (result && node is EntityDeclaration && !(node is Accessor)) { From 7cacb70148b21cc1bf836e9ef52a36e9f16de570 Mon Sep 17 00:00:00 2001 From: LordJZ Date: Sun, 19 Apr 2015 15:50:55 +0300 Subject: [PATCH 5/5] Fixed some corner cases --- ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs | 3 ++- ICSharpCode.Decompiler/Tests/UnsafeCode.cs | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs b/ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs index 8d01fb819..ce62816d7 100644 --- a/ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs +++ b/ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs @@ -839,7 +839,8 @@ namespace ICSharpCode.Decompiler.ILAst } } - adjustmentExpr = new ILExpression(divide ? ILCode.Div_Un : ILCode.Mul, null, adjustmentExpr, sizeOfExpression); + if (!(sizeOfExpression.Code == ILCode.Ldc_I4 && (int)sizeOfExpression.Operand == 1)) + adjustmentExpr = new ILExpression(divide ? ILCode.Div_Un : ILCode.Mul, null, adjustmentExpr, sizeOfExpression); } public static void ReplaceVariables(ILNode node, Func variableMapping) diff --git a/ICSharpCode.Decompiler/Tests/UnsafeCode.cs b/ICSharpCode.Decompiler/Tests/UnsafeCode.cs index 7a40389f4..cce6d525c 100644 --- a/ICSharpCode.Decompiler/Tests/UnsafeCode.cs +++ b/ICSharpCode.Decompiler/Tests/UnsafeCode.cs @@ -143,6 +143,11 @@ public class UnsafeCode return (long*)((byte*)p + 3); } + public unsafe int PointerArithmetic5(void* p, byte* q, int i) + { + return (int)(q[i] + *(byte*)p); + } + public unsafe int PointerSubtraction(long* p, long* q) { return (int)((long)(p - q));