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.

Reply via email to