From d395e8df59ef671c5b6dfee542817adae43a0870 Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Fri, 7 Oct 2016 12:48:01 +0200 Subject: [PATCH 1/7] [tests] Generate some trampoline and registrar tests. Generate trampoline and registrar tests that tests if a return type requires objc_msgSend or objc_msgSend_stret. Now it's much easier to test new return types (a single line of code), which avoids a _lot_ of copy-pasting, and makes sure all the different variations are tested properly. These new tests found several bugs, which are fixed in subsequent commits. --- tests/.gitignore | 1 + tests/bindings-test/ApiDefinition.cs | 11 +- tests/bindings-test/StructsAndEnums.cs | 26 - tests/bindings-test/bindings-test.csproj | 24 +- .../ObjCRuntime/RegistrarTest.cs | 141 +---- .../ObjCRuntime/TrampolineTest.cs | 554 +----------------- tests/monotouch-test/monotouch-test.csproj | 13 + tests/test-libraries/.gitignore | 3 + tests/test-libraries/Makefile | 27 +- tests/test-libraries/libtest.cs | 1 + tests/test-libraries/libtest.h | 30 +- tests/test-libraries/libtest.m | 12 +- tests/test-libraries/testgenerator.cs | 538 +++++++++++++++++ tests/test-libraries/testgenerator.csproj | 38 ++ 14 files changed, 669 insertions(+), 750 deletions(-) create mode 100644 tests/test-libraries/libtest.cs create mode 100644 tests/test-libraries/testgenerator.cs create mode 100644 tests/test-libraries/testgenerator.csproj diff --git a/tests/.gitignore b/tests/.gitignore index 748dd22d4c..adc50df407 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -25,4 +25,5 @@ mac-test-package .nuget logs *.mSYM +*.generated.cs diff --git a/tests/bindings-test/ApiDefinition.cs b/tests/bindings-test/ApiDefinition.cs index 26ce0e20fe..274acbde0b 100644 --- a/tests/bindings-test/ApiDefinition.cs +++ b/tests/bindings-test/ApiDefinition.cs @@ -40,7 +40,7 @@ namespace Bindings.Test { * ObjC test class used for registrar */ [BaseType (typeof (NSObject))] - interface ObjCRegistrarTest { + partial interface ObjCRegistrarTest { [Export ("Pi1")] int Pi1 { get; set; } @@ -137,15 +137,6 @@ namespace Bindings.Test { [Export ("Pc5")] sbyte Pc5 { get; set; } - [Export ("PSiid1")] - Siid PSiid { get; set; } - - [Export ("PSd1")] - Sd PSd { get; set; } - - [Export ("PSf1")] - Sf PSf { get; set; } - [Export ("V")] void V (); diff --git a/tests/bindings-test/StructsAndEnums.cs b/tests/bindings-test/StructsAndEnums.cs index d74a9f6b34..26e6b3c073 100644 --- a/tests/bindings-test/StructsAndEnums.cs +++ b/tests/bindings-test/StructsAndEnums.cs @@ -7,32 +7,6 @@ using nint=System.Int32; namespace Bindings.Test { - public struct Sd { public double d1; } - public struct Sdd { public double d1; public double d2; } - public struct Sddd { public double d1; public double d2; public double d3; } - public struct Sdddd { public double d1; public double d2; public double d3; public double d4; } - public struct Si { public int i1; } - public struct Sii { public int i1; public int i2; } - public struct Siii { public int i1; public int i2; public int i3; } - public struct Siiii { public int i1; public int i2; public int i3; public int i4; } - public struct Siiiii { public int i1; public int i2; public int i3; public int i4; public int i5; } - public struct Sid { public int i1; public double d2; } - public struct Sdi { public double d1; public int i2; } - public struct Sidi { public int i1; public double d2; public int i3; } - public struct Siid { public int i1; public int i2; public double d3; } - public struct Sddi { public double d1; public double d2; public int i3; } - public struct Sl { public nint l1; } - public struct Sll { public nint l1; public nint l2; } - public struct Slll { public nint l1; public nint l2; public nint l3; } - public struct Scccc { public char c1; public char c2; public char c3; public char c4; } - public struct Sffff { public float f1; public float f2; public float f3; public float f4; } - public struct Sif { public int i1; public float f2; } - public struct Sf { public float f1; } - public struct Sff { public float f1; public float f2; } - public struct Siff { public int i1; public float f2; public float f3; } - public struct Siiff { public int i1; public int i2; public float f3; public float f4; } - public struct Sfi { public float f1; public int i2; } - public static class CFunctions { [DllImport ("__Internal")] public static extern int theUltimateAnswer (); diff --git a/tests/bindings-test/bindings-test.csproj b/tests/bindings-test/bindings-test.csproj index 1e89dfd755..ec0a10e6b1 100644 --- a/tests/bindings-test/bindings-test.csproj +++ b/tests/bindings-test/bindings-test.csproj @@ -47,10 +47,12 @@ + + @@ -74,8 +76,26 @@ libtest.h + + libtest.structs.h + + + libtest.properties.h + + + testgenerator.cs + - + + + + + + + + + + - \ No newline at end of file + diff --git a/tests/monotouch-test/ObjCRuntime/RegistrarTest.cs b/tests/monotouch-test/ObjCRuntime/RegistrarTest.cs index 5cf29e80a5..6f5f20f539 100644 --- a/tests/monotouch-test/ObjCRuntime/RegistrarTest.cs +++ b/tests/monotouch-test/ObjCRuntime/RegistrarTest.cs @@ -1638,151 +1638,14 @@ namespace MonoTouchFixtures.ObjCRuntime { public void Test_D () { using (var tc = new ObjCRegistrarTest ()) { - Verify (tc, Pd1: 0); + Assert.AreEqual (tc.Pd1, 0, "Pd1"); Assert.AreEqual (0, tc.D (), "1"); tc.Pd1 = 1.2; Assert.AreEqual (1.2, tc.D (), "2"); - Verify (tc, Pd1: 1.2); + Assert.AreEqual (tc.Pd1, 1.2, "Pd1"); } } - [Test] - public void Test_Sd () - { - using (var tc = new ObjCRegistrarTest ()) { - Assert.AreEqual (0, tc.Sd ().d1, "1"); - Verify (tc, PSd1: new Sd () ); - tc.PSd = new Sd () { d1 = 1.23 }; - Assert.AreEqual (1.23, tc.Sd ().d1, "2"); - Verify (tc, PSd1: new Sd () { d1 = 1.23 }); - } - } - - void Verify (ObjCRegistrarTest obj, string msg = null, - int? Pi1 = null, - int? Pi2 = null, - int? Pi3 = null, - int? Pi4 = null, - int? Pi5 = null, - int? Pi6 = null, - int? Pi7 = null, - int? Pi8 = null, - int? Pi9 = null, - float? Pf1 = null, - float? Pf2 = null, - float? Pf3 = null, - float? Pf4 = null, - float? Pf5 = null, - float? Pf6 = null, - float? Pf7 = null, - float? Pf8 = null, - float? Pf9 = null, - double? Pd1 = null, - double? Pd2 = null, - double? Pd3 = null, - double? Pd4 = null, - double? Pd5 = null, - double? Pd6 = null, - double? Pd7 = null, - double? Pd8 = null, - double? Pd9 = null, - char? Pc1 = null, - char? Pc2 = null, - char? Pc3 = null, - char? Pc4 = null, - char? Pc5 = null, - char? Pc6 = null, - char? Pc7 = null, - char? Pc8 = null, - char? Pc9 = null, - - Siid? PSiid1 = null, - Sd? PSd1 = null, - Sf? PSf1 = null) - { - if (Pi1.HasValue) - Assert.AreEqual (obj.Pi1, Pi1.Value, "Pi1"); - if (Pi2.HasValue) - Assert.AreEqual (obj.Pi2, Pi2.Value, "Pi2"); - if (Pi3.HasValue) - Assert.AreEqual (obj.Pi3, Pi3.Value, "Pi3"); - if (Pi4.HasValue) - Assert.AreEqual (obj.Pi4, Pi4.Value, "Pi4"); - if (Pi5.HasValue) - Assert.AreEqual (obj.Pi5, Pi5.Value, "Pi5"); - if (Pi6.HasValue) - Assert.AreEqual (obj.Pi6, Pi6.Value, "Pi6"); - if (Pi7.HasValue) - Assert.AreEqual (obj.Pi7, Pi7.Value, "Pi7"); - if (Pi8.HasValue) - Assert.AreEqual (obj.Pi8, Pi8.Value, "Pi8"); - if (Pi9.HasValue) - Assert.AreEqual (obj.Pi9, Pi9.Value, "Pi9"); - if (Pf1.HasValue) - Assert.AreEqual (obj.Pf1, Pf1.Value, "Pf1"); - if (Pf2.HasValue) - Assert.AreEqual (obj.Pf2, Pf2.Value, "Pf2"); - if (Pf3.HasValue) - Assert.AreEqual (obj.Pf3, Pf3.Value, "Pf3"); - if (Pf4.HasValue) - Assert.AreEqual (obj.Pf4, Pf4.Value, "Pf4"); - if (Pf5.HasValue) - Assert.AreEqual (obj.Pf5, Pf5.Value, "Pf5"); - if (Pf6.HasValue) - Assert.AreEqual (obj.Pf6, Pf6.Value, "Pf6"); - if (Pf7.HasValue) - Assert.AreEqual (obj.Pf7, Pf7.Value, "Pf7"); - if (Pf8.HasValue) - Assert.AreEqual (obj.Pf8, Pf8.Value, "Pf8"); - if (Pf9.HasValue) - Assert.AreEqual (obj.Pf9, Pf9.Value, "Pf9"); - if (Pd1.HasValue) - Assert.AreEqual (obj.Pd1, Pd1.Value, "Pd1"); - if (Pd2.HasValue) - Assert.AreEqual (obj.Pd2, Pd2.Value, "Pd2"); - if (Pd3.HasValue) - Assert.AreEqual (obj.Pd3, Pd3.Value, "Pd3"); - if (Pd4.HasValue) - Assert.AreEqual (obj.Pd4, Pd4.Value, "Pd4"); - if (Pd5.HasValue) - Assert.AreEqual (obj.Pd5, Pd5.Value, "Pd5"); - if (Pd6.HasValue) - Assert.AreEqual (obj.Pd6, Pd6.Value, "Pd6"); - if (Pd7.HasValue) - Assert.AreEqual (obj.Pd7, Pd7.Value, "Pd7"); - if (Pd8.HasValue) - Assert.AreEqual (obj.Pd8, Pd8.Value, "Pd8"); - if (Pd9.HasValue) - Assert.AreEqual (obj.Pd9, Pd9.Value, "Pd9"); - if (Pc1.HasValue) - Assert.AreEqual (obj.Pc1, Pc1.Value, "Pc1"); - if (Pc2.HasValue) - Assert.AreEqual (obj.Pc2, Pc2.Value, "Pc2"); - if (Pc3.HasValue) - Assert.AreEqual (obj.Pc3, Pc3.Value, "Pc3"); - if (Pc4.HasValue) - Assert.AreEqual (obj.Pc4, Pc4.Value, "Pc4"); - if (Pc5.HasValue) - Assert.AreEqual (obj.Pc5, Pc5.Value, "Pc5"); -// if (Pc6.HasValue) -// Assert.AreEqual (obj.Pc6, Pc6.Value, "Pc6"); -// if (Pc7.HasValue) -// Assert.AreEqual (obj.Pc7, Pc7.Value, "Pc7"); -// if (Pc8.HasValue) -// Assert.AreEqual (obj.Pc8, Pc8.Value, "Pc8"); -// if (Pc9.HasValue) -// Assert.AreEqual (obj.Pc9, Pc9.Value, "Pc9"); - - if (PSiid1.HasValue) - Assert.AreEqual (obj.PSiid, PSiid1.Value, "PSiid1"); - - if (PSd1.HasValue) - Assert.AreEqual (obj.PSd, PSd1.Value, "PSd1"); - - if (PSf1.HasValue) - Assert.AreEqual (obj.PSf, PSf1.Value, "PSf1"); - } - public class TestClass : ObjCRegistrarTest { } diff --git a/tests/monotouch-test/ObjCRuntime/TrampolineTest.cs b/tests/monotouch-test/ObjCRuntime/TrampolineTest.cs index 1508ec3032..aebe4a4d96 100644 --- a/tests/monotouch-test/ObjCRuntime/TrampolineTest.cs +++ b/tests/monotouch-test/ObjCRuntime/TrampolineTest.cs @@ -43,10 +43,19 @@ namespace MonoTouchFixtures.ObjCRuntime { public class TrampolineTest { public static readonly nfloat pi = 3.14159f; - public bool IsSim64 { get { return IntPtr.Size == 8 && Runtime.Arch == Arch.SIMULATOR; } } - public bool IsSim32 { get { return IntPtr.Size == 4 && Runtime.Arch == Arch.SIMULATOR; } } - public bool IsArm64 { get { return IntPtr.Size == 8 && Runtime.Arch == Arch.DEVICE; } } - public bool IsArm32 { get { return IntPtr.Size == 4 && Runtime.Arch == Arch.DEVICE; } } + public static bool IsSim64 { get { return IntPtr.Size == 8 && Runtime.Arch == Arch.SIMULATOR; } } + public static bool IsSim32 { get { return IntPtr.Size == 4 && Runtime.Arch == Arch.SIMULATOR; } } + public static bool IsArm64 { get { return IntPtr.Size == 8 && Runtime.Arch == Arch.DEVICE; } } + public static bool IsArm32 { + get { +#if __WATCHOS__ + return false; +#else + return IntPtr.Size == 4 && Runtime.Arch == Arch.DEVICE; +#endif + } + } + public static bool IsArmv7k { get { #if __WATCHOS__ @@ -76,229 +85,6 @@ namespace MonoTouchFixtures.ObjCRuntime { } #endif // !__WATCHOS__ - [Test] - public void StretIIIITrampolineTest () - { - StretTrampolines obj = new StretTrampolines (); - IntPtr class_ptr = Class.GetHandle ("StretTrampolines"); - IIIIStruct rv = new IIIIStruct (); - double rvd; - float rvf; - - if (IsSim64 || IsArm64 || IsArmv7k) { - rv = IIIIStruct_objc_msgSend (obj.Handle, new Selector ("Test_IIIIStruct").Handle); - } else { - IIIIStruct_objc_msgSend_stret (out rv, obj.Handle, new Selector ("Test_IIIIStruct").Handle); - } - Assert.That ("[1;2;3;4]" == rv.ToString ()); - if (IsSim64 || IsArm64 || IsArmv7k) { - rv = IIIIStruct_objc_msgSend (class_ptr, new Selector ("Test_StaticIIIIStruct").Handle); - } else { - IIIIStruct_objc_msgSend_stret (out rv, class_ptr, new Selector ("Test_StaticIIIIStruct").Handle); - } - Assert.That ("[10;20;30;40]" == rv.ToString ()); - if (IsSim64 || IsArm64 || IsArmv7k) { - rv = IIIIStruct_objc_msgSend (obj.Handle, new Selector ("Test_IIIIStructProperty").Handle); - } else { - IIIIStruct_objc_msgSend_stret (out rv, obj.Handle, new Selector ("Test_IIIIStructProperty").Handle); - } - Assert.That ("[100;200;300;400]" == rv.ToString ()); - if (IsSim64 || IsArm64 || IsArmv7k) { - rv = IIIIStruct_objc_msgSend (class_ptr, new Selector ("Test_StaticIIIIStructProperty").Handle); - } else { - IIIIStruct_objc_msgSend_stret (out rv, class_ptr, new Selector ("Test_StaticIIIIStructProperty").Handle); - } - Assert.That ("[1000;2000;3000;4000]" == rv.ToString ()); - - rvd = rvf = 0; - if (IsSim64 || IsArm64 || IsArmv7k) { - rv = IIIIStruct_objc_msgSend_out_float (class_ptr, new Selector ("Test_StaticIIIIStruct_out_Float:").Handle, out rvf); - } else { - IIIIStruct_objc_msgSend_stret_out_float (out rv, class_ptr, new Selector ("Test_StaticIIIIStruct_out_Float:").Handle, out rvf); - } - //Console.WriteLine ("Got: {0} and {1} and {2}", rv.ToString (), rvf, rvd); - Assert.That ("[10;20;300;4000]" == rv.ToString ()); - Assert.That (rvf == 3.15f); - - rvd = rvf = 0; - if (IsSim64 || IsArm64 || IsArmv7k) { - rv = IIIIStruct_objc_msgSend_out_double (obj.Handle, new Selector ("Test_IIIIStruct_out_Double:").Handle, out rvd); - } else { - IIIIStruct_objc_msgSend_stret_out_double (out rv, obj.Handle, new Selector ("Test_IIIIStruct_out_Double:").Handle, out rvd); - } - //Console.WriteLine ("Got: {0} and {1} and {2}", rv.ToString (), rvf, rvd); - Assert.That ("[1;20;300;4000]" == rv.ToString ()); - Assert.That (rvd == 3.14); - - } - - [Test] - public void StretFFFFTrampolineTest () - { - StretTrampolines obj = new StretTrampolines (); - IntPtr class_ptr = Class.GetHandle ("StretTrampolines"); - var rv = new FFFFStruct (); - double rvd; - float rvf; - - if (IsSim64 || IsArm64 || IsArmv7k) { - rv = FFFFStruct_objc_msgSend (obj.Handle, new Selector ("Test_FFFFStruct").Handle); - } else { - FFFFStruct_objc_msgSend_stret (out rv, obj.Handle, new Selector ("Test_FFFFStruct").Handle); - } - Assert.That ("[1;2;3;4]" == rv.ToString ()); - if (IsSim64 || IsArm64 || IsArmv7k) { - rv = FFFFStruct_objc_msgSend (class_ptr, new Selector ("Test_StaticFFFFStruct").Handle); - } else { - FFFFStruct_objc_msgSend_stret (out rv, class_ptr, new Selector ("Test_StaticFFFFStruct").Handle); - } - Assert.That ("[10;20;30;40]" == rv.ToString ()); - if (IsSim64 || IsArm64 || IsArmv7k) { - rv = FFFFStruct_objc_msgSend (obj.Handle, new Selector ("Test_FFFFStructProperty").Handle); - } else { - FFFFStruct_objc_msgSend_stret (out rv, obj.Handle, new Selector ("Test_FFFFStructProperty").Handle); - } - Assert.That ("[100;200;300;400]" == rv.ToString ()); - if (IsSim64 || IsArm64 || IsArmv7k) { - rv = FFFFStruct_objc_msgSend (class_ptr, new Selector ("Test_StaticFFFFStructProperty").Handle); - } else { - FFFFStruct_objc_msgSend_stret (out rv, class_ptr, new Selector ("Test_StaticFFFFStructProperty").Handle); - } - Assert.That ("[1000;2000;3000;4000]" == rv.ToString ()); - - rvd = rvf = 0; - if (IsSim64 || IsArm64 || IsArmv7k) { - rv = FFFFStruct_objc_msgSend_out_float (class_ptr, new Selector ("Test_StaticFFFFStruct_out_Float:").Handle, out rvf); - } else { - FFFFStruct_objc_msgSend_stret_out_float (out rv, class_ptr, new Selector ("Test_StaticFFFFStruct_out_Float:").Handle, out rvf); - } - //Console.WriteLine ("Got: {0} and {1} and {2}", rv.ToString (), rvf, rvd); - Assert.That ("[10;20;300;4000]" == rv.ToString ()); - Assert.That (rvf == 3.15f); - - rvd = rvf = 0; - if (IsSim64 || IsArm64 || IsArmv7k) { - rv = FFFFStruct_objc_msgSend_out_double (obj.Handle, new Selector ("Test_FFFFStruct_out_Double:").Handle, out rvd); - } else { - FFFFStruct_objc_msgSend_stret_out_double (out rv, obj.Handle, new Selector ("Test_FFFFStruct_out_Double:").Handle, out rvd); - } - //Console.WriteLine ("Got: {0} and {1} and {2}", rv.ToString (), rvf, rvd); - Assert.That ("[1;20;300;4000]" == rv.ToString ()); - Assert.That (rvd == 3.14); - } - - [Test] - public void StretFIFITrampolineTest () - { - StretTrampolines obj = new StretTrampolines (); - IntPtr class_ptr = Class.GetHandle ("StretTrampolines"); - var rv = new FIFIStruct (); - double rvd; - float rvf; - - if (IsSim64 || IsArm64 || IsArmv7k) { - rv = FIFIStruct_objc_msgSend (obj.Handle, new Selector ("Test_FIFIStruct").Handle); - } else { - FIFIStruct_objc_msgSend_stret (out rv, obj.Handle, new Selector ("Test_FIFIStruct").Handle); - } - Assert.That ("[1;2;3;4]" == rv.ToString ()); - if (IsSim64 || IsArm64 || IsArmv7k) { - rv = FIFIStruct_objc_msgSend (class_ptr, new Selector ("Test_StaticFIFIStruct").Handle); - } else { - FIFIStruct_objc_msgSend_stret (out rv, class_ptr, new Selector ("Test_StaticFIFIStruct").Handle); - } - Assert.That ("[10;20;30;40]" == rv.ToString ()); - if (IsSim64 || IsArm64 || IsArmv7k) { - rv = FIFIStruct_objc_msgSend (obj.Handle, new Selector ("Test_FIFIStructProperty").Handle); - } else { - FIFIStruct_objc_msgSend_stret (out rv, obj.Handle, new Selector ("Test_FIFIStructProperty").Handle); - } - Assert.That ("[100;200;300;400]" == rv.ToString ()); - if (IsSim64 || IsArm64 || IsArmv7k) { - rv = FIFIStruct_objc_msgSend (class_ptr, new Selector ("Test_StaticFIFIStructProperty").Handle); - } else { - FIFIStruct_objc_msgSend_stret (out rv, class_ptr, new Selector ("Test_StaticFIFIStructProperty").Handle); - } - Assert.That ("[1000;2000;3000;4000]" == rv.ToString ()); - - rvd = rvf = 0; - if (IsSim64 || IsArm64 || IsArmv7k) { - rv = FIFIStruct_objc_msgSend_out_float (class_ptr, new Selector ("Test_StaticFIFIStruct_out_Float:").Handle, out rvf); - } else { - FIFIStruct_objc_msgSend_stret_out_float (out rv, class_ptr, new Selector ("Test_StaticFIFIStruct_out_Float:").Handle, out rvf); - } - //Console.WriteLine ("Got: {0} and {1} and {2}", rv.ToString (), rvf, rvd); - Assert.That ("[10;20;300;4000]" == rv.ToString ()); - Assert.That (rvf == 3.15f); - - rvd = rvf = 0; - if (IsSim64 || IsArm64 || IsArmv7k) { - rv = FIFIStruct_objc_msgSend_out_double (obj.Handle, new Selector ("Test_FIFIStruct_out_Double:").Handle, out rvd); - } else { - FIFIStruct_objc_msgSend_stret_out_double (out rv, obj.Handle, new Selector ("Test_FIFIStruct_out_Double:").Handle, out rvd); - } - //Console.WriteLine ("Got: {0} and {1} and {2}", rv.ToString (), rvf, rvd); - Assert.That ("[1;20;300;4000]" == rv.ToString ()); - Assert.That (rvd == 3.14); - } - - [Test] - public void StretIFIFTrampolineTest () - { - StretTrampolines obj = new StretTrampolines (); - IntPtr class_ptr = Class.GetHandle ("StretTrampolines"); - var rv = new IFIFStruct (); - double rvd; - float rvf; - - if (IsSim64 || IsArm64 || IsArmv7k) { - rv = IFIFStruct_objc_msgSend (obj.Handle, new Selector ("Test_IFIFStruct").Handle); - } else { - IFIFStruct_objc_msgSend_stret (out rv, obj.Handle, new Selector ("Test_IFIFStruct").Handle); - } - Assert.That ("[1;2;3;4]" == rv.ToString ()); - if (IsSim64 || IsArm64 || IsArmv7k) { - rv = IFIFStruct_objc_msgSend (class_ptr, new Selector ("Test_StaticIFIFStruct").Handle); - } else { - IFIFStruct_objc_msgSend_stret (out rv, class_ptr, new Selector ("Test_StaticIFIFStruct").Handle); - } - Assert.That ("[10;20;30;40]" == rv.ToString ()); - if (IsSim64 || IsArm64 || IsArmv7k) { - rv = IFIFStruct_objc_msgSend (obj.Handle, new Selector ("Test_IFIFStructProperty").Handle); - } else { - IFIFStruct_objc_msgSend_stret (out rv, obj.Handle, new Selector ("Test_IFIFStructProperty").Handle); - } - Assert.That ("[100;200;300;400]" == rv.ToString ()); - if (IsSim64 || IsArm64 || IsArmv7k) { - rv = IFIFStruct_objc_msgSend (class_ptr, new Selector ("Test_StaticIFIFStructProperty").Handle); - } else { - IFIFStruct_objc_msgSend_stret (out rv, class_ptr, new Selector ("Test_StaticIFIFStructProperty").Handle); - } - Assert.That ("[1000;2000;3000;4000]" == rv.ToString ()); - - rvd = rvf = 0; - if (IsSim64 || IsArm64 || IsArmv7k) { - rv = IFIFStruct_objc_msgSend_out_float (class_ptr, new Selector ("Test_StaticIFIFStruct_out_Float:").Handle, out rvf); - } else { - IFIFStruct_objc_msgSend_stret_out_float (out rv, class_ptr, new Selector ("Test_StaticIFIFStruct_out_Float:").Handle, out rvf); - } - //Console.WriteLine ("Got: {0} and {1} and {2}", rv.ToString (), rvf, rvd); - Assert.That ("[10;20;300;4000]" == rv.ToString ()); - Assert.That (rvf == 3.15f); - - rvd = rvf = 0; - if (IsSim64 || IsArm64 || IsArmv7k) { - rv = IFIFStruct_objc_msgSend_out_double (obj.Handle, new Selector ("Test_IFIFStruct_out_Double:").Handle, out rvd); - } else { - IFIFStruct_objc_msgSend_stret_out_double (out rv, obj.Handle, new Selector ("Test_IFIFStruct_out_Double:").Handle, out rvd); - } - //Console.WriteLine ("Got: {0} and {1} and {2}", rv.ToString (), rvf, rvd); - Assert.That ("[1;20;300;4000]" == rv.ToString ()); - Assert.That (rvd == 3.14); - } - - - [Test] public void DoubleReturnTest () { @@ -356,82 +142,6 @@ namespace MonoTouchFixtures.ObjCRuntime { extern static void Matrix4_objc_msgSend_stret (out OpenTK.Matrix4 retval, IntPtr receiver, IntPtr selector); #endif // !__WATCHOS__ - [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend_stret")] - extern static void IIIIStruct_objc_msgSend_stret (out IIIIStruct retval, IntPtr receiver, IntPtr selector); - - [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] - extern static IIIIStruct IIIIStruct_objc_msgSend (IntPtr receiver, IntPtr selector); - - [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend_stret")] - extern static void IIIIStruct_objc_msgSend_stret_out_double (out IIIIStruct retval, IntPtr receiver, IntPtr selector, out double arg1); - - [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] - extern static IIIIStruct IIIIStruct_objc_msgSend_out_double (IntPtr receiver, IntPtr selector, out double arg1); - - [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend_stret")] - extern static void IIIIStruct_objc_msgSend_stret_out_float (out IIIIStruct retval, IntPtr receiver, IntPtr selector, out float arg1); - - [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] - extern static IIIIStruct IIIIStruct_objc_msgSend_out_float (IntPtr receiver, IntPtr selector, out float arg1); - - - [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend_stret")] - extern static void FFFFStruct_objc_msgSend_stret (out FFFFStruct retval, IntPtr receiver, IntPtr selector); - - [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] - extern static FFFFStruct FFFFStruct_objc_msgSend (IntPtr receiver, IntPtr selector); - - [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend_stret")] - extern static void FFFFStruct_objc_msgSend_stret_out_double (out FFFFStruct retval, IntPtr receiver, IntPtr selector, out double arg1); - - [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] - extern static FFFFStruct FFFFStruct_objc_msgSend_out_double (IntPtr receiver, IntPtr selector, out double arg1); - - [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend_stret")] - extern static void FFFFStruct_objc_msgSend_stret_out_float (out FFFFStruct retval, IntPtr receiver, IntPtr selector, out float arg1); - - [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] - extern static FFFFStruct FFFFStruct_objc_msgSend_out_float (IntPtr receiver, IntPtr selector, out float arg1); - - - [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend_stret")] - extern static void IFIFStruct_objc_msgSend_stret (out IFIFStruct retval, IntPtr receiver, IntPtr selector); - - [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] - extern static IFIFStruct IFIFStruct_objc_msgSend (IntPtr receiver, IntPtr selector); - - [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend_stret")] - extern static void IFIFStruct_objc_msgSend_stret_out_double (out IFIFStruct retval, IntPtr receiver, IntPtr selector, out double arg1); - - [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] - extern static IFIFStruct IFIFStruct_objc_msgSend_out_double (IntPtr receiver, IntPtr selector, out double arg1); - - [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend_stret")] - extern static void IFIFStruct_objc_msgSend_stret_out_float (out IFIFStruct retval, IntPtr receiver, IntPtr selector, out float arg1); - - [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] - extern static IFIFStruct IFIFStruct_objc_msgSend_out_float (IntPtr receiver, IntPtr selector, out float arg1); - - - [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend_stret")] - extern static void FIFIStruct_objc_msgSend_stret (out FIFIStruct retval, IntPtr receiver, IntPtr selector); - - [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] - extern static FIFIStruct FIFIStruct_objc_msgSend (IntPtr receiver, IntPtr selector); - - [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend_stret")] - extern static void FIFIStruct_objc_msgSend_stret_out_double (out FIFIStruct retval, IntPtr receiver, IntPtr selector, out double arg1); - - [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] - extern static FIFIStruct FIFIStruct_objc_msgSend_out_double (IntPtr receiver, IntPtr selector, out double arg1); - - [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend_stret")] - extern static void FIFIStruct_objc_msgSend_stret_out_float (out FIFIStruct retval, IntPtr receiver, IntPtr selector, out float arg1); - - [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")] - extern static FIFIStruct FIFIStruct_objc_msgSend_out_float (IntPtr receiver, IntPtr selector, out float arg1); - - [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend_stret")] extern static void double_objc_msgSend_stret_out_double (out double retval, IntPtr receiver, IntPtr selector, out double arg1); @@ -634,14 +344,14 @@ namespace MonoTouchFixtures.ObjCRuntime { PointF point; SizeF size; - if (IsArm32 && !IsArmv7k) { + if (IsArm32) { Messaging.PointF_objc_msgSend_stret (out point, obj.Handle, new Selector ("testPointF").Handle); } else { point = Messaging.PointF_objc_msgSend (obj.Handle, new Selector ("testPointF").Handle); } Assert.That (point == new PointF (pi*2, pi*20), "#testPointF"); - if (IsArm32 && !IsArmv7k) { + if (IsArm32) { Messaging.SizeF_objc_msgSend_stret (out size, obj.Handle, new Selector ("testSizeF").Handle); } else { size = Messaging.SizeF_objc_msgSend (obj.Handle, new Selector ("testSizeF").Handle); @@ -804,88 +514,6 @@ namespace MonoTouchFixtures.ObjCRuntime { return true; } } - - [Preserve (AllMembers = true)] - public struct IIIIStruct - { - public int A, B, C, D; - - public IIIIStruct (int a, int b, int c, int d) - { - A = a; - B = b; - C = c; - D = d; - } - - public override string ToString () - { - return string.Format ("[{0};{1};{2};{3}]", A, B, C, D); - } - } - - [Preserve (AllMembers = true)] - public struct FFFFStruct - { - public float A, B, C, D; - - public FFFFStruct (float a, float b, float c, float d) - { - A = a; - B = b; - C = c; - D = d; - } - - public override string ToString () - { - return string.Format ("[{0};{1};{2};{3}]", A, B, C, D); - } - } - - [Preserve (AllMembers = true)] - public struct FIFIStruct - { - public float A; - public int B; - public float C; - public int D; - - public FIFIStruct (float a, int b, float c, int d) - { - A = a; - B = b; - C = c; - D = d; - } - - public override string ToString () - { - return string.Format ("[{0};{1};{2};{3}]", A, B, C, D); - } - } - - [Preserve (AllMembers = true)] - public struct IFIFStruct - { - public int A; - public float B; - public int C; - public float D; - - public IFIFStruct (int a, float b, int c, float d) - { - A = a; - B = b; - C = c; - D = d; - } - - public override string ToString () - { - return string.Format ("[{0};{1};{2};{3}]", A, B, C, D); - } - } [Preserve (AllMembers = true)] [Register ("LongTrampolines")] @@ -913,158 +541,6 @@ namespace MonoTouchFixtures.ObjCRuntime { [Preserve (AllMembers = true)] public class StretTrampolines : NSObject { - /* IIII */ - - [Export ("Test_IIIIStruct")] - IIIIStruct Test_IIIIStruct () - { - return new IIIIStruct (1, 2, 3, 4); - } - - [Export ("Test_StaticIIIIStruct")] - static IIIIStruct Test_StaticIIIIStruct () - { - return new IIIIStruct (10, 20, 30, 40); - } - - IIIIStruct Test_IIIIStructProperty { - [Export ("Test_IIIIStructProperty")] - get { return new IIIIStruct (100, 200, 300, 400); } - } - - static IIIIStruct Test_StaticIIIIStructProperty { - [Export ("Test_StaticIIIIStructProperty")] - get { return new IIIIStruct (1000, 2000, 3000, 4000); } - } - - [Export ("Test_IIIIStruct_out_Double:")] - IIIIStruct Test_IIIIStruct_out_Double (out double foo) - { - foo = 3.14; - return new IIIIStruct (1, 20, 300, 4000); - } - - [Export ("Test_StaticIIIIStruct_out_Float:")] - static IIIIStruct Test_StaticIIIIStruct_out_Float (out float foo) - { - foo = 3.15f; - return new IIIIStruct (10, 20, 300, 4000); - } - - /* FFFF */ - - [Export ("Test_FFFFStruct")] - FFFFStruct Test_FFFFStruct () - { - return new FFFFStruct (1, 2, 3, 4); - } - - [Export ("Test_StaticFFFFStruct")] - static FFFFStruct Test_StaticFFFFStructStruct () - { - return new FFFFStruct (10, 20, 30, 40); - } - - FFFFStruct Test_FFFFStructtStructProperty { - [Export ("Test_FFFFStructProperty")] - get { return new FFFFStruct (100, 200, 300, 400); } - } - - static FFFFStruct Test_StaticFFFFStructProperty { - [Export ("Test_StaticFFFFStructProperty")] - get { return new FFFFStruct (1000, 2000, 3000, 4000); } - } - - [Export ("Test_FFFFStruct_out_Double:")] - FFFFStruct Test_FFFFStruct_out_Double (out double foo) - { - foo = 3.14; - return new FFFFStruct (1, 20, 300, 4000); - } - - [Export ("Test_StaticFFFFStruct_out_Float:")] - static FFFFStruct Test_StaticFFFFStruct_out_Float (out float foo) - { - foo = 3.15f; - return new FFFFStruct (10, 20, 300, 4000); - } - - /* FIFI */ - - [Export ("Test_FIFIStruct")] - FIFIStruct Test_FIFIStruct () - { - return new FIFIStruct (1, 2, 3, 4); - } - - [Export ("Test_StaticFIFIStruct")] - static FIFIStruct Test_StaticFIFIStructStruct () - { - return new FIFIStruct (10, 20, 30, 40); - } - - FIFIStruct Test_FIFIStructtStructProperty { - [Export ("Test_FIFIStructProperty")] - get { return new FIFIStruct (100, 200, 300, 400); } - } - - static FIFIStruct Test_StaticFIFIStructProperty { - [Export ("Test_StaticFIFIStructProperty")] - get { return new FIFIStruct (1000, 2000, 3000, 4000); } - } - - [Export ("Test_FIFIStruct_out_Double:")] - FIFIStruct Test_FIFIStruct_out_Double (out double foo) - { - foo = 3.14; - return new FIFIStruct (1, 20, 300, 4000); - } - - [Export ("Test_StaticFIFIStruct_out_Float:")] - static FIFIStruct Test_StaticFIFIStruct_out_Float (out float foo) - { - foo = 3.15f; - return new FIFIStruct (10, 20, 300, 4000); - } - - /* IFIF */ - - [Export ("Test_IFIFStruct")] - IFIFStruct Test_IFIFStruct () - { - return new IFIFStruct (1, 2, 3, 4); - } - - [Export ("Test_StaticIFIFStruct")] - static IFIFStruct Test_StaticIFIFStructStruct () - { - return new IFIFStruct (10, 20, 30, 40); - } - - IFIFStruct Test_IFIFStructtStructProperty { - [Export ("Test_IFIFStructProperty")] - get { return new IFIFStruct (100, 200, 300, 400); } - } - - static IFIFStruct Test_StaticIFIFStructProperty { - [Export ("Test_StaticIFIFStructProperty")] - get { return new IFIFStruct (1000, 2000, 3000, 4000); } - } - - [Export ("Test_IFIFStruct_out_Double:")] - IFIFStruct Test_IFIFStruct_out_Double (out double foo) - { - foo = 3.14; - return new IFIFStruct (1, 20, 300, 4000); - } - - [Export ("Test_StaticIFIFStruct_out_Float:")] - static IFIFStruct Test_StaticIFIFStruct_out_Float (out float foo) - { - foo = 3.15f; - return new IFIFStruct (10, 20, 300, 4000); - } - #if !__WATCHOS__ [Export ("myTimeRange")] CMTimeRange TimeRange { diff --git a/tests/monotouch-test/monotouch-test.csproj b/tests/monotouch-test/monotouch-test.csproj index a220bdf11e..77af51a4f7 100644 --- a/tests/monotouch-test/monotouch-test.csproj +++ b/tests/monotouch-test/monotouch-test.csproj @@ -478,7 +478,9 @@ + + @@ -753,4 +755,15 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/tests/test-libraries/.gitignore b/tests/test-libraries/.gitignore index 78b905effc..dcb5821d82 100644 --- a/tests/test-libraries/.gitignore +++ b/tests/test-libraries/.gitignore @@ -3,4 +3,7 @@ .libs libtest-ar.m libtest-object.m +libtest.structs.h +libtest.properties.h +libtest.decompile.m diff --git a/tests/test-libraries/Makefile b/tests/test-libraries/Makefile index 8c126af6ae..a6a267398b 100644 --- a/tests/test-libraries/Makefile +++ b/tests/test-libraries/Makefile @@ -5,6 +5,30 @@ include $(TOP)/Make.config # in system headers show up. export CCACHE_CPP2=1 +GENERATED_FILES = \ + libtest.structs.h \ + libtest.decompile.m \ + libtest.properties.h \ + ../bindings-test/ApiDefinition.generated.cs \ + ../bindings-test/StructsAndEnums.generated.cs \ + ../monotouch-test/ObjCRuntime/RegistrarTest.generated.cs \ + ../monotouch-test/ObjCRuntime/TrampolineTest.generated.cs \ + +GENERATED_FILES_PATTERN = \ + libtest.structs%h \ + libtest.decompile%m \ + libtest.properties%h \ + ../bindings-test/ApiDefinition.generated%cs \ + ../bindings-test/StructsAndEnums.generated%cs \ + ../monotouch-test/ObjCRuntime/RegistrarTest.generated%cs \ + ../monotouch-test/ObjCRuntime/TrampolineTest.generated%cs \ + +testgenerator.exe: testgenerator.cs Makefile + $(Q) mcs -out:$@ $< + +$(GENERATED_FILES_PATTERN): testgenerator.exe + $(Q) mono --debug $< + libtest-object.m libtest-ar.m: $(Q) ln -fhs libtest.m $@ @@ -24,12 +48,13 @@ $(2)_TARGETS = \ $$(foreach arch,$(3),.libs/$(1)/libtest-ar.$$(arch).a) \ .libs/$(1)/XTest.framework \ -all-local:: $$($(2)_TARGETS) +all-local:: $$($(2)_TARGETS) $(GENERATED_FILES) clean-$(1): rm -Rf .libs/$(1) CLEAN_TARGETS += clean-$(1) +EXTRA_DEPENDENCIES = libtest.h $(GENERATED_FILES) .libs/$(1)/libtest-object.%.o: export EXTRA_DEFINES=-DPREFIX=1 .libs/$(1)/libtest-ar.%.o: export EXTRA_DEFINES=-DPREFIX=2 diff --git a/tests/test-libraries/libtest.cs b/tests/test-libraries/libtest.cs new file mode 100644 index 0000000000..3eeccd06f7 --- /dev/null +++ b/tests/test-libraries/libtest.cs @@ -0,0 +1 @@ + diff --git a/tests/test-libraries/libtest.h b/tests/test-libraries/libtest.h index 212a69b4b7..d766173067 100644 --- a/tests/test-libraries/libtest.h +++ b/tests/test-libraries/libtest.h @@ -13,31 +13,7 @@ void useZLib (); * Various structs used in ObjCRegistrarTest */ -struct Sd { double d1; } Sd; -struct Sdd { double d1; double d2; } Sdd; -struct Sddd { double d1; double d2; double d3; } Sddd; -struct Sdddd { double d1; double d2; double d3; double d4; } Sdddd; -struct Si { int i1; } Si; -struct Sii { int i1; int i2; } Sii; -struct Siii { int i1; int i2; int i3; } Siii; -struct Siiii { int i1; int i2; int i3; int i4; } Siiii; -struct Siiiii { int i1; int i2; int i3; int i4; int i5; } Siiiii; -struct Sid { int i1; double d2; } Sid; -struct Sdi { double d1; int i2; } Sdi; -struct Sidi { int i1; double d2; int i3; } Sidi; -struct Siid { int i1; int i2; double d3; } Siid; -struct Sddi { double d1; double d2; int i3; } Sddi; -struct Sl { long l1; } Sl; -struct Sll { long l1; long l2; } Sll; -struct Slll { long l1; long l2; long l3; } Slll; -struct Scccc { char c1; char c2; char c3; char c4; } Scccc; -struct Sffff { float f1; float f2; float f3; float f4; } Sffff; -struct Sif { int i1; float f2; } Sif; -struct Sf { float f1; } Sf; -struct Sff { float f1; float f2; } Sff; -struct Siff { int i1; float f2; float f3; } Siff; -struct Siiff { int i1; int i2; float f3; float f4; } Siiff; -struct Sfi { float f1; int i2; } Sfi; +#include "libtest.structs.h" typedef unsigned int (^RegistrarTestBlock) (unsigned int magic); @@ -79,9 +55,7 @@ typedef unsigned int (^RegistrarTestBlock) (unsigned int magic); @property char Pc4; @property char Pc5; - @property struct Siid PSiid1; - @property struct Sd PSd1; - @property struct Sf PSf1; +#include "libtest.properties.h" -(void) V; diff --git a/tests/test-libraries/libtest.m b/tests/test-libraries/libtest.m index c70afb80a2..e25d9bfe1c 100644 --- a/tests/test-libraries/libtest.m +++ b/tests/test-libraries/libtest.m @@ -80,12 +80,12 @@ static UltimateMachine *shared; -(struct Sd) Sd { - return _PSd1; + return _PSd; } -(struct Sf) Sf { - return _PSf1; + return _PSf; } -(void) V:(int)i1 i:(int)i2 i:(int)i3 i:(int)i4 i:(int)i5 i:(int)i6 i:(int)i7 @@ -115,12 +115,12 @@ static UltimateMachine *shared; -(void) V:(int)i1 i:(int)i2 Siid:(struct Siid)s1 i:(int)i3 i:(int)i4 d:(double)d1 d:(double)d2 d:(double)d3 i:(int)i5 i:(int)i6 i:(int)i7 { - _Pi1 = i1; _Pi2 = i2; _PSiid1 = s1; _Pi3 = i3; _Pi4 = i4; _Pd1 = d1; _Pd2 = d2; _Pd3 = d2; _Pi5 = i5; _Pi6 = i6; _Pi7 = i7; + _Pi1 = i1; _Pi2 = i2; _PSiid = s1; _Pi3 = i3; _Pi4 = i4; _Pd1 = d1; _Pd2 = d2; _Pd3 = d2; _Pi5 = i5; _Pi6 = i6; _Pi7 = i7; } -(void) V:(int)i1 i:(int)i2 f:(float)f1 Siid:(struct Siid)s1 i:(int)i3 i:(int)i4 d:(double)d1 d:(double)d2 d:(double)d3 i:(int)i5 i:(int)i6 i:(int)i7 { - _Pi1 = i1; _Pi2 = i2; _Pf1 = f1; _PSiid1 = s1; _Pi3 = i3; _Pi4 = i4; _Pd1 = d1; _Pd2 = d2; _Pd3 = d3; _Pi5 = i5; _Pi6 = i6; _Pi7 = i7; + _Pi1 = i1; _Pi2 = i2; _Pf1 = f1; _PSiid = s1; _Pi3 = i3; _Pi4 = i4; _Pd1 = d1; _Pd2 = d2; _Pd3 = d3; _Pi5 = i5; _Pi6 = i6; _Pi7 = i7; } -(void) V:(char)c1 c:(char)c2 c:(char)c3 c:(char)c4 c:(char)c5 i:(int)i1 d:(double)d1 @@ -252,4 +252,6 @@ static UltimateMachine *shared; { // Do nothing } -@end \ No newline at end of file +@end + +#include "libtest.decompile.m" diff --git a/tests/test-libraries/testgenerator.cs b/tests/test-libraries/testgenerator.cs new file mode 100644 index 0000000000..a0fed5a378 --- /dev/null +++ b/tests/test-libraries/testgenerator.cs @@ -0,0 +1,538 @@ +using System; +using System.IO; +using System.Linq; +using System.Text; + +static class C { + [Flags] + enum Architecture + { + None = 0, + Sim32 = 1, + Sim64 = 2, + Arm32 = 4, + Armv7k = 8, + // Arm64 is never stret + } + + // X86: structs > 8 + structs with 3 members. + // X64: structs > 16 + // ARM32: all structs, except those matching an integral platform type (i.e. a struct with a single int, but not a struct with a single float). + // ARM64: never + // armv7k: > 16, except homogeneous types with no more than 4 elements (i.e. structs with 3 or 4 doubles). + // the numbers below are bitmasks of Architecture values. + static string [] structs_and_stret = { + /* integral types */ + "c:0", "cc:4", "ccc:5", "cccc:4", + "s:0", "ss:4", "sss:5", "ssss:4", + "i:0", "ii:4", "iii:5", "iiii:5", "iiiii:15", + "l:4", "ll:5", "lll:15", "llll:15", "lllll:15", + /* floating point types */ + "f:4", "ff:4", "fff:5", "ffff:5", "fffff:15", + "d:4", "dd:5", "ddd:7", "dddd:7", "ddddd:15", + /* mixed types */ + "if:4", "fi:4", // 8 bytes + "iff:5", // 12 bytes + "iiff:5", // 16 bytes + "id:5", "di:5", // 16 bytes + "iid:5", // 16 bytes + "idi:15", // 16 bytes on i386 and 24 bytes on x86_64 (due to alignment) + "ddi:15", // 24 bytes + "didi:15", // 24 bytes on 32-bit arch, 32 bytes on 64-bit arch + "idid:15", // 24 bytes on 32-bit arch, 32 bytes on 64-bit arch + "dldl:15", + "ldld:15", + "fifi:5", + "ifif:5", + }; + + static string [] structs = structs_and_stret.Select ((v) => v.IndexOf (':') >= 0 ? v.Substring (0, v.IndexOf (':')) : v).ToArray (); + static Architecture [] strets = structs_and_stret.Select ((v) => v.IndexOf (':') >= 0 ? (Architecture) int.Parse (v.Substring (v.IndexOf (':') + 1)) : Architecture.None).ToArray (); + + static string GetNativeName (char t) + { + switch (t) { + case 'f': return "float"; + case 'd': return "double"; + case 'c': return "char"; + case 's': return "short"; + case 'i': return "int"; + case 'l': return "long long"; + default: + throw new NotImplementedException (); + } + } + + static string GetManagedName (char t) + { + switch (t) { + case 'f': return "float"; + case 'd': return "double"; + case 'c': return "byte"; + case 's': return "short"; + case 'i': return "int"; + case 'l': return "long"; + default: + throw new NotImplementedException (); + } + } + + static string GetValue (char t, int i, int multiplier = 1) + { + switch (t) { + case 'c': + case 's': + case 'i': + case 'l': return ((i + 1) * multiplier).ToString (); + case 'f': return (3.14f * (i + 1) * multiplier) + "f"; + case 'd': return (1.23f * (i + 1) * multiplier).ToString (); + default: + throw new NotImplementedException (); + } + } + + static void WriteLibTestStructH () + { + var w = new StringBuilder (); + + foreach (var s in structs) { + w.Append ($"struct S{s} {{ "); + for (int i = 0; i < s.Length; i++) { + w.Append (GetNativeName (s [i])).Append (" x").Append (i).Append ("; "); + } + w.AppendLine ($"}} S{s};"); + } + + File.WriteAllText ("libtest.structs.h", w.ToString ()); + } + + static void WriteLibTestDecompileM () + { + var w = new StringBuilder (); + + // This is code to be disassembled to see how it's compiled by clang + // to see if a particular structure is using objc_msgSend_stret or not. + // + // To disassemble: + // otool -vVt .libs/ios/libtest.armv7.o + // + // Then in the _decompile_me output, look for the _____* function call, + // matching the structure you want to check, and then backtrack until + // you see either an objc_msgSend or objc_msgSend_stret call, and you + // have your answer. +#if false + w.AppendLine ("extern \"C\" {"); + foreach (var s in structs) + w.AppendLine ($"void _____________________________________{s} (struct S{s} x) __attribute__ ((optnone)) {{ }}"); + w.AppendLine ("void decompile_me () __attribute__ ((optnone))"); + w.AppendLine ("{"); + w.AppendLine ("\tObjCRegistrarTest *obj = NULL;"); + foreach (var s in structs) { + w.AppendLine ($"\t_____________________________________{s} ([obj PS{s}]);"); + } + w.AppendLine ("}"); + w.AppendLine ("}"); +#endif + + File.WriteAllText ("libtest.decompile.m", w.ToString ()); + } + + static void WriteLibTestPropertiesH () + { + var w = new StringBuilder (); + + foreach (var s in structs) + w.AppendLine ($"\t@property struct S{s} PS{s};"); + + File.WriteAllText ("libtest.properties.h", w.ToString ()); + } + + static void WriteApiDefinition () + { + var w = new StringBuilder (); + + w.AppendLine (@"using System; +#if !__WATCHOS__ +using System.Drawing; +#endif + +#if __UNIFIED__ +using ObjCRuntime; +using Foundation; +using UIKit; +#else +using MonoTouch.ObjCRuntime; +using MonoTouch.Foundation; +using MonoTouch.UIKit; +#endif + +namespace Bindings.Test { + partial interface ObjCRegistrarTest { + +"); + + foreach (var s in structs) { + w.AppendLine ($"\t\t[Export (\"PS{s}\")]"); + w.AppendLine ($"\t\tS{s} PS{s} {{ get; set; }}"); + w.AppendLine (); + } + + w.AppendLine (@" } +}"); + + File.WriteAllText ("../bindings-test/ApiDefinition.generated.cs", w.ToString ()); + } + + static void WriteStructsAndEnums () + { + var w = new StringBuilder (); + + w.AppendLine (@"using System; +using System.Runtime.InteropServices; + +#if !__UNIFIED__ +using nint=System.Int32; +#endif + +namespace Bindings.Test +{ +"); + + foreach (var s in structs) { + w.AppendLine ($"\tpublic struct S{s} {{ "); + w.Append ("\t\t"); + for (int i = 0; i < s.Length; i++) { + w.Append ("public ").Append (GetManagedName (s [i])).Append (" x").Append (i).Append ("; "); + } + w.AppendLine (); + w.Append ($"\t\tpublic override string ToString () {{ return $\"S{s} ["); + for (int i = 0; i < s.Length; i++) { + w.Append ("{x").Append (i).Append ("};"); + } + w.Length--; + w.AppendLine ("]\"; } "); + w.AppendLine ("\t}"); + w.AppendLine (); + } + + w.AppendLine (@"}"); + + File.WriteAllText ("../bindings-test/StructsAndEnums.generated.cs", w.ToString ()); + } + + static void WriteRegistrarTests () + { + var w = new StringBuilder (); + + w.AppendLine (@" +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +using MonoTouchException=ObjCRuntime.RuntimeException; +using NativeException=Foundation.MonoTouchException; +#else +using MonoTouch; +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +using MonoTouchException=MonoTouch.RuntimeException; +using NativeException=MonoTouch.Foundation.MonoTouchException; +#endif +using NUnit.Framework; +using Bindings.Test; + +using XamarinTests.ObjCRuntime; + +namespace MonoTouchFixtures.ObjCRuntime { + + [TestFixture] + [Preserve (AllMembers = true)] + public class RegistrarTestGenerated {"); + + foreach (var s in structs) { + w.AppendLine ("\t\t[Test]"); + w.AppendLine ($"\t\tpublic void Test_{s} ()"); + w.AppendLine ("\t\t{"); + w.AppendLine ("\t\t\tusing (var tc = new ObjCRegistrarTest ()) {"); + w.AppendLine ($"\t\t\t\tvar s = tc.PS{s};"); + for (int i = 0; i < s.Length; i++) + w.AppendLine ($"\t\t\t\tAssert.AreEqual (0, s.x{i}, \"pre-#{i}\");"); + w.Append ($"\t\t\t\tvar k = new S{s} () {{ "); + for (int i = 0; i < s.Length; i++) + w.Append ($"x{i} = ").Append (GetValue (s [i], i)).Append (", "); + w.Length -= 2; + w.AppendLine ("};"); + w.AppendLine ($"\t\t\t\ttc.PS{s} = k;"); + w.AppendLine ($"\t\t\t\ts = tc.PS{s};"); + for (int i = 0; i < s.Length; i++) + w.AppendLine ($"\t\t\t\tAssert.AreEqual (k.x{i}, s.x{i}, \"post-#{i}\");"); + w.AppendLine ("\t\t\t}"); + w.AppendLine ("\t\t}"); + w.AppendLine (); + } + + w.AppendLine (@" } +}"); + + File.WriteAllText ("../monotouch-test/ObjCRuntime/RegistrarTest.generated.cs", w.ToString ()); + } + + static void WriteTrampolineTests () + { + var w = new StringBuilder (); + + w.AppendLine (@" +using System; +using System.Runtime.InteropServices; + +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +#else +using MonoTouch; +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +#endif +using NUnit.Framework; +using Bindings.Test; + +using XamarinTests.ObjCRuntime; + +namespace MonoTouchFixtures.ObjCRuntime { + + [TestFixture] + [Preserve (AllMembers = true)] + public class TrampolineTestGenerated {"); + w.AppendLine ("\t\tconst string LIBOBJC_DYLIB = \"/usr/lib/libobjc.dylib\";"); + w.AppendLine (); + + w.AppendLine ("\t\t[Register (\"GeneratedStretTrampolines\")]"); + w.AppendLine ("\t\t[Preserve (AllMembers = true)]"); + w.AppendLine ("\t\tpublic class GeneratedStretTrampolines : NSObject {"); + foreach (var s in structs) { + w.AppendLine (); + w.AppendLine ($"\t\t\t// {s}"); + + w.AppendLine (); + w.AppendLine ($"\t\t\t[Export (\"Test_{s}Struct\")]"); + w.AppendLine ($"\t\t\tS{s} Test_{s}Struct ()"); + w.AppendLine ($"\t\t\t{{"); + w.AppendLine ($"\t\t\t\treturn {GenerateNewExpression (s, 1)};"); + w.AppendLine ($"\t\t\t}}"); + + w.AppendLine (); + w.AppendLine ($"\t\t\t[Export (\"Test_Static{s}Struct\")]"); + w.AppendLine ($"\t\t\tstatic S{s} Test_Static{s}Struct ()"); + w.AppendLine ($"\t\t\t{{"); + w.AppendLine ($"\t\t\t\treturn {GenerateNewExpression (s, 2)};"); + w.AppendLine ($"\t\t\t}}"); + + w.AppendLine (); + w.AppendLine ($"\t\t\tS{s} Test_{s}StructProperty {{"); + w.AppendLine ($"\t\t\t\t[Export (\"Test_{s}StructProperty\")]"); + w.AppendLine ($"\t\t\t\tget {{ return {GenerateNewExpression (s, 3)}; }}"); + w.AppendLine ($"\t\t\t}}"); + + w.AppendLine (); + w.AppendLine ($"\t\t\tstatic S{s} Test_Static{s}StructProperty {{"); + w.AppendLine ($"\t\t\t\t[Export (\"Test_Static{s}StructProperty\")]"); + w.AppendLine ($"\t\t\t\tget {{ return {GenerateNewExpression (s, 4)}; }}"); + w.AppendLine ($"\t\t\t}}"); + + w.AppendLine (); + w.AppendLine ($"\t\t\t[Export (\"Test_{s}Struct_out_double:\")]"); + w.AppendLine ($"\t\t\tS{s} Test_{s}Struct (out double x0)"); + w.AppendLine ($"\t\t\t{{"); + w.AppendLine ($"\t\t\t\tx0 = 3.14;"); + w.AppendLine ($"\t\t\t\treturn {GenerateNewExpression (s, 5)};"); + w.AppendLine ($"\t\t\t}}"); + + w.AppendLine (); + w.AppendLine ($"\t\t\t[Export (\"Test_Static{s}Struct_out_float:\")]"); + w.AppendLine ($"\t\t\tstatic S{s} Test_Static{s}Struct (out float x0)"); + w.AppendLine ($"\t\t\t{{"); + w.AppendLine ($"\t\t\t\tx0 = 3.15f;"); + w.AppendLine ($"\t\t\t\treturn {GenerateNewExpression (s, 6)};"); + w.AppendLine ($"\t\t\t}}"); + } + w.AppendLine ("\t\t}"); + + foreach (var s in structs) { + if (s.Length == 1 || s.Contains ('c')) + continue; // our trampolines don't currently like structs with a single member, nor char members + + bool never; + w.AppendLine (); + w.AppendLine ($"\t\t[Test]"); + w.AppendLine ($"\t\tpublic void Test_{s} ()"); + w.AppendLine ($"\t\t{{"); + w.AppendLine ($"\t\t\tIntPtr class_ptr = Class.GetHandle (typeof (GeneratedStretTrampolines));"); + w.AppendLine ($"\t\t\tS{s} rv = new S{s} ();"); + w.AppendLine ($"\t\t\tdouble rvd;"); + w.AppendLine ($"\t\t\tfloat rvf;"); + w.AppendLine ($"\t\t\tusing (var obj = new GeneratedStretTrampolines ()) {{"); + + WriteStretConditions (w, s, out never); + if (never) { + w.AppendLine ($"\t\t\t\trv = S{s}_objc_msgSend (obj.Handle, new Selector (\"Test_{s}Struct\").Handle);"); + } else { + w.AppendLine ($"\t\t\t\t\tS{s}_objc_msgSend_stret (out rv, obj.Handle, new Selector (\"Test_{s}Struct\").Handle);"); + w.AppendLine ($"\t\t\t\t}} else {{"); + w.AppendLine ($"\t\t\t\t\trv = S{s}_objc_msgSend (obj.Handle, new Selector (\"Test_{s}Struct\").Handle);"); + w.AppendLine ($"\t\t\t\t}}"); + } + w.AppendLine ($"\t\t\t\tAssert.AreEqual (({GenerateNewExpression (s, 1)}).ToString (), rv.ToString (), \"a\");"); + w.AppendLine (); + + WriteStretConditions (w, s, out never); + if (never) { + w.AppendLine ($"\t\t\t\trv = S{s}_objc_msgSend (class_ptr, new Selector (\"Test_Static{s}Struct\").Handle);"); + } else { + w.AppendLine ($"\t\t\t\t\tS{s}_objc_msgSend_stret (out rv, class_ptr, new Selector (\"Test_Static{s}Struct\").Handle);"); + w.AppendLine ($"\t\t\t\t}} else {{"); + w.AppendLine ($"\t\t\t\t\trv = S{s}_objc_msgSend (class_ptr, new Selector (\"Test_Static{s}Struct\").Handle);"); + w.AppendLine ($"\t\t\t\t}}"); + } + w.AppendLine ($"\t\t\t\tAssert.AreEqual (({GenerateNewExpression (s, 2)}).ToString (), rv.ToString (), \"a\");"); + w.AppendLine (); + + WriteStretConditions (w, s, out never); + if (never) { + w.AppendLine ($"\t\t\t\trv = S{s}_objc_msgSend (obj.Handle, new Selector (\"Test_{s}StructProperty\").Handle);"); + } else { + w.AppendLine ($"\t\t\t\t\tS{s}_objc_msgSend_stret (out rv, obj.Handle, new Selector (\"Test_{s}StructProperty\").Handle);"); + w.AppendLine ($"\t\t\t\t}} else {{"); + w.AppendLine ($"\t\t\t\t\trv = S{s}_objc_msgSend (obj.Handle, new Selector (\"Test_{s}StructProperty\").Handle);"); + w.AppendLine ($"\t\t\t\t}}"); + } + w.AppendLine ($"\t\t\t\tAssert.AreEqual (({GenerateNewExpression (s, 3)}).ToString (), rv.ToString (), \"a\");"); + w.AppendLine (); + + WriteStretConditions (w, s, out never); + if (never) { + w.AppendLine ($"\t\t\t\trv = S{s}_objc_msgSend (class_ptr, new Selector (\"Test_Static{s}StructProperty\").Handle);"); + } else { + w.AppendLine ($"\t\t\t\t\tS{s}_objc_msgSend_stret (out rv, class_ptr, new Selector (\"Test_Static{s}StructProperty\").Handle);"); + w.AppendLine ($"\t\t\t\t}} else {{"); + w.AppendLine ($"\t\t\t\t\trv = S{s}_objc_msgSend (class_ptr, new Selector (\"Test_Static{s}StructProperty\").Handle);"); + w.AppendLine ($"\t\t\t\t}}"); + } + w.AppendLine ($"\t\t\t\tAssert.AreEqual (({GenerateNewExpression (s, 4)}).ToString (), rv.ToString (), \"a\");"); + w.AppendLine (); + + w.AppendLine ($"\t\t\t\trvd = 0;"); + WriteStretConditions (w, s, out never); + if (never) { + w.AppendLine ($"\t\t\t\trv = S{s}_objc_msgSend_out_double (obj.Handle, new Selector (\"Test_{s}Struct_out_double:\").Handle, out rvd);"); + } else { + w.AppendLine ($"\t\t\t\t\tS{s}_objc_msgSend_stret_out_double (out rv, obj.Handle, new Selector (\"Test_{s}Struct_out_double:\").Handle, out rvd);"); + w.AppendLine ($"\t\t\t\t}} else {{"); + w.AppendLine ($"\t\t\t\t\trv = S{s}_objc_msgSend_out_double (obj.Handle, new Selector (\"Test_{s}Struct_out_double:\").Handle, out rvd);"); + w.AppendLine ($"\t\t\t\t}}"); + } + w.AppendLine ($"\t\t\t\tAssert.AreEqual (({GenerateNewExpression (s, 5)}).ToString (), rv.ToString (), \"a\");"); + w.AppendLine ($"\t\t\t\tAssert.AreEqual (3.14, rvd, \"double out\");"); + w.AppendLine (); + + w.AppendLine ($"\t\t\t\trvf = 0;"); + WriteStretConditions (w, s, out never); + if (never) { + w.AppendLine ($"\t\t\t\trv = S{s}_objc_msgSend_out_float (class_ptr, new Selector (\"Test_Static{s}Struct_out_float:\").Handle, out rvf);"); + } else { + w.AppendLine ($"\t\t\t\t\tS{s}_objc_msgSend_stret_out_float (out rv, class_ptr, new Selector (\"Test_Static{s}Struct_out_float:\").Handle, out rvf);"); + w.AppendLine ($"\t\t\t\t}} else {{"); + w.AppendLine ($"\t\t\t\t\trv = S{s}_objc_msgSend_out_float (class_ptr, new Selector (\"Test_Static{s}Struct_out_float:\").Handle, out rvf);"); + w.AppendLine ($"\t\t\t\t}}"); + } + w.AppendLine ($"\t\t\t\tAssert.AreEqual (({GenerateNewExpression (s, 6)}).ToString (), rv.ToString (), \"a\");"); + w.AppendLine ($"\t\t\t\tAssert.AreEqual (3.15f, rvf, \"float out\");"); + w.AppendLine (); + + w.AppendLine ($"\t\t\t}}"); + w.AppendLine ($"\t\t}}"); + + + // objc_msgSend variants + w.AppendLine (); + w.AppendLine ($"\t\t[DllImport (LIBOBJC_DYLIB, EntryPoint=\"objc_msgSend\")]"); + w.AppendLine ($"\t\textern static S{s} S{s}_objc_msgSend (IntPtr received, IntPtr selector);"); + + w.AppendLine (); + w.AppendLine ($"\t\t[DllImport (LIBOBJC_DYLIB, EntryPoint=\"objc_msgSend\")]"); + w.AppendLine ($"\t\textern static S{s} S{s}_objc_msgSend_out_float (IntPtr received, IntPtr selector, out float x1);"); + + w.AppendLine (); + w.AppendLine ($"\t\t[DllImport (LIBOBJC_DYLIB, EntryPoint=\"objc_msgSend\")]"); + w.AppendLine ($"\t\textern static S{s} S{s}_objc_msgSend_out_double (IntPtr received, IntPtr selector, out double x1);"); + + w.AppendLine (); + w.AppendLine ($"\t\t[DllImport (LIBOBJC_DYLIB, EntryPoint=\"objc_msgSend_stret\")]"); + w.AppendLine ($"\t\textern static void S{s}_objc_msgSend_stret (out S{s} rv, IntPtr received, IntPtr selector);"); + + w.AppendLine (); + w.AppendLine ($"\t\t[DllImport (LIBOBJC_DYLIB, EntryPoint=\"objc_msgSend_stret\")]"); + w.AppendLine ($"\t\textern static void S{s}_objc_msgSend_stret_out_float (out S{s} rv, IntPtr received, IntPtr selector, out float x1);"); + + w.AppendLine (); + w.AppendLine ($"\t\t[DllImport (LIBOBJC_DYLIB, EntryPoint=\"objc_msgSend_stret\")]"); + w.AppendLine ($"\t\textern static void S{s}_objc_msgSend_stret_out_double (out S{s} rv, IntPtr received, IntPtr selector, out double x1);"); + } + + w.AppendLine (@" } +}"); + + File.WriteAllText ("../monotouch-test/ObjCRuntime/TrampolineTest.generated.cs", w.ToString ()); + } + + static void WriteStretConditions (StringBuilder w, string s, out bool never) + { + var stret = strets [Array.IndexOf (structs, s)]; + if (stret == Architecture.None) { + never = true; + } else { + never = false; + w.Append ("\t\t\t\tif ("); + if ((stret & Architecture.Arm32) == Architecture.Arm32) + w.Append ("TrampolineTest.IsArm32 || "); + if ((stret & Architecture.Armv7k) == Architecture.Armv7k) + w.Append ("TrampolineTest.IsArmv7k || "); + if ((stret & Architecture.Sim32) == Architecture.Sim32) + w.Append ("TrampolineTest.IsSim32 || "); + if ((stret & Architecture.Sim64) == Architecture.Sim64) + w.Append ("TrampolineTest.IsSim64 || "); + w.Length -= 4; + w.AppendLine (") {"); + } + } + + static string GenerateNewExpression (string s, int multiplier = 1) + { + var sb = new StringBuilder (); + sb.Append ($"new S{s} () {{ "); + for (int i = 0; i < s.Length; i++) + sb.Append ("x").Append (i).Append (" = ").Append (GetValue (s [i], i, multiplier)).Append (", "); + sb.Length -= 2; + sb.Append (" }"); + return sb.ToString (); + } + + static void Main () + { + while (Path.GetFileName (Environment.CurrentDirectory) != "test-libraries") + Environment.CurrentDirectory = Path.GetDirectoryName (Environment.CurrentDirectory); + + /* native code */ + WriteLibTestStructH (); + WriteLibTestDecompileM (); + WriteLibTestPropertiesH (); + + /* binding code */ + WriteApiDefinition (); + WriteStructsAndEnums (); + + /* tests */ + WriteRegistrarTests (); + WriteTrampolineTests (); + + Console.WriteLine ("Generated test files"); + } +} diff --git a/tests/test-libraries/testgenerator.csproj b/tests/test-libraries/testgenerator.csproj new file mode 100644 index 0000000000..fccb8d0d4d --- /dev/null +++ b/tests/test-libraries/testgenerator.csproj @@ -0,0 +1,38 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {CD430449-8E59-4ECD-ADD9-ACF79E9E660B} + Exe + testgenerator + testgenerator + v4.5 + + + true + full + false + bin\Debug + DEBUG; + prompt + 4 + true + + + true + bin\Release + prompt + 4 + true + + + + + + + + + \ No newline at end of file From 3df6a433d7344e11808a73d8086d5ef1d2237ed1 Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Tue, 11 Oct 2016 19:09:08 +0200 Subject: [PATCH 2/7] [MetalPerformanceShaders] Fix MPSImageHistogramInfo layout. The Vector4 fields are SIMD types, which means they're 16-bit aligned. There's no way to inform mono about this, so layout the structure explicitly. --- src/MetalPerformanceShaders/MPSDefs.cs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/MetalPerformanceShaders/MPSDefs.cs b/src/MetalPerformanceShaders/MPSDefs.cs index a3bd859962..f59259cd6b 100644 --- a/src/MetalPerformanceShaders/MPSDefs.cs +++ b/src/MetalPerformanceShaders/MPSDefs.cs @@ -1,4 +1,6 @@ using System; +using System.Runtime.InteropServices; + using XamCore.Foundation; using XamCore.ObjCRuntime; @@ -81,10 +83,19 @@ namespace XamCore.MetalPerformanceShaders { } // MPSImageHistogram.h + [StructLayout (LayoutKind.Explicit)] public struct MPSImageHistogramInfo { + [FieldOffset (0)] public nuint NumberOfHistogramEntries; +#if ARCH_64 + [FieldOffset (8)] +#else + [FieldOffset (4)] +#endif public bool HistogramForAlpha; + [FieldOffset (16)] public Vector4 MinPixelValue; + [FieldOffset (32)] public Vector4 MaxPixelValue; } From 9a40b2285793202468ca065ee11a93d7b5003628 Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Tue, 11 Oct 2016 19:11:29 +0200 Subject: [PATCH 3/7] [runtime] Simplify stret check in the x86 trampolines. --- runtime/trampolines-i386.m | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/runtime/trampolines-i386.m b/runtime/trampolines-i386.m index 83ab20fa56..fbc52481b0 100644 --- a/runtime/trampolines-i386.m +++ b/runtime/trampolines-i386.m @@ -101,9 +101,8 @@ marshal_return_value (void *context, const char *type, size_t size, void *vvalue it->state->double_ret = *(double *) mono_object_unbox (value); break; case _C_STRUCT_B: - if (it->state->type == Tramp_DoubleStret || it->state->type == Tramp_StaticDoubleStret) { - void *unboxed = mono_object_unbox (value); - memcpy ((void *) it->stret, unboxed, size); + if ((it->state->type & Tramp_Stret) == Tramp_Stret) { + memcpy ((void *) it->stret, mono_object_unbox (value), size); break; } @@ -127,9 +126,6 @@ marshal_return_value (void *context, const char *type, size_t size, void *vvalue it->state->edx = v[1]; } else if (size == 4) { it->state->eax = *(uint32_t *) mono_object_unbox (value); - } else if (size > 8) { - // Passed in memory. it->stret points to caller-allocated memory. - memcpy ((void *) it->stret, mono_object_unbox (value), size); } else { *exception_gchandle = create_mt_exception (xamarin_strdup_printf ("Xamarin.iOS: Cannot marshal struct return type %s (size: %i)\n", type, (int) size)); } From c660307b556ac4f1df72bd1d66af2f6e2b443c96 Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Tue, 11 Oct 2016 19:14:00 +0200 Subject: [PATCH 4/7] [runtime] Simplify stret check in the x86_64 trampolines. --- runtime/trampolines-x86_64.m | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/runtime/trampolines-x86_64.m b/runtime/trampolines-x86_64.m index 0ae430190d..e19167c94a 100644 --- a/runtime/trampolines-x86_64.m +++ b/runtime/trampolines-x86_64.m @@ -370,6 +370,11 @@ marshal_return_value (void *context, const char *type, size_t size, void *vvalue * */ + if ((it->state->type & Tramp_Stret) == Tramp_Stret) { + memcpy ((void *) it->state->rdi, mono_object_unbox (value), size); + break; + } + if (size > 8 && size <= 16) { uint64_t *i_ptr = &it->state->rax; uint64_t *f_ptr = (uint64_t *) &it->state->xmm0; @@ -462,9 +467,6 @@ marshal_return_value (void *context, const char *type, size_t size, void *vvalue // all other combinations would contain at least one INTEGER-class type. it->state->rax = *(uint64_t *) mono_object_unbox (value); } - } else if (size > 16) { - // Passed in memory. %rdi points to caller-allocated memory. - memcpy ((void *) it->state->rdi, mono_object_unbox (value), size); } else { *exception_gchandle = create_mt_exception (xamarin_strdup_printf ("Xamarin.iOS: Cannot marshal struct return type %s (size: %i)\n", type, (int) size)); return; From f448f6d55ccd75634e3f27841adfd4291d025e79 Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Tue, 11 Oct 2016 19:15:01 +0200 Subject: [PATCH 5/7] [runtime] Fix returning 'float,float' and 'double' structs on x86_64. --- runtime/trampolines-x86_64.m | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/runtime/trampolines-x86_64.m b/runtime/trampolines-x86_64.m index e19167c94a..4a529a54a2 100644 --- a/runtime/trampolines-x86_64.m +++ b/runtime/trampolines-x86_64.m @@ -460,9 +460,10 @@ marshal_return_value (void *context, const char *type, size_t size, void *vvalue }; } else if (size == 8) { - if (!strcmp (type, "[ff]") || !strcmp (type, "[d]")) { + type = skip_type_name (type); + if (!strncmp (type, "ff}", 3) || !strncmp (type, "d}", 2)) { // the only two fully fp combinations are: ff and d - it->state->xmm0 = *(float *) mono_object_unbox (value); + memcpy (&it->state->xmm0, mono_object_unbox (value), 8); } else { // all other combinations would contain at least one INTEGER-class type. it->state->rax = *(uint64_t *) mono_object_unbox (value); From a9188a3bf3eddcb96bc4cb0a763b9955c91956f3 Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Tue, 11 Oct 2016 19:15:18 +0200 Subject: [PATCH 6/7] [runtime] Fix returning structs with size < 8. --- runtime/trampolines-x86_64.m | 2 ++ 1 file changed, 2 insertions(+) diff --git a/runtime/trampolines-x86_64.m b/runtime/trampolines-x86_64.m index 4a529a54a2..5f0c1da2fd 100644 --- a/runtime/trampolines-x86_64.m +++ b/runtime/trampolines-x86_64.m @@ -468,6 +468,8 @@ marshal_return_value (void *context, const char *type, size_t size, void *vvalue // all other combinations would contain at least one INTEGER-class type. it->state->rax = *(uint64_t *) mono_object_unbox (value); } + } else if (size < 8) { + memcpy (&it->state->rax, mono_object_unbox (value), size); } else { *exception_gchandle = create_mt_exception (xamarin_strdup_printf ("Xamarin.iOS: Cannot marshal struct return type %s (size: %i)\n", type, (int) size)); return; From 9d85ca79abb50a3c356a1638364ac9c03735dfcc Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Tue, 11 Oct 2016 19:24:23 +0200 Subject: [PATCH 7/7] Unify stret detection between the generator and platform assemblies, and fix stret detection on watchOS. Fixes #44709. Unify the code to determine whether a particular return type requires a stret signature or not between the generator and platform assemblies. Also fix the stret detection for armv7k, whose calling convention is not identical to armv7(s): there's the concept of homogeneous structures, which contains multiple elements of only one type, and which is sometimes passed in registers on armv7k. https://bugzilla.xamarin.com/show_bug.cgi?id=44709 --- docs/website/mtouch-errors.md | 6 + src/Makefile.generator | 1 + src/ObjCRuntime/Registrar.cs | 68 ++++---- src/ObjCRuntime/Stret.cs | 297 ++++++++++++++++++++++++++++++++++ src/frameworks.sources | 1 + src/generator.cs | 113 ++----------- tools/mtouch/error.cs | 1 + 7 files changed, 352 insertions(+), 135 deletions(-) create mode 100644 src/ObjCRuntime/Stret.cs diff --git a/docs/website/mtouch-errors.md b/docs/website/mtouch-errors.md index b712d9787a..83795142fd 100644 --- a/docs/website/mtouch-errors.md +++ b/docs/website/mtouch-errors.md @@ -1420,3 +1420,9 @@ This usually indicates a bug in Xamarin.iOS; please file a bug at http://bugzill The DelegateProxy attribute for the method in question is invalid. This usually indicates a bug in Xamarin.iOS; please file a bug at http://bugzilla.xamarin.com. + +

