Skip to content
3 changes: 3 additions & 0 deletions src/coreclr/vm/dllimport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3316,8 +3316,11 @@ BOOL NDirect::MarshalingRequired(
FALLTHROUGH;

case ELEMENT_TYPE_VALUETYPE:
case ELEMENT_TYPE_GENERICINST:
{
TypeHandle hndArgType = arg.GetTypeHandleThrowing(pModule, &emptyTypeContext);
if(!hndArgType.IsValueType())
return true;

if (hndArgType.GetMethodTable()->IsInt128OrHasInt128Fields())
{
Expand Down
74 changes: 73 additions & 1 deletion src/tests/Interop/UnmanagedCallersOnly/InvalidCallbacks.il
Original file line number Diff line number Diff line change
Expand Up @@ -240,4 +240,76 @@
call instance void [System.Runtime]System.Object::.ctor()
ret
}
}
}

.class public sequential ansi sealed beforefieldinit InvalidCSharp.MaybeBlittable`1<T>
extends [System.Runtime]System.ValueType
{
// Fields
.field private !T Value
}

.class public auto ansi sealed beforefieldinit InvalidCSharp.NotBlittable`1<T>
extends [System.Runtime]System.Object
{
// Fields
.field private !T Value
// Methods
.method public hidebysig specialname rtspecialname
instance void .ctor () cil managed
{
// Method begins at RVA 0x20a0
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [System.Runtime]System.Object::.ctor()
IL_0006: ret
}
}

.class public auto ansi beforefieldinit InvalidCSharp.InvalidGenericUnmanagedCallersOnlyParameters
extends [System.Runtime]System.Object
{
.method public hidebysig specialname rtspecialname
instance void .ctor () cil managed
{
.maxstack 8
ldarg.0
call instance void [System.Runtime]System.Object::.ctor()
ret
}

.method public hidebysig static
int32 GenericClass (
class InvalidCSharp.NotBlittable`1<int32> param
) cil managed
{
.custom instance void [System.Runtime.InteropServices]System.Runtime.InteropServices.UnmanagedCallersOnlyAttribute::.ctor() = (
01 00 00 00
)
// Method begins at RVA 0x24c4
// Header size: 1
// Code size: 2 (0x2)
.maxstack 8

IL_0000: ldc.i4.0
IL_0001: ret
}

.method public hidebysig static
int32 GenericStructWithObjectField (
valuetype InvalidCSharp.MaybeBlittable`1<object> param
) cil managed
{
.custom instance void [System.Runtime.InteropServices]System.Runtime.InteropServices.UnmanagedCallersOnlyAttribute::.ctor() = (
01 00 00 00
)
// Method begins at RVA 0x24c4
// Header size: 1
// Code size: 2 (0x2)
.maxstack 8

IL_0000: ldc.i4.0
IL_0001: ret
}
}
24 changes: 24 additions & 0 deletions src/tests/Interop/UnmanagedCallersOnly/UnmanagedCallersOnlyTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ public static int Main(string[] args)
NegativeTest_FromInstantiatedGenericClass();
TestUnmanagedCallersOnlyViaUnmanagedCalli();
TestPInvokeMarkedWithUnmanagedCallersOnly();
TestUnmanagedCallersOnlyWithGeneric();

// Exception handling is only supported on CoreCLR Windows.
if (TestLibrary.Utilities.IsWindows && !TestLibrary.Utilities.IsMonoRuntime)
Expand Down Expand Up @@ -217,4 +218,27 @@ public static void TestPInvokeMarkedWithUnmanagedCallersOnly()
int n = 1234;
Assert.Throws<NotSupportedException>(() => ((delegate* unmanaged<int, int>)&CallingUnmanagedCallersOnlyDirectly.PInvokeMarkedWithUnmanagedCallersOnly)(n));
}

public static void TestUnmanagedCallersOnlyWithGeneric()
{
Assert.Equal(0, ((delegate* unmanaged<Blittable<nint>, int>)&BlittableGenericStruct)(new Blittable<nint>()));

Assert.Equal(0, ((delegate* unmanaged<MaybeBlittable<nint>, int>)&MaybeBlittableGenericStruct)(new MaybeBlittable<nint>()));

Assert.Throws<InvalidProgramException> (() => ((delegate* unmanaged<NotBlittable<int>, int>)&InvalidGenericUnmanagedCallersOnlyParameters.GenericClass)(new NotBlittable<int>()));

Assert.Throws<InvalidProgramException> (() => ((delegate* unmanaged<MaybeBlittable<object>, int>)&InvalidGenericUnmanagedCallersOnlyParameters.GenericStructWithObjectField)(new MaybeBlittable<object>()));
}

internal struct Blittable<T> where T : unmanaged
{
T Value;
}


[UnmanagedCallersOnly]
internal static int BlittableGenericStruct(Blittable<nint> param) => 0;

[UnmanagedCallersOnly]
internal static int MaybeBlittableGenericStruct(MaybeBlittable<nint> param) => 0;
}