ffi 1.16.3 → 1.17.2

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.
Files changed (140) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/CHANGELOG.md +59 -0
  4. data/Gemfile +11 -2
  5. data/README.md +1 -1
  6. data/Rakefile +19 -7
  7. data/ext/ffi_c/AbstractMemory.c +39 -38
  8. data/ext/ffi_c/ArrayType.c +2 -2
  9. data/ext/ffi_c/Buffer.c +4 -4
  10. data/ext/ffi_c/Call.c +12 -6
  11. data/ext/ffi_c/Call.h +3 -2
  12. data/ext/ffi_c/DynamicLibrary.c +2 -2
  13. data/ext/ffi_c/Function.c +52 -34
  14. data/ext/ffi_c/FunctionInfo.c +1 -1
  15. data/ext/ffi_c/LastError.c +4 -4
  16. data/ext/ffi_c/MemoryPointer.c +2 -2
  17. data/ext/ffi_c/Pointer.c +14 -11
  18. data/ext/ffi_c/Struct.c +11 -4
  19. data/ext/ffi_c/StructLayout.c +13 -13
  20. data/ext/ffi_c/Type.c +17 -16
  21. data/ext/ffi_c/Types.c +7 -1
  22. data/ext/ffi_c/Types.h +0 -1
  23. data/ext/ffi_c/Variadic.c +6 -3
  24. data/ext/ffi_c/libffi/.allow-ai-service +0 -0
  25. data/ext/ffi_c/libffi/.github/workflows/build.yml +34 -15
  26. data/ext/ffi_c/libffi/.github/workflows/emscripten.yml +50 -61
  27. data/ext/ffi_c/libffi/LICENSE +1 -1
  28. data/ext/ffi_c/libffi/Makefile.am +4 -3
  29. data/ext/ffi_c/libffi/Makefile.in +5 -25
  30. data/ext/ffi_c/libffi/README.md +28 -6
  31. data/ext/ffi_c/libffi/acinclude.m4 +6 -0
  32. data/ext/ffi_c/libffi/config.guess +80 -22
  33. data/ext/ffi_c/libffi/config.sub +161 -80
  34. data/ext/ffi_c/libffi/configure +46 -30
  35. data/ext/ffi_c/libffi/configure.ac +10 -9
  36. data/ext/ffi_c/libffi/configure.host +1 -6
  37. data/ext/ffi_c/libffi/doc/Makefile.in +1 -0
  38. data/ext/ffi_c/libffi/doc/libffi.texi +4 -4
  39. data/ext/ffi_c/libffi/doc/version.texi +4 -4
  40. data/ext/ffi_c/libffi/fficonfig.h.in +3 -3
  41. data/ext/ffi_c/libffi/include/Makefile.in +1 -0
  42. data/ext/ffi_c/libffi/include/ffi.h.in +2 -11
  43. data/ext/ffi_c/libffi/include/ffi_cfi.h +2 -0
  44. data/ext/ffi_c/libffi/include/ffi_common.h +21 -2
  45. data/ext/ffi_c/libffi/libffi.map.in +5 -0
  46. data/ext/ffi_c/libffi/libtool-version +1 -1
  47. data/ext/ffi_c/libffi/ltmain.sh +8 -20
  48. data/ext/ffi_c/libffi/man/Makefile.in +1 -0
  49. data/ext/ffi_c/libffi/msvc_build/aarch64/aarch64_include/ffi.h +1 -1
  50. data/ext/ffi_c/libffi/src/aarch64/ffi.c +33 -17
  51. data/ext/ffi_c/libffi/src/aarch64/ffitarget.h +2 -2
  52. data/ext/ffi_c/libffi/src/aarch64/internal.h +63 -17
  53. data/ext/ffi_c/libffi/src/aarch64/sysv.S +213 -57
  54. data/ext/ffi_c/libffi/src/arc/arcompact.S +2 -2
  55. data/ext/ffi_c/libffi/src/arc/ffi.c +6 -2
  56. data/ext/ffi_c/libffi/src/closures.c +6 -6
  57. data/ext/ffi_c/libffi/src/debug.c +2 -2
  58. data/ext/ffi_c/libffi/src/dlmalloc.c +2 -1
  59. data/ext/ffi_c/libffi/src/loongarch64/ffi.c +3 -0
  60. data/ext/ffi_c/libffi/src/mips/ffi.c +12 -4
  61. data/ext/ffi_c/libffi/src/mips/ffitarget.h +2 -4
  62. data/ext/ffi_c/libffi/src/mips/n32.S +69 -14
  63. data/ext/ffi_c/libffi/src/mips/o32.S +4 -0
  64. data/ext/ffi_c/libffi/src/or1k/ffi.c +2 -2
  65. data/ext/ffi_c/libffi/src/powerpc/ffi.c +13 -0
  66. data/ext/ffi_c/libffi/src/powerpc/ffi_darwin.c +36 -24
  67. data/ext/ffi_c/libffi/src/powerpc/ffi_linux64.c +26 -19
  68. data/ext/ffi_c/libffi/src/powerpc/ffi_sysv.c +26 -16
  69. data/ext/ffi_c/libffi/src/powerpc/internal.h +10 -0
  70. data/ext/ffi_c/libffi/src/powerpc/linux64_closure.S +47 -0
  71. data/ext/ffi_c/libffi/src/powerpc/ppc_closure.S +24 -0
  72. data/ext/ffi_c/libffi/src/prep_cif.c +1 -4
  73. data/ext/ffi_c/libffi/src/s390/ffi.c +28 -1
  74. data/ext/ffi_c/libffi/src/s390/internal.h +11 -0
  75. data/ext/ffi_c/libffi/src/s390/sysv.S +38 -0
  76. data/ext/ffi_c/libffi/src/sparc/ffi.c +16 -0
  77. data/ext/ffi_c/libffi/src/sparc/ffi64.c +7 -1
  78. data/ext/ffi_c/libffi/src/tramp.c +1 -1
  79. data/ext/ffi_c/libffi/src/types.c +4 -6
  80. data/ext/ffi_c/libffi/src/wasm32/ffi.c +23 -262
  81. data/ext/ffi_c/libffi/src/x86/ffi.c +4 -1
  82. data/ext/ffi_c/libffi/src/x86/ffi64.c +4 -1
  83. data/ext/ffi_c/libffi/src/x86/ffiw64.c +1 -1
  84. data/ext/ffi_c/libffi/testsuite/Makefile.am +80 -127
  85. data/ext/ffi_c/libffi/testsuite/Makefile.in +81 -127
  86. data/ext/ffi_c/libffi/testsuite/emscripten/build-tests.sh +4 -24
  87. data/ext/ffi_c/libffi/testsuite/emscripten/build.sh +8 -25
  88. data/ext/ffi_c/libffi/testsuite/emscripten/conftest.py +6 -0
  89. data/ext/ffi_c/libffi/testsuite/emscripten/node-tests.sh +3 -28
  90. data/ext/ffi_c/libffi/testsuite/libffi.call/callback.c +99 -0
  91. data/ext/ffi_c/libffi/testsuite/libffi.call/callback2.c +108 -0
  92. data/ext/ffi_c/libffi/testsuite/libffi.call/callback3.c +114 -0
  93. data/ext/ffi_c/libffi/testsuite/libffi.call/callback4.c +119 -0
  94. data/ext/ffi_c/libffi/testsuite/libffi.call/overread.c +54 -0
  95. data/ext/ffi_c/libffi/testsuite/libffi.call/struct_int_float.c +88 -0
  96. data/ext/ffi_c/libffi/testsuite/libffi.call/va_struct2.c +1 -0
  97. data/ext/ffi_c/libffi/testsuite/libffi.call/va_struct3.c +1 -0
  98. data/ext/ffi_c/libffi/testsuite/libffi.call/x32.c +31 -0
  99. data/ext/ffi_c/libffi/testsuite/libffi.closures/cls_multi_sshortchar.c +1 -1
  100. data/ext/ffi_c/libffi/testsuite/libffi.closures/cls_multi_ushortchar.c +1 -1
  101. data/ext/ffi_c/libffi/testsuite/libffi.complex/complex_int.c +1 -1
  102. data/ext/ffi_c/libffi.darwin.mk +2 -2
  103. data/lib/ffi/autopointer.rb +1 -9
  104. data/lib/ffi/dynamic_library.rb +34 -5
  105. data/lib/ffi/enum.rb +0 -1
  106. data/lib/ffi/ffi.rb +59 -0
  107. data/lib/ffi/function.rb +1 -1
  108. data/lib/ffi/io.rb +2 -2
  109. data/lib/ffi/library.rb +23 -23
  110. data/lib/ffi/platform/aarch64-linux/types.conf +74 -3
  111. data/lib/ffi/pointer.rb +6 -6
  112. data/lib/ffi/struct.rb +4 -4
  113. data/lib/ffi/struct_layout.rb +2 -2
  114. data/lib/ffi/struct_layout_builder.rb +8 -8
  115. data/lib/ffi/types.rb +51 -49
  116. data/lib/ffi/version.rb +1 -1
  117. data/sig/ffi/abstract_memory.rbs +165 -0
  118. data/sig/ffi/auto_pointer.rbs +26 -0
  119. data/sig/ffi/buffer.rbs +18 -0
  120. data/sig/ffi/data_converter.rbs +10 -0
  121. data/sig/ffi/dynamic_library.rbs +9 -0
  122. data/sig/ffi/enum.rbs +38 -0
  123. data/sig/ffi/function.rbs +39 -0
  124. data/sig/ffi/library.rbs +42 -0
  125. data/sig/ffi/native_type.rbs +86 -0
  126. data/sig/ffi/pointer.rbs +42 -0
  127. data/sig/ffi/struct.rbs +76 -0
  128. data/sig/ffi/struct_by_reference.rbs +11 -0
  129. data/sig/ffi/struct_by_value.rbs +7 -0
  130. data/sig/ffi/struct_layout.rbs +9 -0
  131. data/sig/ffi/struct_layout_builder.rbs +5 -0
  132. data/sig/ffi/type.rbs +39 -0
  133. data/sig/ffi.rbs +26 -0
  134. data.tar.gz.sig +0 -0
  135. metadata +41 -22
  136. metadata.gz.sig +0 -0
  137. data/ext/ffi_c/libffi/.circleci/config.yml +0 -156
  138. data/ext/ffi_c/libffi/src/nios2/ffi.c +0 -304
  139. data/ext/ffi_c/libffi/src/nios2/ffitarget.h +0 -52
  140. data/ext/ffi_c/libffi/src/nios2/sysv.S +0 -136
