From 03fe0a76a8050775abd9bec547fd7042b2f44f9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Hei=C3=9F?= Date: Mon, 27 Oct 2025 23:57:38 +0100 Subject: [PATCH 01/13] Build correct signatures for member references to unmanaged function pointers --- .../Reflection/Emit/ModuleBuilderImpl.cs | 27 ++++++++++++-- .../System/Reflection/Emit/SignatureHelper.cs | 12 +++++- .../AssemblySaveTypeBuilderTests.cs | 37 +++++++++++++------ 3 files changed, 58 insertions(+), 18 deletions(-) diff --git a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/ModuleBuilderImpl.cs b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/ModuleBuilderImpl.cs index 26d43dbaa1083e..0adff66a0c13e2 100644 --- a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/ModuleBuilderImpl.cs +++ b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/ModuleBuilderImpl.cs @@ -690,6 +690,8 @@ internal void WriteCustomAttributes(List? customAttribut private EntityHandle GetTypeReferenceOrSpecificationHandle(Type type) { + type = type.UnderlyingSystemType; + if (!_typeReferences.TryGetValue(type, out var typeHandle)) { if (type.HasElementType || type.IsGenericParameter || @@ -740,7 +742,12 @@ private EntityHandle GetMemberReferenceHandle(MemberInfo memberInfo) declaringType = declaringType.MakeGenericType(declaringType.GetGenericArguments()); } - Type fieldType = ((FieldInfo)GetOriginalMemberIfConstructedType(field)).FieldType; + FieldInfo originalField = (FieldInfo)GetOriginalMemberIfConstructedType(field); + Type fieldType = originalField.FieldType; + + if (fieldType.IsUnmanagedFunctionPointer) + fieldType = originalField.GetModifiedFieldType(); + memberHandle = AddMemberReference(field.Name, GetTypeHandle(declaringType), MetadataSignatureHelper.GetFieldSignature(fieldType, field.GetRequiredCustomModifiers(), field.GetOptionalCustomModifiers(), this)); @@ -790,9 +797,16 @@ private EntityHandle GetMethodReference(MethodInfo methodInfo, Type[] optionalPa return memberHandle; } - private BlobBuilder GetMethodSignature(MethodInfo method, Type[]? optionalParameterTypes) => - MetadataSignatureHelper.GetMethodSignature(this, ParameterTypes(method.GetParameters()), method.ReturnType, + private BlobBuilder GetMethodSignature(MethodInfo method, Type[]? optionalParameterTypes) + { + Type returnType = method.ReturnType; + + if (returnType.IsUnmanagedFunctionPointer) + returnType = method.ReturnParameter.GetModifiedParameterType(); + + return MetadataSignatureHelper.GetMethodSignature(this, ParameterTypes(method.GetParameters()), returnType, GetSignatureConvention(method.CallingConvention), method.GetGenericArguments().Length, !method.IsStatic, optionalParameterTypes); + } private BlobBuilder GetMethodArrayMethodSignature(ArrayMethod method) => MetadataSignatureHelper.GetMethodSignature( this, method.ParameterTypes, method.ReturnType, GetSignatureConvention(method.CallingConvention), isInstance: IsInstance(method.CallingConvention)); @@ -840,7 +854,12 @@ private static Type[] ParameterTypes(ParameterInfo[] parameterInfos) for (int i = 0; i < parameterInfos.Length; i++) { - parameterTypes[i] = parameterInfos[i].ParameterType; + Type paramType = parameterInfos[i].ParameterType; + + if (paramType.IsUnmanagedFunctionPointer) + paramType = parameterInfos[i].GetModifiedParameterType(); + + parameterTypes[i] = paramType; } return parameterTypes; diff --git a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/SignatureHelper.cs b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/SignatureHelper.cs index 0cacbcc8c3f1a7..7712633e100255 100644 --- a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/SignatureHelper.cs +++ b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/SignatureHelper.cs @@ -276,7 +276,11 @@ private static void WriteSignatureForFunctionPointerType(SignatureTypeEncoder si if (returnType.GetRequiredCustomModifiers() is Type[] retModReqs) WriteCustomModifiers(retModifiersEncoder, retModReqs, isOptional: false, module); - WriteSignatureForType(retTypeEncoder.Type(), returnType, module); + Type returnTypeToWrite = returnType; + if (!returnTypeToWrite.IsFunctionPointer) + returnTypeToWrite = returnTypeToWrite.UnderlyingSystemType; + + WriteSignatureForType(retTypeEncoder.Type(), returnTypeToWrite, module); foreach (Type paramType in paramTypes) { @@ -289,7 +293,11 @@ private static void WriteSignatureForFunctionPointerType(SignatureTypeEncoder si if (paramType.GetRequiredCustomModifiers() is Type[] paramModReqs) WriteCustomModifiers(paramModifiersEncoder, paramModReqs, isOptional: false, module); - WriteSignatureForType(paramEncoder.Type(), paramType, module); + Type paramTypeToWrite = paramType; + if (!paramTypeToWrite.IsFunctionPointer) + paramTypeToWrite = paramTypeToWrite.UnderlyingSystemType; + + WriteSignatureForType(paramEncoder.Type(), paramTypeToWrite, module); } } diff --git a/src/libraries/System.Reflection.Emit/tests/PersistedAssemblyBuilder/AssemblySaveTypeBuilderTests.cs b/src/libraries/System.Reflection.Emit/tests/PersistedAssemblyBuilder/AssemblySaveTypeBuilderTests.cs index 4645dae1b7a92c..bd09551644cdb0 100644 --- a/src/libraries/System.Reflection.Emit/tests/PersistedAssemblyBuilder/AssemblySaveTypeBuilderTests.cs +++ b/src/libraries/System.Reflection.Emit/tests/PersistedAssemblyBuilder/AssemblySaveTypeBuilderTests.cs @@ -864,7 +864,7 @@ public void SaveFunctionPointerFields() } [Fact] - public void ConsumeFunctionPointerFields() + public void ConsumeFunctionPointerMembers() { // public unsafe class Container // { @@ -915,16 +915,23 @@ public void ConsumeFunctionPointerFields() MethodBuilder mainMethod = programType.DefineMethod("Main", MethodAttributes.Public | MethodAttributes.Static); mainMethod.SetReturnType(typeof(int)); ILGenerator il = mainMethod.GetILGenerator(); - il.Emit(OpCodes.Ldsfld, typeof(ClassWithFunctionPointerFields).GetField("field1")); + il.Emit(OpCodes.Ldsfld, typeof(ClassWithFunctionPointerMembers).GetField("field1")); + il.Emit(OpCodes.Pop); + il.Emit(OpCodes.Ldsfld, typeof(ClassWithFunctionPointerMembers).GetField("field2")); + il.Emit(OpCodes.Pop); + il.Emit(OpCodes.Ldsfld, typeof(ClassWithFunctionPointerMembers).GetField("field3")); + il.Emit(OpCodes.Pop); + //il.Emit(OpCodes.Ldsfld, typeof(ClassWithFunctionPointerMembers).GetField("field4")); + //il.Emit(OpCodes.Pop); + il.Emit(OpCodes.Call, typeof(ClassWithFunctionPointerMembers).GetMethod("Method1")); + il.Emit(OpCodes.Pop); + il.Emit(OpCodes.Call, typeof(ClassWithFunctionPointerMembers).GetMethod("Method2")); + il.Emit(OpCodes.Pop); + il.Emit(OpCodes.Call, typeof(ClassWithFunctionPointerMembers).GetMethod("Method3")); + il.Emit(OpCodes.Pop); + il.Emit(OpCodes.Call, typeof(ClassWithFunctionPointerMembers).GetMethod("Method4")); + il.Emit(OpCodes.Call, typeof(ClassWithFunctionPointerMembers).GetMethod("Method5")); il.Emit(OpCodes.Pop); - // References to fields with unmanaged calling convention are broken - // [ActiveIssue("https://github.com/dotnet/runtime/issues/120909")] - // il.Emit(OpCodes.Ldsfld, typeof(ClassWithFunctionPointerFields).GetField("field2")); - // il.Emit(OpCodes.Pop); - // il.Emit(OpCodes.Ldsfld, typeof(ClassWithFunctionPointerFields).GetField("field3")); - // il.Emit(OpCodes.Pop); - // il.Emit(OpCodes.Ldsfld, typeof(ClassWithFunctionPointerFields).GetField("field4")); - // il.Emit(OpCodes.Pop); il.Emit(OpCodes.Call, assembly1FromDisk.GetType("Container").GetMethod("Init")); il.Emit(OpCodes.Ldc_I4_2); il.Emit(OpCodes.Ldc_I4_3); @@ -989,11 +996,17 @@ public class ClassWithFields : EmptyTestClass public byte field2; } - public unsafe class ClassWithFunctionPointerFields + public unsafe class ClassWithFunctionPointerMembers { - public static delegate* field1; + public static delegate* field1; public static delegate* unmanaged field2; public static delegate* unmanaged[Cdecl] field3; public static delegate* unmanaged[Cdecl, SuppressGCTransition], Vector> field4; + + public static delegate* Method1() => null; + public static delegate* unmanaged Method2() => null; + public static delegate* unmanaged[Fastcall] Method3() => null; + public static delegate* unmanaged[Cdecl], Guid> Method4() => null; + public static delegate* unmanaged[Cdecl] Method5(delegate* unmanaged[Cdecl], Guid> funcPtr) => null; } } From 3083bc100e01bacf8b377d880a714ecdeab9b266 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Hei=C3=9F?= Date: Tue, 28 Oct 2025 00:00:24 +0100 Subject: [PATCH 02/13] Remove empty lines --- .../src/System/Reflection/Emit/ModuleBuilderImpl.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/ModuleBuilderImpl.cs b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/ModuleBuilderImpl.cs index 0adff66a0c13e2..602a777e325ea0 100644 --- a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/ModuleBuilderImpl.cs +++ b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/ModuleBuilderImpl.cs @@ -800,7 +800,6 @@ private EntityHandle GetMethodReference(MethodInfo methodInfo, Type[] optionalPa private BlobBuilder GetMethodSignature(MethodInfo method, Type[]? optionalParameterTypes) { Type returnType = method.ReturnType; - if (returnType.IsUnmanagedFunctionPointer) returnType = method.ReturnParameter.GetModifiedParameterType(); @@ -855,7 +854,6 @@ private static Type[] ParameterTypes(ParameterInfo[] parameterInfos) for (int i = 0; i < parameterInfos.Length; i++) { Type paramType = parameterInfos[i].ParameterType; - if (paramType.IsUnmanagedFunctionPointer) paramType = parameterInfos[i].GetModifiedParameterType(); From 77497a1aae61aff1d3c89f8a181dc3a54ffc7f0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Hei=C3=9F?= Date: Tue, 28 Oct 2025 19:25:36 +0100 Subject: [PATCH 03/13] Strip modifiers off types in WriteSimpleSignature --- .../src/System/Reflection/Emit/SignatureHelper.cs | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/SignatureHelper.cs b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/SignatureHelper.cs index 7712633e100255..561adf1bd32580 100644 --- a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/SignatureHelper.cs +++ b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/SignatureHelper.cs @@ -276,11 +276,7 @@ private static void WriteSignatureForFunctionPointerType(SignatureTypeEncoder si if (returnType.GetRequiredCustomModifiers() is Type[] retModReqs) WriteCustomModifiers(retModifiersEncoder, retModReqs, isOptional: false, module); - Type returnTypeToWrite = returnType; - if (!returnTypeToWrite.IsFunctionPointer) - returnTypeToWrite = returnTypeToWrite.UnderlyingSystemType; - - WriteSignatureForType(retTypeEncoder.Type(), returnTypeToWrite, module); + WriteSignatureForType(retTypeEncoder.Type(), returnType, module); foreach (Type paramType in paramTypes) { @@ -293,16 +289,13 @@ private static void WriteSignatureForFunctionPointerType(SignatureTypeEncoder si if (paramType.GetRequiredCustomModifiers() is Type[] paramModReqs) WriteCustomModifiers(paramModifiersEncoder, paramModReqs, isOptional: false, module); - Type paramTypeToWrite = paramType; - if (!paramTypeToWrite.IsFunctionPointer) - paramTypeToWrite = paramTypeToWrite.UnderlyingSystemType; - - WriteSignatureForType(paramEncoder.Type(), paramTypeToWrite, module); + WriteSignatureForType(paramEncoder.Type(), paramType, module); } } private static void WriteSimpleSignature(SignatureTypeEncoder signature, Type type, ModuleBuilderImpl module) { + type = type.UnderlyingSystemType; CoreTypeId? typeId = module.GetTypeIdFromCoreTypes(type); switch (typeId) From 9d0f7fd71d36238c3ba20acf9b6be1eabbaa02ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Hei=C3=9F?= Date: Tue, 28 Oct 2025 19:50:16 +0100 Subject: [PATCH 04/13] Reverse order of modifiers on function pointers --- .../src/System/Reflection/Emit/SignatureHelper.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/SignatureHelper.cs b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/SignatureHelper.cs index 561adf1bd32580..3e0474a60aa43b 100644 --- a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/SignatureHelper.cs +++ b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/SignatureHelper.cs @@ -271,10 +271,16 @@ private static void WriteSignatureForFunctionPointerType(SignatureTypeEncoder si CustomModifiersEncoder retModifiersEncoder = retTypeEncoder.CustomModifiers(); if (returnType.GetOptionalCustomModifiers() is Type[] retModOpts) + { + Array.Reverse(retModOpts); WriteCustomModifiers(retModifiersEncoder, retModOpts, isOptional: true, module); + } if (returnType.GetRequiredCustomModifiers() is Type[] retModReqs) + { + Array.Reverse(retModReqs); WriteCustomModifiers(retModifiersEncoder, retModReqs, isOptional: false, module); + } WriteSignatureForType(retTypeEncoder.Type(), returnType, module); @@ -284,10 +290,16 @@ private static void WriteSignatureForFunctionPointerType(SignatureTypeEncoder si CustomModifiersEncoder paramModifiersEncoder = paramEncoder.CustomModifiers(); if (paramType.GetOptionalCustomModifiers() is Type[] paramModOpts) + { + Array.Reverse(paramModOpts); WriteCustomModifiers(paramModifiersEncoder, paramModOpts, isOptional: true, module); + } if (paramType.GetRequiredCustomModifiers() is Type[] paramModReqs) + { + Array.Reverse(paramModReqs); WriteCustomModifiers(paramModifiersEncoder, paramModReqs, isOptional: false, module); + } WriteSignatureForType(paramEncoder.Type(), paramType, module); } From d87f8e49980372c5a0883bc0d90e1297e0888aab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Hei=C3=9F?= Date: Tue, 28 Oct 2025 22:01:39 +0100 Subject: [PATCH 05/13] Reverse order in WriteCustomModifiers --- .../src/System/Reflection/Emit/SignatureHelper.cs | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/SignatureHelper.cs b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/SignatureHelper.cs index 3e0474a60aa43b..7ffdbc89130b80 100644 --- a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/SignatureHelper.cs +++ b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/SignatureHelper.cs @@ -122,6 +122,8 @@ private static void WriteReturnTypeCustomModifiers(CustomModifiersEncoder encode private static void WriteCustomModifiers(CustomModifiersEncoder encoder, Type[] customModifiers, bool isOptional, ModuleBuilderImpl module) { + // GetOptionalCustomModifiers and GetRequiredCustomModifiers return modifiers in reverse order + Array.Reverse(customModifiers); foreach (Type modifier in customModifiers) { encoder.AddModifier(module.GetTypeHandle(modifier), isOptional); @@ -271,16 +273,10 @@ private static void WriteSignatureForFunctionPointerType(SignatureTypeEncoder si CustomModifiersEncoder retModifiersEncoder = retTypeEncoder.CustomModifiers(); if (returnType.GetOptionalCustomModifiers() is Type[] retModOpts) - { - Array.Reverse(retModOpts); WriteCustomModifiers(retModifiersEncoder, retModOpts, isOptional: true, module); - } if (returnType.GetRequiredCustomModifiers() is Type[] retModReqs) - { - Array.Reverse(retModReqs); WriteCustomModifiers(retModifiersEncoder, retModReqs, isOptional: false, module); - } WriteSignatureForType(retTypeEncoder.Type(), returnType, module); @@ -290,16 +286,10 @@ private static void WriteSignatureForFunctionPointerType(SignatureTypeEncoder si CustomModifiersEncoder paramModifiersEncoder = paramEncoder.CustomModifiers(); if (paramType.GetOptionalCustomModifiers() is Type[] paramModOpts) - { - Array.Reverse(paramModOpts); WriteCustomModifiers(paramModifiersEncoder, paramModOpts, isOptional: true, module); - } if (paramType.GetRequiredCustomModifiers() is Type[] paramModReqs) - { - Array.Reverse(paramModReqs); WriteCustomModifiers(paramModifiersEncoder, paramModReqs, isOptional: false, module); - } WriteSignatureForType(paramEncoder.Type(), paramType, module); } From 637d5b7e0d56a6ac86f8f326d69f977b70362ebe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Hei=C3=9F?= Date: Tue, 28 Oct 2025 22:35:18 +0100 Subject: [PATCH 06/13] Use modified types unconditionally --- .../Reflection/Emit/ModuleBuilderImpl.cs | 24 +++++++++++++------ .../System/Reflection/Emit/SignatureHelper.cs | 18 +++++++------- .../AssemblySaveTypeBuilderAPIsTests.cs | 4 ++-- .../AssemblySaveTypeBuilderTests.cs | 17 +++++++++++-- 4 files changed, 43 insertions(+), 20 deletions(-) diff --git a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/ModuleBuilderImpl.cs b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/ModuleBuilderImpl.cs index 602a777e325ea0..01aa17bf3e82b9 100644 --- a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/ModuleBuilderImpl.cs +++ b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/ModuleBuilderImpl.cs @@ -5,6 +5,7 @@ using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Diagnostics.SymbolStore; +using System.IO; using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; using System.Reflection.PortableExecutable; @@ -184,7 +185,8 @@ internal void AppendMetadata(MethodBodyStreamEncoder methodBodyEncoder, BlobBuil } // Now write all generic parameters in order - genericParams.Sort((x, y) => { + genericParams.Sort((x, y) => + { int primary = CodedIndex.TypeOrMethodDef(x._parentHandle).CompareTo(CodedIndex.TypeOrMethodDef(y._parentHandle)); if (primary != 0) return primary; @@ -744,9 +746,11 @@ private EntityHandle GetMemberReferenceHandle(MemberInfo memberInfo) FieldInfo originalField = (FieldInfo)GetOriginalMemberIfConstructedType(field); Type fieldType = originalField.FieldType; - - if (fieldType.IsUnmanagedFunctionPointer) + try + { fieldType = originalField.GetModifiedFieldType(); + } + catch { } memberHandle = AddMemberReference(field.Name, GetTypeHandle(declaringType), MetadataSignatureHelper.GetFieldSignature(fieldType, field.GetRequiredCustomModifiers(), field.GetOptionalCustomModifiers(), this)); @@ -800,8 +804,11 @@ private EntityHandle GetMethodReference(MethodInfo methodInfo, Type[] optionalPa private BlobBuilder GetMethodSignature(MethodInfo method, Type[]? optionalParameterTypes) { Type returnType = method.ReturnType; - if (returnType.IsUnmanagedFunctionPointer) + try + { returnType = method.ReturnParameter.GetModifiedParameterType(); + } + catch { } return MetadataSignatureHelper.GetMethodSignature(this, ParameterTypes(method.GetParameters()), returnType, GetSignatureConvention(method.CallingConvention), method.GetGenericArguments().Length, !method.IsStatic, optionalParameterTypes); @@ -842,7 +849,7 @@ private MemberInfo GetOriginalMemberIfConstructedType(MemberInfo memberInfo) return memberInfo; } - private static Type[] ParameterTypes(ParameterInfo[] parameterInfos) + internal static Type[] ParameterTypes(ParameterInfo[] parameterInfos) { if (parameterInfos.Length == 0) { @@ -854,8 +861,11 @@ private static Type[] ParameterTypes(ParameterInfo[] parameterInfos) for (int i = 0; i < parameterInfos.Length; i++) { Type paramType = parameterInfos[i].ParameterType; - if (paramType.IsUnmanagedFunctionPointer) + try + { paramType = parameterInfos[i].GetModifiedParameterType(); + } + catch { } parameterTypes[i] = paramType; } @@ -878,7 +888,7 @@ private AssemblyReferenceHandle GetAssemblyReference(Assembly assembly) } else { - publicKeyOrToken = aName.GetPublicKeyToken(); + publicKeyOrToken = aName.GetPublicKeyToken(); } handle = AddAssemblyReference(aName.Name, aName.Version, aName.CultureName, publicKeyOrToken, assemblyFlags); _assemblyReferences.Add(assembly, handle); diff --git a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/SignatureHelper.cs b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/SignatureHelper.cs index 7ffdbc89130b80..8c109d77736910 100644 --- a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/SignatureHelper.cs +++ b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/SignatureHelper.cs @@ -48,7 +48,7 @@ internal static BlobBuilder GetConstructorSignature(ParameterInfo[]? parameters, retType.Void(); - WriteParametersSignature(module, Array.ConvertAll(parameters, p => p.ParameterType), parameterEncoder); + WriteParametersSignature(module, ModuleBuilderImpl.ParameterTypes(parameters), parameterEncoder); return constructorSignature; } @@ -203,13 +203,13 @@ private static void WriteSignatureForType(SignatureTypeEncoder signature, Type t module.GetTypeHandle(type.GetGenericTypeDefinition()), genericArguments.Length, type.IsValueType); foreach (Type gType in genericArguments) { - if (gType.IsGenericMethodParameter) + if (gType.UnderlyingSystemType.IsGenericMethodParameter) { - encoder.AddArgument().GenericMethodTypeParameter(gType.GenericParameterPosition); + encoder.AddArgument().GenericMethodTypeParameter(gType.UnderlyingSystemType.GenericParameterPosition); } - else if (gType.IsGenericParameter) + else if (gType.UnderlyingSystemType.IsGenericParameter) { - encoder.AddArgument().GenericTypeParameter(gType.GenericParameterPosition); + encoder.AddArgument().GenericTypeParameter(gType.UnderlyingSystemType.GenericParameterPosition); } else { @@ -217,13 +217,13 @@ private static void WriteSignatureForType(SignatureTypeEncoder signature, Type t } } } - else if (type.IsGenericMethodParameter) + else if (type.UnderlyingSystemType.IsGenericMethodParameter) { - signature.GenericMethodTypeParameter(type.GenericParameterPosition); + signature.GenericMethodTypeParameter(type.UnderlyingSystemType.GenericParameterPosition); } - else if (type.IsGenericParameter) + else if (type.UnderlyingSystemType.IsGenericParameter) { - signature.GenericTypeParameter(type.GenericParameterPosition); + signature.GenericTypeParameter(type.UnderlyingSystemType.GenericParameterPosition); } else if (type.IsFunctionPointer) { diff --git a/src/libraries/System.Reflection.Emit/tests/PersistedAssemblyBuilder/AssemblySaveTypeBuilderAPIsTests.cs b/src/libraries/System.Reflection.Emit/tests/PersistedAssemblyBuilder/AssemblySaveTypeBuilderAPIsTests.cs index d9d1e1e50269b5..c3eff0b525b79a 100644 --- a/src/libraries/System.Reflection.Emit/tests/PersistedAssemblyBuilder/AssemblySaveTypeBuilderAPIsTests.cs +++ b/src/libraries/System.Reflection.Emit/tests/PersistedAssemblyBuilder/AssemblySaveTypeBuilderAPIsTests.cs @@ -633,8 +633,8 @@ public void ReturnTypeAndParameterRequiredOptionalCustomModifiers() Type[] par0RequiredMods = allModMethod.GetParameters()[0].GetRequiredCustomModifiers(); Type[] par0OptionalMods = allModMethod.GetParameters()[0].GetOptionalCustomModifiers(); Assert.Equal(2, returnReqMods.Length); - Assert.Equal(mlc.CoreAssembly.GetType(typeof(short).FullName), returnReqMods[0]); - Assert.Equal(mlc.CoreAssembly.GetType(typeof(int).FullName), returnReqMods[1]); + Assert.Equal(mlc.CoreAssembly.GetType(typeof(int).FullName), returnReqMods[0]); + Assert.Equal(mlc.CoreAssembly.GetType(typeof(short).FullName), returnReqMods[1]); Assert.Equal(1, returnOptMods.Length); Assert.Equal(mlc.CoreAssembly.GetType(typeof(Version).FullName), returnOptMods[0]); Assert.Equal(cmodsReq1.Length, par0RequiredMods.Length); diff --git a/src/libraries/System.Reflection.Emit/tests/PersistedAssemblyBuilder/AssemblySaveTypeBuilderTests.cs b/src/libraries/System.Reflection.Emit/tests/PersistedAssemblyBuilder/AssemblySaveTypeBuilderTests.cs index bd09551644cdb0..8c3c780ac3aea1 100644 --- a/src/libraries/System.Reflection.Emit/tests/PersistedAssemblyBuilder/AssemblySaveTypeBuilderTests.cs +++ b/src/libraries/System.Reflection.Emit/tests/PersistedAssemblyBuilder/AssemblySaveTypeBuilderTests.cs @@ -921,8 +921,10 @@ public void ConsumeFunctionPointerMembers() il.Emit(OpCodes.Pop); il.Emit(OpCodes.Ldsfld, typeof(ClassWithFunctionPointerMembers).GetField("field3")); il.Emit(OpCodes.Pop); - //il.Emit(OpCodes.Ldsfld, typeof(ClassWithFunctionPointerMembers).GetField("field4")); - //il.Emit(OpCodes.Pop); + il.Emit(OpCodes.Ldsfld, typeof(ClassWithFunctionPointerMembers).GetField("field4")); + il.Emit(OpCodes.Pop); + il.Emit(OpCodes.Ldsfld, typeof(ClassWithFunctionPointerMembers).GetField("field5")); + il.Emit(OpCodes.Pop); il.Emit(OpCodes.Call, typeof(ClassWithFunctionPointerMembers).GetMethod("Method1")); il.Emit(OpCodes.Pop); il.Emit(OpCodes.Call, typeof(ClassWithFunctionPointerMembers).GetMethod("Method2")); @@ -932,6 +934,10 @@ public void ConsumeFunctionPointerMembers() il.Emit(OpCodes.Call, typeof(ClassWithFunctionPointerMembers).GetMethod("Method4")); il.Emit(OpCodes.Call, typeof(ClassWithFunctionPointerMembers).GetMethod("Method5")); il.Emit(OpCodes.Pop); + il.Emit(OpCodes.Ldsfld, typeof(GenericClassWithFunctionPointerMembers).GetField("Field")); + il.Emit(OpCodes.Pop); + il.Emit(OpCodes.Call, typeof(GenericClassWithFunctionPointerMembers).GetMethod("Method").MakeGenericMethod(typeof(string))); + il.Emit(OpCodes.Pop); il.Emit(OpCodes.Call, assembly1FromDisk.GetType("Container").GetMethod("Init")); il.Emit(OpCodes.Ldc_I4_2); il.Emit(OpCodes.Ldc_I4_3); @@ -1002,6 +1008,7 @@ public unsafe class ClassWithFunctionPointerMembers public static delegate* unmanaged field2; public static delegate* unmanaged[Cdecl] field3; public static delegate* unmanaged[Cdecl, SuppressGCTransition], Vector> field4; + public static List*[]> field5; public static delegate* Method1() => null; public static delegate* unmanaged Method2() => null; @@ -1009,4 +1016,10 @@ public unsafe class ClassWithFunctionPointerMembers public static delegate* unmanaged[Cdecl], Guid> Method4() => null; public static delegate* unmanaged[Cdecl] Method5(delegate* unmanaged[Cdecl], Guid> funcPtr) => null; } + + public unsafe class GenericClassWithFunctionPointerMembers + { + public static delegate* unmanaged[Cdecl] Field; + public static delegate* unmanaged[Fastcall, MemberFunction] Method() => null; + } } From 38e2d85c29c8b3a65344a3ee5dcef66c64c22c5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Hei=C3=9F?= Date: Tue, 28 Oct 2025 22:36:01 +0100 Subject: [PATCH 07/13] Remove unnecessary using --- .../src/System/Reflection/Emit/ModuleBuilderImpl.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/ModuleBuilderImpl.cs b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/ModuleBuilderImpl.cs index 01aa17bf3e82b9..7f0e148949d4aa 100644 --- a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/ModuleBuilderImpl.cs +++ b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/ModuleBuilderImpl.cs @@ -5,7 +5,6 @@ using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Diagnostics.SymbolStore; -using System.IO; using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; using System.Reflection.PortableExecutable; From c49060b25ad3b2f872319aeb6138a8dccb8cc546 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Hei=C3=9F?= Date: Wed, 29 Oct 2025 22:23:55 +0100 Subject: [PATCH 08/13] Do not call GetModifiedFieldType on SRE internals --- .../Reflection/Emit/ModuleBuilderImpl.cs | 58 ++++++++++++------- .../AssemblySaveTypeBuilderTests.cs | 2 +- 2 files changed, 37 insertions(+), 23 deletions(-) diff --git a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/ModuleBuilderImpl.cs b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/ModuleBuilderImpl.cs index 7f0e148949d4aa..4d287af8881bbc 100644 --- a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/ModuleBuilderImpl.cs +++ b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/ModuleBuilderImpl.cs @@ -5,6 +5,7 @@ using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Diagnostics.SymbolStore; +using System.IO; using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; using System.Reflection.PortableExecutable; @@ -744,12 +745,7 @@ private EntityHandle GetMemberReferenceHandle(MemberInfo memberInfo) } FieldInfo originalField = (FieldInfo)GetOriginalMemberIfConstructedType(field); - Type fieldType = originalField.FieldType; - try - { - fieldType = originalField.GetModifiedFieldType(); - } - catch { } + Type fieldType = GetFieldType(originalField); memberHandle = AddMemberReference(field.Name, GetTypeHandle(declaringType), MetadataSignatureHelper.GetFieldSignature(fieldType, field.GetRequiredCustomModifiers(), field.GetOptionalCustomModifiers(), this)); @@ -802,14 +798,7 @@ private EntityHandle GetMethodReference(MethodInfo methodInfo, Type[] optionalPa private BlobBuilder GetMethodSignature(MethodInfo method, Type[]? optionalParameterTypes) { - Type returnType = method.ReturnType; - try - { - returnType = method.ReturnParameter.GetModifiedParameterType(); - } - catch { } - - return MetadataSignatureHelper.GetMethodSignature(this, ParameterTypes(method.GetParameters()), returnType, + return MetadataSignatureHelper.GetMethodSignature(this, ParameterTypes(method.GetParameters()), GetReturnType(method), GetSignatureConvention(method.CallingConvention), method.GetGenericArguments().Length, !method.IsStatic, optionalParameterTypes); } @@ -859,14 +848,7 @@ internal static Type[] ParameterTypes(ParameterInfo[] parameterInfos) for (int i = 0; i < parameterInfos.Length; i++) { - Type paramType = parameterInfos[i].ParameterType; - try - { - paramType = parameterInfos[i].GetModifiedParameterType(); - } - catch { } - - parameterTypes[i] = paramType; + parameterTypes[i] = GetParameterType(parameterInfos[i]); } return parameterTypes; @@ -1428,5 +1410,37 @@ internal List GetNestedTypeBuilders(TypeBuilderImpl declaringTy return nestedTypes; } + + private static Type GetFieldType(FieldInfo field) + { + if (field.GetType().FullName == "System.Reflection.Emit.FieldBuilderImpl" + || field.GetType().FullName == "System.Reflection.Emit.FieldOnTypeBuilderInstantiation") + { + return field.FieldType; + } + + return field.GetModifiedFieldType(); + } + + private static Type GetParameterType(ParameterInfo param) + { + if (param.GetType().FullName == "System.Reflection.Emit.ParameterBuilderImpl" + || param.GetType().FullName == "System.Reflection.Emit.ParameterInfoWrapper") + { + return param.ParameterType; + } + + return param.GetModifiedParameterType(); + } + + private static Type GetReturnType(MethodInfo meth) + { + if (meth.GetType().FullName == "System.Reflection.Emit.MethodOnTypeBuilderInstantiation") + { + return meth.ReturnType; + } + + return GetParameterType(meth.ReturnParameter); + } } } diff --git a/src/libraries/System.Reflection.Emit/tests/PersistedAssemblyBuilder/AssemblySaveTypeBuilderTests.cs b/src/libraries/System.Reflection.Emit/tests/PersistedAssemblyBuilder/AssemblySaveTypeBuilderTests.cs index 8c3c780ac3aea1..c57b19a2307cd6 100644 --- a/src/libraries/System.Reflection.Emit/tests/PersistedAssemblyBuilder/AssemblySaveTypeBuilderTests.cs +++ b/src/libraries/System.Reflection.Emit/tests/PersistedAssemblyBuilder/AssemblySaveTypeBuilderTests.cs @@ -1008,7 +1008,7 @@ public unsafe class ClassWithFunctionPointerMembers public static delegate* unmanaged field2; public static delegate* unmanaged[Cdecl] field3; public static delegate* unmanaged[Cdecl, SuppressGCTransition], Vector> field4; - public static List*[]> field5; + public static List*[]> field5; public static delegate* Method1() => null; public static delegate* unmanaged Method2() => null; From ef7f3ce2282f21832899d640824dafa884d7b5ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Hei=C3=9F?= Date: Wed, 29 Oct 2025 22:24:54 +0100 Subject: [PATCH 09/13] Clean up usings --- .../src/System/Reflection/Emit/ModuleBuilderImpl.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/ModuleBuilderImpl.cs b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/ModuleBuilderImpl.cs index 4d287af8881bbc..9b18efd83c4449 100644 --- a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/ModuleBuilderImpl.cs +++ b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/ModuleBuilderImpl.cs @@ -5,7 +5,6 @@ using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Diagnostics.SymbolStore; -using System.IO; using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; using System.Reflection.PortableExecutable; From f198f8a44380993b1c9575680ed7c7aec2c94e13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Hei=C3=9F?= Date: Thu, 30 Oct 2025 17:43:39 +0100 Subject: [PATCH 10/13] Implement GetModifiedFieldType/GetModifiedParameterType for Reflection.Emit APIs --- .../Emit/FieldOnTypeBuilderInstantiation.cs | 1 + .../Emit/MethodOnTypeBuilderInstantiation.cs | 2 +- .../Reflection/Emit/FieldBuilderImpl.cs | 2 + .../Reflection/Emit/ModuleBuilderImpl.cs | 44 ++----------------- .../Reflection/Emit/ParameterBuilderImpl.cs | 5 ++- 5 files changed, 11 insertions(+), 43 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/FieldOnTypeBuilderInstantiation.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/FieldOnTypeBuilderInstantiation.cs index 006795ce3692e5..b269d598a01d2e 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/FieldOnTypeBuilderInstantiation.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/FieldOnTypeBuilderInstantiation.cs @@ -56,6 +56,7 @@ internal FieldOnTypeBuilderInstantiation(FieldInfo field, TypeBuilderInstantiati #region Public Abstract\Virtual Members public override Type[] GetRequiredCustomModifiers() { return _field.GetRequiredCustomModifiers(); } public override Type[] GetOptionalCustomModifiers() { return _field.GetOptionalCustomModifiers(); } + public override Type GetModifiedFieldType() => _field.GetModifiedFieldType(); public override void SetValueDirect(TypedReference obj, object value) { throw new NotImplementedException(); diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/MethodOnTypeBuilderInstantiation.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/MethodOnTypeBuilderInstantiation.cs index bfa9ef0359c502..5e0b8c317ad770 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/MethodOnTypeBuilderInstantiation.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/MethodOnTypeBuilderInstantiation.cs @@ -118,7 +118,7 @@ public override MethodInfo MakeGenericMethod(params Type[] typeArgs) #region Public Abstract\Virtual Members public override Type ReturnType => _method.ReturnType; - public override ParameterInfo ReturnParameter => throw new NotSupportedException(); + public override ParameterInfo ReturnParameter => _method.ReturnParameter; public override ICustomAttributeProvider ReturnTypeCustomAttributes => throw new NotSupportedException(); public override MethodInfo GetBaseDefinition() { throw new NotSupportedException(); } #endregion diff --git a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/FieldBuilderImpl.cs b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/FieldBuilderImpl.cs index 8d0561d15be47b..f5ef7912f19b39 100644 --- a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/FieldBuilderImpl.cs +++ b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/FieldBuilderImpl.cs @@ -113,6 +113,8 @@ public override void SetValue(object? obj, object? val, BindingFlags invokeAttr, public override Type[] GetOptionalCustomModifiers() => _optionalCustomModifiers ?? Type.EmptyTypes; + public override Type GetModifiedFieldType() => FieldType; + #endregion #region ICustomAttributeProvider Implementation diff --git a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/ModuleBuilderImpl.cs b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/ModuleBuilderImpl.cs index 9b18efd83c4449..2ce30d533701a2 100644 --- a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/ModuleBuilderImpl.cs +++ b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/ModuleBuilderImpl.cs @@ -743,9 +743,7 @@ private EntityHandle GetMemberReferenceHandle(MemberInfo memberInfo) declaringType = declaringType.MakeGenericType(declaringType.GetGenericArguments()); } - FieldInfo originalField = (FieldInfo)GetOriginalMemberIfConstructedType(field); - Type fieldType = GetFieldType(originalField); - + Type fieldType = ((FieldInfo)GetOriginalMemberIfConstructedType(field)).GetModifiedFieldType(); memberHandle = AddMemberReference(field.Name, GetTypeHandle(declaringType), MetadataSignatureHelper.GetFieldSignature(fieldType, field.GetRequiredCustomModifiers(), field.GetOptionalCustomModifiers(), this)); @@ -795,11 +793,9 @@ private EntityHandle GetMethodReference(MethodInfo methodInfo, Type[] optionalPa return memberHandle; } - private BlobBuilder GetMethodSignature(MethodInfo method, Type[]? optionalParameterTypes) - { - return MetadataSignatureHelper.GetMethodSignature(this, ParameterTypes(method.GetParameters()), GetReturnType(method), + private BlobBuilder GetMethodSignature(MethodInfo method, Type[]? optionalParameterTypes) => + MetadataSignatureHelper.GetMethodSignature(this, ParameterTypes(method.GetParameters()), method.ReturnParameter.GetModifiedParameterType(), GetSignatureConvention(method.CallingConvention), method.GetGenericArguments().Length, !method.IsStatic, optionalParameterTypes); - } private BlobBuilder GetMethodArrayMethodSignature(ArrayMethod method) => MetadataSignatureHelper.GetMethodSignature( this, method.ParameterTypes, method.ReturnType, GetSignatureConvention(method.CallingConvention), isInstance: IsInstance(method.CallingConvention)); @@ -847,7 +843,7 @@ internal static Type[] ParameterTypes(ParameterInfo[] parameterInfos) for (int i = 0; i < parameterInfos.Length; i++) { - parameterTypes[i] = GetParameterType(parameterInfos[i]); + parameterTypes[i] = parameterInfos[i].GetModifiedParameterType(); } return parameterTypes; @@ -1409,37 +1405,5 @@ internal List GetNestedTypeBuilders(TypeBuilderImpl declaringTy return nestedTypes; } - - private static Type GetFieldType(FieldInfo field) - { - if (field.GetType().FullName == "System.Reflection.Emit.FieldBuilderImpl" - || field.GetType().FullName == "System.Reflection.Emit.FieldOnTypeBuilderInstantiation") - { - return field.FieldType; - } - - return field.GetModifiedFieldType(); - } - - private static Type GetParameterType(ParameterInfo param) - { - if (param.GetType().FullName == "System.Reflection.Emit.ParameterBuilderImpl" - || param.GetType().FullName == "System.Reflection.Emit.ParameterInfoWrapper") - { - return param.ParameterType; - } - - return param.GetModifiedParameterType(); - } - - private static Type GetReturnType(MethodInfo meth) - { - if (meth.GetType().FullName == "System.Reflection.Emit.MethodOnTypeBuilderInstantiation") - { - return meth.ReturnType; - } - - return GetParameterType(meth.ReturnParameter); - } } } diff --git a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/ParameterBuilderImpl.cs b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/ParameterBuilderImpl.cs index f1b6446be8e0f8..d2e504fd73b583 100644 --- a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/ParameterBuilderImpl.cs +++ b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/ParameterBuilderImpl.cs @@ -68,8 +68,7 @@ protected override void SetCustomAttributeCore(ConstructorInfo con, ReadOnlySpan internal sealed class ParameterInfoWrapper : ParameterInfo { private readonly ParameterBuilderImpl _pb; - private readonly Type _type -; + private readonly Type _type; public ParameterInfoWrapper(ParameterBuilderImpl pb, Type type) { _pb = pb; @@ -87,5 +86,7 @@ public ParameterInfoWrapper(ParameterBuilderImpl pb, Type type) public override bool HasDefaultValue => _pb._defaultValue != DBNull.Value; public override object? DefaultValue => HasDefaultValue ? _pb._defaultValue : null; + + public override Type GetModifiedParameterType() => ParameterType; } } From 483b6cc5cc1b941c4c574ed22586094c5c9dc81f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Hei=C3=9F?= Date: Sat, 1 Nov 2025 17:26:50 +0100 Subject: [PATCH 11/13] Address review comments --- .../src/System/Reflection/ModifiedType.cs | 2 ++ .../System/Reflection/Emit/SignatureHelper.cs | 20 +++++++++---------- .../AssemblySaveTypeBuilderAPIsTests.cs | 4 ++-- 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/ModifiedType.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/ModifiedType.cs index 70ea199dc47368..89d5401a50b1bc 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/ModifiedType.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/ModifiedType.cs @@ -172,8 +172,10 @@ public override Type[] GetOptionalCustomModifiers() public override bool IsEnum => _unmodifiedType.IsEnum; protected override bool IsPrimitiveImpl() => _unmodifiedType.IsPrimitive; protected override bool IsByRefImpl() => _unmodifiedType.IsByRef; + public override bool IsGenericParameter => _unmodifiedType.IsGenericParameter; public override bool IsGenericTypeParameter => _unmodifiedType.IsGenericTypeParameter; public override bool IsGenericMethodParameter => _unmodifiedType.IsGenericMethodParameter; + public override int GenericParameterPosition => _unmodifiedType.GenericParameterPosition; protected override bool IsPointerImpl() => _unmodifiedType.IsPointer; protected override bool IsValueTypeImpl() => _unmodifiedType.IsValueType; protected override bool IsCOMObjectImpl() => _unmodifiedType.IsCOMObject; diff --git a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/SignatureHelper.cs b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/SignatureHelper.cs index 8c109d77736910..a3c3ec1a0a3250 100644 --- a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/SignatureHelper.cs +++ b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/SignatureHelper.cs @@ -123,9 +123,9 @@ private static void WriteReturnTypeCustomModifiers(CustomModifiersEncoder encode private static void WriteCustomModifiers(CustomModifiersEncoder encoder, Type[] customModifiers, bool isOptional, ModuleBuilderImpl module) { // GetOptionalCustomModifiers and GetRequiredCustomModifiers return modifiers in reverse order - Array.Reverse(customModifiers); - foreach (Type modifier in customModifiers) + for (int i = customModifiers.Length - 1; i >= 0; i--) { + Type modifier = customModifiers[i]; encoder.AddModifier(module.GetTypeHandle(modifier), isOptional); } } @@ -203,13 +203,13 @@ private static void WriteSignatureForType(SignatureTypeEncoder signature, Type t module.GetTypeHandle(type.GetGenericTypeDefinition()), genericArguments.Length, type.IsValueType); foreach (Type gType in genericArguments) { - if (gType.UnderlyingSystemType.IsGenericMethodParameter) + if (gType.IsGenericMethodParameter) { - encoder.AddArgument().GenericMethodTypeParameter(gType.UnderlyingSystemType.GenericParameterPosition); + encoder.AddArgument().GenericMethodTypeParameter(gType.GenericParameterPosition); } - else if (gType.UnderlyingSystemType.IsGenericParameter) + else if (gType.IsGenericParameter) { - encoder.AddArgument().GenericTypeParameter(gType.UnderlyingSystemType.GenericParameterPosition); + encoder.AddArgument().GenericTypeParameter(gType.GenericParameterPosition); } else { @@ -217,13 +217,13 @@ private static void WriteSignatureForType(SignatureTypeEncoder signature, Type t } } } - else if (type.UnderlyingSystemType.IsGenericMethodParameter) + else if (type.IsGenericMethodParameter) { - signature.GenericMethodTypeParameter(type.UnderlyingSystemType.GenericParameterPosition); + signature.GenericMethodTypeParameter(type.GenericParameterPosition); } - else if (type.UnderlyingSystemType.IsGenericParameter) + else if (type.IsGenericParameter) { - signature.GenericTypeParameter(type.UnderlyingSystemType.GenericParameterPosition); + signature.GenericTypeParameter(type.GenericParameterPosition); } else if (type.IsFunctionPointer) { diff --git a/src/libraries/System.Reflection.Emit/tests/PersistedAssemblyBuilder/AssemblySaveTypeBuilderAPIsTests.cs b/src/libraries/System.Reflection.Emit/tests/PersistedAssemblyBuilder/AssemblySaveTypeBuilderAPIsTests.cs index c3eff0b525b79a..8063964e4473b7 100644 --- a/src/libraries/System.Reflection.Emit/tests/PersistedAssemblyBuilder/AssemblySaveTypeBuilderAPIsTests.cs +++ b/src/libraries/System.Reflection.Emit/tests/PersistedAssemblyBuilder/AssemblySaveTypeBuilderAPIsTests.cs @@ -638,8 +638,8 @@ public void ReturnTypeAndParameterRequiredOptionalCustomModifiers() Assert.Equal(1, returnOptMods.Length); Assert.Equal(mlc.CoreAssembly.GetType(typeof(Version).FullName), returnOptMods[0]); Assert.Equal(cmodsReq1.Length, par0RequiredMods.Length); - Assert.Equal(mlc.CoreAssembly.GetType(cmodsReq1[1].FullName), par0RequiredMods[0]); - Assert.Equal(mlc.CoreAssembly.GetType(cmodsReq1[0].FullName), par0RequiredMods[1]); + Assert.Equal(mlc.CoreAssembly.GetType(cmodsReq1[0].FullName), par0RequiredMods[0]); + Assert.Equal(mlc.CoreAssembly.GetType(cmodsReq1[1].FullName), par0RequiredMods[1]); Assert.Equal(cmodsOpt1.Length, par0OptionalMods.Length); Assert.Equal(mlc.CoreAssembly.GetType(cmodsOpt1[0].FullName), par0OptionalMods[0]); Assert.Equal(cmodsReq2.Length, allModMethod.GetParameters()[1].GetRequiredCustomModifiers().Length); From 82a6f413e74667fc361cf6c9559624074fdfa5f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Hei=C3=9F?= Date: Sun, 2 Nov 2025 12:34:58 +0100 Subject: [PATCH 12/13] Move GetParameterTypes to MetadataSignatureHelper --- .../Reflection/Emit/ModuleBuilderImpl.cs | 19 +------------------ .../System/Reflection/Emit/SignatureHelper.cs | 19 ++++++++++++++++++- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/ModuleBuilderImpl.cs b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/ModuleBuilderImpl.cs index 2ce30d533701a2..e87fa61926efb9 100644 --- a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/ModuleBuilderImpl.cs +++ b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/ModuleBuilderImpl.cs @@ -794,7 +794,7 @@ private EntityHandle GetMethodReference(MethodInfo methodInfo, Type[] optionalPa } private BlobBuilder GetMethodSignature(MethodInfo method, Type[]? optionalParameterTypes) => - MetadataSignatureHelper.GetMethodSignature(this, ParameterTypes(method.GetParameters()), method.ReturnParameter.GetModifiedParameterType(), + MetadataSignatureHelper.GetMethodSignature(this, MetadataSignatureHelper.GetParameterTypes(method.GetParameters()), method.ReturnParameter.GetModifiedParameterType(), GetSignatureConvention(method.CallingConvention), method.GetGenericArguments().Length, !method.IsStatic, optionalParameterTypes); private BlobBuilder GetMethodArrayMethodSignature(ArrayMethod method) => MetadataSignatureHelper.GetMethodSignature( @@ -832,23 +832,6 @@ private MemberInfo GetOriginalMemberIfConstructedType(MemberInfo memberInfo) return memberInfo; } - internal static Type[] ParameterTypes(ParameterInfo[] parameterInfos) - { - if (parameterInfos.Length == 0) - { - return Type.EmptyTypes; - } - - Type[] parameterTypes = new Type[parameterInfos.Length]; - - for (int i = 0; i < parameterInfos.Length; i++) - { - parameterTypes[i] = parameterInfos[i].GetModifiedParameterType(); - } - - return parameterTypes; - } - private AssemblyReferenceHandle GetAssemblyReference(Assembly assembly) { if (!_assemblyReferences.TryGetValue(assembly, out var handle)) diff --git a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/SignatureHelper.cs b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/SignatureHelper.cs index a3c3ec1a0a3250..2ec00b90743525 100644 --- a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/SignatureHelper.cs +++ b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/SignatureHelper.cs @@ -48,7 +48,7 @@ internal static BlobBuilder GetConstructorSignature(ParameterInfo[]? parameters, retType.Void(); - WriteParametersSignature(module, ModuleBuilderImpl.ParameterTypes(parameters), parameterEncoder); + WriteParametersSignature(module, GetParameterTypes(parameters), parameterEncoder); return constructorSignature; } @@ -106,6 +106,23 @@ internal static BlobBuilder GetMethodSignature(ModuleBuilderImpl module, Type[]? return methodSignature; } + internal static Type[] GetParameterTypes(ParameterInfo[] parameterInfos) + { + if (parameterInfos.Length == 0) + { + return Type.EmptyTypes; + } + + Type[] parameterTypes = new Type[parameterInfos.Length]; + + for (int i = 0; i < parameterInfos.Length; i++) + { + parameterTypes[i] = parameterInfos[i].GetModifiedParameterType(); + } + + return parameterTypes; + } + private static void WriteReturnTypeCustomModifiers(CustomModifiersEncoder encoder, Type[]? requiredModifiers, Type[]? optionalModifiers, ModuleBuilderImpl module) { From c7a3c0c11c3a5fd7d3b64c5e4568924437cd90f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Hei=C3=9F?= Date: Sun, 2 Nov 2025 12:59:12 +0100 Subject: [PATCH 13/13] Disable ConsumeFunctionPointerMembers test on Mono --- .../PersistedAssemblyBuilder/AssemblySaveTypeBuilderTests.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libraries/System.Reflection.Emit/tests/PersistedAssemblyBuilder/AssemblySaveTypeBuilderTests.cs b/src/libraries/System.Reflection.Emit/tests/PersistedAssemblyBuilder/AssemblySaveTypeBuilderTests.cs index c57b19a2307cd6..5b7911bed07f88 100644 --- a/src/libraries/System.Reflection.Emit/tests/PersistedAssemblyBuilder/AssemblySaveTypeBuilderTests.cs +++ b/src/libraries/System.Reflection.Emit/tests/PersistedAssemblyBuilder/AssemblySaveTypeBuilderTests.cs @@ -864,6 +864,7 @@ public void SaveFunctionPointerFields() } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/2383", TestRuntimes.Mono)] public void ConsumeFunctionPointerMembers() { // public unsafe class Container