diff --git a/src/coreclr/tools/Common/Compiler/NativeAotNameMangler.cs b/src/coreclr/tools/Common/Compiler/NativeAotNameMangler.cs index 65e58642acaf45..dcd464d5753d5a 100644 --- a/src/coreclr/tools/Common/Compiler/NativeAotNameMangler.cs +++ b/src/coreclr/tools/Common/Compiler/NativeAotNameMangler.cs @@ -303,9 +303,8 @@ private string ComputeMangledTypeName(TypeDesc type) mangledName = GetMangledTypeName(((PointerType)type).ParameterType) + NestMangledName("Pointer"); break; case TypeFlags.FunctionPointer: - // TODO: need to also encode calling convention (or all modopts?) var fnPtrType = (FunctionPointerType)type; - mangledName = "__FnPtr" + EnterNameScopeSequence; + mangledName = "__FnPtr_" + ((int)fnPtrType.Signature.Flags).ToString("X2") + EnterNameScopeSequence; mangledName += GetMangledTypeName(fnPtrType.Signature.ReturnType); mangledName += EnterNameScopeSequence; diff --git a/src/mono/mono/metadata/class.c b/src/mono/mono/metadata/class.c index 9ac6c35553bbd7..dc72646333f7ff 100644 --- a/src/mono/mono/metadata/class.c +++ b/src/mono/mono/metadata/class.c @@ -4218,11 +4218,11 @@ mono_class_is_assignable_from_general (MonoClass *klass, MonoClass *oklass, gboo } if (m_class_get_byval_arg (klass)->type == MONO_TYPE_FNPTR) { - /* - * if both klass and oklass are fnptr, and they're equal, we would have returned at the - * beginning. - */ - /* Is this right? or do we need to look at signature compatibility? */ + if (mono_metadata_signature_equal (klass_byval_arg->data.method, oklass_byval_arg->data.method)) { + *result = TRUE; + return; + } + *result = FALSE; return; } diff --git a/src/mono/mono/metadata/marshal.c b/src/mono/mono/metadata/marshal.c index 6caac8e640b333..f7262ee0dff8d4 100644 --- a/src/mono/mono/metadata/marshal.c +++ b/src/mono/mono/metadata/marshal.c @@ -4618,6 +4618,8 @@ is_monomorphic_array (MonoClass *klass) return FALSE; element_class = m_class_get_element_class (klass); + if (m_class_get_byval_arg (element_class)->type == MONO_TYPE_FNPTR) + return FALSE; return mono_class_is_sealed (element_class) || m_class_is_valuetype (element_class); } diff --git a/src/tests/Loader/classloader/Casting/Functionpointer.cs b/src/tests/Loader/classloader/Casting/Functionpointer.cs new file mode 100644 index 00000000000000..95d7bf33b1303c --- /dev/null +++ b/src/tests/Loader/classloader/Casting/Functionpointer.cs @@ -0,0 +1,46 @@ +using System; +using System.Runtime.InteropServices; + +namespace TestFunctionPointer +{ + unsafe class TestThings + { + public static delegate* managed[][] Functions = { + new delegate* managed[] + { + &Function, + }, + }; + + public static int Function() => 100; + + public static delegate* unmanaged[][] Functions1 = { + new delegate* unmanaged[] + { + &Function1, + }, + }; + + [UnmanagedCallersOnly] + public static int Function1() => 100; + + public static delegate* managed[][] Functions2 = { + new delegate* managed[] + { + &Function2, + }, + }; + + public static int Function2(int a) { + return a; + } + } + + unsafe class Program + { + public static int Main() + { + return TestThings.Functions2[0][0](TestThings.Functions[0][0]()); + } + } +} \ No newline at end of file diff --git a/src/tests/Loader/classloader/Casting/Functionpointer.csproj b/src/tests/Loader/classloader/Casting/Functionpointer.csproj new file mode 100644 index 00000000000000..51f7075c49c815 --- /dev/null +++ b/src/tests/Loader/classloader/Casting/Functionpointer.csproj @@ -0,0 +1,9 @@ + + + Exe + true + + + + + \ No newline at end of file