@@ -27,6 +27,7 @@
27
27
  #define LIBFFI_ASM
28
28
  #include <fficonfig.h>
29
29
  #include <ffi.h>
30
+ #include "internal.h"
30
31
  #include <powerpc/asm.h>
31
32
 
32
33
  .file "ppc_closure.S"
@@ -391,6 +392,29 @@ ENTRY(ffi_go_closure_sysv)
391
392
  .cfi_endproc
392
393
  END(ffi_go_closure_sysv)
393
394
 
395
+ #ifdef FFI_EXEC_STATIC_TRAMP
396
+ .text
397
+ .align PPC_TRAMP_MAP_SHIFT
398
+ FFI_HIDDEN (trampoline_code_table)
399
+ .globl trampoline_code_table
400
+ .type trampoline_code_table,@function
401
+ trampoline_code_table:
402
+ .rept PPC_TRAMP_MAP_SIZE / PPC_TRAMP_SIZE
403
+ mflr %r0
404
+ bcl 20,31,$+4
405
+ mflr %r11
406
+ addis %r11,%r11,PPC_TRAMP_MAP_SIZE@ha
407
+ mtlr %r0
408
+ lwz %r0,(PPC_TRAMP_MAP_SIZE-4)@l(%r11)
409
+ mtctr %r0
410
+ lwz %r11,(PPC_TRAMP_MAP_SIZE-8)@l(%r11)
411
+ bctr
412
+ nop
413
+ .endr
414
+ .size trampoline_code_table,.-trampoline_code_table
415
+ .align PPC_TRAMP_MAP_SHIFT
416
+ #endif /* FFI_EXEC_STATIC_TRAMP */
417
+
394
418
  #if defined __ELF__ && defined __linux__
