IL.Emit.Tail() produces wrong IL
See original GitHub issueAs tail. is a prefix instruction, the only valid code sequence is tail. call
(or calli or callvirt) (see link).
Tail();
Calli(new StandAloneMethodSig(CallingConvention.Cdecl, typeof(void)));
produces
IL_0007: tail.
IL_0009: calli void()
instead of (the expected)
IL_0007: tail. calli void()
(the space after the .
is sensitive though).
Issue Analytics
- State:
- Created 4 years ago
- Comments:11 (6 by maintainers)
Top Results From Across the Web
c# - What's wrong with the IL I'm emitting in a Reflection. ...
Ideally I want to be using the CreateObject delegate because the code generating these dynamic methods is for a deserializer that should be...
Read more >The frustrating state of tails calls in .NET · Issue #2191
From my my experience of x86 tail calls might not be as bad as x64 but it's IMHO not fast. I find that...
Read more >Proposal: `tail return` recursive calls · Issue #2304
tail IL should be emitted even in the absence of the tail constraint. proposed syntax : tail qualifiedmethodname(parameters); // (the syntax is ...
Read more >Sigil: Adding Some (More) Magic To IL
Sigil wraps ILGenerator, exposes much less error prone alternatives to Emit, and does immediate verification of the instruction stream. The ...
Read more >OpCodes.Tailcall Field (System.Reflection.Emit)
Performs a postfixed method call instruction such that the current method's stack frame is removed before the actual call instruction is executed.
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
Thanks 👍 for the quick fix!
Well that was a pretty stupid oversight: debug builds insert
nop
instructions between lines of code. Your example compiles to something similar to the following:Which is incorrect because a tail call needs to be immediately followed by a
ret
.Non-void calls are even worse:
The value goes into a local so the debugger can display it before the function returns, but that gets in the way too.
InlineIL will now validate tail calls and remove the boilerplate code, leaving just
ret
, but that will fail horribly if you have multiple tail calls in a single method. I’ll decide what to do with this case later. In the meantime, v1.1.1 should fix the issue reported here.