Make ILBlittablePtrMarshaler participate in marshaller inheritance (#39389)
authorAaron Robinson <arobins@microsoft.com>
Thu, 16 Jul 2020 15:50:54 +0000 (08:50 -0700)
committerGitHub <noreply@github.com>
Thu, 16 Jul 2020 15:50:54 +0000 (08:50 -0700)
* Make ILBlittablePtrMarshaler participate in marshaller inheritance

* Add test for class layout with Out attribute scenario.

src/coreclr/src/vm/ilmarshalers.cpp
src/coreclr/src/vm/ilmarshalers.h
src/tests/Interop/LayoutClass/LayoutClassNative.cpp
src/tests/Interop/LayoutClass/LayoutClassTest.cs

index 4905061..8f57b1c 100644 (file)
@@ -2374,21 +2374,15 @@ void ILBlittablePtrMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslIL
     pslILEmit->EmitLabel(pNullRefLabel);
 }
 
-bool ILBlittablePtrMarshaler::CanUsePinnedLayoutClass()
+bool ILBlittablePtrMarshaler::CanMarshalViaPinning()
 {
     return IsCLRToNative(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags) && !IsFieldMarshal(m_dwMarshalFlags);
 }
 
-void ILBlittablePtrMarshaler::EmitConvertSpaceAndContentsCLRToNativeTemp(ILCodeStream* pslILEmit)
+void ILBlittablePtrMarshaler::EmitMarshalViaPinning(ILCodeStream* pslILEmit)
 {
     STANDARD_VM_CONTRACT;
 
-    if (!CanUsePinnedLayoutClass())
-    {
-        ILLayoutClassPtrMarshalerBase::EmitConvertSpaceAndContentsCLRToNativeTemp(pslILEmit);
-        return;
-    }
-
     ILCodeLabel* pSkipAddLabel = pslILEmit->NewCodeLabel();
     LocalDesc managedTypePinned = GetManagedType();
     managedTypePinned.MakePinned();
index be1e23e..2b4e607 100644 (file)
@@ -2942,9 +2942,8 @@ public:
 protected:
     void EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit) override;
     void EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) override;
-    void EmitConvertSpaceAndContentsCLRToNativeTemp(ILCodeStream* pslILEmit) override;
-private:
-    bool CanUsePinnedLayoutClass();
+    bool CanMarshalViaPinning() override;
+    void EmitMarshalViaPinning(ILCodeStream* pslILEmit) override;
 };
 
 class ILLayoutClassMarshaler : public ILMarshaler
index e7980b7..0bf0af9 100644 (file)
@@ -8,21 +8,21 @@ typedef void *voidPtr;
  
 struct SeqClass
 {
-    int a; 
+    int a;
     bool b;
     char* str;
 };
 
 struct ExpClass
 { 
-       int a;
-       int extra; //padding needs to be added here as we have added 8 byte offset.
-       union
-       {
-               int i;
-               BOOL b;
-               double d;
-       } udata;
+    int a;
+    int padding; //padding needs to be added here as we have added 8 byte offset.
+    union
+    {
+        int i;
+        BOOL b;
+        double d;
+    } udata;
 };
 
 struct BlittableClass
@@ -36,43 +36,55 @@ struct NestedLayoutClass
 };
 
 extern "C"
-DLL_EXPORT BOOL STDMETHODCALLTYPE SimpleSeqLayoutClassByRef(SeqClass *p) 
+DLL_EXPORT BOOL STDMETHODCALLTYPE SimpleSeqLayoutClassByRef(SeqClass* p)
 {
     if((p->a != 0) || (p->b) || strcmp(p->str, "before") != 0)
     {
-        printf("\np->a=%d, p->b=%s, p->str=%s", p->a, p->b ? "true" : "false", p->str);
+        printf("FAIL: p->a=%d, p->b=%s, p->str=%s\n", p->a, p->b ? "true" : "false", p->str);
+        return FALSE;
+    }
+    return TRUE;
+}
+
+extern "C"
+DLL_EXPORT BOOL STDMETHODCALLTYPE SimpleExpLayoutClassByRef(ExpClass* p)
+{
+    if((p->a != 0) || (p->udata.i != 10))
+    {
+        printf("FAIL: p->a=%d, p->udata.i=%d\n",p->a,p->udata.i);
         return FALSE;
     }
     return TRUE;
 }
 
 extern "C"