395
419
  .section .note.GNU-stack,"",@progbits
396
420
  #endif
@@ -1,5 +1,5 @@
1
1
  /* -----------------------------------------------------------------------
2
- prep_cif.c - Copyright (c) 2011, 2012, 2021 Anthony Green
2
+ prep_cif.c - Copyright (c) 2011, 2012, 2021, 2025 Anthony Green
3
3
  Copyright (c) 1996, 1998, 2007 Red Hat, Inc.
4
4
  Copyright (c) 2022 Oracle and/or its affiliates.
5
5
 
@@ -158,9 +158,6 @@ ffi_status FFI_HIDDEN ffi_prep_cif_core(ffi_cif *cif, ffi_abi abi,
158
158
  #endif
159
159
  #ifdef XTENSA
160
160
  && (cif->rtype->size > 16)
161
- #endif
162
- #ifdef NIOS2
163
- && (cif->rtype->size > 8)
164
161
  #endif
165
162
  )
166
163
  bytes = STACK_ARG_SIZE(sizeof(void*));
@@ -32,6 +32,7 @@
32
32
  #include <ffi_common.h>
33
33
  #include <stdint.h>
34
34
  #include "internal.h"
35
+ #include <tramp.h>
35
36
 
36
37
  /*====================== End of Includes =============================*/
37
38
 
@@ -720,16 +721,30 @@ ffi_prep_closure_loc (ffi_closure *closure,
720
721
  #endif
721
722
  0x07f1 /* br %r1 */
722
723
  };
723
-
724
+ void (*dest)(void);
724
725
  unsigned long *tramp = (unsigned long *)&closure->tramp;
725
726
 
726
727
  if (cif->abi != FFI_SYSV)
727
728
  return FFI_BAD_ABI;
728
729
 
730
+
731
+ #if defined(FFI_EXEC_STATIC_TRAMP)
732
+ if (ffi_tramp_is_present(closure))
733
+ {
734
+ /* Initialize the static trampoline's parameters. */
735
+ dest = ffi_closure_SYSV;
736
+ ffi_tramp_set_parms (closure->ftramp, dest, closure);
737
+ goto out;
738
+ }
739
+ #endif
740
+
729
741
  memcpy (tramp, template, sizeof(template));
730
742
  tramp[2] = (unsigned long)codeloc;
731
743
  tramp[3] = (unsigned long)&ffi_closure_SYSV;
732
744
 
745
+ #if defined(FFI_EXEC_STATIC_TRAMP)
746
+ out:
747
+ #endif
733
748
  closure->cif = cif;
734
749
  closure->fun = fun;
735
750
  closure->user_data = user_data;
@@ -754,3 +769,15 @@ ffi_prep_go_closure (ffi_go_closure *closure, ffi_cif *cif,
754
769
 
755
770
  return FFI_OK;
756
771
  }
772
+
773
+ #if defined(FFI_EXEC_STATIC_TRAMP)
774
+ void *
775
+ ffi_tramp_arch (size_t *tramp_size, size_t *map_size)
776
+ {
777
+ extern void *trampoline_code_table;
778
+
779
+ *tramp_size = FFI390_TRAMP_SIZE;
780
+ *map_size = FFI390_TRAMP_MAP_SIZE;
781
+ return &trampoline_code_table;
782
+ }
783
+ #endif
@@ -9,3 +9,14 @@
9
9
  #define FFI390_RET_IN_MEM 8
10
10
 
11
11
  #define FFI390_RET_STRUCT (FFI390_RET_VOID | FFI390_RET_IN_MEM)
12
+
13
+
14
+ #if defined(FFI_EXEC_STATIC_TRAMP)
15
+ /*
16
+ * For the trampoline code table mapping, a mapping size of 4K is chosen.
17
+ */
18
+ #define FFI390_TRAMP_MAP_SHIFT 12
19
+ #define FFI390_TRAMP_MAP_SIZE (1 << FFI390_TRAMP_MAP_SHIFT)
20
+ #define FFI390_TRAMP_SIZE 16
21
+
22
+ #endif
@@ -28,6 +28,7 @@
28
28
  #define LIBFFI_ASM
29
29
  #include <fficonfig.h>
