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); }); }
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); }
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); }