Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion src/coreclr/vm/callconvbuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -550,7 +550,7 @@ bool CallConv::TryGetCallingConventionFromUnmanagedCallersOnly(_In_ MethodDesc*

// UnmanagedCallersOnly each
// have optional named arguments.
CaNamedArg namedArgs[2];
CaNamedArg namedArgs[3];

// For the UnmanagedCallersOnly scenario.
CaType caCallConvs;
Expand All @@ -563,6 +563,9 @@ bool CallConv::TryGetCallingConventionFromUnmanagedCallersOnly(_In_ MethodDesc*
CaTypeCtor caEntryPoint(SERIALIZATION_TYPE_STRING);
namedArgs[1].Init("EntryPoint", SERIALIZATION_TYPE_STRING, caEntryPoint);

CaTypeCtor caAssociatedSourceType(SERIALIZATION_TYPE_TYPE);
namedArgs[2].Init("AssociatedSourceType", SERIALIZATION_TYPE_TYPE, caAssociatedSourceType);

InlineFactory<SArray<CaValue>, 4> caValueArrayFactory;
Assembly* assembly = pMD->GetLoaderModule()->GetAssembly();
IfFailThrow(CustomAttribute::ParseArgumentValues(
Expand Down
9 changes: 5 additions & 4 deletions src/mono/mono/metadata/marshal.c
Original file line number Diff line number Diff line change
Expand Up @@ -3474,17 +3474,18 @@ mono_marshal_set_callconv_from_unmanaged_callers_only_attribute (MonoMethod *met
}

if (attr != NULL) {
MonoDecodeCustomAttr *decoded_args = mono_reflection_create_custom_attr_data_args_noalloc (mono_defaults.corlib, attr->ctor, attr->data, attr->data_size, error);
MonoDecodeCustomAttr *decoded_args = mono_reflection_create_custom_attr_data_args_noalloc (m_class_get_image (method->klass), attr->ctor, attr->data, attr->data_size, error);
mono_error_assert_ok (error);
for (int i = 0; i < decoded_args->named_args_num; ++i) {
if (decoded_args->named_args_info [i].field && !strcmp (decoded_args->named_args_info [i].field->name, "CallConvs")) {
g_assertf(decoded_args->named_args_info [i].field->type->type == MONO_TYPE_SZARRAY, "UnmanagedCallersOnlyAttribute parameter %s must be an array, specified for method %s", decoded_args->named_args_info [i].field->name, method->name);
g_assertf (decoded_args->named_args_info [i].field->type->type == MONO_TYPE_SZARRAY, "Expected UnmanagedCallersOnlyAttribute field %s to be SZARRAY type, specified for method %s. This indicates a malformed attribute or incorrect usage pattern.", decoded_args->named_args_info [i].field->name, method->name);
MonoCustomAttrValueArray *calling_conventions = decoded_args->named_args[i]->value.array;
if (calling_conventions->len > 0) {
if (calling_conventions->len > 1)
g_warning ("Multiple calling conventions are not supported for UnmanagedCallersOnlyAttribute parameter %s, specified for method %s. Only the first calling convention will be taken into account", decoded_args->named_args_info [i].field->name, method->name);
g_warning ("Multiple calling conventions are not supported for UnmanagedCallersOnlyAttribute field %s, specified for method %s. Only the first calling convention will be taken into account", decoded_args->named_args_info [i].field->name, method->name);
// TODO: Support multiple conventions?
MonoType* calling_convention = (MonoType*)calling_conventions->values[0].value.primitive;
// System.Type values are stored in the primitive union member by load_cattr_value_noalloc.
MonoType *calling_convention = (MonoType*)calling_conventions->values[0].value.primitive;
mono_marshal_set_signature_callconv_from_attribute (csig, calling_convention, error);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@ public static int ManagedDoubleCallback(int n)
return DoubleImpl(n);
}

[UnmanagedCallersOnly(AssociatedSourceType = typeof(UnmanagedCallersOnlyBasicTest))]
public static int ManagedDoubleCallback_AssociatedSourceType(int n)
{
return DoubleImpl(n);
}

[ActiveIssue("https://github.com/dotnet/runtime/issues/64127", typeof(PlatformDetection), nameof(PlatformDetection.PlatformDoesNotSupportNativeTestAssets))]
[ActiveIssue("Needs coreclr build", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoFULLAOT))]
[ActiveIssue("needs triage", TestPlatforms.Android)]
Expand All @@ -60,7 +66,21 @@ public static void TestUnmanagedCallersOnlyValid()
Assert.Equal(expected, UnmanagedCallersOnlyDll.CallManagedProc((IntPtr)(delegate* unmanaged<int, int>)&ManagedDoubleCallback, n));
}

[UnmanagedCallersOnly(CallConvs = [typeof(CallConvStdcall)])]
[ActiveIssue("https://github.com/dotnet/runtime/issues/64127", typeof(PlatformDetection), nameof(PlatformDetection.PlatformDoesNotSupportNativeTestAssets))]
[ActiveIssue("Needs coreclr build", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoFULLAOT))]
[ActiveIssue("needs triage", TestPlatforms.Android)]
[ActiveIssue("needs triage", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)]
[Fact]
public static void TestUnmanagedCallersOnlyValid_AssociatedSourceType()
{
Console.WriteLine($"Running {nameof(TestUnmanagedCallersOnlyValid_AssociatedSourceType)}...");

int n = 12345;
int expected = DoubleImpl(n);
Assert.Equal(expected, ((delegate* unmanaged<int, int>)&ManagedDoubleCallback_AssociatedSourceType)(n));
}

[UnmanagedCallersOnly(CallConvs = [typeof(CallConvStdcall)])]
public static int ManagedDoubleCallback_Stdcall(int n)
{
return DoubleImpl(n);
Expand Down
Loading