From dd4388c801e2fb6104a603cad0ab439d4053ae09 Mon Sep 17 00:00:00 2001 From: Sejong OH Date: Mon, 18 Apr 2016 03:31:33 -0700 Subject: [PATCH] Vector3 Interop tests The native type of Vector3 is struct {float x,y,z} whose size is 12 bytes. RyuJit uses 16-byte register or stack location to store a Vector3 variable with the assumptions below. New testcases are added to check whether RyuJit properly handle interop cases. RyuJIt back-end makes two assumptions about Vector3 types. Assumption1: Vector3 type args passed in registers or on stack is rounded to POINTER_SIZE and hence on 64-bit targets it can be read/written as if it were TYP_SIMD16. Assumption2: Vector3 args passed in registers (e.g. unix) or on stack have their upper 4-bytes being zero. Similarly Vector3 return type value returned from a method will have its upper 4-bytes zeroed out. --- tests/src/JIT/SIMD/CMakeLists.txt | 10 + tests/src/JIT/SIMD/Vector3Interop.cs | 339 ++++++++++++++++++++++++++++ tests/src/JIT/SIMD/Vector3Interop_r.csproj | 53 +++++ tests/src/JIT/SIMD/Vector3Interop_ro.csproj | 53 +++++ tests/src/JIT/SIMD/Vector3TestNative.cpp | 281 +++++++++++++++++++++++ tests/src/JIT/SIMD/project.json | 1 + 6 files changed, 737 insertions(+) create mode 100755 tests/src/JIT/SIMD/CMakeLists.txt create mode 100755 tests/src/JIT/SIMD/Vector3Interop.cs create mode 100644 tests/src/JIT/SIMD/Vector3Interop_r.csproj create mode 100644 tests/src/JIT/SIMD/Vector3Interop_ro.csproj create mode 100755 tests/src/JIT/SIMD/Vector3TestNative.cpp diff --git a/tests/src/JIT/SIMD/CMakeLists.txt b/tests/src/JIT/SIMD/CMakeLists.txt new file mode 100755 index 0000000..555703b --- /dev/null +++ b/tests/src/JIT/SIMD/CMakeLists.txt @@ -0,0 +1,10 @@ +cmake_minimum_required (VERSION 2.6) +project (Vector3TestNative) +include_directories(${INC_PLATFORM_DIR}) +set(SOURCES Vector3TestNative.cpp ) + +# add the executable +add_library (Vector3TestNative SHARED ${SOURCES}) + +# add the install targets +install (TARGETS Vector3TestNative DESTINATION bin) diff --git a/tests/src/JIT/SIMD/Vector3Interop.cs b/tests/src/JIT/SIMD/Vector3Interop.cs new file mode 100755 index 0000000..7ef77cd --- /dev/null +++ b/tests/src/JIT/SIMD/Vector3Interop.cs @@ -0,0 +1,339 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Diagnostics; +using System.Numerics; +using System.Runtime.InteropServices; +using System.Text; + + +public struct DT +{ + public Vector3 a; + public Vector3 b; +}; + +[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] +public struct ComplexDT +{ + public int iv; + public DT vecs; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst=256)] public string str; + public Vector3 v3; +}; + +class PInvokeTest +{ + [DllImport(@"Vector3TestNative", CallingConvention = CallingConvention.StdCall)] + public static extern int nativeCall_PInvoke_CheckVector3Size(); + + [DllImport(@"Vector3TestNative", CallingConvention = CallingConvention.StdCall)] + public static extern float nativeCall_PInvoke_Vector3Arg( + int i, + Vector3 v1, + [MarshalAs(UnmanagedType.LPStr)] string s, + Vector3 v2); + + [DllImport(@"Vector3TestNative", CallingConvention = CallingConvention.StdCall)] + public static extern Vector3 nativeCall_PInvoke_Vector3Ret(); + + [DllImport(@"Vector3TestNative", CallingConvention = CallingConvention.StdCall)] + public static extern float nativeCall_PInvoke_Vector3Array(Vector3[] v_array); + + [DllImport(@"Vector3TestNative", CallingConvention = CallingConvention.StdCall)] + public static extern DT nativeCall_PInvoke_Vector3InStruct(DT d); + + [DllImport(@"Vector3TestNative", CallingConvention = CallingConvention.StdCall)] + public static extern void nativeCall_PInvoke_Vector3InComplexStruct(ref ComplexDT cdt); + + public static bool test() + { + + // Expected return value is 12 bytes. + if (nativeCall_PInvoke_CheckVector3Size() != 12) + { + Console.WriteLine("The size of native Vector3 type is not 12 bytes"); + return false; + } + + { + int iv = 123; + Vector3 v1 = new Vector3(1,2,3); + string str = "abcdefg"; + Vector3 v2 = new Vector3(10,11,12); + // Expected return value = 1 + 2 + 3 + 10 + 11 + 12 = 39 + if (nativeCall_PInvoke_Vector3Arg(iv, v1, str, v2) != 39) + { + Console.Write("PInvoke Vector3Arg test failed\n"); + return false; + } + } + + // JIT crashes with this testcase. + // Disabled temporarily. + // { + // // Expected return value = 1 + 2 + 3 = 6 + // Vector3 ret = nativeCall_PInvoke_Vector3Ret(); + // float sum = ret.X + ret.Y + ret.Z; + // if (sum != 6) { + // Console.WriteLine("PInvoke Vector3Ret test failed"); + // return false; + // } + // } + + + { + Vector3[] v3_array = new Vector3[2]; + v3_array[0].X = 1; v3_array[0].Y = 2; v3_array[0].Z = 3; + v3_array[1].X = 5; v3_array[1].Y = 6; v3_array[1].Z = 7; + // Expected resutn value = 1 + 2 + 3 + 5 + 6 + 7 = 24 + if (nativeCall_PInvoke_Vector3Array(v3_array) != 24) + { + Console.WriteLine("PInvoke Vector3Array test failed"); + return false; + } + } + + { + DT data = new DT(); + data.a = new Vector3(1,2,3); + data.b = new Vector3(5,6,7); + DT ret = nativeCall_PInvoke_Vector3InStruct(data); + // Expected return value = 2 + 3 + 4 + 6 + 7 + 8 = 30 + float sum = ret.a.X + ret.a.Y + ret.a.Z + ret.b.X + ret.b.Y + ret.b.Z; + if (sum != 30) + { + Console.WriteLine("PInvoke Vector3InStruct test failed"); + return false; + } + } + + { + ComplexDT cdt = new ComplexDT(); + cdt.iv = 99; + cdt.str = "arg_string"; + cdt.vecs.a = new Vector3(1,2,3); + cdt.vecs.b = new Vector3(5,6,7); + cdt.v3 = new Vector3(10, 20, 30); + + nativeCall_PInvoke_Vector3InComplexStruct(ref cdt); + + Console.WriteLine(" Managed ival: {0}", cdt.iv); + Console.WriteLine(" Managed Vector3 v1: ({0} {1} {2})", cdt.vecs.a.X, cdt.vecs.a.Y, cdt.vecs.a.Z); + Console.WriteLine(" Managed Vector3 v2: ({0} {1} {2})", cdt.vecs.b.X, cdt.vecs.b.Y, cdt.vecs.b.Z); + Console.WriteLine(" Managed Vector3 v3: ({0} {1} {2})", cdt.v3.X, cdt.v3.Y, cdt.v3.Z); + Console.WriteLine(" Managed string arg: {0}", cdt.str); + + // Expected return value = 2 + 3 + 4 + 6 + 7 + 8 + 11 + 12 + 13 = 93 + float sum = cdt.vecs.a.X + cdt.vecs.a.Y + cdt.vecs.a.Z + + cdt.vecs.b.X + cdt.vecs.b.Y + cdt.vecs.b.Z + + cdt.v3.X + cdt.v3.Y + cdt.v3.Z; + if ((sum != 93) || (cdt.iv != 100) || (cdt.str.ToString() != "ret_string") ) + { + Console.WriteLine("PInvoke Vector3InStruct test failed"); + return false; + } + } + + Console.WriteLine("All PInvoke testcases passed"); + return true; + } +} + +class RPInvokeTest +{ + public delegate void CallBackDelegate_RPInvoke_Vector3Arg( + int i, + Vector3 v1, + [MarshalAs(UnmanagedType.LPStr)] string s, + Vector3 v2); + + public delegate Vector3 CallBackDelegate_RPInvoke_Vector3Ret(); + + public delegate void CallBackDelegate_RPInvoke_Vector3Array( + [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=1)] Vector3[] v, + int size); + + public delegate void CallBackDelegate_RPInvoke_Vector3InStruct( + DT v); + + public delegate void CallBackDelegate_RPInvoke_Vector3InComplexStruct( + ref ComplexDT v); + + [DllImport(@"Vector3TestNative", CallingConvention = CallingConvention.StdCall)] + public static extern void nativeCall_RPInvoke_Vector3Arg( + CallBackDelegate_RPInvoke_Vector3Arg callBack); + + [DllImport(@"Vector3TestNative", CallingConvention = CallingConvention.StdCall)] + public static extern bool nativeCall_RPInvoke_Vector3Ret( + CallBackDelegate_RPInvoke_Vector3Ret callBack); + + [DllImport(@"Vector3TestNative", CallingConvention = CallingConvention.StdCall)] + public static extern void nativeCall_RPInvoke_Vector3Array( + CallBackDelegate_RPInvoke_Vector3Array callBack, + int v); + + [DllImport(@"Vector3TestNative", CallingConvention = CallingConvention.StdCall)] + public static extern void nativeCall_RPInvoke_Vector3InStruct( + CallBackDelegate_RPInvoke_Vector3InStruct callBack, + int v); + + [DllImport(@"Vector3TestNative", CallingConvention = CallingConvention.StdCall)] + public static extern bool nativeCall_RPInvoke_Vector3InComplexStruct( + CallBackDelegate_RPInvoke_Vector3InComplexStruct callBack); + + static bool result = false; + + static void callBack_RPInvoke_Vector3Arg( + int i, + Vector3 v1, + [MarshalAs(UnmanagedType.LPStr)] string s, + Vector3 v2) + { + Vector3 tmp = new Vector3(2, 2, 2); + + // sum = (1, 2, 3) dot (2, 2, 2) = 12 + float sum0 = Vector3.Dot(v1, tmp); + // sum = (10, 20, 30) dot (2, 2, 2) = 20 + 40 + 60 = 120 + float sum1 = Vector3.Dot(v2, tmp); + + Console.WriteLine("callBack_RPInvoke_Vector3Arg:"); + Console.WriteLine(" iVal {0}", i); + Console.WriteLine(" SumOfEles(v1) = {0} SumOfEles(v2) = {1}", sum0, sum1); + Console.WriteLine(" str {0}", s); + + result = (sum0 == 12) && (sum1 == 120) && (s == "abcdefg") && (i == 123); + } + + static Vector3 callBack_RPInvoke_Vector3Ret() + { + Vector3 tmp = new Vector3(1, 2, 3); + return tmp; + } + + static void callBack_RPInvoke_Vector3Array( + [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=1)] Vector3[] v, + int size) + { + Vector3 tmp = new Vector3(2, 2, 2); + + // sum0 = (2,3,4) dot (2,2,2) = 4 + 6 + 8 = 18 + float sum0 = Vector3.Dot(v[0], tmp); + // sum0 = (11,21,31) dot (2,2,2) = 22 + 42 + 62 = 126 + float sum1 = Vector3.Dot(v[1], tmp); + + Console.WriteLine("callBack_RPInvoke_Vector3Array: Sum0 = {0} Sum1 = {1}", sum0, sum1); + + result = (sum0 == 18) && (sum1 == 126); + } + + + static void callBack_RPInvoke_Vector3InStruct(DT v) + { + Vector3 tmp = new Vector3(2, 2, 2); + + // sum0 = (2,3,4) dot (2,2,2) = 4 + 6 + 8 = 18 + float sum0 = Vector3.Dot(v.a, tmp); + // sum1 = (11,21,31) dot (2,2,2) = 22 + 42 + 62 = 126 + float sum1 = Vector3.Dot(v.b, tmp); + + Console.WriteLine("callBack_RPInvoke_Vector3InStruct: Sum0 = {0} Sum1 = {1}", sum0, sum1); + + result = (sum0 == 18) && (sum1 == 126); + } + + static void callBack_RPInvoke_Vector3InComplexStruct(ref ComplexDT arg) + { + ComplexDT ret; + Console.WriteLine("callBack_RPInvoke_Vector3InComplexStruct"); + Console.WriteLine(" Arg ival: {0}", arg.iv); + Console.WriteLine(" Arg Vector3 v1: ({0} {1} {2})", arg.vecs.a.X, arg.vecs.a.Y, arg.vecs.a.Z); + Console.WriteLine(" Arg Vector3 v2: ({0} {1} {2})", arg.vecs.b.X, arg.vecs.b.Y, arg.vecs.b.Z); + Console.WriteLine(" Arg Vector3 v3: ({0} {1} {2})", arg.v3.X, arg.v3.Y, arg.v3.Z); + Console.WriteLine(" Arg string arg: {0}", arg.str); + + arg.vecs.a.X = arg.vecs.a.X + 1; + arg.vecs.a.Y = arg.vecs.a.Y + 1; + arg.vecs.a.Z = arg.vecs.a.Z + 1; + arg.vecs.b.X = arg.vecs.b.X + 1; + arg.vecs.b.Y = arg.vecs.b.Y + 1; + arg.vecs.b.Z = arg.vecs.b.Z + 1; + arg.v3.X = arg.v3.X + 1; + arg.v3.Y = arg.v3.Y + 1; + arg.v3.Z = arg.v3.Z + 1; + arg.iv = arg.iv + 1; + arg.str = "ret_string"; + + Console.WriteLine(" Return ival: {0}", arg.iv); + Console.WriteLine(" Return Vector3 v1: ({0} {1} {2})", arg.vecs.a.X, arg.vecs.a.Y, arg.vecs.a.Z); + Console.WriteLine(" Return Vector3 v2: ({0} {1} {2})", arg.vecs.b.X, arg.vecs.b.Y, arg.vecs.b.Z); + Console.WriteLine(" Return Vector3 v3: ({0} {1} {2})", arg.v3.X, arg.v3.Y, arg.v3.Z); + Console.WriteLine(" Return string arg: {0}", arg.str); + float sum = arg.vecs.a.X + arg.vecs.a.Y + arg.vecs.a.Z + + arg.vecs.b.X + arg.vecs.b.Y + arg.vecs.b.Z + + arg.v3.X + arg.v3.Y + arg.v3.Z; + Console.WriteLine(" Sum of all return float scalar values = {0}", sum); + } + + public static bool test() { + int x = 1; + + nativeCall_RPInvoke_Vector3Arg(callBack_RPInvoke_Vector3Arg); + if (!result) + { + Console.WriteLine("RPInvoke Vector3Arg test failed"); + return false; + } + + result = nativeCall_RPInvoke_Vector3Ret(callBack_RPInvoke_Vector3Ret); + if (!result) + { + Console.WriteLine("RPInvoke Vector3Ret test failed"); + return false; + } + + nativeCall_RPInvoke_Vector3Array(callBack_RPInvoke_Vector3Array, x); + if (!result) + { + Console.WriteLine("RPInvoke Vector3Array test failed"); + return false; + } + + nativeCall_RPInvoke_Vector3InStruct(callBack_RPInvoke_Vector3InStruct, x); + if (!result) + { + Console.WriteLine("RPInvoke Vector3InStruct test failed"); + return false; + } + + result = nativeCall_RPInvoke_Vector3InComplexStruct(callBack_RPInvoke_Vector3InComplexStruct); + if (!result) + { + Console.WriteLine("RPInvoke Vector3InComplexStruct test failed"); + return false; + } + + Console.WriteLine("All RPInvoke testcases passed"); + return true; + } +} + +class Test +{ + public static int Main() + { + + if (!PInvokeTest.test()) + { + return 101; + } + + if (!RPInvokeTest.test()) + { + return 101; + } + return 100; + } +} diff --git a/tests/src/JIT/SIMD/Vector3Interop_r.csproj b/tests/src/JIT/SIMD/Vector3Interop_r.csproj new file mode 100644 index 0000000..7eb82e5 --- /dev/null +++ b/tests/src/JIT/SIMD/Vector3Interop_r.csproj @@ -0,0 +1,53 @@ + + + + + Debug + AnyCPU + 2.0 + {95DFC527-4DC1-495E-97D7-E94EE1F7140D} + Exe + Properties + 512 + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + $(ProgramFiles)\Common Files\microsoft shared\VSTT\11.0\UITestExtensionPackages + ..\..\ + 7a9bfb7d + + + + + + pdbonly + true + + + + False + + + + None + + + + + + + + + + + + + + + + + + + + diff --git a/tests/src/JIT/SIMD/Vector3Interop_ro.csproj b/tests/src/JIT/SIMD/Vector3Interop_ro.csproj new file mode 100644 index 0000000..7eb82e5 --- /dev/null +++ b/tests/src/JIT/SIMD/Vector3Interop_ro.csproj @@ -0,0 +1,53 @@ + + + + + Debug + AnyCPU + 2.0 + {95DFC527-4DC1-495E-97D7-E94EE1F7140D} + Exe + Properties + 512 + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + $(ProgramFiles)\Common Files\microsoft shared\VSTT\11.0\UITestExtensionPackages + ..\..\ + 7a9bfb7d + + + + + + pdbonly + true + + + + False + + + + None + + + + + + + + + + + + + + + + + + + + diff --git a/tests/src/JIT/SIMD/Vector3TestNative.cpp b/tests/src/JIT/SIMD/Vector3TestNative.cpp new file mode 100755 index 0000000..51b4b86 --- /dev/null +++ b/tests/src/JIT/SIMD/Vector3TestNative.cpp @@ -0,0 +1,281 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#include +#include + +#if defined(__clang__) +#define EXPORT(type) __attribute__((visibility("default"))) extern "C" type +#elif defined(_MSC_VER) +#define EXPORT(type) extern "C" __declspec(dllexport) type +#else // defined(__clang__) +#define EXPORT(type) type +#endif // !defined(__clang__) + +#if !defined(_MSC_VER) +#if __i386__ +#define __stdcall __attribute__((stdcall)) +#else // __i386__ +#define __stdcall +#endif // !__i386__ +#endif // !defined(_MSC_VER) + +typedef struct _Vector3 +{ + float x; + float y; + float z; +} Vector3; + +typedef struct _DT +{ + Vector3 a; + Vector3 b; +} DT; + +typedef struct _ComplexDT +{ + int iv; + DT vecs; + char str[256]; + Vector3 v3; +} ComplexDT; + +// +// PInvoke native call for Vector3 size check +// + +EXPORT(int) __stdcall nativeCall_PInvoke_CheckVector3Size() +{ + printf("nativeCall_PInvoke_CheckVector3Size: sizeof(Vector3) == %d\n", (int)sizeof(Vector3)); + fflush(stdout); + return sizeof(Vector3); +} + +// +// PInvoke native call for Vector3 argument +// + +EXPORT(float) __stdcall nativeCall_PInvoke_Vector3Arg(int i, Vector3 v1, char* s, Vector3 v2) +{ + float sum0 = v1.x + v1.y + v1.z; + float sum1 = v2.x + v2.y + v2.z; + printf("nativeCall_PInvoke_Vector3Arg:\n"); + printf(" iVal %d\n", i); + printf(" sumOfEles(%f, %f, %f) = %f\n", v1.x, v1.y, v1.z, sum0); + printf(" str %s\n", s); + printf(" sumOfEles(%f, %f, %f) = %f\n", v2.x, v2.y, v2.z, sum1); + fflush(stdout); + if ((strncmp(s, "abcdefg", strnlen(s, 32)) != 0) || i != 123) { + return 0; + } + return sum0 + sum1; +} + +// +// PInvoke native call for Vector3 argument +// + +EXPORT(Vector3) __stdcall nativeCall_PInvoke_Vector3Ret() +{ + Vector3 ret; + ret.x = 1; + ret.y = 2; + ret.z = 3; + float sum = ret.x + ret.y + ret.z; + printf("nativeCall_PInvoke_Vector3Ret:\n"); + printf(" Return value: (%f, %f, %f)\n", ret.x, ret.y, ret.z); + printf(" Sum of return scalar values = %f\n", sum); + fflush(stdout); + return ret; +} + +// +// PInvoke native call for Vector3 array +// + +EXPORT(float) __stdcall nativeCall_PInvoke_Vector3Array(Vector3* arr) +{ + float sum = 0.0; + printf("nativeCall_PInvoke_Vector3Array\n"); + for (unsigned i = 0; i < 2; ++i) + { + Vector3* e = &arr[i]; + printf(" arrEle[%d]: %f %f %f\n", i, e->x, e->y, e->z); + sum += e->x + e->y + e->z; + } + printf(" Sum = %f\n", sum); + fflush(stdout); + return sum; +} + +// +// PInvoke native call for Vector3 in struct +// + +EXPORT(DT) __stdcall nativeCall_PInvoke_Vector3InStruct(DT data) +{ + printf("nativeCall_PInvoke_Vector3InStruct\n"); + DT ret; + ret.a.x = data.a.x + 1; + ret.a.y = data.a.y + 1; + ret.a.z = data.a.z + 1; + ret.b.x = data.b.x + 1; + ret.b.y = data.b.y + 1; + ret.b.z = data.b.z + 1; + printf(" First struct memeber: (%f %f %f) -> (%f %f %f)\n", + data.a.x, data.a.y, data.a.z, ret.a.x, ret.a.y, ret.a.z); + printf(" Second struct member: (%f %f %f) -> (%f %f %f)\n", + data.b.x, data.b.y, data.b.z, ret.b.x, ret.b.y, ret.b.z); + float sum = ret.a.x + ret.a.y + ret.a.z + ret.b.x + ret.b.y + ret.b.z; + printf(" Sum of all return scalar values = %f\n", sum); + fflush(stdout); + return ret; +} + +// +// PInvoke native call for Vector3 in complex struct +// + +EXPORT(void) __stdcall nativeCall_PInvoke_Vector3InComplexStruct(ComplexDT* arg) +{ + static const char* ret_str = "ret_string"; + printf("nativeCall_PInvoke_Vector3InStruct\n"); + printf(" Arg ival: %d\n", arg->iv); + printf(" Arg Vector3 v1: (%f %f %f)\n", arg->vecs.a.x, arg->vecs.a.y, arg->vecs.a.z); + printf(" Arg Vector3 v2: (%f %f %f)\n", arg->vecs.b.x, arg->vecs.b.y, arg->vecs.b.z); + printf(" Arg Vector3 v3: (%f %f %f)\n", arg->v3.x, arg->v3.y, arg->v3.z); + printf(" Arg string arg: %s\n", arg->str); + + + arg->vecs.a.x = arg->vecs.a.x + 1; + arg->vecs.a.y = arg->vecs.a.y + 1; + arg->vecs.a.z = arg->vecs.a.z + 1; + arg->vecs.b.x = arg->vecs.b.x + 1; + arg->vecs.b.y = arg->vecs.b.y + 1; + arg->vecs.b.z = arg->vecs.b.z + 1; + arg->v3.x = arg->v3.x + 1; + arg->v3.y = arg->v3.y + 1; + arg->v3.z = arg->v3.z + 1; + arg->iv = arg->iv + 1; + strncpy(arg->str, ret_str, strnlen("ret_str", 32)); + + printf(" Return ival: %d\n", arg->iv); + printf(" Return Vector3 v1: (%f %f %f)\n", arg->vecs.a.x, arg->vecs.a.y, arg->vecs.a.z); + printf(" Return Vector3 v2: (%f %f %f)\n", arg->vecs.b.x, arg->vecs.b.y, arg->vecs.b.z); + printf(" Return Vector3 v3: (%f %f %f)\n", arg->v3.x, arg->v3.y, arg->v3.z); + printf(" Return string arg: %s\n", arg->str); + float sum = arg->vecs.a.x + arg->vecs.a.y + arg->vecs.a.z + + arg->vecs.b.x + arg->vecs.b.y + arg->vecs.b.z + + arg->v3.x + arg->v3.y + arg->v3.z; + printf(" Sum of all return float scalar values = %f\n", sum); + fflush(stdout); +} + +// +// RPInvoke native call for Vector3 argument +// +typedef void (__stdcall *CallBack_RPInvoke_Vector3Arg)(int i, Vector3 v1, char* s, Vector3 v2); + + +EXPORT(void) __stdcall nativeCall_RPInvoke_Vector3Arg( + CallBack_RPInvoke_Vector3Arg notify) +{ + int i = 123; + const static char* str = "abcdefg"; + Vector3 v1, v2; + v1.x = 1; v1.y = 2; v1.z = 3; + v2.x = 10; v2.y = 20; v2.z = 30; + notify(i, v1, (char*)str, v2); +} + +// +// RPInvoke native call for Vector3 array +// + +typedef Vector3 (__stdcall *CallBack_RPInvoke_Vector3Ret)(); + +EXPORT(bool) __stdcall nativeCall_RPInvoke_Vector3Ret( + CallBack_RPInvoke_Vector3Ret notify) +{ + Vector3 ret = notify(); + printf("nativeCall_RPInvoke_Vector3Ret: Return value (%f %f %f)\n", + ret.x, ret.y, ret.z); + fflush(stdout); + if (ret.x == 1 && ret.y == 2 && ret.z == 3) { + return true; + } + return false; +} + +// +// RPInvoke native call for Vector3 array +// + +typedef void (__stdcall *CallBack_RPInvoke_Vector3Array)(Vector3* v, int size); + +static Vector3 arr[2]; + +EXPORT(void) __stdcall nativeCall_RPInvoke_Vector3Array( + CallBack_RPInvoke_Vector3Array notify, + int a) +{ + arr[0].x = a + 1; arr[0].y = a + 2; arr[0].z = a + 3; + arr[1].x = a + 10; arr[1].y = a + 20; arr[1].z = a + 30; + notify(arr, 2); +} + +// +// RPInvoke native call for Vector3-in-struct test +// + +typedef void (__stdcall *CallBack_RPInvoke_Vector3InStruct)(DT v); + +static DT v; + +EXPORT(void) __stdcall nativeCall_RPInvoke_Vector3InStruct( + CallBack_RPInvoke_Vector3InStruct notify, + int a) +{ + v.a.x = a + 1; v.a.y = a + 2; v.a.z = a + 3; + v.b.x = a + 10; v.b.y = a + 20; v.b.z = a + 30; + notify(v); +} + +// +// RPInvoke native call for complex Vector3-in-struct test +// + +typedef bool (__stdcall *CallBack_RPInvoke_Vector3InComplexStruct)(ComplexDT* v); + +EXPORT(bool) __stdcall nativeCall_RPInvoke_Vector3InComplexStruct( + CallBack_RPInvoke_Vector3InComplexStruct notify) +{ + static ComplexDT cdt; + cdt.iv = 99; + strncpy(cdt.str, "arg_string", strnlen("arg_string", 32)); + cdt.vecs.a.x = 1; cdt.vecs.a.y = 2; cdt.vecs.a.z = 3; + cdt.vecs.b.x = 5; cdt.vecs.b.y = 6; cdt.vecs.b.z = 7; + cdt.v3.x = 10; cdt.v3.y = 20; cdt.v3.z = 30; + + notify(&cdt); + + printf(" Native ival: %d\n", cdt.iv); + printf(" Native Vector3 v1: (%f %f %f)\n", cdt.vecs.a.x, cdt.vecs.a.y, cdt.vecs.a.z); + printf(" Native Vector3 v2: (%f %f %f)\n", cdt.vecs.b.x, cdt.vecs.b.y, cdt.vecs.b.z); + printf(" Native Vector3 v3: (%f %f %f)\n", cdt.v3.x, cdt.v3.y, cdt.v3.z); + printf(" Native string arg: %s\n", cdt.str); + fflush(stdout); + + // Expected return value = 2 + 3 + 4 + 6 + 7 + 8 + 11 + 12 + 13 = 93 + float sum = cdt.vecs.a.x + cdt.vecs.a.y + cdt.vecs.a.z + + cdt.vecs.b.x + cdt.vecs.b.y + cdt.vecs.b.z + + cdt.v3.x + cdt.v3.y + cdt.v3.z; + + if ((sum != 93) || (cdt.iv != 100) || (strcmp(cdt.str, "ret_string")!=0) ) + { + return false; + } + return true; +} diff --git a/tests/src/JIT/SIMD/project.json b/tests/src/JIT/SIMD/project.json index 5d47446..8de132f 100644 --- a/tests/src/JIT/SIMD/project.json +++ b/tests/src/JIT/SIMD/project.json @@ -7,6 +7,7 @@ "System.Numerics.Vectors": "4.1.1-rc2-23816", "System.Runtime": "4.1.0-rc2-23816", "System.Runtime.Extensions": "4.0.10", + "System.Runtime.InteropServices": "4.1.0-rc2-23816", "System.Threading": "4.0.0", "System.Threading.Thread": "4.0.0-rc2-23816" }, -- 2.7.4