diff --git a/src/libraries/System.Runtime.Intrinsics/tests/System.Runtime.Intrinsics.Tests.csproj b/src/libraries/System.Runtime.Intrinsics/tests/System.Runtime.Intrinsics.Tests.csproj index e956491c0a63b1..5d98f157e174a3 100644 --- a/src/libraries/System.Runtime.Intrinsics/tests/System.Runtime.Intrinsics.Tests.csproj +++ b/src/libraries/System.Runtime.Intrinsics/tests/System.Runtime.Intrinsics.Tests.csproj @@ -13,6 +13,7 @@ + diff --git a/src/libraries/System.Runtime.Intrinsics/tests/Wasm/PackedSimdTests.cs b/src/libraries/System.Runtime.Intrinsics/tests/Wasm/PackedSimdTests.cs new file mode 100644 index 00000000000000..a53ce142c37cac --- /dev/null +++ b/src/libraries/System.Runtime.Intrinsics/tests/Wasm/PackedSimdTests.cs @@ -0,0 +1,447 @@ +using System.Diagnostics.CodeAnalysis; +using System.Numerics; +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.Wasm; +using System.Tests; +using Xunit; + +namespace System.Runtime.Intrinsics.Wasm.Tests +{ + [PlatformSpecific(TestPlatforms.Browser)] + public sealed class PackedSimdTests + { + [Fact] + public unsafe void BasicArithmeticTest() + { + var v1 = Vector128.Create(1, 2, 3, 4); + var v2 = Vector128.Create(5, 6, 7, 8); + + var addResult = PackedSimd.Add(v1, v2); + var subResult = PackedSimd.Subtract(v1, v2); + var mulResult = PackedSimd.Multiply(v1, v2); + + Assert.Equal(Vector128.Create(6, 8, 10, 12), addResult); + Assert.Equal(Vector128.Create(-4, -4, -4, -4), subResult); + Assert.Equal(Vector128.Create(5, 12, 21, 32), mulResult); + } + + [Fact] + public unsafe void BitwiseOperationsTest() + { + var v1 = Vector128.Create(0b1100, 0b1010, 0b1110, 0b1111); + var v2 = Vector128.Create(0b1010, 0b1100, 0b0011, 0b0101); + + var andResult = PackedSimd.And(v1, v2); + var orResult = PackedSimd.Or(v1, v2); + var xorResult = PackedSimd.Xor(v1, v2); + + Assert.Equal(Vector128.Create(0b1000, 0b1000, 0b0010, 0b0101), andResult); + Assert.Equal(Vector128.Create(0b1110, 0b1110, 0b1111, 0b1111), orResult); + Assert.Equal(Vector128.Create(0b0110, 0b0110, 0b1101, 0b1010), xorResult); + } + + [Fact] + public unsafe void ShiftOperationsTest() + { + var v = Vector128.Create(16, -16, 32, -32); + + var leftShift = PackedSimd.ShiftLeft(v, 2); + var rightShiftArith = PackedSimd.ShiftRightArithmetic(v, 2); + var rightShiftLogical = PackedSimd.ShiftRightLogical(v, 2); + + Assert.Equal(Vector128.Create(64, -64, 128, -128), leftShift); + Assert.Equal(Vector128.Create(4, -4, 8, -8), rightShiftArith); + Assert.Equal(Vector128.Create(4, 1073741820, 8, 1073741816), rightShiftLogical); + } + + [Fact] + public unsafe void ComparisonOperationsTest() + { + var v1 = Vector128.Create(1.0f, 2.0f, 3.0f, 4.0f); + var v2 = Vector128.Create(4.0f, 3.0f, 2.0f, 1.0f); + + var minResult = PackedSimd.Min(v1, v2); + var maxResult = PackedSimd.Max(v1, v2); + + Assert.Equal(Vector128.Create(1.0f, 2.0f, 2.0f, 1.0f), minResult); + Assert.Equal(Vector128.Create(4.0f, 3.0f, 3.0f, 4.0f), maxResult); + } + + [Fact] + public unsafe void FloatingPointOperationsTest() + { + var v = Vector128.Create(4.0f, 9.0f, 16.0f, 25.0f); + + var sqrtResult = PackedSimd.Sqrt(v); + var ceilResult = PackedSimd.Ceiling(v); + var floorResult = PackedSimd.Floor(v); + + Assert.Equal(Vector128.Create(2.0f, 3.0f, 4.0f, 5.0f), sqrtResult); + Assert.Equal(Vector128.Create(4.0f, 9.0f, 16.0f, 25.0f), ceilResult); + Assert.Equal(Vector128.Create(4.0f, 9.0f, 16.0f, 25.0f), floorResult); + } + + [Fact] + public unsafe void LoadStoreTest() + { + int[] values = new int[] { 1, 2, 3, 4 }; + fixed (int* ptr = values) + { + var loaded = PackedSimd.LoadVector128(ptr); + Assert.Equal(Vector128.Create(1, 2, 3, 4), loaded); + + int[] storeTarget = new int[4]; + fixed (int* storePtr = storeTarget) + { + PackedSimd.Store(storePtr, loaded); + Assert.Equal(values, storeTarget); + } + } + } + + [Fact] + public unsafe void ExtractInsertScalarTest() + { + var v = Vector128.Create(1, 2, 3, 4); + + int extracted = PackedSimd.ExtractScalar(v, 2); + Assert.Equal(3, extracted); + + var modified = PackedSimd.ReplaceScalar(v, 2, 10); + Assert.Equal(Vector128.Create(1, 2, 10, 4), modified); + } + + [Fact] + public unsafe void SaturatingArithmeticTest() + { + var v1 = Vector128.Create((byte)250, (byte)251, (byte)252, (byte)253, (byte)254, (byte)255, (byte)255, (byte)255, + (byte)250, (byte)251, (byte)252, (byte)253, (byte)254, (byte)255, (byte)255, (byte)255); + var v2 = Vector128.Create((byte)10, (byte)10, (byte)10, (byte)10, (byte)10, (byte)10, (byte)10, (byte)10, + (byte)10, (byte)10, (byte)10, (byte)10, (byte)10, (byte)10, (byte)10, (byte)10); + + var addSat = PackedSimd.AddSaturate(v1, v2); + var subSat = PackedSimd.SubtractSaturate(v1, v2); + + // Verify saturation at 255 for addition + Assert.Equal(Vector128.Create((byte)255, (byte)255, (byte)255, (byte)255, (byte)255, (byte)255, (byte)255, (byte)255, + (byte)255, (byte)255, (byte)255, (byte)255, (byte)255, (byte)255, (byte)255, (byte)255), addSat); + + // Verify expected subtraction results + Assert.Equal(Vector128.Create((byte)240, (byte)241, (byte)242, (byte)243, (byte)244, (byte)245, (byte)245, (byte)245, + (byte)240, (byte)241, (byte)242, (byte)243, (byte)244, (byte)245, (byte)245, (byte)245), subSat); + } + + [Fact] + public unsafe void WideningOperationsTest() + { + var v = Vector128.Create((short)1000, (short)2000, (short)3000, (short)4000, + (short)5000, (short)6000, (short)7000, (short)8000); + + var lowerWidened = PackedSimd.SignExtendWideningLower(v); + var upperWidened = PackedSimd.SignExtendWideningUpper(v); + + Assert.Equal(Vector128.Create(1000, 2000, 3000, 4000), lowerWidened); + Assert.Equal(Vector128.Create(5000, 6000, 7000, 8000), upperWidened); + } + + [Fact] + public unsafe void SwizzleTest() + { + var v = Vector128.Create((byte)1, (byte)2, (byte)3, (byte)4, (byte)5, (byte)6, (byte)7, (byte)8, + (byte)9, (byte)10, (byte)11, (byte)12, (byte)13, (byte)14, (byte)15, (byte)16); + var indices = Vector128.Create((byte)3, (byte)2, (byte)1, (byte)0, (byte)7, (byte)6, (byte)5, (byte)4, + (byte)11, (byte)10, (byte)9, (byte)8, (byte)15, (byte)14, (byte)13, (byte)12); + + var swizzled = PackedSimd.Swizzle(v, indices); + + Assert.Equal(Vector128.Create((byte)4, (byte)3, (byte)2, (byte)1, (byte)8, (byte)7, (byte)6, (byte)5, + (byte)12, (byte)11, (byte)10, (byte)9, (byte)16, (byte)15, (byte)14, (byte)13), swizzled); + } + + [Fact] + public unsafe void LoadScalarAndSplatTest() + { + int value = 42; + float fValue = 3.14f; + + int* intPtr = &value; + float* floatPtr = &fValue; + + var intSplat = PackedSimd.LoadScalarAndSplatVector128(intPtr); + var floatSplat = PackedSimd.LoadScalarAndSplatVector128(floatPtr); + + Assert.Equal(Vector128.Create(42, 42, 42, 42), intSplat); + Assert.Equal(Vector128.Create(3.14f, 3.14f, 3.14f, 3.14f), floatSplat); + } + + [Fact] + public unsafe void LoadWideningTest() + { + byte[] bytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 }; + fixed (byte* ptr = bytes) + { + var widened = PackedSimd.LoadWideningVector128(ptr); + Assert.Equal(Vector128.Create((ushort)1, (ushort)2, (ushort)3, (ushort)4, + (ushort)5, (ushort)6, (ushort)7, (ushort)8), widened); + } + } + + [Fact] + public unsafe void StoreSelectedScalarTest() + { + var v = Vector128.Create(1, 2, 3, 4); + int value = 0; + int* ptr = &value; + + PackedSimd.StoreSelectedScalar(ptr, v, 2); + Assert.Equal(3, value); + } + + [Fact] + public unsafe void LoadScalarAndInsertTest() + { + var v = Vector128.Create(1, 2, 3, 4); + int newValue = 42; + int* ptr = &newValue; + + var result = PackedSimd.LoadScalarAndInsert(ptr, v, 2); + Assert.Equal(Vector128.Create(1, 2, 42, 4), result); + } + + [Fact] + public unsafe void ConversionTest() + { + var intVector = Vector128.Create(1, 2, 3, 4); + var floatVector = Vector128.Create(1.5f, 2.5f, 3.5f, 4.5f); + var doubleVector = Vector128.Create(1.5, 2.5); + + var intToFloat = PackedSimd.ConvertToSingle(intVector); + var floatToDouble = PackedSimd.ConvertToDoubleLower(floatVector); + + Assert.Equal(Vector128.Create(1.0f, 2.0f, 3.0f, 4.0f), intToFloat); + Assert.Equal(Vector128.Create(1.5, 2.5), floatToDouble); + } + + [Fact] + public unsafe void AddPairwiseWideningTest() + { + var bytes = Vector128.Create((byte)1, (byte)2, (byte)3, (byte)4, + (byte)5, (byte)6, (byte)7, (byte)8, + (byte)9, (byte)10, (byte)11, (byte)12, + (byte)13, (byte)14, (byte)15, (byte)16); + + var widened = PackedSimd.AddPairwiseWidening(bytes); + + Assert.Equal(Vector128.Create((ushort)3, (ushort)7, (ushort)11, (ushort)15, + (ushort)19, (ushort)23, (ushort)27, (ushort)31), widened); + } + + [Fact] + public unsafe void MultiplyWideningTest() + { + var shorts = Vector128.Create((short)10, (short)20, (short)30, (short)40, + (short)50, (short)60, (short)70, (short)80); + var multiplier = Vector128.Create((short)2, (short)2, (short)2, (short)2, + (short)2, (short)2, (short)2, (short)2); + + var lowerResult = PackedSimd.MultiplyWideningLower(shorts, multiplier); + var upperResult = PackedSimd.MultiplyWideningUpper(shorts, multiplier); + + Assert.Equal(Vector128.Create(20, 40, 60, 80), lowerResult); + Assert.Equal(Vector128.Create(100, 120, 140, 160), upperResult); + } + + [Fact] + public unsafe void DotProductTest() + { + var v1 = Vector128.Create((short)1, (short)2, (short)3, (short)4, + (short)5, (short)6, (short)7, (short)8); + var v2 = Vector128.Create((short)2, (short)2, (short)2, (short)2, + (short)2, (short)2, (short)2, (short)2); + + var dot = PackedSimd.Dot(v1, v2); + + // Each pair of values is multiplied and added: + // (1*2 + 2*2) = 6 for first int + // (3*2 + 4*2) = 14 for second int + // (5*2 + 6*2) = 22 for third int + // (7*2 + 8*2) = 30 for fourth int + Assert.Equal(Vector128.Create(6, 14, 22, 30), dot); + } + + [Fact] + public unsafe void FloatingPointNegationTest() + { + var v = Vector128.Create(1.0f, -2.0f, 3.0f, -4.0f); + var d = Vector128.Create(1.0, -2.0); + + var negatedFloat = PackedSimd.Negate(v); + var negatedDouble = PackedSimd.Negate(d); + + Assert.Equal(Vector128.Create(-1.0f, 2.0f, -3.0f, 4.0f), negatedFloat); + Assert.Equal(Vector128.Create(-1.0, 2.0), negatedDouble); + } + + [Fact] + public unsafe void FloatingPointAbsTest() + { + var v = Vector128.Create(-1.0f, 2.0f, -3.0f, 4.0f); + var d = Vector128.Create(-1.0, 2.0); + + var absFloat = PackedSimd.Abs(v); + var absDouble = PackedSimd.Abs(d); + + Assert.Equal(Vector128.Create(1.0f, 2.0f, 3.0f, 4.0f), absFloat); + Assert.Equal(Vector128.Create(1.0, 2.0), absDouble); + } + + [Fact] + public unsafe void FloatingPointDivisionTest() + { + var v1 = Vector128.Create(2.0f, 4.0f, 6.0f, 8.0f); + var v2 = Vector128.Create(2.0f, 2.0f, 2.0f, 2.0f); + var d1 = Vector128.Create(2.0, 4.0); + var d2 = Vector128.Create(2.0, 2.0); + + var divFloat = PackedSimd.Divide(v1, v2); + var divDouble = PackedSimd.Divide(d1, d2); + + Assert.Equal(Vector128.Create(1.0f, 2.0f, 3.0f, 4.0f), divFloat); + Assert.Equal(Vector128.Create(1.0, 2.0), divDouble); + } + + [Fact] + public unsafe void IntegerAbsTest() + { + var bytes = Vector128.Create((sbyte)-1, (sbyte)2, (sbyte)-3, (sbyte)4, + (sbyte)-5, (sbyte)6, (sbyte)-7, (sbyte)8, + (sbyte)-9, (sbyte)10, (sbyte)-11, (sbyte)12, + (sbyte)-13, (sbyte)14, (sbyte)-15, (sbyte)16); + var shorts = Vector128.Create((short)-1, (short)2, (short)-3, (short)4, + (short)-5, (short)6, (short)-7, (short)8); + var ints = Vector128.Create(-1, 2, -3, 4); + + var absBytes = PackedSimd.Abs(bytes); + var absShorts = PackedSimd.Abs(shorts); + + Assert.Equal(Vector128.Create((sbyte)1, (sbyte)2, (sbyte)3, (sbyte)4, + (sbyte)5, (sbyte)6, (sbyte)7, (sbyte)8, + (sbyte)9, (sbyte)10, (sbyte)11, (sbyte)12, + (sbyte)13, (sbyte)14, (sbyte)15, (sbyte)16), absBytes); + Assert.Equal(Vector128.Create((short)1, (short)2, (short)3, (short)4, + (short)5, (short)6, (short)7, (short)8), absShorts); + } + + [Fact] + public unsafe void AverageRoundedTest() + { + var bytes1 = Vector128.Create((byte)1, (byte)3, (byte)5, (byte)7, + (byte)9, (byte)11, (byte)13, (byte)15, + (byte)17, (byte)19, (byte)21, (byte)23, + (byte)25, (byte)27, (byte)29, (byte)31); + var bytes2 = Vector128.Create((byte)3, (byte)5, (byte)7, (byte)9, + (byte)11, (byte)13, (byte)15, (byte)17, + (byte)19, (byte)21, (byte)23, (byte)25, + (byte)27, (byte)29, (byte)31, (byte)33); + + var avgBytes = PackedSimd.AverageRounded(bytes1, bytes2); + + // Average is rounded up: (a + b + 1) >> 1 + Assert.Equal(Vector128.Create((byte)2, (byte)4, (byte)6, (byte)8, + (byte)10, (byte)12, (byte)14, (byte)16, + (byte)18, (byte)20, (byte)22, (byte)24, + (byte)26, (byte)28, (byte)30, (byte)32), avgBytes); + } + + [Fact] + public unsafe void MinMaxSignedUnsignedTest() + { + var signedBytes = Vector128.Create((sbyte)-1, (sbyte)2, (sbyte)-3, (sbyte)4, + (sbyte)-5, (sbyte)6, (sbyte)-7, (sbyte)8, + (sbyte)-9, (sbyte)10, (sbyte)-11, (sbyte)12, + (sbyte)-13, (sbyte)14, (sbyte)-15, (sbyte)16); + + var unsignedBytes = Vector128.Create((byte)255, (byte)2, (byte)253, (byte)4, + (byte)251, (byte)6, (byte)249, (byte)8, + (byte)247, (byte)10, (byte)245, (byte)12, + (byte)243, (byte)14, (byte)241, (byte)16); + + var signedMin = PackedSimd.Min(signedBytes, signedBytes.WithElement(0, (sbyte)0)); + var unsignedMin = PackedSimd.Min(unsignedBytes, unsignedBytes.WithElement(0, (byte)0)); + + // Verify different comparison behavior for signed vs unsigned + Assert.Equal((sbyte)-1, signedMin.GetElement(0)); + Assert.Equal((byte)0, unsignedMin.GetElement(0)); + } + + [Fact] + public unsafe void LoadScalarAndSplatInfinityTest() + { + float fInf = float.PositiveInfinity; + double dInf = double.PositiveInfinity; + + float* fPtr = &fInf; + double* dPtr = &dInf; + + var floatSplat = PackedSimd.LoadScalarAndSplatVector128(fPtr); + var doubleSplat = PackedSimd.LoadScalarAndSplatVector128(dPtr); + + for (int i = 0; i < 4; i++) + { + Assert.True(float.IsPositiveInfinity(floatSplat.GetElement(i))); + } + + for (int i = 0; i < 2; i++) + { + Assert.True(double.IsPositiveInfinity(doubleSplat.GetElement(i))); + } + } + + [Fact] + public unsafe void FloatingPointTruncateTest() + { + var v1 = Vector128.Create(1.7f, -2.3f, 3.5f, -4.8f); + var d1 = Vector128.Create(1.7, -2.3); + + var truncFloat = PackedSimd.Truncate(v1); + var truncDouble = PackedSimd.Truncate(d1); + + Assert.Equal(Vector128.Create(1.0f, -2.0f, 3.0f, -4.0f), truncFloat); + Assert.Equal(Vector128.Create(1.0, -2.0), truncDouble); + } + + [Fact] + public unsafe void ComparisonWithNaNTest() + { + var v1 = Vector128.Create(1.0f, float.NaN, 3.0f, float.PositiveInfinity); + var v2 = Vector128.Create(float.NegativeInfinity, 2.0f, float.NaN, 4.0f); + + var minResult = PackedSimd.Min(v1, v2); + var maxResult = PackedSimd.Max(v1, v2); + + // IEEE 754 rules: if either operand is NaN, the result should be NaN + Assert.True(float.IsNaN(minResult.GetElement(1))); + Assert.True(float.IsNaN(maxResult.GetElement(2))); + Assert.Equal(float.NegativeInfinity, minResult.GetElement(0)); + Assert.Equal(float.PositiveInfinity, maxResult.GetElement(3)); + } + + [Fact] + public unsafe void NativeIntegerArithmeticTest() + { + var v1 = PackedSimd.Splat((nint)1); + var v2 = PackedSimd.Splat((nint)2); + + var addResult = PackedSimd.Add(v1, v2); + var subResult = PackedSimd.Subtract(v1, v2); + var mulResult = PackedSimd.Multiply(v1, v2); + + Assert.Equal(PackedSimd.Splat((nint)3), addResult); + Assert.Equal(PackedSimd.Splat((nint)(-1)), subResult); + Assert.Equal(PackedSimd.Splat((nint)2), mulResult); + } + } +} \ No newline at end of file diff --git a/src/mono/mono/mini/interp/interp-simd-intrins.def b/src/mono/mono/mini/interp/interp-simd-intrins.def index d88e543af23471..197b3c269d6612 100644 --- a/src/mono/mono/mini/interp/interp-simd-intrins.def +++ b/src/mono/mono/mini/interp/interp-simd-intrins.def @@ -351,7 +351,7 @@ INTERP_WASM_SIMD_INTRINSIC_V_V (ConvertToSingle, U4, wasm_f32x4_convert_u32x4, INTERP_WASM_SIMD_INTRINSIC_V_V (ConvertToSingle, R8, wasm_f32x4_demote_f64x2_zero, 0x5e) INTERP_WASM_SIMD_INTRINSIC_V_V (ConvertToDoubleLower, I4, wasm_f64x2_convert_low_i32x4, 0xfe) INTERP_WASM_SIMD_INTRINSIC_V_V (ConvertToDoubleLower, U4, wasm_f64x2_convert_low_u32x4, 0xff) -INTERP_WASM_SIMD_INTRINSIC_V_V (ConvertToDoubleLower, R8, wasm_f64x2_promote_low_f32x4, 0x5f) +INTERP_WASM_SIMD_INTRINSIC_V_V (ConvertToDoubleLower, R4, wasm_f64x2_promote_low_f32x4, 0x5f) INTERP_WASM_SIMD_INTRINSIC_V_V (ConvertToInt32Saturate, R4, wasm_i32x4_trunc_sat_f32x4, 0xf8) INTERP_WASM_SIMD_INTRINSIC_V_V (ConvertToUInt32Saturate, R4, wasm_u32x4_trunc_sat_f32x4, 0xf9) INTERP_WASM_SIMD_INTRINSIC_V_V (ConvertToInt32Saturate, R8, wasm_i32x4_trunc_sat_f64x2_zero, 0xfc) diff --git a/src/mono/mono/mini/interp/transform-simd.c b/src/mono/mono/mini/interp/transform-simd.c index c1d6b81019d02f..70b88cf0c148d0 100644 --- a/src/mono/mono/mini/interp/transform-simd.c +++ b/src/mono/mono/mini/interp/transform-simd.c @@ -779,6 +779,24 @@ emit_sn_vector4 (TransformData *td, MonoMethod *cmethod, MonoMethodSignature *cs } #if HOST_BROWSER +static MonoTypeEnum +resolve_native_size (MonoTypeEnum type) +{ + if (type == MONO_TYPE_I) +#if TARGET_SIZEOF_VOID_P == 4 + return MONO_TYPE_I4; +#else + return MONO_TYPE_I8; +#endif + else if (type == MONO_TYPE_U) +#if TARGET_SIZEOF_VOID_P == 4 + return MONO_TYPE_U4; +#else + return MONO_TYPE_U8; +#endif + return type; + +} #define PSIMD_ARGTYPE_I1 MONO_TYPE_I1 #define PSIMD_ARGTYPE_I2 MONO_TYPE_I2 @@ -803,6 +821,7 @@ emit_sn_vector4 (TransformData *td, MonoMethod *cmethod, MonoMethodSignature *cs static gboolean packedsimd_type_matches (MonoTypeEnum type, int expected_type) { + type = resolve_native_size (type); if (expected_type == PSIMD_ARGTYPE_ANY) return TRUE; else if (type == expected_type) @@ -906,6 +925,8 @@ lookup_packedsimd_intrinsic (const char *name, MonoType *arg1) arg_type = mono_class_get_context (vector_klass)->class_inst->type_argv [0]; } else if (arg1->type == MONO_TYPE_PTR) { arg_type = arg1->data.type; + } else if (MONO_TYPE_IS_VECTOR_PRIMITIVE(arg1)) { + arg_type = arg1; } else { // g_printf ("%s arg1 type was not pointer or simd type: %s\n", name, m_class_get_name (vector_klass)); return FALSE; @@ -989,7 +1010,13 @@ emit_sri_packedsimd (TransformData *td, MonoMethod *cmethod, MonoMethodSignature int id = lookup_intrins (sri_packedsimd_methods, sizeof (sri_packedsimd_methods), cmethod->name); // We don't early-out for an unrecognized method, we will generate an NIY later - MonoClass *vector_klass = mono_class_from_mono_type_internal (csignature->ret); + MonoClass *vector_klass = NULL; + if (csignature->ret->type == MONO_TYPE_VOID && csignature->param_count > 1 && mono_type_is_pointer (csignature->params [0])) { + // The Store* methods have a more complicated signature + vector_klass = mono_class_from_mono_type_internal (csignature->params [1]); + } else { + vector_klass = mono_class_from_mono_type_internal (csignature->ret); + } MonoTypeEnum atype; int vector_size = -1, arg_size, scalar_arg;