MT8018: Internal consistency error. Please file a bug report at http://bugzilla.xamarin.com.

+ +This indicates a bug in Xamarin.iOS. Please file a bug at [http://bugzilla.xamarin.com](https://bugzilla.xamarin.com/enter_bug.cgi?product=iOS). + +

< diff --git a/src/Makefile.generator b/src/Makefile.generator index 3c965638c6..284c2a2388 100644 --- a/src/Makefile.generator +++ b/src/Makefile.generator @@ -5,6 +5,7 @@ GENERATOR_SOURCES = \ $(TOP)/src/generator.cs \ $(TOP)/src/generator-enums.cs \ $(TOP)/src/generator-filters.cs \ + $(TOP)/src/ObjCRuntime/Stret.cs \ $(MONO_PATH)/mcs/class/Mono.Options/Mono.Options/Options.cs \ GENERATOR_DEFINES = -d:GENERATOR -d:NET_4_0 diff --git a/src/ObjCRuntime/Registrar.cs b/src/ObjCRuntime/Registrar.cs index 0b4cc4a930..0f9c8fa9ea 100644 --- a/src/ObjCRuntime/Registrar.cs +++ b/src/ObjCRuntime/Registrar.cs @@ -566,53 +566,59 @@ namespace XamCore.Registrar { get { if (trampoline != Trampoline.None) return trampoline; - - var isStaticTrampoline = IsStatic && !IsCategoryInstance; - trampoline = isStaticTrampoline ? Trampoline.Static : Trampoline.Normal; - var return_type = Registrar.GetReturnType (Method); - var is_value_type = Registrar.IsValueType (return_type) && !Registrar.IsEnum (return_type); - var is_corlib = is_value_type ? Registrar.IsCorlibType (return_type) : false; +#if MTOUCH || MMP + throw ErrorHelper.CreateError (8018, "Internal consistency error. Please file a bug report at http://bugzilla.xamarin.com."); +#else + var mi = (System.Reflection.MethodInfo) Method; + bool is_stret; +#if __WATCHOS__ + is_stret = Runtime.Arch == Arch.DEVICE ? Stret.ArmNeedStret (mi) : Stret.X86NeedStret (mi); +#elif MONOMAC + is_stret = IntPtr.Size == 8 ? Stret.X86_64NeedStret (mi) : Stret.X86NeedStret (mi); +#elif __IOS__ + if (Runtime.Arch == Arch.DEVICE) { + is_stret = IntPtr.Size == 4 && Stret.ArmNeedStret (mi); + } else { + is_stret = IntPtr.Size == 4 ? Stret.X86NeedStret (mi) : Stret.X86_64NeedStret (mi); + } +#elif __TVOS__ + is_stret = Runtime.Arch == Arch.SIMULATOR && Stret.X86_64NeedStret (mi); +#else + #error unknown architecture +#endif + var is_static_trampoline = IsStatic && !IsCategoryInstance; + var is_value_type = Registrar.IsValueType (ReturnType) && !Registrar.IsEnum (ReturnType); - if (is_value_type && Registrar.IsGenericType (return_type)) - throw Registrar.CreateException (4104, Method, "The registrar cannot marshal the return value of type `{0}` in the method `{1}.{2}`.", Registrar.GetTypeFullName (return_type), Registrar.GetTypeFullName (DeclaringType.Type), Registrar.GetDescriptiveMethodName (Method)); - - var size = is_value_type ? Registrar.GetValueTypeSize (return_type) : 0; - - if (is_value_type && !is_corlib && (!Registrar.IsSimulatorOrDesktop || size > 4)) { - trampoline = isStaticTrampoline ? Trampoline.StaticStret : Trampoline.Stret; - - if (Registrar.IsSimulatorOrDesktop) { - if (Registrar.Is64Bits) { - if (size > 16) { - trampoline = isStaticTrampoline ? Trampoline.StaticStret : Trampoline.Stret; - } else { - trampoline = isStaticTrampoline ? Trampoline.Static : Trampoline.Normal; - } - } else { - if (size > 8) { - trampoline = isStaticTrampoline ? Trampoline.X86_DoubleABI_StaticStretTrampoline : Trampoline.X86_DoubleABI_StretTrampoline; - } else { - trampoline = isStaticTrampoline ? Trampoline.StaticLong : Trampoline.Long; - } - } + if (is_value_type && Registrar.IsGenericType (ReturnType)) + throw Registrar.CreateException (4104, Method, "The registrar cannot marshal the return value of type `{0}` in the method `{1}.{2}`.", Registrar.GetTypeFullName (ReturnType), Registrar.GetTypeFullName (DeclaringType.Type), Registrar.GetDescriptiveMethodName (Method)); + + if (is_stret) { + if (Registrar.IsSimulatorOrDesktop && !Registrar.Is64Bits) { + trampoline = is_static_trampoline ? Trampoline.X86_DoubleABI_StaticStretTrampoline : Trampoline.X86_DoubleABI_StretTrampoline; + } else { + trampoline = is_static_trampoline ? Trampoline.StaticStret : Trampoline.Stret; } } else { switch (Signature [0]) { case 'Q': case 'q': - trampoline = isStaticTrampoline ? Trampoline.StaticLong : Trampoline.Long; + trampoline = is_static_trampoline ? Trampoline.StaticLong : Trampoline.Long; break; case 'f': - trampoline = isStaticTrampoline ? Trampoline.StaticSingle : Trampoline.Single; + trampoline = is_static_trampoline ? Trampoline.StaticSingle : Trampoline.Single; break; case 'd': - trampoline = isStaticTrampoline ? Trampoline.StaticDouble : Trampoline.Double; + trampoline = is_static_trampoline ? Trampoline.StaticDouble : Trampoline.Double; + break; + default: + trampoline = is_static_trampoline ? Trampoline.Static : Trampoline.Normal; break; } } return trampoline; +#endif } set { trampoline = value; diff --git a/src/ObjCRuntime/Stret.cs b/src/ObjCRuntime/Stret.cs new file mode 100644 index 0000000000..4b100a0a74 --- /dev/null +++ b/src/ObjCRuntime/Stret.cs @@ -0,0 +1,297 @@ +// +// Stret.cs: Code to determine if a function is a stret function or not. +// +// This file is shared between the product assemblies and the generator. +// +// Authors: +// Rolf Bjarne Kvinge +// +// Copyright 2016 Xamarin Inc. +// + +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Runtime.InteropServices; + +using XamCore.Foundation; + +namespace XamCore.ObjCRuntime +{ + class Stret + { +#if __WATCHOS__ + static bool IsHomogeneousAggregateSmallEnough_Armv7k (Type t, int members) + { + // https://github.com/llvm-mirror/clang/blob/82f6d5c9ae84c04d6e7b402f72c33638d1fb6bc8/lib/CodeGen/TargetInfo.cpp#L5516-L5519 + return members <= 4; + } + + static bool IsHomogeneousAggregateBaseType_Armv7k (Type t) + { + // https://github.com/llvm-mirror/clang/blob/82f6d5c9ae84c04d6e7b402f72c33638d1fb6bc8/lib/CodeGen/TargetInfo.cpp#L5500-L5514 + if (t == typeof (float) || t == typeof (double) || t == typeof (nfloat)) + return true; + + return false; + } + + static bool IsHomogeneousAggregate_Armv7k (List fieldTypes) + { + // Very simplified version of https://github.com/llvm-mirror/clang/blob/82f6d5c9ae84c04d6e7b402f72c33638d1fb6bc8/lib/CodeGen/TargetInfo.cpp#L4051 + // since C# supports a lot less types than clang does. + + if (fieldTypes.Count == 0) + return false; + + if (!IsHomogeneousAggregateSmallEnough_Armv7k (fieldTypes [0], fieldTypes.Count)) + return false; + + if (!IsHomogeneousAggregateBaseType_Armv7k (fieldTypes [0])) + return false; + + for (int i = 1; i < fieldTypes.Count; i++) { + if (fieldTypes [0] != fieldTypes [i]) + return false; + } + + return true; + } +#endif + + static bool IsMagicTypeOrCorlibType (Type t) + { +#if __UNIFIED__ + switch (t.Name) { + case "nint": + case "nuint": + case "nfloat": + if (t.Namespace != "System") + return false; + return t.Assembly == typeof (NSObject).Assembly; + default: + return t.Assembly == typeof (object).Assembly; + } +#else + return t.Assembly == typeof (object).Assembly; +#endif + } + + public static bool ArmNeedStret (MethodInfo mi) + { +#if MONOMAC || __TVOS__ + return false; +#else + Type t = mi.ReturnType; + + if (!t.IsValueType || t.IsEnum || IsMagicTypeOrCorlibType (t)) + return false; + + var fieldTypes = new List (); + var size = GetValueTypeSize (t, fieldTypes, false); + +#if __WATCHOS__ + // According to clang watchOS passes arguments bigger than 16 bytes by reference. + // https://github.com/llvm-mirror/clang/blob/82f6d5c9ae84c04d6e7b402f72c33638d1fb6bc8/lib/CodeGen/TargetInfo.cpp#L5248-L5250 + // https://github.com/llvm-mirror/clang/blob/82f6d5c9ae84c04d6e7b402f72c33638d1fb6bc8/lib/CodeGen/TargetInfo.cpp#L5542-L5543 + if (size <= 16) + return false; + + // Except homogeneous aggregates, which are not stret either. + if (IsHomogeneousAggregate_Armv7k (fieldTypes)) + return false; + +#elif __IOS__ + if (size <= 4 && fieldTypes.Count == 1) { + switch (fieldTypes [0].FullName) { + case "System.Char": + case "System.Byte": + case "System.SByte": + case "System.UInt16": + case "System.Int16": + case "System.UInt32": + case "System.Int32": + case "System.IntPtr": + case "System.nuint": + case "System.uint": + return false; + // floating-point types are stret + } + } +#else + #error Unknown architecture +#endif + + return true; +#endif // MONOMAC + } + + public static bool X86NeedStret (MethodInfo mi) + { + Type t = mi.ReturnType; + + if (!t.IsValueType || t.IsEnum || IsMagicTypeOrCorlibType (t)) + return false; + + var fieldTypes = new List (); + var size = GetValueTypeSize (t, fieldTypes, false); + + if (size > 8) + return true; + + if (fieldTypes.Count == 3) + return true; + + return false; + } + + public static bool X86_64NeedStret (MethodInfo mi) + { +#if __UNIFIED__ + Type t = mi.ReturnType; + + if (!t.IsValueType || t.IsEnum || IsMagicTypeOrCorlibType (t)) + return false; + + var fieldTypes = new List (); + return GetValueTypeSize (t, fieldTypes, true) > 16; +#else + return false; +#endif + } + + static int GetValueTypeSize (Type type, List fieldTypes, bool is_64_bits) + { + int size = 0; + int maxElementSize = 1; + + if (type.IsExplicitLayout) { + // Find the maximum of "field size + field offset" for each field. + foreach (var field in type.GetFields (BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) { + var fieldOffset = (FieldOffsetAttribute) Attribute.GetCustomAttribute (field, typeof (FieldOffsetAttribute)); + var elementSize = 0; + GetValueTypeSize (type, field.FieldType, fieldTypes, is_64_bits, ref elementSize, ref maxElementSize); + size = Math.Max (size, elementSize + fieldOffset.Value); + } + } else { + GetValueTypeSize (type, type, fieldTypes, is_64_bits, ref size, ref maxElementSize); + } + + if (size % maxElementSize != 0) + size += (maxElementSize - size % maxElementSize); + + return size; + } + + static int AlignAndAdd (Type original_type, int size, int add, ref int max_element_size) + { + max_element_size = Math.Max (max_element_size, add); + if (size % add != 0) + size += add - size % add; + return size += add; + } + + static void GetValueTypeSize (Type original_type, Type type, List field_types, bool is_64_bits, ref int size, ref int max_element_size) + { + // FIXME: + // SIMD types are not handled correctly here (they need 16-bit alignment). + // However we don't annotate those types in any way currently, so first we'd need to + // add the proper attributes so that the generator can distinguish those types from other types. + + var type_size = 0; + switch (type.FullName) { + case "System.Char": + case "System.Boolean": + case "System.SByte": + case "System.Byte": + type_size = 1; + break; + case "System.Int16": + case "System.UInt16": + type_size = 2; + break; + case "System.Single": + case "System.Int32": + case "System.UInt32": + type_size = 4; + break; + case "System.Double": + case "System.Int64": + case "System.UInt64": + type_size = 8; + break; + case "System.IntPtr": + case "System.nfloat": + case "System.nuint": + case "System.nint": + type_size = is_64_bits ? 8 : 4; + break; + } + + if (type_size != 0) { + field_types.Add (type); + size = AlignAndAdd (original_type, size, type_size, ref max_element_size); + return; + } + + // composite struct + foreach (var field in type.GetFields (BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) { + var marshalAs = (MarshalAsAttribute) Attribute.GetCustomAttribute (field, typeof (MarshalAsAttribute)); + if (marshalAs == null) { + GetValueTypeSize (original_type, field.FieldType, field_types, is_64_bits, ref size, ref max_element_size); + continue; + } + + var multiplier = 1; + switch (marshalAs.Value) { + case UnmanagedType.ByValArray: + var types = new List (); + GetValueTypeSize (original_type, field.FieldType.GetElementType (), types, is_64_bits, ref type_size, ref max_element_size); + multiplier = marshalAs.SizeConst; + break; + case UnmanagedType.U1: + case UnmanagedType.I1: + type_size = 1; + break; + case UnmanagedType.U2: + case UnmanagedType.I2: + type_size = 2; + break; + case UnmanagedType.U4: + case UnmanagedType.I4: + case UnmanagedType.R4: + type_size = 4; + break; + case UnmanagedType.U8: + case UnmanagedType.I8: + case UnmanagedType.R8: + type_size = 8; + break; + default: + throw new Exception ($"Unhandled MarshalAs attribute: {marshalAs.Value} on field {field.DeclaringType.FullName}.{field.Name}"); + } + field_types.Add (field.FieldType); + size = AlignAndAdd (original_type, size, type_size, ref max_element_size); + size += (multiplier - 1) * size; + } + } + + public static bool NeedStret (MethodInfo mi) + { + if (X86NeedStret (mi)) + return true; + +#if __UNIFIED__ + if (X86_64NeedStret (mi)) + return true; +#endif + +#if !MONOMAC + if (ArmNeedStret (mi)) + return true; +#endif + + return false; + } + } +} diff --git a/src/frameworks.sources b/src/frameworks.sources index e014aa3700..5ac019f18f 100644 --- a/src/frameworks.sources +++ b/src/frameworks.sources @@ -1473,6 +1473,7 @@ SHARED_SOURCES = \ ObjCRuntime/Selector.iOS.cs \ ObjCRuntime/Selector.mac.cs \ ObjCRuntime/SelectorMarshaler.cs \ + ObjCRuntime/Stret.cs \ ObjCRuntime/ThreadSafeAttribute.cs \ ObjCRuntime/TransientAttribute.cs \ ObjCRuntime/TypeConverter.cs \ diff --git a/src/generator.cs b/src/generator.cs index 748c15ed59..ee6e911170 100644 --- a/src/generator.cs +++ b/src/generator.cs @@ -2348,101 +2348,6 @@ public partial class Generator : IMemberGatherer { need_stret ? (aligned ? "IntPtr" : "out " + FormatTypeUsedIn (ns.CoreObjCRuntime, mi.ReturnType)) + " retval, " : ""); } - bool IsMagicType (Type t) - { - switch (t.Name) { - case "nint": - case "nuint": - case "nfloat": - return t.Assembly == typeof (NSObject).Assembly; - default: - return t.Assembly == typeof (object).Assembly; - } - } - - bool ArmNeedStret (MethodInfo mi) - { - Type t = mi.ReturnType; - - bool assembly = Compat ? t.Assembly == typeof (object).Assembly : IsMagicType (t); - if (!t.IsValueType || t.IsEnum || assembly) - return false; - -#if WATCH - // According to clang watchOS passes arguments bigger than 16 bytes by reference. - // https://github.com/llvm-mirror/clang/blob/82f6d5c9ae84c04d6e7b402f72c33638d1fb6bc8/lib/CodeGen/TargetInfo.cpp#L5248-L5250 - // https://github.com/llvm-mirror/clang/blob/82f6d5c9ae84c04d6e7b402f72c33638d1fb6bc8/lib/CodeGen/TargetInfo.cpp#L5542-L5543 - if (GetValueTypeSize (t, false) <= 16) - return false; -#endif - - return true; - } - - bool X86NeedStret (MethodInfo mi) - { - Type t = mi.ReturnType; - - if (!t.IsValueType || t.IsEnum || t.Assembly == typeof (object).Assembly) - return false; - - return GetValueTypeSize (t, false) > 8; - } - - bool X86_64NeedStret (MethodInfo mi) - { - Type t = mi.ReturnType; - - if (!t.IsValueType || t.IsEnum || t.Assembly == typeof (object).Assembly) - return false; - - return GetValueTypeSize (t, true) > 16; - } - - public static int GetValueTypeSize (Type type, bool is_64_bits) - { - switch (type.FullName) { - case "System.Char": - case "System.Boolean": - case "System.SByte": - case "System.Byte": return 1; - case "System.Int16": - case "System.UInt16": return 2; - case "System.Single": - case "System.Int32": - case "System.UInt32": return 4; - case "System.Double": - case "System.Int64": - case "System.UInt64": return 8; - case "System.IntPtr": - case "System.nfloat": - case "System.nuint": - case "System.nint": return is_64_bits ? 8 : 4; - default: - int size = 0; - foreach (var field in type.GetFields (BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) { - int s = GetValueTypeSize (field.FieldType, is_64_bits); - if (s == -1) - return -1; - size += s; - } - return size; - } - } - - bool NeedStret (MethodInfo mi) - { - if (Compat) - return ArmNeedStret (mi) || X86NeedStret (mi); - - bool no_arm_stret = X86NeedStret (mi) || X86_64NeedStret (mi); - - if (OnlyDesktop) - return no_arm_stret; - - return no_arm_stret || ArmNeedStret (mi); - } - bool IsNativeEnum (Type type) { return type.IsEnum && HasAttribute (type, typeof (NativeAttribute)); @@ -2483,12 +2388,12 @@ public partial class Generator : IMemberGatherer { try { if (Compat) { - bool arm_stret = ArmNeedStret (mi); + bool arm_stret = Stret.ArmNeedStret (mi); bool is_aligned = HasAttribute (mi, typeof (AlignAttribute)); RegisterMethod (arm_stret, mi, MakeSig (mi, arm_stret, arm_stret && is_aligned), arm_stret && is_aligned); RegisterMethod (arm_stret, mi, MakeSuperSig (mi, arm_stret, arm_stret && is_aligned), arm_stret && is_aligned); - bool x86_stret = X86NeedStret (mi); + bool x86_stret = Stret.X86NeedStret (mi); if (x86_stret != arm_stret){ RegisterMethod (x86_stret, mi, MakeSig (mi, x86_stret, x86_stret && is_aligned), x86_stret && is_aligned); RegisterMethod (x86_stret, mi, MakeSuperSig (mi, x86_stret, x86_stret && is_aligned), x86_stret && is_aligned); @@ -2505,7 +2410,7 @@ public partial class Generator : IMemberGatherer { RegisterMethod (false, mi, MakeSig (mi, false, enum_mode: mode), false, mode); RegisterMethod (false, mi, MakeSuperSig (mi, false, enum_mode: mode), false, mode); - if (NeedStret (mi)) { + if (Stret.NeedStret (mi)) { RegisterMethod (true, mi, MakeSig (mi, true, enum_mode: mode), false, mode); RegisterMethod (true, mi, MakeSuperSig (mi, true, enum_mode: mode), false, mode); @@ -4095,8 +4000,8 @@ public partial class Generator : IMemberGatherer { return; } - bool arm_stret = ArmNeedStret (mi); - bool x86_stret = X86NeedStret (mi); + bool arm_stret = Stret.ArmNeedStret (mi); + bool x86_stret = Stret.X86NeedStret (mi); bool aligned = HasAttribute (mi, typeof(AlignAttribute)); if (OnlyDesktop){ @@ -4122,9 +4027,9 @@ public partial class Generator : IMemberGatherer { void GenerateNewStyleInvoke (bool supercall, MethodInfo mi, MemberInformation minfo, string selector, string[] args, bool assign_to_temp, Type category_type) { - bool arm_stret = ArmNeedStret (mi); - bool x86_stret = X86NeedStret (mi); - bool x64_stret = X86_64NeedStret (mi); + bool arm_stret = Stret.ArmNeedStret (mi); + bool x86_stret = Stret.X86NeedStret (mi); + bool x64_stret = Stret.X86_64NeedStret (mi); bool dual_enum = HasNativeEnumInSignature (mi); bool is_stret_multi = arm_stret || x86_stret || x64_stret; bool need_multi_path = is_stret_multi || dual_enum; @@ -4556,7 +4461,7 @@ public partial class Generator : IMemberGatherer { bool use_temp_return = minfo.is_return_release || - (mi.Name != "Constructor" && (NeedStret (mi) || disposes.Length > 0 || postget != null) && mi.ReturnType != typeof (void)) || + (mi.Name != "Constructor" && (Stret.NeedStret (mi) || disposes.Length > 0 || postget != null) && mi.ReturnType != typeof (void)) || (HasAttribute (mi, typeof (FactoryAttribute))) || ((body_options & BodyOption.NeedsTempReturn) == BodyOption.NeedsTempReturn) || (mi.ReturnType.IsSubclassOf (typeof (Delegate))) || diff --git a/tools/mtouch/error.cs b/tools/mtouch/error.cs index ce9f1b53a2..ce5af31ef5 100644 --- a/tools/mtouch/error.cs +++ b/tools/mtouch/error.cs @@ -338,6 +338,7 @@ namespace Xamarin.Bundler { // MT8015 Invalid DelegateProxyAttribute for the return value for the method {0}.{1}: The DelegateType's ({2}) 'Handler' field is not a delegate, it's a {3}. Please file a bug at http://bugzilla.xamarin.com. // MT8016 Unable to convert delegate to block for the return value for the method {0}.{1}, because the input isn't a delegate, it's a {1}. Please file a bug at http://bugzilla.xamarin.com. // MT8017 ** reserved Xamarin.Mac ** + // MT8018 Internal consistency error. Please file a bug report at http://bugzilla.xamarin.com. // MT9xxx Licensing //