Search code examples
c#.netclrcil

How to emit IL for ref locals using ILGenerator?


The following C# snippet:

int x = 10;
ref int y = ref x;

is compiled to this IL:

.locals init (
    [0] int32 x,
    [1] int32& y
)

ldc.i4.s 10
stloc.0
ldloca.s 0
stloc.1
ret

How do I create a local of type int32& using ILGenerator?

I looked at the ILGenerator.DeclareLocal() method, but did not find a suitable overload.


Solution

  • By-reference locals are just locals with different type. To make type by-ref, you should call .MakeByRefType()

            // void Foo()
            var meth = new DynamicMethod("Foo", returnType: typeof(void), parameterTypes: null);
            var il = meth.GetILGenerator();
    
            // int x;
            var xLocal = il.DeclareLocal(typeof(int));
            // ref int y;
            var yLocal = il.DeclareLocal(typeof(int).MakeByRefType());
    
            // x = 10;
            il.Emit(OpCodes.Ldc_I4, 10);
            il.Emit(OpCodes.Stloc, xLocal);
    
            // ref y = ref x;
            il.Emit(OpCodes.Ldloca, xLocal);
            il.Emit(OpCodes.Stloc, yLocal);
    
            il.Emit(OpCodes.Ret);
    
            var action = meth.CreateDelegate<Action>();
            action(); // ensure no InvalidProgramException