-DLL_EXPORT BOOL STDMETHODCALLTYPE SimpleBlittableSeqLayoutClassByRef(BlittableClass *p) 
+DLL_EXPORT BOOL STDMETHODCALLTYPE SimpleBlittableSeqLayoutClassByRef(BlittableClass* p)
 {
     if(p->a != 10)
     {
-        printf("\np->a=%d", p->a);
+        printf("FAIL: p->a=%d\n", p->a);
         return FALSE;
     }
     return TRUE;
 }
 
 extern "C"
-DLL_EXPORT BOOL STDMETHODCALLTYPE SimpleExpLayoutClassByRef(ExpClass *p)
+DLL_EXPORT BOOL STDMETHODCALLTYPE SimpleBlittableSeqLayoutClassByOutAttr(BlittableClass* p)
 {
-       if((p->a != 0) || (p->udata.i != 10))
-       {
-               printf("\np->a=%d, p->udata.i=%d\n",p->a,p->udata.i);
-               return FALSE;
-       }
-       return TRUE;
+    if(!SimpleBlittableSeqLayoutClassByRef(p))
+        return FALSE;
+
+    p->a++;
+    return TRUE;
 }
 
-extern "C" DLL_EXPORT BOOL STDMETHODCALLTYPE SimpleNestedLayoutClassByValue(NestedLayoutClass v)
+extern "C"
+DLL_EXPORT BOOL STDMETHODCALLTYPE SimpleNestedLayoutClassByValue(NestedLayoutClass v)
 {
     return SimpleSeqLayoutClassByRef(&v.str);
 }
 
-extern "C" DLL_EXPORT void __cdecl Invalid(...)
+extern "C"
+DLL_EXPORT void __cdecl Invalid(...)
 {
 }
index 63b52de..32ecfcb 100644 (file)
@@ -18,7 +18,7 @@ namespace PInvokeTests
         {
             a = _a;
             b = _b;
-            str = String.Concat(_str, "");
+            str = string.Concat(_str, "");
         }
     }
 
@@ -58,7 +58,7 @@ namespace PInvokeTests
             c = 0;
             b = bnum;
         }
-     }
+    }
 
     public enum DialogResult
     {
@@ -67,7 +67,6 @@ namespace PInvokeTests
         Cancel = 2
     }
 
-    
     [StructLayout(LayoutKind.Sequential)]
     public class Blittable
     {
@@ -84,7 +83,6 @@ namespace PInvokeTests
         public SeqClass value;
     }
 
