From cfd638e413cbfc6e0fc272d45bfb24f0b1d2fbd4 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Sun, 10 Jul 2016 00:54:39 +0200 Subject: [PATCH] Fix fixed statement --- .../IL/ControlFlow/DetectPinnedRegions.cs | 28 ++++++++++++++++++- ICSharpCode.Decompiler/IL/Instructions.tt | 2 +- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/ICSharpCode.Decompiler/IL/ControlFlow/DetectPinnedRegions.cs b/ICSharpCode.Decompiler/IL/ControlFlow/DetectPinnedRegions.cs index 7e69975ca..ac379a309 100644 --- a/ICSharpCode.Decompiler/IL/ControlFlow/DetectPinnedRegions.cs +++ b/ICSharpCode.Decompiler/IL/ControlFlow/DetectPinnedRegions.cs @@ -62,6 +62,19 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow CreatePinnedRegion(block); container.Blocks.RemoveAll(b => b.Instructions.Count == 0); // remove dummy blocks } + // Sometimes there's leftover writes to the original pinned locals + foreach (var block in function.Descendants.OfType()) { + for (int i = 0; i < block.Instructions.Count; i++) { + var stloc = block.Instructions[i] as StLoc; + if (stloc != null && stloc.Variable.Kind == VariableKind.PinnedLocal && stloc.Variable.LoadCount == 0 && stloc.Variable.AddressCount == 0) { + if (SemanticHelper.IsPure(stloc.Value.Flags)) { + block.Instructions.RemoveAt(i--); + } else { + stloc.ReplaceWith(stloc.Value); + } + } + } + } } /// @@ -335,7 +348,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow if (body.EntryPoint.IncomingEdgeCount == 1 && body.EntryPoint.Instructions.Count == 3 && body.EntryPoint.Instructions[0].MatchStLoc(out nativeVar, out initInst) - && nativeVar.Type.Kind == TypeKind.Pointer + && nativeVar.Type.GetStackType() == StackType.I && nativeVar.StoreCount == 2 && initInst.UnwrapConv(ConversionKind.StopGCTracking).MatchLdLoc(pinnedRegion.Variable) && IsBranchOnNull(body.EntryPoint.Instructions[1], nativeVar, out targetBlock) @@ -351,6 +364,19 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow body.Blocks.RemoveAt(targetBlock.ChildIndex); body.Blocks.Insert(0, targetBlock); pinnedRegion.Init = new ArrayToPointer(pinnedRegion.Init); + + ILVariable otherVar; + ILInstruction otherVarInit; + // In optimized builds, the 'nativeVar' may end up being a stack slot, + // and only gets assigned to a real variable after the offset adjustment. + if (nativeVar.Kind == VariableKind.StackSlot && nativeVar.LoadCount == 1 + && body.EntryPoint.Instructions[0].MatchStLoc(out otherVar, out otherVarInit) + && otherVarInit.MatchLdLoc(nativeVar) + && otherVar.IsSingleDefinition) + { + body.EntryPoint.Instructions.RemoveAt(0); + nativeVar = otherVar; + } ILVariable newVar; if (nativeVar.Kind == VariableKind.Local) { newVar = new ILVariable(VariableKind.PinnedLocal, nativeVar.Type, nativeVar.Index); diff --git a/ICSharpCode.Decompiler/IL/Instructions.tt b/ICSharpCode.Decompiler/IL/Instructions.tt index 5bc831d8e..dfd067207 100644 --- a/ICSharpCode.Decompiler/IL/Instructions.tt +++ b/ICSharpCode.Decompiler/IL/Instructions.tt @@ -200,7 +200,7 @@ new OpCode("ldelema", "Load address of array element.", CustomClassName("LdElema"), HasTypeOperand, CustomChildren(new [] { new ArgumentInfo("array"), new ArgumentInfo("indices") { IsCollection = true } }, true), MayThrow, ResultType("Ref"), SupportsReadonlyPrefix), - new OpCode("array.to.pointer", "Converts an array pointer (O) to a reference to the first element, or to a null reference if the array is null or empty.\n" + new OpCode("array.to.pointer", "Converts an array pointer (O) to a reference to the first element, or to a null reference if the array is null or empty." + Environment.NewLine + "Also used to convert a string to a reference to the first character.", CustomArguments("array"), ResultType("Ref")),