Please report the issue at github.com/icsharpcode/ILSpy Thanks!
On Wed, Aug 16, 2017 at 12:00 AM, Ahmed el-Sawalhy <[email protected]> wrote: > Consider the following snippet of code: > > private string GetFieldValueAsString(string nonAliasedEntityName = > null, string nonAliasedName = null) > { > return nonAliasedEntityName ?? nonAliasedName; // simplified > code of course! > } > > It is compiled to the following IL code: > > .method private hidebysig > instance string GetFieldValueAsString ( > [opt] string nonAliasedEntityName, > [opt] string nonAliasedName > ) cil managed > { > .param [1] = nullref > .param [2] = nullref > // Method begins at RVA 0x2cb6f > // Code size 7 (0x7) > .maxstack 8 > > IL_0000: ldarg.1 > IL_0001: dup > IL_0002: brtrue.s IL_0006 > > IL_0004: pop > IL_0005: ldarg.2 > > IL_0006: ret > } // end of method MessageBuilder::GetFieldValueAsString > > I borrowed the 'fix the returns' from Anotar to my add-in. I get the > following IL code when I compile: > > .method private hidebysig > instance string GetFieldValueAsString ( > [opt] string nonAliasedEntityName, > [opt] string nonAliasedName > ) cil managed > { > .param [1] = nullref > .param [2] = nullref > // Method begins at RVA 0x2cb70 > // Code size 15 (0xf) > .maxstack 3 > .locals ( > [0] string $returnVariable > ) > > IL_0000: ldarg.1 > IL_0001: dup > IL_0002: dup > IL_0003: stloc.0 > IL_0004: brtrue.s IL_000b > > IL_0006: pop > IL_0007: ldarg.2 > IL_0008: stloc.0 > IL_0009: br.s IL_000b > > IL_000b: nop > IL_000c: nop > IL_000d: ldloc.0 > IL_000e: ret > } // end of method MessageBuilder::GetFieldValueAsString > > It gives me the following error when decompiling in ILSpy, and fails to > run: > > ICSharpCode.Decompiler.DecompilerException: Error decompiling > System.String LinkDev.Notifications.Steps.MessageBuilder:: > GetFieldValueAsString(System.String,System.String) > ---> System.Exception: Inconsistent stack size at IL_09 > at > ICSharpCode.Decompiler.ILAst.ILAstBuilder.StackAnalysis(MethodDefinition > methodDef) > at ICSharpCode.Decompiler.ILAst.ILAstBuilder.Build(MethodDefinition > methodDef, Boolean optimize, DecompilerContext context) > at > ICSharpCode.Decompiler.Ast.AstMethodBodyBuilder.CreateMethodBody(IEnumerable`1 > parameters) > at ICSharpCode.Decompiler.Ast.AstMethodBodyBuilder. > CreateMethodBody(MethodDefinition methodDef, DecompilerContext context, > IEnumerable`1 parameters) > --- End of inner exception stack trace --- > at ICSharpCode.Decompiler.Ast.AstMethodBodyBuilder. > CreateMethodBody(MethodDefinition methodDef, DecompilerContext context, > IEnumerable`1 parameters) > at ICSharpCode.Decompiler.Ast.AstBuilder.CreateMethod(MethodDefinition > methodDef) > at ICSharpCode.Decompiler.Ast.AstBuilder.AddMethod(MethodDefinition > method) > at ICSharpCode.ILSpy.CSharpLanguage.DecompileMethod(MethodDefinition > method, ITextOutput output, DecompilationOptions options) > at > ICSharpCode.ILSpy.TextView.DecompilerTextView.DecompileNodes(DecompilationContext > context, ITextOutput textOutput) > at ICSharpCode.ILSpy.TextView.DecompilerTextView.<>c__ > DisplayClass31_0.<DecompileAsync>b__0() > > I traced the stack size, and it seems to hold. Any idea what could be > causing this issue? > > The ReturnFixer class is as follows: > > using Mono.Cecil; > using Mono.Cecil.Cil; > using Mono.Collections.Generic; > > public class ReturnFixer > { > public MethodDefinition Method; > Instruction nopForHandleEnd; > Collection<Instruction> instructions; > public Instruction NopBeforeReturn; > Instruction sealBranchesNop; > public VariableDefinition ReturnVariable; > > public void MakeLastStatementReturn() > { > > instructions = Method.Body.Instructions; > FixHangingHandlerEnd(); > > sealBranchesNop = Instruction.Create(OpCodes.Nop); > instructions.Add(sealBranchesNop); > > NopBeforeReturn = Instruction.Create(OpCodes.Nop); > > if (IsMethodReturnValue()) > { > ReturnVariable = > Method.Body.DeclareVariable("$returnVariable", > Method.MethodReturnType.ReturnType); > } > > for (var index = 0; index < instructions.Count; index++) > { > var operand = instructions[index].Operand as Instruction; > > if (operand == null || operand.OpCode != OpCodes.Ret) > { > continue; > } > > if (IsMethodReturnValue()) > { > // The C# compiler never jumps directly to a ret > // when returning a value from the method. But other > Fody > // modules and other compilers might. So store the > value here. > instructions.Insert(index, > Instruction.Create(OpCodes.Stloc, > ReturnVariable)); > instructions.Insert(index, Instruction.Create(OpCodes. > Dup)); > index += 2; > } > > instructions[index].Operand = sealBranchesNop; > } > > if (IsMethodReturnValue()) > { > WithReturnValue(); > } > else > { > WithNoReturn(); > } > } > > bool IsMethodReturnValue() > { > return Method.MethodReturnType.ReturnType.Name != "Void"; > } > > void FixHangingHandlerEnd() > { > if (Method.Body.ExceptionHandlers.Count == 0) > { > return; > } > > nopForHandleEnd = Instruction.Create(OpCodes.Nop); > Method.Body.Instructions.Add(nopForHandleEnd); > foreach (var handler in Method.Body.ExceptionHandlers) > { > if (handler.HandlerStart != null && handler.HandlerEnd == > null) > { > handler.HandlerEnd = nopForHandleEnd; > } > } > } > > > void WithReturnValue() > { > > for (var index = 0; index < instructions.Count; index++) > { > var instruction = instructions[index]; > if (instruction.OpCode == OpCodes.Ret) > { > instructions.Insert(index, > Instruction.Create(OpCodes.Stloc, > ReturnVariable)); > instruction.OpCode = OpCodes.Br; > instruction.Operand = sealBranchesNop; > index++; > } > } > instructions.Add(NopBeforeReturn); > instructions.Add(Instruction.Create(OpCodes.Ldloc, > ReturnVariable)); > instructions.Add(Instruction.Create(OpCodes.Ret)); > > } > > void WithNoReturn() > { > > foreach (var instruction in instructions) > { > if (instruction.OpCode == OpCodes.Ret) > { > instruction.OpCode = OpCodes.Br; > instruction.Operand = sealBranchesNop; > } > } > instructions.Add(NopBeforeReturn); > instructions.Add(Instruction.Create(OpCodes.Ret)); > } > > } > > -- > -- > -- > mono-cecil > --- > You received this message because you are subscribed to the Google Groups > "mono-cecil" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to [email protected]. > For more options, visit https://groups.google.com/d/optout. > -- -- -- mono-cecil --- You received this message because you are subscribed to the Google Groups "mono-cecil" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. For more options, visit https://groups.google.com/d/optout.