30
30
  #include <ffi.h>
31
+ #include "internal.h"
31
32
 
32
33
  .text
33
34
 
@@ -318,6 +319,43 @@ ffi_closure_SYSV:
318
319
  br %r14
319
320
  .cfi_endproc
320
321
  .size ffi_closure_SYSV,.-ffi_closure_SYSV
322
+
323
+
324
+ #if defined(FFI_EXEC_STATIC_TRAMP)
325
+ /*
326
+ * Below is the definition of the trampoline code table. Each element in
327
+ * the code table is a trampoline.
328
+ */
329
+ /*
330
+ * The trampoline uses the volatile register r0 and r1. As the registers are
331
+ * marked volatile in the ABI, the original values are not saved.
332
+ *
333
+ * The trampoline has two parameters - target code to jump to and data for
334
+ * the target code. The trampoline extracts the parameters from its parameter
335
+ * block (see tramp_table_map()). The trampoline saves the data address in r0.
336
+ * Finally, it jumps to the target code.
337
+ */
338
+
339
+ .align FFI390_TRAMP_MAP_SIZE
340
+ trampoline_code_table:
341
+ .rept FFI390_TRAMP_MAP_SIZE / FFI390_TRAMP_SIZE
342
+ basr %r1,0 # load next instruction address to r1
343
+ lmg %r0,%r1,4094(%r1) # load parameter block
344
+ # r0 -> data
345
+ # r1 -> code
346
+ br %r1 # jump to r1/code
347
+ .balign 8
348
+ .endr
349
+
350
+ .globl trampoline_code_table
351
+ FFI_HIDDEN(trampoline_code_table)
352
+ #ifdef __ELF__
353
+ .type trampoline_code_table, @function
354
+ .size trampoline_code_table,.- trampoline_code_table
355
+ #endif
356
+ .align FFI390_TRAMP_MAP_SIZE
357
+ #endif /* FFI_EXEC_STATIC_TRAMP */
358
+
321
359
  #endif /* !s390x */
322
360
 
323
361
  #if defined __ELF__ && defined __linux__
@@ -286,6 +286,8 @@ ffi_call_int (ffi_cif *cif, void (*fn)(void), void *rvalue,
286
286
  void **avalue, void *closure)
287
287
  {
288
288
  size_t bytes = cif->bytes;
289
+ size_t i, nargs = cif->nargs;
290
+ ffi_type **arg_types = cif->arg_types;
289
291
 
290
292
  FFI_ASSERT (cif->abi == FFI_V8);
291
293
 
@@ -295,6 +297,20 @@ ffi_call_int (ffi_cif *cif, void (*fn)(void), void *rvalue,
295
297
  && (cif->flags & SPARC_FLAG_RET_MASK) == SPARC_RET_STRUCT)
296
298
  bytes += FFI_ALIGN (cif->rtype->size, 8);
297
299
 
300
+ /* If we have any structure arguments, make a copy so we are passing
301
+ by value. */
302
+ for (i = 0; i < nargs; i++)
303
+ {
304
+ ffi_type *at = arg_types[i];
305
+ int size = at->size;
306
+ if (at->type == FFI_TYPE_STRUCT)
307
+ {
308
+ char *argcopy = alloca (size);
309
+ memcpy (argcopy, avalue[i], size);
310
+ avalue[i] = argcopy;
311
+ }
312
+ }
313
+
298
314
  ffi_call_v8(cif, fn, rvalue, avalue, -bytes, closure);
299
315
  }
300
316
 
@@ -382,13 +382,19 @@ ffi_prep_args_v9(ffi_cif *cif, unsigned long *argp, void *rvalue, void **avalue)
382
382
  *argp++ = *(SINT32 *)a;
383
383
  break;
384
384
  case FFI_TYPE_UINT32:
385
- case FFI_TYPE_FLOAT:
386
385
  *argp++ = *(UINT32 *)a;
387
386
  break;
388
387
  case FFI_TYPE_SINT64:
389
388
  case FFI_TYPE_UINT64:
390
389
  case FFI_TYPE_POINTER:
390
+ *argp++ = *(UINT64 *)a;
391
+ break;
392
+ case FFI_TYPE_FLOAT:
393
+ flags |= SPARC_FLAG_FP_ARGS;
394
+ *argp++ = *(UINT32 *)a;
395
+ break;
391
396
  case FFI_TYPE_DOUBLE:
397
+ flags |= SPARC_FLAG_FP_ARGS;
392
398
  *argp++ = *(UINT64 *)a;
393
399
  break;
394
400
 
@@ -307,7 +307,7 @@ ffi_tramp_lock(void)
307
307
  }
308
308
 
309
309
  static void
310
- ffi_tramp_unlock()
310
+ ffi_tramp_unlock(void)
311
311
  {
312
312
  pthread_mutex_unlock (&tramp_globals_mutex);
313
313
  }
@@ -1,6 +1,6 @@
1
1
  /* -----------------------------------------------------------------------
2
- types.c - Copyright (c) 1996, 1998 Red Hat, Inc.
3
-
2
+ types.c - Copyright (c) 1996, 1998, 2024 Red Hat, Inc.
3
+
4
4
  Predefined ffi_types needed by libffi.
5
5
 
6
6
  Permission is hereby granted, free of charge, to any person obtaining
@@ -87,7 +87,7 @@ FFI_TYPEDEF(double, double, FFI_TYPE_DOUBLE, const);
87
87
  #endif
88
88
 
89
89
  #ifdef __alpha__
90
- /* Even if we're not configured to default to 128-bit long double,
90
+ /* Even if we're not configured to default to 128-bit long double,
91
91
  maintain binary compatibility, as -mlong-double-128 can be used
92
92
  at any time. */
