ffi 1.17.1 → 1.17.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/CHANGELOG.md +33 -0
- data/Gemfile +8 -3
- data/README.md +1 -0
- data/Rakefile +7 -4
- data/Steepfile +8 -0
- data/ext/ffi_c/DynamicLibrary.c +1 -1
- data/ext/ffi_c/Function.c +2 -0
- data/ext/ffi_c/MethodHandle.c +4 -2
- data/ext/ffi_c/libffi/.ci/Containerfile.ppc64le +12 -0
- data/ext/ffi_c/libffi/.ci/build.sh +38 -33
- data/ext/ffi_c/libffi/.ci/install.sh +46 -50
- data/ext/ffi_c/libffi/.ci/site.exp +6 -0
- data/ext/ffi_c/libffi/.gail-labels +44 -0
- data/ext/ffi_c/libffi/.github/workflows/build.yml +212 -333
- data/ext/ffi_c/libffi/.github/workflows/emscripten.yml +101 -58
- data/ext/ffi_c/libffi/.github/workflows/label-new-issue.yaml +15 -0
- data/ext/ffi_c/libffi/.github/workflows/tarball.yml +55 -0
- data/ext/ffi_c/libffi/LICENSE +1 -1
- data/ext/ffi_c/libffi/Makefile.am +20 -15
- data/ext/ffi_c/libffi/Makefile.in +41 -54
- data/ext/ffi_c/libffi/README.md +40 -4
- data/ext/ffi_c/libffi/acinclude.m4 +6 -0
- data/ext/ffi_c/libffi/config.guess +80 -22
- data/ext/ffi_c/libffi/config.sub +161 -80
- data/ext/ffi_c/libffi/configure +1058 -1372
- data/ext/ffi_c/libffi/configure.ac +28 -14
- data/ext/ffi_c/libffi/configure.host +6 -6
- data/ext/ffi_c/libffi/doc/Makefile.in +4 -0
- data/ext/ffi_c/libffi/doc/libffi.texi +27 -4
- data/ext/ffi_c/libffi/doc/version.texi +4 -4
- data/ext/ffi_c/libffi/fficonfig.h.in +9 -9
- data/ext/ffi_c/libffi/generate-darwin-source-and-headers.py +1 -28
- data/ext/ffi_c/libffi/include/Makefile.in +4 -0
- data/ext/ffi_c/libffi/include/ffi.h.in +19 -1
- data/ext/ffi_c/libffi/include/ffi_cfi.h +2 -0
- data/ext/ffi_c/libffi/include/ffi_common.h +17 -0
- data/ext/ffi_c/libffi/libffi.map.in +13 -1
- data/ext/ffi_c/libffi/libtool-version +1 -1
- data/ext/ffi_c/libffi/m4/asmcfi.m4 +28 -11
- data/ext/ffi_c/libffi/m4/ax_check_compile_flag.m4 +13 -3
- data/ext/ffi_c/libffi/man/Makefile.in +4 -0
- data/ext/ffi_c/libffi/src/aarch64/ffi.c +7 -4
- data/ext/ffi_c/libffi/src/aarch64/ffitarget.h +2 -2
- data/ext/ffi_c/libffi/src/aarch64/internal.h +63 -17
- data/ext/ffi_c/libffi/src/aarch64/sysv.S +22 -12
- data/ext/ffi_c/libffi/src/arc/arcompact.S +2 -2
- data/ext/ffi_c/libffi/src/arc/ffi.c +6 -2
- data/ext/ffi_c/libffi/src/arm/sysv.S +1 -1
- data/ext/ffi_c/libffi/src/closures.c +3 -3
- data/ext/ffi_c/libffi/src/dlmalloc.c +1 -0
- data/ext/ffi_c/libffi/src/mips/ffitarget.h +2 -4
- data/ext/ffi_c/libffi/src/mips/n32.S +4 -0
- data/ext/ffi_c/libffi/src/mips/o32.S +4 -0
- data/ext/ffi_c/libffi/src/or1k/ffi.c +2 -2
- data/ext/ffi_c/libffi/src/pa/linux.S +4 -0
- data/ext/ffi_c/libffi/src/powerpc/ffi.c +19 -0
- data/ext/ffi_c/libffi/src/powerpc/ffi_linux64.c +26 -19
- data/ext/ffi_c/libffi/src/powerpc/ffi_sysv.c +26 -16
- data/ext/ffi_c/libffi/src/powerpc/internal.h +10 -0
- data/ext/ffi_c/libffi/src/powerpc/linux64_closure.S +47 -0
- data/ext/ffi_c/libffi/src/powerpc/ppc_closure.S +24 -0
- data/ext/ffi_c/libffi/src/prep_cif.c +1 -4
- data/ext/ffi_c/libffi/src/riscv/ffi.c +39 -16
- data/ext/ffi_c/libffi/src/riscv/internal.h +7 -0
- data/ext/ffi_c/libffi/src/riscv/sysv.S +24 -0
- data/ext/ffi_c/libffi/src/s390/ffi.c +28 -1
- data/ext/ffi_c/libffi/src/s390/internal.h +11 -0
- data/ext/ffi_c/libffi/src/s390/sysv.S +38 -0
- data/ext/ffi_c/libffi/src/sparc/ffi.c +16 -0
- data/ext/ffi_c/libffi/src/tramp.c +6 -1
- data/ext/ffi_c/libffi/src/types.c +23 -1
- data/ext/ffi_c/libffi/src/{wasm32 → wasm}/ffi.c +166 -315
- data/ext/ffi_c/libffi/src/{wasm32 → wasm}/ffitarget.h +17 -0
- data/ext/ffi_c/libffi/src/x86/ffi.c +4 -1
- data/ext/ffi_c/libffi/src/x86/ffi64.c +4 -1
- data/ext/ffi_c/libffi/src/x86/ffitarget.h +0 -3
- data/ext/ffi_c/libffi/src/x86/sysv.S +1 -3
- data/ext/ffi_c/libffi/src/x86/sysv_intel.S +1 -3
- data/ext/ffi_c/libffi/testsuite/Makefile.am +6 -4
- data/ext/ffi_c/libffi/testsuite/Makefile.in +10 -4
- data/ext/ffi_c/libffi/testsuite/emscripten/build-tests.sh +4 -24
- data/ext/ffi_c/libffi/testsuite/emscripten/build.sh +10 -27
- data/ext/ffi_c/libffi/testsuite/emscripten/node-tests.sh +6 -31
- data/ext/ffi_c/libffi/testsuite/lib/libffi.exp +269 -256
- data/ext/ffi_c/libffi/testsuite/libffi.bhaible/testcases.c +1 -1
- data/ext/ffi_c/libffi/testsuite/libffi.call/callback.c +2 -2
- data/ext/ffi_c/libffi/testsuite/libffi.call/callback2.c +2 -2
- data/ext/ffi_c/libffi/testsuite/libffi.call/callback3.c +2 -2
- data/ext/ffi_c/libffi/testsuite/libffi.call/callback4.c +2 -2
- data/ext/ffi_c/libffi/testsuite/libffi.call/ffitest.h +3 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/longjmp.c +60 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/overread.c +54 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/struct_int_float.c +88 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/va_struct2.c +1 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/va_struct3.c +1 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/x32.c +31 -0
- data/ext/ffi_c/libffi/testsuite/libffi.closures/cls_dbls_struct.c +1 -1
- data/ext/ffi_c/libffi/testsuite/libffi.closures/cls_multi_sshortchar.c +1 -1
- data/ext/ffi_c/libffi/testsuite/libffi.closures/cls_multi_ushortchar.c +1 -1
- data/ext/ffi_c/libffi/testsuite/libffi.closures/huge_struct.c +1 -2
- data/ext/ffi_c/libffi/testsuite/libffi.closures/unwindtest.cc +2 -0
- data/ext/ffi_c/libffi/testsuite/libffi.closures/unwindtest_ffi_call.cc +2 -0
- data/ext/ffi_c/libffi/testsuite/libffi.complex/complex_int.c +1 -1
- data/ext/ffi_c/libffi/testsuite/libffi.threads/ffitest.h +1 -0
- data/ext/ffi_c/libffi/testsuite/libffi.threads/threads.exp +50 -0
- data/ext/ffi_c/libffi/testsuite/libffi.threads/tsan.c +74 -0
- data/ext/ffi_c/libffi.mk +5 -0
- data/ffi.gemspec +4 -5
- data/lib/ffi/autopointer.rb +6 -0
- data/lib/ffi/compat.rb +11 -0
- data/lib/ffi/function.rb +23 -0
- data/lib/ffi/library.rb +19 -3
- data/lib/ffi/struct_by_reference.rb +1 -1
- data/lib/ffi/version.rb +1 -1
- data/samples/hello_ractor.rb +9 -1
- data/samples/qsort_ractor.rb +9 -1
- data/sig/ffi/auto_pointer.rbs +1 -1
- data/sig/ffi/errno.rbs +8 -0
- data/sig/ffi/platform.rbs +49 -0
- data/sig/ffi/struct.rbs +2 -2
- data/sig/ffi/struct_by_reference.rbs +1 -1
- data/sig/ffi.rbs +4 -1
- data.tar.gz.sig +0 -0
- metadata +37 -83
- metadata.gz.sig +0 -0
- data/ext/ffi_c/libffi/.appveyor/site.exp +0 -16
- data/ext/ffi_c/libffi/.appveyor.yml +0 -84
- data/ext/ffi_c/libffi/.circleci/config.yml +0 -156
- data/ext/ffi_c/libffi/src/nios2/ffi.c +0 -304
- data/ext/ffi_c/libffi/src/nios2/ffitarget.h +0 -52
- data/ext/ffi_c/libffi/src/nios2/sysv.S +0 -136
- data/lib/ffi/tools/types_generator.rb +0 -137
- data/rakelib/ffi_gem_helper.rb +0 -65
- /data/ext/ffi_c/libffi/{.appveyor → .ci}/unix-noexec.exp +0 -0
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/* Area: ffi_call
|
|
2
|
+
Purpose: Test longjmp over ffi_call frames */
|
|
3
|
+
|
|
4
|
+
/* Test code adapted from Lars Kanis' bug report:
|
|
5
|
+
https://github.com/libffi/libffi/issues/905 */
|
|
6
|
+
|
|
7
|
+
/* { dg-do run } */
|
|
8
|
+
|
|
9
|
+
#include "ffitest.h"
|
|
10
|
+
#include "ffi_common.h"
|
|
11
|
+
|
|
12
|
+
#include <setjmp.h>
|
|
13
|
+
|
|
14
|
+
static jmp_buf buf;
|
|
15
|
+
|
|
16
|
+
static void ABI_ATTR lev2(const char *str) {
|
|
17
|
+
printf("lev2 %s\n", str);
|
|
18
|
+
// jumps back to where setjmp was called - making setjmp now return 1
|
|
19
|
+
longjmp(buf, 1);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
static void ABI_ATTR lev1(const char *str) {
|
|
23
|
+
lev2(str);
|
|
24
|
+
|
|
25
|
+
// will not be reached
|
|
26
|
+
printf("lev1 %s\n", str);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
int main()
|
|
30
|
+
{
|
|
31
|
+
ffi_cif cif;
|
|
32
|
+
ffi_type *args[1];
|
|
33
|
+
void *values[1];
|
|
34
|
+
char *s;
|
|
35
|
+
ffi_arg rc;
|
|
36
|
+
/* Initialize the argument info vectors */
|
|
37
|
+
args[0] = &ffi_type_pointer;
|
|
38
|
+
values[0] = &s;
|
|
39
|
+
/* Initialize the cif */
|
|
40
|
+
if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
|
|
41
|
+
&ffi_type_sint, args) == FFI_OK)
|
|
42
|
+
{
|
|
43
|
+
s = "direct call";
|
|
44
|
+
if (!setjmp(buf)){
|
|
45
|
+
// works on x64 and arm64
|
|
46
|
+
lev1(s);
|
|
47
|
+
} else {
|
|
48
|
+
printf("back to main\n");
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
s = "through libffi";
|
|
52
|
+
if (!setjmp(buf)){
|
|
53
|
+
// works on x64 but segfaults on arm64
|
|
54
|
+
ffi_call(&cif, (void (*)(void))lev1, &rc, values);
|
|
55
|
+
} else {
|
|
56
|
+
printf("back to main\n");
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return 0;
|
|
60
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/* Area: ffi_call
|
|
2
|
+
Purpose: Tests if ffi_call reads data beyond end.
|
|
3
|
+
Limitations: needs mmap.
|
|
4
|
+
PR: 887
|
|
5
|
+
Originator: Mikulas Patocka <mikulas@twibright.com> */
|
|
6
|
+
|
|
7
|
+
/* { dg-do run } */
|
|
8
|
+
|
|
9
|
+
#include "ffitest.h"
|
|
10
|
+
|
|
11
|
+
#ifdef __linux__
|
|
12
|
+
#include <sys/mman.h>
|
|
13
|
+
#include <unistd.h>
|
|
14
|
+
|
|
15
|
+
static int ABI_ATTR fn(unsigned char a, unsigned short b, unsigned int c, unsigned long d)
|
|
16
|
+
{
|
|
17
|
+
return (int)(a + b + c + d);
|
|
18
|
+
}
|
|
19
|
+
#endif
|
|
20
|
+
|
|
21
|
+
int main(void)
|
|
22
|
+
{
|
|
23
|
+
#ifdef __linux__
|
|
24
|
+
ffi_cif cif;
|
|
25
|
+
ffi_type *args[MAX_ARGS];
|
|
26
|
+
void *values[MAX_ARGS];
|
|
27
|
+
ffi_arg rint;
|
|
28
|
+
char *m;
|
|
29
|
+
int ps;
|
|
30
|
+
args[0] = &ffi_type_uchar;
|
|
31
|
+
args[1] = &ffi_type_ushort;
|
|
32
|
+
args[2] = &ffi_type_uint;
|
|
33
|
+
args[3] = &ffi_type_ulong;
|
|
34
|
+
CHECK(ffi_prep_cif(&cif, ABI_NUM, 4, &ffi_type_sint, args) == FFI_OK);
|
|
35
|
+
ps = getpagesize();
|
|
36
|
+
m = mmap(NULL, ps * 3, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
|
|
37
|
+
CHECK(m != MAP_FAILED);
|
|
38
|
+
CHECK(mprotect(m, ps, PROT_NONE) == 0);
|
|
39
|
+
CHECK(mprotect(m + ps * 2, ps, PROT_NONE) == 0);
|
|
40
|
+
values[0] = m + ps * 2 - sizeof(unsigned char);
|
|
41
|
+
values[1] = m + ps * 2 - sizeof(unsigned short);
|
|
42
|
+
values[2] = m + ps * 2 - sizeof(unsigned int);
|
|
43
|
+
values[3] = m + ps * 2 - sizeof(unsigned long);
|
|
44
|
+
ffi_call(&cif, FFI_FN(fn), &rint, values);
|
|
45
|
+
CHECK((int)rint == 0);
|
|
46
|
+
values[0] = m + ps;
|
|
47
|
+
values[1] = m + ps;
|
|
48
|
+
values[2] = m + ps;
|
|
49
|
+
values[3] = m + ps;
|
|
50
|
+
ffi_call(&cif, FFI_FN(fn), &rint, values);
|
|
51
|
+
CHECK((int)rint == 0);
|
|
52
|
+
#endif
|
|
53
|
+
exit(0);
|
|
54
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/* Area: ffi_call
|
|
2
|
+
Purpose: Demonstrate structures with integers corrupting earlier floats
|
|
3
|
+
Limitations: none.
|
|
4
|
+
PR: #848
|
|
5
|
+
Originator: kellda */
|
|
6
|
+
|
|
7
|
+
/* { dg-do run } */
|
|
8
|
+
#include "ffitest.h"
|
|
9
|
+
|
|
10
|
+
typedef struct
|
|
11
|
+
{
|
|
12
|
+
unsigned long i;
|
|
13
|
+
float f;
|
|
14
|
+
} test_structure_int_float;
|
|
15
|
+
|
|
16
|
+
static float ABI_ATTR struct_int_float(test_structure_int_float ts1,
|
|
17
|
+
test_structure_int_float ts2 __UNUSED__,
|
|
18
|
+
test_structure_int_float ts3 __UNUSED__,
|
|
19
|
+
test_structure_int_float ts4 __UNUSED__,
|
|
20
|
+
test_structure_int_float ts5 __UNUSED__,
|
|
21
|
+
test_structure_int_float ts6 __UNUSED__)
|
|
22
|
+
{
|
|
23
|
+
return ts1.f;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
int main (void)
|
|
27
|
+
{
|
|
28
|
+
ffi_cif cif;
|
|
29
|
+
ffi_type *args[MAX_ARGS];
|
|
30
|
+
void *values[MAX_ARGS];
|
|
31
|
+
ffi_type ts_type;
|
|
32
|
+
ffi_type *ts_type_elements[3];
|
|
33
|
+
float rfloat;
|
|
34
|
+
|
|
35
|
+
test_structure_int_float ts_arg[6];
|
|
36
|
+
|
|
37
|
+
ts_type.size = 0;
|
|
38
|
+
ts_type.alignment = 0;
|
|
39
|
+
ts_type.type = FFI_TYPE_STRUCT;
|
|
40
|
+
ts_type.elements = ts_type_elements;
|
|
41
|
+
ts_type_elements[0] = &ffi_type_ulong;
|
|
42
|
+
ts_type_elements[1] = &ffi_type_float;
|
|
43
|
+
ts_type_elements[2] = NULL;
|
|
44
|
+
|
|
45
|
+
args[0] = &ts_type;
|
|
46
|
+
values[0] = &ts_arg[0];
|
|
47
|
+
args[1] = &ts_type;
|
|
48
|
+
values[1] = &ts_arg[1];
|
|
49
|
+
args[2] = &ts_type;
|
|
50
|
+
values[2] = &ts_arg[2];
|
|
51
|
+
args[3] = &ts_type;
|
|
52
|
+
values[3] = &ts_arg[3];
|
|
53
|
+
args[4] = &ts_type;
|
|
54
|
+
values[4] = &ts_arg[4];
|
|
55
|
+
args[5] = &ts_type;
|
|
56
|
+
values[5] = &ts_arg[5];
|
|
57
|
+
|
|
58
|
+
/* Initialize the cif */
|
|
59
|
+
CHECK(ffi_prep_cif(&cif, ABI_NUM, 6, &ffi_type_float, args) == FFI_OK);
|
|
60
|
+
|
|
61
|
+
ts_arg[0].i = 1;
|
|
62
|
+
ts_arg[0].f = 11.11f;
|
|
63
|
+
ts_arg[1].i = 2;
|
|
64
|
+
ts_arg[1].f = 22.22f;
|
|
65
|
+
ts_arg[2].i = 3;
|
|
66
|
+
ts_arg[2].f = 33.33f;
|
|
67
|
+
ts_arg[3].i = 4;
|
|
68
|
+
ts_arg[3].f = 44.44f;
|
|
69
|
+
ts_arg[4].i = 5;
|
|
70
|
+
ts_arg[4].f = 55.55f;
|
|
71
|
+
ts_arg[5].i = 6;
|
|
72
|
+
ts_arg[5].f = 66.66f;
|
|
73
|
+
|
|
74
|
+
printf ("%g\n", ts_arg[0].f);
|
|
75
|
+
printf ("%g\n", ts_arg[1].f);
|
|
76
|
+
printf ("%g\n", ts_arg[2].f);
|
|
77
|
+
printf ("%g\n", ts_arg[3].f);
|
|
78
|
+
printf ("%g\n", ts_arg[4].f);
|
|
79
|
+
printf ("%g\n", ts_arg[5].f);
|
|
80
|
+
|
|
81
|
+
ffi_call(&cif, FFI_FN(struct_int_float), &rfloat, values);
|
|
82
|
+
|
|
83
|
+
printf ("%g\n", rfloat);
|
|
84
|
+
|
|
85
|
+
CHECK(fabs(rfloat - 11.11) < 3 * FLT_EPSILON);
|
|
86
|
+
|
|
87
|
+
exit(0);
|
|
88
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/* Area: ffi_call
|
|
2
|
+
Purpose: Check zero-extension of pointers on x32.
|
|
3
|
+
Limitations: none.
|
|
4
|
+
PR: 887
|
|
5
|
+
Originator: Mikulas Patocka <mikulas@twibright.com> */
|
|
6
|
+
|
|
7
|
+
/* { dg-do run } */
|
|
8
|
+
|
|
9
|
+
#include "ffitest.h"
|
|
10
|
+
|
|
11
|
+
static int ABI_ATTR fn(int *a)
|
|
12
|
+
{
|
|
13
|
+
if (a)
|
|
14
|
+
return *a;
|
|
15
|
+
return -1;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
int main(void)
|
|
19
|
+
{
|
|
20
|
+
ffi_cif cif;
|
|
21
|
+
ffi_type *args[MAX_ARGS];
|
|
22
|
+
void *values[MAX_ARGS];
|
|
23
|
+
void *z[2] = { (void *)0, (void *)1 };
|
|
24
|
+
ffi_arg rint;
|
|
25
|
+
args[0] = &ffi_type_pointer;
|
|
26
|
+
values[0] = z;
|
|
27
|
+
CHECK(ffi_prep_cif(&cif, ABI_NUM, 1, &ffi_type_sint, args) == FFI_OK);
|
|
28
|
+
ffi_call(&cif, FFI_FN(fn), &rint, values);
|
|
29
|
+
CHECK((int)rint == -1);
|
|
30
|
+
exit(0);
|
|
31
|
+
}
|
|
@@ -80,7 +80,7 @@ int main (void)
|
|
|
80
80
|
/* { dg-output "1 32765 127 -128: 32765" } */
|
|
81
81
|
printf("res: %d\n", (signed short)res_call);
|
|
82
82
|
/* { dg-output "\nres: 32765" } */
|
|
83
|
-
CHECK(res_call == 32765);
|
|
83
|
+
CHECK((signed short)res_call == 32765);
|
|
84
84
|
|
|
85
85
|
CHECK(ffi_prep_closure_loc(pcl, &cif, test_func_gn, NULL, code) == FFI_OK);
|
|
86
86
|
|
|
@@ -80,7 +80,7 @@ int main (void)
|
|
|
80
80
|
/* { dg-output "1 2 127 128: 258" } */
|
|
81
81
|
printf("res: %d\n", (unsigned short)res_call);
|
|
82
82
|
/* { dg-output "\nres: 258" } */
|
|
83
|
-
CHECK(res_call == 258);
|
|
83
|
+
CHECK((unsigned short)res_call == 258);
|
|
84
84
|
|
|
85
85
|
CHECK(ffi_prep_closure_loc(pcl, &cif, test_func_gn, NULL, code) == FFI_OK);
|
|
86
86
|
|
|
@@ -216,8 +216,7 @@ cls_large_fn(ffi_cif* cif __UNUSED__, void* resp, void** args, void* userdata __
|
|
|
216
216
|
ui8_5, si8_5);
|
|
217
217
|
}
|
|
218
218
|
|
|
219
|
-
int
|
|
220
|
-
main(int argc __UNUSED__, const char** argv __UNUSED__)
|
|
219
|
+
int main (void)
|
|
221
220
|
{
|
|
222
221
|
void *code;
|
|
223
222
|
ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
|
|
@@ -76,7 +76,7 @@ int main (void)
|
|
|
76
76
|
|
|
77
77
|
printf ("%d,%di %d,%di, x %d 1234, y %d 11110\n",
|
|
78
78
|
(int)tc_result, (int)(tc_result * -I), 2, 8, tc_int_arg_x, tc_y);
|
|
79
|
-
/* dg-output "-2,8i 2,8i, x 1234 1234, y 11110 11110" */
|
|
79
|
+
/* { dg-output "-2,8i 2,8i, x 1234 1234, y 11110 11110" } */
|
|
80
80
|
CHECK (creal (tc_result) == -2);
|
|
81
81
|
CHECK (cimag (tc_result) == 8);
|
|
82
82
|
CHECK (tc_int_arg_x == 1234);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
#include "../libffi.call/ffitest.h"
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Copyright (C) 2003, 2006, 2009, 2010, 2014 Free Software Foundation, Inc.
|
|
2
|
+
|
|
3
|
+
# This program is free software; you can redistribute it and/or modify
|
|
4
|
+
# it under the terms of the GNU General Public License as published by
|
|
5
|
+
# the Free Software Foundation; either version 3 of the License, or
|
|
6
|
+
# (at your option) any later version.
|
|
7
|
+
#
|
|
8
|
+
# This program is distributed in the hope that it will be useful,
|
|
9
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
10
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
11
|
+
# GNU General Public License for more details.
|
|
12
|
+
#
|
|
13
|
+
# You should have received a copy of the GNU General Public License
|
|
14
|
+
# along with this program; see the file COPYING3. If not see
|
|
15
|
+
# <http://www.gnu.org/licenses/>.
|
|
16
|
+
|
|
17
|
+
dg-init
|
|
18
|
+
libffi-init
|
|
19
|
+
|
|
20
|
+
global srcdir subdir
|
|
21
|
+
|
|
22
|
+
if { [string match $compiler_vendor "microsoft"] } {
|
|
23
|
+
# -wd4005 macro redefinition
|
|
24
|
+
# -wd4244 implicit conversion to type of smaller size
|
|
25
|
+
# -wd4305 truncation to smaller type
|
|
26
|
+
# -wd4477 printf %lu of uintptr_t
|
|
27
|
+
# -wd4312 implicit conversion to type of greater size
|
|
28
|
+
# -wd4311 pointer truncation to unsigned long
|
|
29
|
+
# -EHsc C++ Exception Handling (no SEH exceptions)
|
|
30
|
+
set additional_options "-wd4005 -wd4244 -wd4305 -wd4477 -wd4312 -wd4311 -EHsc";
|
|
31
|
+
} else {
|
|
32
|
+
set additional_options "";
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
set tlist [lsort [glob -nocomplain -- $srcdir/$subdir/*.c]]
|
|
36
|
+
|
|
37
|
+
# No pthreads for windows or wasm
|
|
38
|
+
if { [string match $compiler_vendor "microsoft"] || [istarget "wasm*-*-*"] } {
|
|
39
|
+
foreach test $tlist {
|
|
40
|
+
unsupported "$test"
|
|
41
|
+
}
|
|
42
|
+
} else {
|
|
43
|
+
run-many-tests $tlist $additional_options
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
dg-finish
|
|
47
|
+
|
|
48
|
+
# Local Variables:
|
|
49
|
+
# tcl-indent-level:4
|
|
50
|
+
# End:
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/* { dg-do run } */
|
|
2
|
+
|
|
3
|
+
#include "ffitest.h"
|
|
4
|
+
|
|
5
|
+
#include <pthread.h>
|
|
6
|
+
#include <stdio.h>
|
|
7
|
+
#include <stdlib.h>
|
|
8
|
+
|
|
9
|
+
#define NUM_THREADS 20
|
|
10
|
+
|
|
11
|
+
#if defined(_POSIX_BARRIERS) && _POSIX_BARRIERS > 0
|
|
12
|
+
pthread_barrier_t barrier;
|
|
13
|
+
#endif
|
|
14
|
+
|
|
15
|
+
typedef float (*callback_fn)(float, float);
|
|
16
|
+
|
|
17
|
+
void callback(ffi_cif *cif __UNUSED__, void *ret, void **args, void *userdata __UNUSED__) {
|
|
18
|
+
float a = *(float *)args[0];
|
|
19
|
+
float b = *(float *)args[1];
|
|
20
|
+
*(float *)ret = a / 2 + b / 2;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
void *thread_func(void *arg) {
|
|
24
|
+
#if defined(_POSIX_BARRIERS) && _POSIX_BARRIERS > 0
|
|
25
|
+
pthread_barrier_wait(&barrier);
|
|
26
|
+
#endif
|
|
27
|
+
|
|
28
|
+
ffi_cif cif;
|
|
29
|
+
ffi_type *args[2] = { &ffi_type_float, &ffi_type_float };
|
|
30
|
+
|
|
31
|
+
if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &ffi_type_float, args) != FFI_OK) {
|
|
32
|
+
fprintf(stderr, "ffi_prep_cif failed\n");
|
|
33
|
+
return NULL;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
ffi_closure *closure = ffi_closure_alloc(sizeof(ffi_closure), (void **)&arg);
|
|
37
|
+
|
|
38
|
+
if (ffi_prep_closure_loc(closure, &cif, callback, NULL, arg) != FFI_OK) {
|
|
39
|
+
fprintf(stderr, "ffi_prep_closure_loc failed\n");
|
|
40
|
+
return NULL;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
callback_fn fn = (callback_fn)arg;
|
|
44
|
+
(void) fn(4.0f, 6.0f);
|
|
45
|
+
|
|
46
|
+
ffi_closure_free(closure);
|
|
47
|
+
return NULL;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
int main() {
|
|
51
|
+
pthread_t threads[NUM_THREADS];
|
|
52
|
+
|
|
53
|
+
#if defined(_POSIX_BARRIERS) && _POSIX_BARRIERS > 0
|
|
54
|
+
pthread_barrier_init(&barrier, NULL, NUM_THREADS);
|
|
55
|
+
#endif
|
|
56
|
+
|
|
57
|
+
for (int i = 0; i < NUM_THREADS; ++i) {
|
|
58
|
+
if (pthread_create(&threads[i], NULL, thread_func, NULL) != 0) {
|
|
59
|
+
perror("pthread_create");
|
|
60
|
+
exit(EXIT_FAILURE);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
for (int i = 0; i < NUM_THREADS; ++i) {
|
|
65
|
+
pthread_join(threads[i], NULL);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
#if defined(_POSIX_BARRIERS) && _POSIX_BARRIERS > 0
|
|
69
|
+
pthread_barrier_destroy(&barrier);
|
|
70
|
+
#endif
|
|
71
|
+
|
|
72
|
+
printf("Completed\n");
|
|
73
|
+
return 0;
|
|
74
|
+
}
|
data/ext/ffi_c/libffi.mk
CHANGED
data/ffi.gemspec
CHANGED
|
@@ -15,9 +15,10 @@ Gem::Specification.new do |s|
|
|
|
15
15
|
s.metadata['wiki_uri'] = 'https://github.com/ffi/ffi/wiki'
|
|
16
16
|
s.metadata['source_code_uri'] = 'https://github.com/ffi/ffi/'
|
|
17
17
|
s.metadata['mailing_list_uri'] = 'http://groups.google.com/group/ruby-ffi'
|
|
18
|
+
s.metadata['rubygems_mfa_required'] = 'true'
|
|
18
19
|
end
|
|
19
20
|
s.files = `git ls-files -z`.split("\x0").reject do |f|
|
|
20
|
-
f =~ /^(\.|bench|gen|libtest|nbproject|spec)/
|
|
21
|
+
f =~ /^(\.|bench|gen|libtest|nbproject|spec|rakelib)/
|
|
21
22
|
end
|
|
22
23
|
|
|
23
24
|
# Add libffi git files
|
|
@@ -35,8 +36,6 @@ Gem::Specification.new do |s|
|
|
|
35
36
|
s.license = 'BSD-3-Clause'
|
|
36
37
|
s.require_paths << 'ext/ffi_c'
|
|
37
38
|
s.required_ruby_version = '>= 2.5'
|
|
38
|
-
|
|
39
|
-
s.
|
|
40
|
-
s.add_development_dependency 'rake-compiler-dock', '~> 1.0'
|
|
41
|
-
s.add_development_dependency 'rspec', '~> 2.14.1'
|
|
39
|
+
|
|
40
|
+
s.metadata['msys2_mingw_dependencies'] = 'libffi'
|
|
42
41
|
end
|
data/lib/ffi/autopointer.rb
CHANGED
data/lib/ffi/compat.rb
CHANGED
|
@@ -40,4 +40,15 @@ module FFI
|
|
|
40
40
|
obj.freeze
|
|
41
41
|
end
|
|
42
42
|
end
|
|
43
|
+
|
|
44
|
+
if defined?(Ractor.shareable_proc)
|
|
45
|
+
# This is for FFI internal use only.
|
|
46
|
+
def self.shareable_proc(**kwargs, &block)
|
|
47
|
+
Ractor.shareable_proc(**kwargs, &block)
|
|
48
|
+
end
|
|
49
|
+
else
|
|
50
|
+
def self.shareable_proc(**_kwargs, &block)
|
|
51
|
+
block
|
|
52
|
+
end
|
|
53
|
+
end
|
|
43
54
|
end
|
data/lib/ffi/function.rb
CHANGED
|
@@ -51,6 +51,29 @@ module FFI
|
|
|
51
51
|
end
|
|
52
52
|
end
|
|
53
53
|
|
|
54
|
+
if RUBY_PLATFORM == 'aarch64-mingw-ucrt'
|
|
55
|
+
# Use a workaround for https://github.com/libffi/libffi/issues/905
|
|
56
|
+
def attach(mod, name)
|
|
57
|
+
this = self
|
|
58
|
+
body = proc do |*args, &block|
|
|
59
|
+
this.call(*args, &block)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
mod.define_method(name, body)
|
|
63
|
+
mod.define_singleton_method(name, body)
|
|
64
|
+
|
|
65
|
+
# Store function Proc's for re-definition as Ractor-shareable in Library#freeze
|
|
66
|
+
funcs = mod.instance_variable_get("@ffi_function_procs")
|
|
67
|
+
unless funcs
|
|
68
|
+
funcs = {}
|
|
69
|
+
mod.instance_variable_set("@ffi_function_procs", funcs)
|
|
70
|
+
end
|
|
71
|
+
funcs[name] = self
|
|
72
|
+
|
|
73
|
+
self
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
54
77
|
# Stash the Function in a module variable so it can be inspected by attached_functions.
|
|
55
78
|
# On CRuby it also ensures that it does not get garbage collected.
|
|
56
79
|
module RegisterAttach
|
data/lib/ffi/library.rb
CHANGED
|
@@ -287,7 +287,7 @@ module FFI
|
|
|
287
287
|
if type.is_a?(Class) && type < FFI::Struct
|
|
288
288
|
# If it is a global struct, just attach directly to the pointer
|
|
289
289
|
s = s = type.new(address) # Assigning twice to suppress unused variable warning
|
|
290
|
-
self.module_eval
|
|
290
|
+
self.module_eval(<<-code, __FILE__, __LINE__)
|
|
291
291
|
@ffi_gsvars = {} unless defined?(@ffi_gsvars)
|
|
292
292
|
@ffi_gsvars[#{mname.inspect}] = s
|
|
293
293
|
def self.#{mname}
|
|
@@ -302,7 +302,7 @@ module FFI
|
|
|
302
302
|
#
|
|
303
303
|
# Attach to this module as mname/mname=
|
|
304
304
|
#
|
|
305
|
-
self.module_eval
|
|
305
|
+
self.module_eval(<<-code, __FILE__, __LINE__)
|
|
306
306
|
@ffi_gvars = {} unless defined?(@ffi_gvars)
|
|
307
307
|
@ffi_gvars[#{mname.inspect}] = s
|
|
308
308
|
def self.#{mname}
|
|
@@ -564,12 +564,28 @@ module FFI
|
|
|
564
564
|
# Freeze all definitions of the module
|
|
565
565
|
#
|
|
566
566
|
# This freezes the module's definitions, so that it can be used in a Ractor.
|
|
567
|
-
# No further
|
|
567
|
+
# No further functions or variables can be attached and no further enums or typedefs can be created in this module afterwards.
|
|
568
568
|
def freeze
|
|
569
|
+
# @ffi_function_procs is only used on aarch64-mingw-ucrt
|
|
570
|
+
instance_variable_get("@ffi_function_procs")&.each do |name, func|
|
|
571
|
+
# Redefine attached functions as Ractor-shareable.
|
|
572
|
+
# The function Proc can't be shareable from the beginning, since it references enums and typedefs.
|
|
573
|
+
this = FFI.make_shareable(func)
|
|
574
|
+
body = FFI.shareable_proc(self: nil) do |*args, &block|
|
|
575
|
+
this.call(*args, &block)
|
|
576
|
+
end
|
|
577
|
+
undef_method(name)
|
|
578
|
+
singleton_class.undef_method(name)
|
|
579
|
+
|
|
580
|
+
define_method(name, body)
|
|
581
|
+
define_singleton_method(name, body)
|
|
582
|
+
end
|
|
583
|
+
|
|
569
584
|
instance_variables.each do |name|
|
|
570
585
|
var = instance_variable_get(name)
|
|
571
586
|
FFI.make_shareable(var)
|
|
572
587
|
end
|
|
588
|
+
super
|
|
573
589
|
nil
|
|
574
590
|
end
|
|
575
591
|
end
|