Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inspection / interception of IL generated by LambdaCompiler #18447

Open
bartdesmet opened this issue Sep 6, 2016 · 0 comments
Open

Inspection / interception of IL generated by LambdaCompiler #18447

bartdesmet opened this issue Sep 6, 2016 · 0 comments
Labels
area-System.Linq.Expressions help wanted [up-for-grabs] Good issue for external contributors test-enhancement Improvements of test source code
Milestone

Comments

@bartdesmet
Copy link
Contributor

IL generated by LambdaCompiler and ILGen turns out to be quite tricky to inspect. On desktop CLR, I used to emit IL to an assembly using CompileToMethod for offline inspection, or use SOS to !dumpil. While the latter still works, it's not an option at runtime, e.g. for testing purposes. In particular, when testing code emit optimizations, we don't have a good option to assert the output.

One option is to perform private reflection on DynamicMethod to obtain the byte[] m_iLStream and use one of the decoders to print it as textual IL. Some code is around to do that on the MSDN blogs, so it's one option worth looking into. In fact, I've been using this over at https://github.com/bartdesmet/ExpressionFutures and it works ok-ish. There are some issues with visualizing some metadata tokens but it may be possible to work around that. It may suffice for testing purposes.

An alternative which I've put in place in my https://github.com/bartdesmet/corefx/tree/CheaperClosures branch is an indirection of ILGenerator calls through an interface, currently only when a conditional compilation symbol is set. Unfortunately, one can't derive from ILGenerator because it only has internal constructors (and one of its Emit overloads is not virtual either), so an additional interface has to be put in place. My implementation logs all the calls made, so a ToString can be obtained.

Note that the last option offers some benefits because one could implement e.g. an optimizing back-end by capturing the emitted instructions and run a post-process step on it (assuming we add one additional method call to "bake" the emitted IL, which could flush to the underlying emitter target after running post-process steps):

interface IILGenerator
{
    void Emit(OpCode opcode);
    // quite a lot more methods, see ILGenerator

    void Bake();
}

An interceptor for logging would implement IILGenerator and get passed an IILGenerator that's the target to emit to. Its Bake method can simply forward to the underlying generator; every other method forwards and logs to populate data structures that allow for pretty printing.

An optimizer would implement IILGenerator but won't forward the Emit methods directly; it'd build up internal data structures that are used upon a call to Bake to run optimizations prior to making Emit calls to the underlying generator, followed by a Bake call.

Of course, this would add a level of indirection with virtual calls, unless ILGenerator would implement such an interface (and make the Emit(OpCode, sbyte) overload virtual) so there's no additional cost if no wrapper is installed around the ILGenerator obtained from DynamicMethod. See https://github.com/dotnet/corefx/issues/11454 for a case where such a back-end could provide value.

I got the last thing implemented (including an inspector and a basic optimizer) in an offline copy here in Bing, which is based on a fork of the expression API a few years back. I'll to port it to CoreFX as a proof of concept so the merits can be debated with some concrete piece of code to back it up.

@VSadov VSadov removed their assignment Nov 10, 2016
JonHanna referenced this issue in JonHanna/corefx Feb 18, 2017
Special-cased by compiler and not yet covered in testing.

Contributes to #11460
@msftgits msftgits transferred this issue from dotnet/corefx Jan 31, 2020
@msftgits msftgits added this to the Future milestone Jan 31, 2020
@maryamariyan maryamariyan added the untriaged New issue has not been triaged by the area owner label Feb 23, 2020
@cston cston removed the untriaged New issue has not been triaged by the area owner label Jul 7, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-System.Linq.Expressions help wanted [up-for-grabs] Good issue for external contributors test-enhancement Improvements of test source code
Projects
None yet
Development

No branches or pull requests

5 participants