93
93
  /* Validate the hard-coded number below. */
@@ -95,14 +95,12 @@ FFI_TYPEDEF(double, double, FFI_TYPE_DOUBLE, const);
95
95
  # error FFI_TYPE_LONGDOUBLE out of date
96
96
  # endif
97
97
  const ffi_type ffi_type_longdouble = { 16, 16, 4, NULL };
98
- #elif FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
98
+ #else
99
99
  FFI_TYPEDEF(longdouble, long double, FFI_TYPE_LONGDOUBLE, FFI_LDBL_CONST);
100
100
  #endif
101
101
 
102
102
  #ifdef FFI_TARGET_HAS_COMPLEX_TYPE
103
103
  FFI_COMPLEX_TYPEDEF(float, float, const);
104
104
  FFI_COMPLEX_TYPEDEF(double, double, const);
105
- #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
106
105
  FFI_COMPLEX_TYPEDEF(longdouble, long double, FFI_LDBL_CONST);
107
106
  #endif
108
- #endif
@@ -41,28 +41,7 @@
41
41
 
42
42
  #define EM_JS_MACROS(ret, name, args, body...) EM_JS(ret, name, args, body)
43
43
 
44
- #if WASM_BIGINT
45
44
  EM_JS_DEPS(libffi, "$getWasmTableEntry,$setWasmTableEntry,$getEmptyTableSlot,$convertJsFunctionToWasm");
46
- #define CALL_FUNCTION_POINTER(ptr, args...) \
47
- (LOG_DEBUG("CALL_FUNC_PTR", ptr, args), \
48
- getWasmTableEntry(ptr).apply(null, args))
49
-
50
- #define JS_FUNCTION_TO_WASM convertJsFunctionToWasm
51
- #else
52
- EM_JS_DEPS(libffi, "$getWasmTableEntry,$setWasmTableEntry,$getEmptyTableSlot,$convertJsFunctionToWasm,$dynCall,$generateFuncType,$uleb128Encode");
53
- #define CALL_FUNCTION_POINTER(ptr, args...) \
54
- (LOG_DEBUG("CALL_FUNC_PTR", sig, ptr, args), \
55
- dynCall(sig, ptr, args))
56
-
57
- #define JS_FUNCTION_TO_WASM createLegalizerWrapper
58
- #endif
59
-
60
- // Signature calculations are not needed if WASM_BIGINT is present.
61
- #if WASM_BIGINT
62
- #define SIG(sig)
63
- #else
64
- #define SIG(sig) sig
65
- #endif
66
45
 
67
46
  #define DEREF_U8(addr, offset) HEAPU8[addr + offset]
68
47
  #define DEREF_S8(addr, offset) HEAP8[addr + offset]
