@@ -14,11 +14,7 @@ namespace ffi {
14
14
const NativeCallingConvention& RunSignatureTest (
15
15
dart::Zone* zone,
16
16
const char * name,
17
- const NativeTypes& argument_types,
18
- const NativeType& return_type) {
19
- const auto & native_signature =
20
- *new (zone) NativeFunctionType (argument_types, return_type);
21
-
17
+ const NativeFunctionType& native_signature) {
22
18
const auto & native_calling_convention =
23
19
NativeCallingConvention::FromSignature (zone, native_signature);
24
20
@@ -47,6 +43,17 @@ const NativeCallingConvention& RunSignatureTest(
47
43
return native_calling_convention;
48
44
}
49
45
46
+ const NativeCallingConvention& RunSignatureTest (
47
+ dart::Zone* zone,
48
+ const char * name,
49
+ const NativeTypes& argument_types,
50
+ const NativeType& return_type) {
51
+ const auto & native_signature =
52
+ *new (zone) NativeFunctionType (argument_types, return_type);
53
+
54
+ return RunSignatureTest (zone, name, native_signature);
55
+ }
56
+
50
57
UNIT_TEST_CASE_WITH_ZONE (NativeCallingConvention_int8x10) {
51
58
const auto & int8type = *new (Z) NativePrimitiveType (kInt8 );
52
59
@@ -729,6 +736,176 @@ UNIT_TEST_CASE_WITH_ZONE(NativeCallingConvention_regress_fuchsia105336) {
729
736
RunSignatureTest (Z, " regress_fuchsia105336" , arguments, void_type);
730
737
}
731
738
739
+ // Binding in Dart with variadic arguments:
740
+ // `IntPtr Function(IntPtr, VarArgs<(IntPtr, IntPtr, IntPtr, IntPtr)>)`
741
+ //
742
+ // See the *.expect in ./unit_tests for this behavior.
743
+ UNIT_TEST_CASE_WITH_ZONE (NativeCallingConvention_variadic_int) {
744
+ #if defined(TARGET_ARCH_IS_32_BIT)
745
+ const auto & intptr_type = *new (Z) NativePrimitiveType (kInt32 );
746
+ #elif defined(TARGET_ARCH_IS_64_BIT)
747
+ const auto & intptr_type = *new (Z) NativePrimitiveType (kInt64 );
748
+ #endif
749
+
750
+ auto & arguments = *new (Z) NativeTypes (Z, 5 );
751
+ arguments.Add (&intptr_type);
752
+ arguments.Add (&intptr_type);
753
+ arguments.Add (&intptr_type);
754
+ arguments.Add (&intptr_type);
755
+ arguments.Add (&intptr_type);
756
+
757
+ const auto & native_signature = *new (Z) NativeFunctionType (
758
+ arguments, intptr_type, /* variadic_arguments_index=*/ 1 );
759
+
760
+ RunSignatureTest (Z, " variadic_int" , native_signature);
761
+ }
762
+
763
+ // Binding in Dart with variadic arguments:
764
+ // `Double Function(Double, VarArgs<(Double, Double, Double, Double)>)`
765
+ //
766
+ // See the *.expect in ./unit_tests for this behavior.
767
+ UNIT_TEST_CASE_WITH_ZONE (NativeCallingConvention_variadic_double) {
768
+ const auto & double_type = *new (Z) NativePrimitiveType (kDouble );
769
+
770
+ auto & arguments = *new (Z) NativeTypes (Z, 5 );
771
+ arguments.Add (&double_type);
772
+ arguments.Add (&double_type);
773
+ arguments.Add (&double_type);
774
+ arguments.Add (&double_type);
775
+ arguments.Add (&double_type);
776
+
777
+ const auto & native_signature = *new (Z) NativeFunctionType (
778
+ arguments, double_type, /* variadic_arguments_index=*/ 1 );
779
+
780
+ RunSignatureTest (Z, " variadic_double" , native_signature);
781
+ }
782
+
783
+ // Binding in Dart with variadic arguments:
784
+ // `Double Function(Double, VarArgs<(Struct20BytesHomogeneousFloat, Double)>)`
785
+ //
786
+ // See the *.expect in ./unit_tests for this behavior.
787
+ UNIT_TEST_CASE_WITH_ZONE (NativeCallingConvention_variadic_with_struct) {
788
+ const auto & double_type = *new (Z) NativePrimitiveType (kDouble );
789
+ const auto & float_type = *new (Z) NativePrimitiveType (kFloat );
790
+
791
+ auto & member_types = *new (Z) NativeTypes (Z, 5 );
792
+ member_types.Add (&float_type);
793
+ member_types.Add (&float_type);
794
+ member_types.Add (&float_type);
795
+ member_types.Add (&float_type);
796
+ member_types.Add (&float_type);
797
+ const auto & struct_type = NativeStructType::FromNativeTypes (Z, member_types);
798
+
799
+ auto & arguments = *new (Z) NativeTypes (Z, 3 );
800
+ arguments.Add (&double_type);
801
+ arguments.Add (&struct_type);
802
+ arguments.Add (&double_type);
803
+
804
+ const auto & native_signature = *new (Z) NativeFunctionType (
805
+ arguments, double_type, /* variadic_arguments_index=*/ 1 );
806
+
807
+ RunSignatureTest (Z, " variadic_with_struct" , native_signature);
808
+ }
809
+
810
+ // Binding in Dart with variadic arguments.
811
+ //
812
+ // Especially macos_arm64 is interesting due to stack alignment.
813
+ //
814
+ // See the *.expect in ./unit_tests for this behavior.
815
+ UNIT_TEST_CASE_WITH_ZONE (
816
+ NativeCallingConvention_variadic_with_homogenous_struct) {
817
+ const auto & double_type = *new (Z) NativePrimitiveType (kDouble );
818
+ const auto & float_type = *new (Z) NativePrimitiveType (kFloat );
819
+ const auto & int64_type = *new (Z) NativePrimitiveType (kInt64 );
820
+ const auto & int32_type = *new (Z) NativePrimitiveType (kInt32 );
821
+
822
+ auto & member_types = *new (Z) NativeTypes (Z, 3 );
823
+ member_types.Add (&float_type);
824
+ member_types.Add (&float_type);
825
+ member_types.Add (&float_type);
826
+ const auto & struct_type = NativeStructType::FromNativeTypes (Z, member_types);
827
+
828
+ auto & arguments = *new (Z) NativeTypes (Z, 13 );
829
+ arguments.Add (&double_type);
830
+ arguments.Add (&double_type);
831
+ arguments.Add (&double_type);
832
+ arguments.Add (&double_type);
833
+ arguments.Add (&double_type);
834
+ arguments.Add (&double_type);
835
+ arguments.Add (&double_type);
836
+ arguments.Add (&double_type); // Exhaust FPU registers
837
+ arguments.Add (&float_type); // Misalign stack.
838
+ arguments.Add (
839
+ &struct_type); // Homogenous struct, not aligned to wordsize on stack.
840
+ arguments.Add (&int64_type); // Start varargs.
841
+ arguments.Add (&int32_type); // Misalign stack again.
842
+ arguments.Add (
843
+ &struct_type); // Homogenous struct, aligned to wordsize on stack.
844
+
845
+ const auto & native_signature = *new (Z) NativeFunctionType (
846
+ arguments, double_type, /* variadic_arguments_index=*/ 11 );
847
+
848
+ RunSignatureTest (Z, " variadic_with_homogenous_struct" , native_signature);
849
+ }
850
+
851
+ // Binding in Dart with variadic arguments.
852
+ //
853
+ // Especially linux_riscv32 is interesting due to register alignment.
854
+ //
855
+ // See the *.expect in ./unit_tests for this behavior.
856
+ UNIT_TEST_CASE_WITH_ZONE (NativeCallingConvention_variadic_register_alignment) {
857
+ const auto & double_type = *new (Z) NativePrimitiveType (kDouble );
858
+
859
+ auto & member_types = *new (Z) NativeTypes (Z, 4 );
860
+ member_types.Add (&double_type);
861
+ member_types.Add (&double_type);
862
+ member_types.Add (&double_type);
863
+ member_types.Add (&double_type);
864
+ const auto & struct_type = NativeStructType::FromNativeTypes (Z, member_types);
865
+
866
+ auto & arguments = *new (Z) NativeTypes (Z, 13 );
867
+ arguments.Add (&double_type);
868
+ arguments.Add (&double_type); // Passed in int register pair on RISC-V 32.
869
+ arguments.Add (
870
+ &struct_type); // Passed using single integer register on RISC-V 32.
871
+ arguments.Add (
872
+ &double_type); // Passed in _aligned_ int register pair on RISC-V 32.
873
+
874
+ const auto & native_signature = *new (Z) NativeFunctionType (
875
+ arguments, double_type, /* variadic_arguments_index=*/ 1 );
876
+
877
+ RunSignatureTest (Z, " variadic_register_alignment" , native_signature);
878
+ }
879
+
880
+ // Variadic function in C:
881
+ // `int ioctl(int, unsigned long, ...)`
882
+ //
883
+ // Binding in Dart with single variadic argument:
884
+ // `Int32 Function(Int32, Int64, VarArgs<Pointer<Void>>)`
885
+ //
886
+ // https://github.com/dart-lang/sdk/issues/49460
887
+ //
888
+ // See the *.expect in ./unit_tests for this behavior.
889
+ UNIT_TEST_CASE_WITH_ZONE (NativeCallingConvention_regress49460) {
890
+ const auto & int32_type = *new (Z) NativePrimitiveType (kInt32 );
891
+ const auto & int64_type = *new (Z) NativePrimitiveType (kInt64 );
892
+ #if defined(TARGET_ARCH_IS_32_BIT)
893
+ const auto & intptr_type = *new (Z) NativePrimitiveType (kInt32 );
894
+ #elif defined(TARGET_ARCH_IS_64_BIT)
895
+ const auto & intptr_type = *new (Z) NativePrimitiveType (kInt64 );
896
+ #endif
897
+
898
+ auto & arguments = *new (Z) NativeTypes (Z, 3 );
899
+ arguments.Add (&int32_type);
900
+ arguments.Add (&int64_type);
901
+ arguments.Add (&intptr_type); // pointer
902
+
903
+ const auto & native_signature = *new (Z) NativeFunctionType (
904
+ arguments, int32_type, /* variadic_arguments_index=*/ 2 );
905
+
906
+ RunSignatureTest (Z, " regress49460" , native_signature);
907
+ }
908
+
732
909
} // namespace ffi
733
910
} // namespace compiler
734
911
} // namespace dart
0 commit comments