Пример #1
0
        static ILGeneratorExtensions()
        {
            var emit = typeof(ILGenerator).GetMethod(nameof(ILGenerator.EmitCalli),
                                                     new[] { typeof(OpCode), typeof(CallingConvention), typeof(Type), typeof(Type) });
            var getSigHelper = (GetMethodSigHelper)typeof(SignatureHelper)
                               .GetMethod(nameof(SignatureHelper.GetMethodSigHelper), new[] { typeof(CallingConvention), typeof(Type) })
                               ?.CreateDelegate(typeof(GetMethodSigHelper));

            _emitCalliDelegate = (EmitCalliDelegate)emit?.CreateDelegate(typeof(EmitCalliDelegate)) ??
                                 ((il, op, convention, ret, types) =>
            {
                if (getSigHelper is null)
                {
                    // TODO: Update this with a link to documentation.
                    throw new PlatformNotSupportedException(
                        "Unmanaged indirect call emission is not supported on this platform.");
                }

                var sigHelper = getSigHelper(convention, ret);
                foreach (var param in types)
                {
                    sigHelper.AddArgument(param);
                }

                il.Emit(op, sigHelper);
            });
        }
Пример #2
0
        private static void GenerateCheckedMethodIl(ILGenerator generator, FieldInfo apiField, string fieldName, Type[] parameters, EmitCalliDelegate emitCalli)
        {
            for (int i = 0; i < parameters.Length; i++)
            {
                generator.Emit(OpCodes.Ldarg, i + 1); // Load parameter, +1 from static
            }

            generator.Emit(OpCodes.Ldarg_0);                                                       // Load this
            generator.Emit(OpCodes.Ldfld, apiField);                                               // Load address of field
            generator.Emit(OpCodes.Ldfld, typeof(NativeQuicApi).GetField(fieldName));              // Load function pointer
            emitCalli(generator, OpCodes.Calli, CallingConvention.Cdecl, typeof(int), parameters); // call function pointer

            var local = generator.DeclareLocal(typeof(int));

            generator.Emit(OpCodes.Stloc_0);
            generator.Emit(OpCodes.Ldloc_0);

            generator.Emit(OpCodes.Ldc_I4_0);
            var label = generator.DefineLabel();

            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
            {
                // generate check for failures = < 0
                generator.Emit(OpCodes.Bge, label);
            }
            else
            {
                // generate check for failures = > 0
                generator.Emit(OpCodes.Ble, label);
            }
            generator.Emit(OpCodes.Ldloc_0);
            generator.Emit(OpCodes.Call, typeof(Helpers).GetMethod(nameof(Helpers.CheckException)));
            generator.MarkLabel(label);
            generator.Emit(OpCodes.Ret);
        }
Пример #3
0
        private static void GenerateMethodIl(ILGenerator generator, FieldInfo apiField, string fieldName, Type[] parameters, Type returnType, EmitCalliDelegate emitCalli)
        {
            for (int i = 0; i < parameters.Length; i++)
            {
                generator.Emit(OpCodes.Ldarg, i + 1); // Load parameter, +1 from static
            }

            generator.Emit(OpCodes.Ldarg_0);                                                      // Load this
            generator.Emit(OpCodes.Ldfld, apiField);                                              // Load address of field
            generator.Emit(OpCodes.Ldfld, typeof(NativeQuicApi).GetField(fieldName));             // Load function pointer
            emitCalli(generator, OpCodes.Calli, CallingConvention.Cdecl, returnType, parameters); // call function pointer
            generator.Emit(OpCodes.Ret);
        }