@@ -73,12 +52,7 @@ EM_JS_DEPS(libffi, "$getWasmTableEntry,$setWasmTableEntry,$getEmptyTableSlot,$co
73
52
 
74
53
  #define DEREF_F32(addr, offset) HEAPF32[(addr >> 2) + offset]
75
54
  #define DEREF_F64(addr, offset) HEAPF64[(addr >> 3) + offset]
76
-
77
- #if WASM_BIGINT
78
- // We have HEAPU64 in this case.
79
55
  #define DEREF_U64(addr, offset) HEAPU64[(addr >> 3) + offset]
80
- #endif
81
-
82
56
 
83
57
  #define CHECK_FIELD_OFFSET(struct, field, offset) \
84
58
  _Static_assert( \
@@ -172,6 +146,19 @@ void,
172
146
  unbox_small_structs, (ffi_type type_ptr), {
173
147
  var type_id = FFI_TYPE__TYPEID(type_ptr);
174
148
  while (type_id === FFI_TYPE_STRUCT) {
149
+ // Don't unbox single element structs if they are bigger than 16 bytes. This
150
+ // is a work around for the fact that Python will give incorrect values for
151
+ // the size of the field in these cases: it says that the struct has pointer
152
+ // size and alignment and are of type pointer, even though it is more
153
+ // accurately a struct and has a larger size. Keeping it as a struct here
154
+ // will let us get the ABI right (which is in fact that the true argument is
155
+ // a pointer to the stack... so maybe Python issn't so wrong??)
156
+ //
157
+ // See the Python comment here:
158
+ // https://github.com/python/cpython/blob/a16a9f978f42b8a09297c1efbf33877f6388c403/Modules/_ctypes/stgdict.c#L718-L779
159
+ if (FFI_TYPE__SIZE(type_ptr) > 16) {
160
+ break;
161
+ }
175
162
  var elements = FFI_TYPE__ELEMENTS(type_ptr);
176
163
  var first_element = DEREF_U32(elements, 0);
177
164
  if (first_element === 0) {
@@ -222,40 +209,6 @@ ffi_call_js, (ffi_cif *cif, ffi_fp fn, void *rvalue, void **avalue),
222
209
  ret_by_arg = true;
223
210
  }
224
211
 
225
- SIG(var sig = "");
226
-
227
- #if !WASM_BIGINT
228
- switch(rtype_id) {
229
- case FFI_TYPE_VOID:
230
- SIG(sig = 'v');
231
- break;
232
- case FFI_TYPE_STRUCT:
233
- case FFI_TYPE_LONGDOUBLE:
234
- SIG(sig = 'vi');
235
- break;
236
- case FFI_TYPE_INT:
237
- case FFI_TYPE_UINT8:
238
- case FFI_TYPE_SINT8:
239
- case FFI_TYPE_UINT16:
240
- case FFI_TYPE_SINT16:
241
- case FFI_TYPE_UINT32:
242
- case FFI_TYPE_SINT32:
243
- case FFI_TYPE_POINTER:
244
- SIG(sig = 'i');
245
- break;
246
- case FFI_TYPE_FLOAT:
247
- SIG(sig = 'f');
248
- break;
249
- case FFI_TYPE_DOUBLE:
250
- SIG(sig = 'd');
251
- break;
252
- case FFI_TYPE_UINT64:
253
- case FFI_TYPE_SINT64:
254
- SIG(sig = 'j');
255
- break;
256
- }
257
- #endif
258
-
259
212
  // Accumulate a Javascript list of arguments for the Javascript wrapper for
260
213
  // the wasm function. The Javascript wrapper does a type conversion from
261
214
  // Javascript to C automatically, here we manually do the inverse conversion
@@ -275,54 +228,33 @@ ffi_call_js, (ffi_cif *cif, ffi_fp fn, void *rvalue, void **avalue),
275
228
  case FFI_TYPE_UINT32:
276
229
  case FFI_TYPE_POINTER:
277
230
  args.push(DEREF_U32(arg_ptr, 0));
278
- SIG(sig += 'i');
279
231
  break;
280
232
  case FFI_TYPE_FLOAT:
281
233
  args.push(DEREF_F32(arg_ptr, 0));
282
- SIG(sig += 'f');
283
234
  break;
284
235
  case FFI_TYPE_DOUBLE:
285
236
  args.push(DEREF_F64(arg_ptr, 0));
286
- SIG(sig += 'd');
287
237
  break;
288
238
  case FFI_TYPE_UINT8:
289
239
  args.push(DEREF_U8(arg_ptr, 0));
290
- SIG(sig += 'i');
291
240
  break;
292
241
  case FFI_TYPE_SINT8:
293
242
  args.push(DEREF_S8(arg_ptr, 0));
294
- SIG(sig += 'i');
295
243
  break;
296
244
  case FFI_TYPE_UINT16:
297
245
  args.push(DEREF_U16(arg_ptr, 0));
298
- SIG(sig += 'i');
299
246
  break;
300
247
  case FFI_TYPE_SINT16:
301
248
  args.push(DEREF_S16(arg_ptr, 0));
302
- SIG(sig += 'i');
303
249
  break;
304
250
  case FFI_TYPE_UINT64:
305
251
  case FFI_TYPE_SINT64:
306
- #if WASM_BIGINT
307
252
  args.push(DEREF_U64(arg_ptr, 0));
308
- #else
309
- args.push(DEREF_U32(arg_ptr, 0));
310
- args.push(DEREF_U32(arg_ptr, 1));
311
- #endif
312
- SIG(sig += 'j');
313
253
  break;
314
254
  case FFI_TYPE_LONGDOUBLE:
315
255
  // long double is passed as a pair of BigInts.
316
- #if WASM_BIGINT
317
256
  args.push(DEREF_U64(arg_ptr, 0));
318
257
  args.push(DEREF_U64(arg_ptr, 1));
319
- #else
320
- args.push(DEREF_U32(arg_ptr, 0));
321
- args.push(DEREF_U32(arg_ptr, 1));
322
- args.push(DEREF_U32(arg_ptr, 2));
323
- args.push(DEREF_U32(arg_ptr, 3));
324
- #endif
325
- SIG(sig += "jj");
326
258
  break;
327
259
  case FFI_TYPE_STRUCT:
328
260
  // Nontrivial structs are passed by pointer.
@@ -333,7 +265,6 @@ ffi_call_js, (ffi_cif *cif, ffi_fp fn, void *rvalue, void **avalue),
333
265
  STACK_ALLOC(cur_stack_ptr, size, align);
334
266
  HEAP8.subarray(cur_stack_ptr, cur_stack_ptr+size).set(HEAP8.subarray(arg_ptr, arg_ptr + size));
335
267
  args.push(cur_stack_ptr);
336
- SIG(sig += 'i');
337
268
  break;
338
269
  case FFI_TYPE_COMPLEX:
339
270
  throw new Error('complex marshalling nyi');
@@ -352,7 +283,6 @@ ffi_call_js, (ffi_cif *cif, ffi_fp fn, void *rvalue, void **avalue),
352
283
  // just always copy extra nonsense past the end. The ownwards call will know
353
284
  // not to look at it.
354
285
  if (nfixedargs != nargs) {
355
- SIG(sig += 'i');
356
286
  var struct_arg_info = [];
357
287
  for (var i = nargs - 1; i >= nfixedargs; i--) {
358
288
  var arg_ptr = DEREF_U32(avalue, i);
@@ -421,7 +351,8 @@ ffi_call_js, (ffi_cif *cif, ffi_fp fn, void *rvalue, void **avalue),
421
351
  }
422
352
  stackRestore(cur_stack_ptr);
423
353
  stackAlloc(0); // stackAlloc enforces alignment invariants on the stack pointer
424
- var result = CALL_FUNCTION_POINTER(fn, args);
354
+ LOG_DEBUG("CALL_FUNC_PTR", "fn:", fn, "args:", args);
355
+ var result = getWasmTableEntry(fn).apply(null, args);
425
356
  // Put the stack pointer back (we moved it if there were any struct args or we
426
357
  // made a varargs call)
427
358
  stackRestore(orig_stack_ptr);
@@ -459,12 +390,7 @@ ffi_call_js, (ffi_cif *cif, ffi_fp fn, void *rvalue, void **avalue),
459
390
  break;
460
391
  case FFI_TYPE_UINT64:
461
392
  case FFI_TYPE_SINT64:
462
- #if WASM_BIGINT
463
393
  DEREF_U64(rvalue, 0) = result;
464
- #else
465
- DEREF_U32(rvalue, 0) = result;
466
- DEREF_U32(rvalue, 1) = getTempRet0();
467
- #endif
468
394
  break;
469
395
  case FFI_TYPE_COMPLEX:
470
396
  throw new Error('complex ret marshalling nyi');
@@ -511,146 +437,6 @@ ffi_closure_free(void *closure) {
511
437
  return ffi_closure_free_js(closure);
512
438
  }
513
439
 
514
- #if !WASM_BIGINT
515
-
516
- // When !WASM_BIGINT, we assume there is no JS bigint integration, so JavaScript
517
- // functions cannot take 64 bit integer arguments.
518
- //
519
- // We need to make our own wasm legalizer adaptor that splits 64 bit integer
520
- // arguments and then calls the JavaScript trampoline, then the JavaScript
521
- // trampoline reassembles them, calls the closure, then splits the result (if
522
- // it's a 64 bit integer) and the adaptor puts it back together.
523
- //
524
- // This is basically the reverse of the Emscripten function
525
- // createDyncallWrapper.
526
- EM_JS(void, createLegalizerWrapper, (int trampoline, int sig), {
527
- if(!sig.includes("j")) {
528
- return convertJsFunctionToWasm(trampoline, sig);
529
- }
530
- var sections = [];
531
- var prelude = [
532
- 0x00, 0x61, 0x73, 0x6d, // magic ("\0asm")
533
- 0x01, 0x00, 0x00, 0x00, // version: 1
534
- ];
535
- sections.push(prelude);
536
- var wrappersig = [
537
- // if return type is j, we will put the upper 32 bits into tempRet0.
538
- sig[0].replace("j", "i"),
539
- // in the rest of the argument list, one 64 bit integer is legalized into
540
- // two 32 bit integers.
541
- sig.slice(1).replace(/j/g, "ii"),
542
- ].join("");
543
-
544
- var typeSectionBody = [
545
- 0x03, // number of types = 3
546
- ];
547
- generateFuncType(wrappersig, typeSectionBody); // The signature of the wrapper we are generating
548
- generateFuncType(sig, typeSectionBody); // the signature of the function pointer we will call
549
- generateFuncType("i", typeSectionBody); // the signature of getTempRet0
550
-
551
- var typeSection = [0x01 /* Type section code */];
552
- uleb128Encode(typeSectionBody.length, typeSection); // length of section in bytes
553
- typeSection.push.apply(typeSection, typeSectionBody);
554
- sections.push(typeSection);
555
-
556
- var importSection = [
557
- 0x02, // import section code
558
- 0x0d, // length of section in bytes
559
- 0x02, // number of imports = 2
560
- // Import the getTempRet0 function, which we will call "r"
561
- 0x01, 0x65, // name "e"
562
- 0x01, 0x72, // name "r"
563
- 0x00, // importing a function
564
- 0x02, // type 2 = () -> i32
565
- // Import the wrapped function, which we will call "f"
566
- 0x01, 0x65, // name "e"
567
- 0x01, 0x66, // name "f"
568
- 0x00, // importing a function
569
- 0x00, // type 0 = wrappersig
570
- ];
571
- sections.push(importSection);
572
-
573
- var functionSection = [
574
- 0x03, // function section code
575
- 0x02, // length of section in bytes
576
- 0x01, // number of functions = 1
577
- 0x01, // type 1 = sig
578
- ];
579
- sections.push(functionSection);
580
-
581
- var exportSection = [
582
- 0x07, // export section code
583
- 0x05, // length of section in bytes
584
- 0x01, // One export
585
- 0x01, 0x66, // name "f"
586
- 0x00, // type: function
587
- 0x02, // function index 2 = the wrapper function
588
- ];
589
- sections.push(exportSection);
590
-
591
- var convert_code = [];
592
- convert_code.push(0x00); // no local variables (except the arguments)
593
-
594
- function localGet(j) {
595
- convert_code.push(0x20); // local.get
596
- uleb128Encode(j, convert_code);
597
- }
598
-
599
- for (var i = 1; i < sig.length; i++) {
600
- if (sig[i] == "j") {
601
- localGet(i - 1);
602
- convert_code.push(
603
- 0xa7 // i32.wrap_i64
604
- );
605
- localGet(i - 1);
606
- convert_code.push(
607
- 0x42, 0x20, // i64.const 32
608
- 0x88, // i64.shr_u
609
- 0xa7 // i32.wrap_i64
610
- );
611
- } else {
612
- localGet(i - 1);
613
- }
614
- }
615
- convert_code.push(
616
- 0x10, 0x01 // call f
617
- );
618
- if (sig[0] === "j") {
619
- // Need to reassemble a 64 bit integer. Lower 32 bits is on stack. Upper 32
620
- // bits we get from getTempRet0
621
- convert_code.push(
622
- 0xad, // i64.extend_i32_unsigned
623
- 0x10, 0x00, // Call function 0 (r = getTempRet0)
624
- // join lower 32 bits and upper 32 bits
625
- 0xac, // i64.extend_i32_signed
626
- 0x42, 0x20, // i64.const 32
627
- 0x86, // i64.shl,
628
- 0x84 // i64.or
629
- );
630
- }
631
- convert_code.push(0x0b); // end
632
-
633
- var codeBody = [0x01]; // one code
634
- uleb128Encode(convert_code.length, codeBody);
635
- codeBody.push.apply(codeBody, convert_code);
636
- var codeSection = [0x0a /* Code section code */];
637
- uleb128Encode(codeBody.length, codeSection);
638
- codeSection.push.apply(codeSection, codeBody);
639
- sections.push(codeSection);
640
-
641
- var bytes = new Uint8Array([].concat.apply([], sections));
642
- // We can compile this wasm module synchronously because it is small.
643
- var module = new WebAssembly.Module(bytes);
644
- var instance = new WebAssembly.Instance(module, {
645
- e: {
646
- r: getTempRet0,
647
- f: trampoline,
648
- },
649
- });
650
- return instance.exports.f;
651
- });
652
- #endif
653
-
654
440
  EM_JS_MACROS(
655
441
  ffi_status,
656
442
  ffi_prep_closure_loc_js,
@@ -746,9 +532,9 @@ ffi_prep_closure_loc_js,
746
532
  }
747
533
  if (nfixedargs < nargs) {
748
534
  // extra pointer to varargs stack
749
- sig += "i";
535
+ sig += 'i';
750
536
  }
751
- LOG_DEBUG("CREATE_CLOSURE", "sig:", sig);
537
+ LOG_DEBUG("CREATE_CLOSURE", "sig:", sig);
752
538
  function trampoline() {
753
539
  var args = Array.prototype.slice.call(arguments);
754
540
  var size = 0;
@@ -825,32 +611,14 @@ ffi_prep_closure_loc_js,
825
611
  case FFI_TYPE_SINT64:
826
612
  STACK_ALLOC(cur_ptr, 8, 8);
827
613
  DEREF_U32(args_ptr, carg_idx) = cur_ptr;
828
- #if WASM_BIGINT
829
614
  DEREF_U64(cur_ptr, 0) = cur_arg;
830
- #else
831
- // Bigint arg was split by legalizer adaptor
832
- DEREF_U32(cur_ptr, 0) = cur_arg;
833
- cur_arg = args[jsarg_idx++];
834
- DEREF_U32(cur_ptr, 1) = cur_arg;
835
- #endif
836
615
  break;
837
616
  case FFI_TYPE_LONGDOUBLE:
838
617
  STACK_ALLOC(cur_ptr, 16, 8);
839
618
  DEREF_U32(args_ptr, carg_idx) = cur_ptr;
840
- #if WASM_BIGINT
841
619
  DEREF_U64(cur_ptr, 0) = cur_arg;
842
620
  cur_arg = args[jsarg_idx++];
843
621
  DEREF_U64(cur_ptr, 1) = cur_arg;
844
- #else
845
- // Was split by legalizer adaptor
846
- DEREF_U32(cur_ptr, 0) = cur_arg;
847
- cur_arg = args[jsarg_idx++];
848
- DEREF_U32(cur_ptr, 1) = cur_arg;
849
- cur_arg = args[jsarg_idx++];
850
- DEREF_U32(cur_ptr, 2) = cur_arg;
851
- cur_arg = args[jsarg_idx++];
852
- DEREF_U32(cur_ptr, 3) = cur_arg;
853
- #endif
854
622
  break;
855
623
  }
856
624
  }
@@ -882,7 +650,7 @@ ffi_prep_closure_loc_js,
882
650
  }
883
651
  stackRestore(cur_ptr);
884
652
  stackAlloc(0); // stackAlloc enforces alignment invariants on the stack pointer
885
- LOG_DEBUG("CALL_CLOSURE", "closure:", closure, "fptr", CLOSURE__fun(closure), "cif", CLOSURE__cif(closure));
653
+ LOG_DEBUG("CALL_CLOSURE", "closure:", closure, "fptr", CLOSURE__fun(closure), "cif", CLOSURE__cif(closure));
886
654
  getWasmTableEntry(CLOSURE__fun(closure))(
887
655
  CLOSURE__cif(closure), ret_ptr, args_ptr,
888
656
  CLOSURE__user_data(closure)
@@ -892,26 +660,19 @@ ffi_prep_closure_loc_js,
892
660
  // If we aren't supposed to return by argument, figure out what to return.
893
661
  if (!ret_by_arg) {
894
662
  switch (sig[0]) {
895
- case "i":
663
+ case 'i':
896
664
  return DEREF_U32(ret_ptr, 0);
897
- case "j":
898
- #if WASM_BIGINT
665
+ case 'j':
899
666
  return DEREF_U64(ret_ptr, 0);
900
- #else
901
- // Split the return i64, set the upper 32 bits into tempRet0 and return
902
- // the lower 32 bits.
903
- setTempRet0(DEREF_U32(ret_ptr, 1));
904
- return DEREF_U32(ret_ptr, 0);
905
- #endif
906
- case "d":
667
+ case 'd':
907
668
  return DEREF_F64(ret_ptr, 0);
908
- case "f":
669
+ case 'f':
909
670
  return DEREF_F32(ret_ptr, 0);
910
671
  }
911
672
  }
912
673
  }
913
674
  try {
914
- var wasm_trampoline = JS_FUNCTION_TO_WASM(trampoline, sig);
675
+ var wasm_trampoline = convertJsFunctionToWasm(trampoline, sig);
915
676
  } catch(e) {
916
677
  return FFI_BAD_TYPEDEF_MACRO;
917
678
  }