Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to insert CIL code to C#

Tags:

c#

cil

Is it possible to insert IL code to C# method?

like image 803
Duiner Avatar asked Jul 25 '10 10:07

Duiner


4 Answers

I just posted a utility which allows entire C# function bodies to be automatically replaced with inline IL, using a custom attribute. Like similar utilities, this works via the ILDASM/ILASM round-trip which can be set up as a post-build step. The tool also adjusts the PDB in order to preserve single-stepping and setting breakpoints on individual IL instructions in the debugger. It's different from some of the other round-trip IL inliners in that it (only) substitutes for entire function bodies, like this:

    class MyClass
    {
        [ILFunc(@"
    .locals init ([0] int32 i_arg)
        ldc.i4.3
        ret
    ")]
        int MyFunc(int i_arg)
        {
            return 3;
        }
    };

For highly performance-critical methods, I tried using DynamicMethod to improve upon compiler-generated IL, but found that the benefit is lost due to the delegate-calling overhead. Inline IL gives the the beneft of hand-tuned IL without that hit, assuming there are no runtime customizations that you would truly need DynamicMethod for.

The complete source code is located at http://www.glennslayden.com/code/c-sharp/inline-il

like image 148
Glenn Slayden Avatar answered Dec 06 '22 15:12

Glenn Slayden


I'll add my own tool to the list of solutions already provided here: InlineIL.Fody.

This uses the Fody assembly weaving tool to modify the assembly at build time. Which means all you have to do is install a NuGet package, add a config file to your project and you're done.

You're then provided with a simple and type-safe API to emit IL instructions, which you can mix with C# code. I believe it's easier to write IL in this way than writing text, and it's also more convenient than ILGenerator since each opcode gets its own method with relevant overloads only.

Here's an example, with using static InlineIL.IL.Emit;:

public static void ZeroInit<T>(ref T value)
    where T : struct
{
    Ldarg(nameof(value));
    Ldc_I4_0();
    Sizeof(typeof(T));
    Unaligned(1);
    Initblk();
}

This shows how to access the initblk instruction which C# doesn't currently expose.

like image 35
Lucas Trzesniewski Avatar answered Dec 06 '22 16:12

Lucas Trzesniewski


If inline IL (in the same spirit of inline assembly supported by C and C++ compilers) is what you're looking for, this can be achieved using post-compilation round-trip compiling.

Mike Stall has once written a tool for that, as far as I know it's fairly mature:

Other than that, you could use F# which supports Inline IL.

like image 21
Johannes Rudolph Avatar answered Dec 06 '22 16:12

Johannes Rudolph


DynamicMethod is the lightweight way to accomplish this at runtime.

The Microsoft C# compiler doesn't support injection of IL at compile-time, but a code-weaving tool could do so as a post-compile step.

like image 42
Ben Voigt Avatar answered Dec 06 '22 15:12

Ben Voigt