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.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/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 26d43dbaa1083e..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 @@ -184,7 +184,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; @@ -690,6 +691,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 +743,7 @@ private EntityHandle GetMemberReferenceHandle(MemberInfo memberInfo) declaringType = declaringType.MakeGenericType(declaringType.GetGenericArguments()); } - Type fieldType = ((FieldInfo)GetOriginalMemberIfConstructedType(field)).FieldType; + Type fieldType = ((FieldInfo)GetOriginalMemberIfConstructedType(field)).GetModifiedFieldType(); memberHandle = AddMemberReference(field.Name, GetTypeHandle(declaringType), MetadataSignatureHelper.GetFieldSignature(fieldType, field.GetRequiredCustomModifiers(), field.GetOptionalCustomModifiers(), this)); @@ -791,7 +794,7 @@ private EntityHandle GetMethodReference(MethodInfo methodInfo, Type[] optionalPa } private BlobBuilder GetMethodSignature(MethodInfo method, Type[]? optionalParameterTypes) => - MetadataSignatureHelper.GetMethodSignature(this, ParameterTypes(method.GetParameters()), method.ReturnType, + 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( @@ -829,23 +832,6 @@ private MemberInfo GetOriginalMemberIfConstructedType(MemberInfo memberInfo) return memberInfo; } - private 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].ParameterType; - } - - return parameterTypes; - } - private AssemblyReferenceHandle GetAssemblyReference(Assembly assembly) { if (!_assemblyReferences.TryGetValue(assembly, out var handle)) @@ -861,7 +847,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/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; } } 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..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, Array.ConvertAll(parameters, p => p.ParameterType), 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) { @@ -122,8 +139,10 @@ private static void WriteReturnTypeCustomModifiers(CustomModifiersEncoder encode private static void WriteCustomModifiers(CustomModifiersEncoder encoder, Type[] customModifiers, bool isOptional, ModuleBuilderImpl module) { - foreach (Type modifier in customModifiers) + // GetOptionalCustomModifiers and GetRequiredCustomModifiers return modifiers in reverse order + for (int i = customModifiers.Length - 1; i >= 0; i--) { + Type modifier = customModifiers[i]; encoder.AddModifier(module.GetTypeHandle(modifier), isOptional); } } @@ -295,6 +314,7 @@ private static void WriteSignatureForFunctionPointerType(SignatureTypeEncoder si private static void WriteSimpleSignature(SignatureTypeEncoder signature, Type type, ModuleBuilderImpl module) { + type = type.UnderlyingSystemType; CoreTypeId? typeId = module.GetTypeIdFromCoreTypes(type); switch (typeId) diff --git a/src/libraries/System.Reflection.Emit/tests/PersistedAssemblyBuilder/AssemblySaveTypeBuilderAPIsTests.cs b/src/libraries/System.Reflection.Emit/tests/PersistedAssemblyBuilder/AssemblySaveTypeBuilderAPIsTests.cs index d9d1e1e50269b5..8063964e4473b7 100644 --- a/src/libraries/System.Reflection.Emit/tests/PersistedAssemblyBuilder/AssemblySaveTypeBuilderAPIsTests.cs +++ b/src/libraries/System.Reflection.Emit/tests/PersistedAssemblyBuilder/AssemblySaveTypeBuilderAPIsTests.cs @@ -633,13 +633,13 @@ 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); - 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); diff --git a/src/libraries/System.Reflection.Emit/tests/PersistedAssemblyBuilder/AssemblySaveTypeBuilderTests.cs b/src/libraries/System.Reflection.Emit/tests/PersistedAssemblyBuilder/AssemblySaveTypeBuilderTests.cs index 4645dae1b7a92c..5b7911bed07f88 100644 --- a/src/libraries/System.Reflection.Emit/tests/PersistedAssemblyBuilder/AssemblySaveTypeBuilderTests.cs +++ b/src/libraries/System.Reflection.Emit/tests/PersistedAssemblyBuilder/AssemblySaveTypeBuilderTests.cs @@ -864,7 +864,8 @@ public void SaveFunctionPointerFields() } [Fact] - public void ConsumeFunctionPointerFields() + [ActiveIssue("https://github.com/dotnet/runtime/issues/2383", TestRuntimes.Mono)] + public void ConsumeFunctionPointerMembers() { // public unsafe class Container // { @@ -915,16 +916,29 @@ 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.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")); + 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); + 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); - // 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 +1003,24 @@ 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 List*[]> field5; + + 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; + } + + public unsafe class GenericClassWithFunctionPointerMembers + { + public static delegate* unmanaged[Cdecl] Field; + public static delegate* unmanaged[Fastcall, MemberFunction] Method() => null; } }