Vector3 Interop tests
authorSejong OH <sejooh@microsoft.com>
Mon, 18 Apr 2016 10:31:33 +0000 (03:31 -0700)
committerSejong OH <sejooh@microsoft.com>
Thu, 21 Apr 2016 23:47:11 +0000 (16:47 -0700)
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 [new file with mode: 0755]
tests/src/JIT/SIMD/Vector3Interop.cs [new file with mode: 0755]
tests/src/JIT/SIMD/Vector3Interop_r.csproj [new file with mode: 0644]
tests/src/JIT/SIMD/Vector3Interop_ro.csproj [new file with mode: 0644]
tests/src/JIT/SIMD/Vector3TestNative.cpp [new file with mode: 0755]
tests/src/JIT/SIMD/project.json

diff --git a/tests/src/JIT/SIMD/CMakeLists.txt b/tests/src/JIT/SIMD/CMakeLists.txt
new file mode 100755 (executable)
index 0000000..555703b
--- /dev/null
@@ -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 (executable)
index 0000000..7ef77cd
--- /dev/null
@@ -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 (file)
index 0000000..7eb82e5
--- /dev/null
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{95DFC527-4DC1-495E-97D7-E94EE1F7140D}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <FileAlignment>512</FileAlignment>
+    <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+    <ReferencePath>$(ProgramFiles)\Common Files\microsoft shared\VSTT\11.0\UITestExtensionPackages</ReferencePath>
+    <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
+    <NuGetPackageImportStamp>7a9bfb7d</NuGetPackageImportStamp>
+  </PropertyGroup>
+  <!-- Default configurations to help VS understand the configurations -->
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+  </PropertyGroup>
+  <ItemGroup>
+    <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
+      <Visible>False</Visible>
+    </CodeAnalysisDependentAssemblyPaths>
+  </ItemGroup>
+  <PropertyGroup>
+    <DebugType>None</DebugType>
+    <Optimize></Optimize>
+  </PropertyGroup>
+  <ItemGroup>
+    <None Include="$(JitPackagesConfigFileDirectory)threading+thread\project.json" />
+  </ItemGroup>
+  <ItemGroup>
+    <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Vector3Interop.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="project.json" />
+    <ProjectReference Include="CMakeLists.txt" />
+  </ItemGroup>
+  <!--  <PropertyGroup>
+    <ProjectJson>$(JitPackagesConfigFileDirectory)threading+thread\project.json</ProjectJson>
+    <ProjectLockJson>$(JitPackagesConfigFileDirectory)threading+thread\project.lock.json</ProjectLockJson>
+  </PropertyGroup>-->
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+  <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' ">
+  </PropertyGroup>
+</Project>
diff --git a/tests/src/JIT/SIMD/Vector3Interop_ro.csproj b/tests/src/JIT/SIMD/Vector3Interop_ro.csproj
new file mode 100644 (file)
index 0000000..7eb82e5
--- /dev/null
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{95DFC527-4DC1-495E-97D7-E94EE1F7140D}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <FileAlignment>512</FileAlignment>
+    <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+    <ReferencePath>$(ProgramFiles)\Common Files\microsoft shared\VSTT\11.0\UITestExtensionPackages</ReferencePath>
+    <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
+    <NuGetPackageImportStamp>7a9bfb7d</NuGetPackageImportStamp>
+  </PropertyGroup>
+  <!-- Default configurations to help VS understand the configurations -->
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+  </PropertyGroup>
+  <ItemGroup>
+    <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
+      <Visible>False</Visible>
+    </CodeAnalysisDependentAssemblyPaths>
+  </ItemGroup>
+  <PropertyGroup>
+    <DebugType>None</DebugType>
+    <Optimize></Optimize>
+  </PropertyGroup>
+  <ItemGroup>
+    <None Include="$(JitPackagesConfigFileDirectory)threading+thread\project.json" />
+  </ItemGroup>
+  <ItemGroup>
+    <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Vector3Interop.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="project.json" />
+    <ProjectReference Include="CMakeLists.txt" />
+  </ItemGroup>
+  <!--  <PropertyGroup>
+    <ProjectJson>$(JitPackagesConfigFileDirectory)threading+thread\project.json</ProjectJson>
+    <ProjectLockJson>$(JitPackagesConfigFileDirectory)threading+thread\project.lock.json</ProjectLockJson>
+  </PropertyGroup>-->
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+  <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' ">
+  </PropertyGroup>
+</Project>
diff --git a/tests/src/JIT/SIMD/Vector3TestNative.cpp b/tests/src/JIT/SIMD/Vector3TestNative.cpp
new file mode 100755 (executable)
index 0000000..51b4b86
--- /dev/null
@@ -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 <stdio.h>
+#include <string.h>
+
+#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;
+}
index 5d47446..8de132f 100644 (file)
@@ -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"
   },