-
     [StructLayout(LayoutKind.Sequential)]
     public class RecursiveTestClass
     {
@@ -105,155 +103,91 @@ namespace PInvokeTests
         private static extern bool SimpleExpLayoutClassByRef(ExpClass p);
 
         [DllImport("LayoutClassNative")]
-        private static extern bool SimpleNestedLayoutClassByValue(NestedLayout p);
+        private static extern bool SimpleBlittableSeqLayoutClassByRef(Blittable p);
 
         [DllImport("LayoutClassNative")]
-        private static extern bool SimpleBlittableSeqLayoutClassByRef(Blittable p);
+        private static extern bool SimpleBlittableSeqLayoutClassByOutAttr([Out] Blittable p);
+
+        [DllImport("LayoutClassNative")]
+        private static extern bool SimpleNestedLayoutClassByValue(NestedLayout p);
 
         [DllImport("LayoutClassNative", EntryPoint = "Invalid")]
         private static extern void RecursiveNativeLayoutInvalid(RecursiveTestStruct str);
 
-        public static bool SequentialClass()
+        public static void SequentialClass()
         {
-            string s = "before";
-            bool retval = true;
-            SeqClass p = new SeqClass(0, false, s);
-
-            TestFramework.BeginScenario("Test #1 Pass a sequential layout class.");
-
-            try
-            {
-                retval = SimpleSeqLayoutClassByRef(p);
-
-                if (retval == false)
-                {
-                    TestFramework.LogError("01", "PInvokeTests->SequentialClass : Unexpected error occured on unmanaged side");
-                    return false;
-                }
-            }
-            catch (Exception e)
-            {
-                TestFramework.LogError("04", "Unexpected exception: " + e.ToString());
-                retval = false;
-            }
+            Console.WriteLine($"Running {nameof(SequentialClass)}...");
 
-            return retval;
+            string s = "before";
+            var p = new SeqClass(0, false, s);
+            Assert.IsTrue(SimpleSeqLayoutClassByRef(p));
         }
 
-        public static bool ExplicitClass()
+        public static void ExplicitClass()
         {
-            ExpClass p;
-            bool retval = false;
-
-            TestFramework.BeginScenario("Test #2 Pass an explicit layout class.");
-
-            try
-            {
-                p = new ExpClass(DialogResult.None, 10);
-                retval = SimpleExpLayoutClassByRef(p);
-
-                if (retval == false)
-                {
-                    TestFramework.LogError("01", "PInvokeTests->ExplicitClass : Unexpected error occured on unmanaged side");
-                    return false;
-                }
+            Console.WriteLine($"Running {nameof(ExplicitClass)}...");
 
-            }
-            catch (Exception e)
-            {
-                TestFramework.LogError("03", "Unexpected exception: " + e.ToString());
-                retval = false;
-            }
-
-            return retval;
+            var p = new ExpClass(DialogResult.None, 10);
+            Assert.IsTrue(SimpleExpLayoutClassByRef(p));
         }
 
-        public static bool BlittableClass()
+        public static void BlittableClass()
         {
-            bool retval = true;
-            Blittable p = new Blittable(10);
+            Console.WriteLine($"Running {nameof(BlittableClass)}...");
 
-            TestFramework.BeginScenario("Test #3 Pass a blittable sequential layout class.");
-
-            try
-            {
-                retval = SimpleBlittableSeqLayoutClassByRef(p);
+            Blittable p = new Blittable(10);
+            Assert.IsTrue(SimpleBlittableSeqLayoutClassByRef(p));
+        }
 
-                if (retval == false)
-                {
-                    TestFramework.LogError("01", "PInvokeTests->Blittable : Unexpected error occured on unmanaged side");
-                    return false;
-                }
-            }
-            catch (Exception e)
-            {
-                TestFramework.LogError("04", "Unexpected exception: " + e.ToString());
-                retval = false;
-            }
+        public static void BlittableClassByOutAttr()
+        {
+            Console.WriteLine($"Running {nameof(BlittableClassByOutAttr)}...");
 
-            return retval;
+            int a = 10;
+            int expected = a + 1;
+            Blittable p = new Blittable(a);
+            Assert.IsTrue(SimpleBlittableSeqLayoutClassByOutAttr(p));
+            Assert.AreEqual(expected, p.a);
         }
-        
-        public static bool NestedLayoutClass()
+
+        public static void NestedLayoutClass()
         {
+            Console.WriteLine($"Running {nameof(NestedLayoutClass)}...");
+
             string s = "before";
-            bool retval = true;
-            SeqClass p = new SeqClass(0, false, s);
-            NestedLayout target = new NestedLayout
+            var p = new SeqClass(0, false, s);
+            var target = new NestedLayout
             {
                 value = p
             };
+            Assert.IsTrue(SimpleNestedLayoutClassByValue(target));
+        }
 
-            TestFramework.BeginScenario("Test #4 Nested sequential layout class in a structure.");
-
-            try
-            {
-                retval = SimpleNestedLayoutClassByValue(target);
-
-                if (retval == false)
-                {
-                    TestFramework.LogError("01", "PInvokeTests->NestedLayoutClass : Unexpected error occured on unmanaged side");
-                    return false;
-                }
-            }
-            catch (Exception e)
-            {
-                TestFramework.LogError("04", "Unexpected exception: " + e.ToString());
-                retval = false;
-            }
+        public static void RecursiveNativeLayout()
+        {
+            Console.WriteLine($"Running {nameof(RecursiveNativeLayout)}...");
 
-            return retval;
+            Assert.Throws<TypeLoadException>(() => RecursiveNativeLayoutInvalid(new RecursiveTestStruct()));
         }
 
-        public static bool RecursiveNativeLayout()
+        public static int Main(string[] argv)
         {
-            TestFramework.BeginScenario("Test #5 Structure with field of nested layout class with field of containing structure.");
-
             try
             {
-                RecursiveNativeLayoutInvalid(new RecursiveTestStruct());
+                SequentialClass();
+                ExplicitClass();
+                BlittableClass();
+                BlittableClassByOutAttr();
+                NestedLayoutClass();
+                RecursiveNativeLayout();
             }
-            catch (TypeLoadException)
+            catch (Exception e)
             {
-                return true;
+                Console.WriteLine($"Test Failure: {e}");
+                return 101;
             }
 
-            return false;
+            return 100;
         }
-
-        public static int Main(string[] argv)
-        {
-            bool retVal = true;
-
-            retVal = retVal && SequentialClass();
-            retVal = retVal && ExplicitClass();
-            retVal = retVal && BlittableClass();
-            retVal = retVal && NestedLayoutClass();
-            retVal = retVal && RecursiveNativeLayout();
-
-            return (retVal ? 100 : 101);
-        }
-
-
     }
 }