Skip to content
Merged
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
18 changes: 16 additions & 2 deletions src/mono/mono/mini/interp/transform.c
Original file line number Diff line number Diff line change
Expand Up @@ -2886,8 +2886,22 @@ interp_type_as_ptr (MonoType *tp)
return TRUE;
if ((tp)->type == MONO_TYPE_CHAR)
return TRUE;
if ((tp)->type == MONO_TYPE_VALUETYPE && m_class_is_enumtype (m_type_data_get_klass_unchecked (tp)))
return TRUE;
if ((tp)->type == MONO_TYPE_VALUETYPE) {
MonoClass *tp_klass = m_type_data_get_klass_unchecked (tp);
if (m_class_is_enumtype (tp_klass)) {
/*
* A 64-bit enum (e.g. 'enum : ulong') must not be treated as a pointer-sized icall
* argument on 32-bit targets such as wasm32: it would otherwise be passed through
* do_icall's gpointer signature and cause a native call_indirect signature mismatch.
* Defer to the underlying type, which is width-guarded, for those cases; enums with
* a smaller underlying type keep their existing classification.
*/
MonoType *base_type = mono_class_enum_basetype_internal (tp_klass);
if (base_type && (base_type->type == MONO_TYPE_I8 || base_type->type == MONO_TYPE_U8))
return interp_type_as_ptr (base_type);
return TRUE;
}
}
if (is_scalar_vtype (tp))
return TRUE;
return FALSE;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -408,6 +408,9 @@ private async Task EnsureWasmAbiRulesAreFollowed(Configuration config, bool aot)
Assert.Contains(result.TestOutput, m => m.Contains("iares[0]=32"));
Assert.Contains(result.TestOutput, m => m.Contains("iares[1]=2"));
Assert.Contains("fares.elements[1]=2", result.TestOutput);
// https://github.com/dotnet/runtime/issues/112262: 64-bit enum pinvoke args
Assert.Contains("eu (eu)=18374966859414961921", result.TestOutput);
Assert.Contains("ei (ei)=-2", result.TestOutput);
}

[Theory]
Expand Down
17 changes: 17 additions & 0 deletions src/mono/wasm/testassets/EntryPoints/PInvoke/AbiRules.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ public struct MyInlineArray {
public int element0;
}

public enum U64Enum : ulong { A = 0, B = 0xFF00FF00FF00FF00UL }
public enum I64Enum : long { A = 0, B = -3 }

public class Test
{
public static unsafe int Main(string[] argv)
Expand Down Expand Up @@ -66,6 +69,14 @@ public static unsafe int Main(string[] argv)
var fares = accept_and_return_fixedarray(fa);
Console.WriteLine("TestOutput -> fares.elements[1]=" + fares.elements[1]);

// Regression test for https://github.com/dotnet/runtime/issues/112262: a pinvoke
// with a 64-bit enum argument must not be routed through the pointer-sized fast
// icall path on wasm, otherwise the native call traps with a signature mismatch.
var euRes = direct_enum_u64(U64Enum.B);
Console.WriteLine("TestOutput -> eu (eu)=" + (ulong)euRes);
var eiRes = direct_enum_i64(I64Enum.B);
Console.WriteLine("TestOutput -> ei (ei)=" + (long)eiRes);

int exitCode = (int)res.Value;
return exitCode;
}
Expand Down Expand Up @@ -104,4 +115,10 @@ public static unsafe MyInlineArray InlineArrayTest2 (MyInlineArray ia) {

[DllImport("wasm-abi", EntryPoint="accept_and_return_inlinearray")]
public static extern MyInlineArray accept_and_return_inlinearray(MyInlineArray arg);

[DllImport("wasm-abi", EntryPoint="accept_and_return_ulong")]
public static extern U64Enum direct_enum_u64(U64Enum arg);

[DllImport("wasm-abi", EntryPoint="accept_and_return_long")]
public static extern I64Enum direct_enum_i64(I64Enum arg);
}
10 changes: 10 additions & 0 deletions src/mono/wasm/testassets/native-libs/wasm-abi.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,3 +69,13 @@ MyInlineArray accept_and_return_inlinearray (MyInlineArray arg) {
MyInlineArray accept_and_return_fixedarray (MyInlineArray arg) {
return accept_and_return_inlinearray (arg);
}

// Regression coverage for https://github.com/dotnet/runtime/issues/112262:
// a pinvoke whose argument is a 64-bit enum must be passed as a real i64 on wasm.
unsigned long long accept_and_return_ulong (unsigned long long arg) {
return arg + 1;
}

long long accept_and_return_long (long long arg) {
return arg + 1;
}
Loading