ltrzesniewski / InlineIL.Fody

Inject arbitrary IL code at compile time.
MIT License
240 stars 17 forks source link

Error in .NET 7 Preview 7 #26

Closed buybackoff closed 2 years ago

buybackoff commented 2 years ago

This is the same method we use in Disruptor and have discussed a lot recently.

ArrayUtil.cs(91, 13): [] Fody/InlineIL: Unexpected instruction, expected newarr or call to Array.Empty but was: IL_0003: call !!0[] System.GC::AllocateUninitializedArray<InlineIL.LocalVar>(System.Int32,System.Boolean) - InlineIL requires that arguments to IL-emitting methods be constructed in place. (in T& ArrayUtil::UnsafeGetAt(T[],System.Int32) at instruction IL_0003: call !!0[] System.GC::AllocateUninitializedArray<InlineIL.LocalVar>(System.Int32,System.Boolean))
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static ref T UnsafeGetAt<T>(this T[] array, int index)
        {
            IL.DeclareLocals(false, typeof(T[]).MakeByRefType());
            Ldarg_0();
            Stloc_0(); // convert the object pointer to a byref
            Ldloc_0(); // load the object pointer as a byref

            Ldarg(nameof(index));
            Conv_U(); // zero extend

            Sizeof(typeof(T));
            Mul(); // index x sizeof(T)

            Call(MethodRef.PropertyGet(typeof(ArrayUtil), nameof(ArrayDataOffset)));

            Add(); // index x sizeof(T) +  ArrayDataOffset

            Add(); // array + index x sizeof(T) +  ArrayDataOffset

            Ret();

            throw IL.Unreachable();
        }
ltrzesniewski commented 2 years ago

Thanks for raising the issue.

Looks like they changed the codegen, and now emit GC::AllocateUninitializedArray instread of newarr. I'll handle that.

buybackoff commented 2 years ago

Yep, it seems simple, but I'm not familiar with the internals.

A global switch like "EnableValidation" could be useful (like in Jil library).

ltrzesniewski commented 2 years ago

What do you mean by "EnableValidation" more precisely?

buybackoff commented 2 years ago

When it's off, do not do any checks.

ltrzesniewski commented 2 years ago

There's no check I can disable here. InlineIL does pattern matching on the IL emitted by Roslyn, and in this case Roslyn now emits different IL for method calls with params. InlineIL has no clue what to do with this. I need to account for that.

ltrzesniewski commented 2 years ago

This is caused by https://github.com/dotnet/roslyn/pull/62392, which will be reverted, but I'll still add support for this pattern to InlineIL.

ltrzesniewski commented 2 years ago

Fixed in v1.7.2.