ffi 1.9.23 → 1.9.24

Sign up to get free protection for your applications and to get access to all the features.
Files changed (78) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +66 -0
  3. data/Rakefile +1 -1
  4. data/ext/ffi_c/Call.c +5 -2
  5. data/ext/ffi_c/Function.c +8 -5
  6. data/ext/ffi_c/Thread.c +1 -0
  7. data/ext/ffi_c/extconf.rb +1 -0
  8. data/ext/ffi_c/libffi/.appveyor.yml +6 -4
  9. data/ext/ffi_c/libffi/.github/issue_template.md +10 -0
  10. data/ext/ffi_c/libffi/.gitignore +2 -0
  11. data/ext/ffi_c/libffi/.travis.yml +20 -16
  12. data/ext/ffi_c/libffi/.travis/ar-lib +270 -0
  13. data/ext/ffi_c/libffi/.travis/build.sh +34 -0
  14. data/ext/ffi_c/libffi/.travis/compile +351 -0
  15. data/ext/ffi_c/libffi/.travis/install.sh +11 -3
  16. data/ext/ffi_c/libffi/.travis/moxie-sim.exp +60 -0
  17. data/ext/ffi_c/libffi/.travis/site.exp +18 -0
  18. data/ext/ffi_c/libffi/LICENSE-BUILDTOOLS +352 -0
  19. data/ext/ffi_c/libffi/Makefile.am +4 -45
  20. data/ext/ffi_c/libffi/{README → README.md} +237 -230
  21. data/ext/ffi_c/libffi/configure.ac +10 -8
  22. data/ext/ffi_c/libffi/configure.host +5 -0
  23. data/ext/ffi_c/libffi/include/ffi.h.in +48 -26
  24. data/ext/ffi_c/libffi/include/ffi_common.h +2 -0
  25. data/ext/ffi_c/libffi/m4/ax_append_flag.m4 +18 -16
  26. data/ext/ffi_c/libffi/m4/ax_cc_maxopt.m4 +21 -8
  27. data/ext/ffi_c/libffi/m4/ax_cflags_warn_all.m4 +4 -4
  28. data/ext/ffi_c/libffi/m4/ax_check_compile_flag.m4 +9 -7
  29. data/ext/ffi_c/libffi/m4/ax_compiler_vendor.m4 +8 -5
  30. data/ext/ffi_c/libffi/m4/ax_configure_args.m4 +5 -5
  31. data/ext/ffi_c/libffi/m4/ax_enable_builddir.m4 +7 -6
  32. data/ext/ffi_c/libffi/m4/ax_gcc_archflag.m4 +99 -61
  33. data/ext/ffi_c/libffi/m4/ax_gcc_x86_cpuid.m4 +18 -8
  34. data/ext/ffi_c/libffi/m4/ax_require_defined.m4 +37 -0
  35. data/ext/ffi_c/libffi/msvcc.sh +82 -14
  36. data/ext/ffi_c/libffi/src/aarch64/ffi.c +8 -31
  37. data/ext/ffi_c/libffi/src/closures.c +31 -1
  38. data/ext/ffi_c/libffi/src/ia64/ffi.c +24 -6
  39. data/ext/ffi_c/libffi/src/ia64/ffitarget.h +2 -1
  40. data/ext/ffi_c/libffi/src/ia64/unix.S +6 -1
  41. data/ext/ffi_c/libffi/src/mips/ffi.c +29 -12
  42. data/ext/ffi_c/libffi/src/mips/ffitarget.h +7 -12
  43. data/ext/ffi_c/libffi/src/moxie/eabi.S +1 -1
  44. data/ext/ffi_c/libffi/src/moxie/ffi.c +18 -5
  45. data/ext/ffi_c/libffi/src/powerpc/ffi_linux64.c +45 -16
  46. data/ext/ffi_c/libffi/src/riscv/ffi.c +445 -0
  47. data/ext/ffi_c/libffi/src/riscv/ffitarget.h +68 -0
  48. data/ext/ffi_c/libffi/src/riscv/sysv.S +214 -0
  49. data/ext/ffi_c/libffi/src/types.c +3 -1
  50. data/ext/ffi_c/libffi/src/x86/ffi.c +18 -0
  51. data/ext/ffi_c/libffi/src/x86/ffi64.c +15 -9
  52. data/ext/ffi_c/libffi/src/x86/ffitarget.h +8 -2
  53. data/ext/ffi_c/libffi/src/x86/ffiw64.c +30 -9
  54. data/ext/ffi_c/libffi/src/xtensa/sysv.S +6 -1
  55. data/ext/ffi_c/libffi/testsuite/Makefile.am +108 -77
  56. data/ext/ffi_c/libffi/testsuite/lib/libffi.exp +195 -5
  57. data/ext/ffi_c/libffi/testsuite/libffi.bhaible/Makefile +28 -0
  58. data/ext/ffi_c/libffi/testsuite/libffi.bhaible/README +78 -0
  59. data/ext/ffi_c/libffi/testsuite/libffi.bhaible/alignof.h +50 -0
  60. data/ext/ffi_c/libffi/testsuite/libffi.bhaible/bhaible.exp +58 -0
  61. data/ext/ffi_c/libffi/testsuite/libffi.bhaible/test-call.c +1745 -0
  62. data/ext/ffi_c/libffi/testsuite/libffi.bhaible/test-callback.c +2885 -0
  63. data/ext/ffi_c/libffi/testsuite/libffi.bhaible/testcases.c +743 -0
  64. data/ext/ffi_c/libffi/testsuite/libffi.call/align_stdcall.c +46 -0
  65. data/ext/ffi_c/libffi/testsuite/libffi.call/call.exp +14 -1
  66. data/ext/ffi_c/libffi/testsuite/libffi.call/ffitest.h +3 -1
  67. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct10.c +1 -0
  68. data/ext/ffi_c/libffi/testsuite/libffi.call/struct10.c +57 -0
  69. data/ext/ffi_c/libffi/testsuite/libffi.call/unwindtest.cc +1 -1
  70. data/ext/ffi_c/libffi/testsuite/libffi.call/unwindtest_ffi_call.cc +1 -1
  71. data/lib/ffi/library.rb +2 -4
  72. data/lib/ffi/platform/mips64-linux/types.conf +104 -0
  73. data/lib/ffi/platform/mipsisa32r6-linux/types.conf +102 -0
  74. data/lib/ffi/platform/mipsisa32r6el-linux/types.conf +102 -0
  75. data/lib/ffi/platform/mipsisa64r6-linux/types.conf +104 -0
  76. data/lib/ffi/platform/mipsisa64r6el-linux/types.conf +104 -0
  77. data/lib/ffi/version.rb +1 -1
  78. metadata +29 -3
@@ -224,26 +224,21 @@ typedef enum ffi_abi {
224
224
  #endif
225
225
  } ffi_abi;
226
226
 
227
- #define FFI_EXTRA_CIF_FIELDS unsigned rstruct_flag
227
+ #define FFI_EXTRA_CIF_FIELDS unsigned rstruct_flag; unsigned mips_nfixedargs
228
+ #define FFI_TARGET_SPECIFIC_VARIADIC
228
229
  #endif /* !LIBFFI_ASM */
229
230
 
230
231
  /* ---- Definitions for closures ----------------------------------------- */
231
232
 
232
- #if defined(FFI_MIPS_O32)
233
233
  #define FFI_CLOSURES 1
234
234
  #define FFI_GO_CLOSURES 1
235
- #define FFI_TRAMPOLINE_SIZE 20
236
- #else
237
- /* N32/N64. */
238
- # define FFI_CLOSURES 1
239
- #define FFI_GO_CLOSURES 1
240
- #if _MIPS_SIM==_ABI64
241
- #define FFI_TRAMPOLINE_SIZE 56
235
+ #define FFI_NATIVE_RAW_API 0
236
+
237
+ #if defined(FFI_MIPS_O32) || (_MIPS_SIM ==_ABIN32)
238
+ # define FFI_TRAMPOLINE_SIZE 20
242
239
  #else
243
- #define FFI_TRAMPOLINE_SIZE 20
240
+ # define FFI_TRAMPOLINE_SIZE 56
244
241
  #endif
245
- #endif /* FFI_MIPS_O32 */
246
- #define FFI_NATIVE_RAW_API 0
247
242
 
248
243
  #endif
249
244
 
@@ -59,7 +59,7 @@ ffi_call_EABI:
59
59
  mov $r6, $r4 /* Save result buffer */
60
60
  mov $r7, $r5 /* Save the target fn */
61
61
  mov $r8, $r3 /* Save the flags */
62
- sub.l $sp, $r2 /* Allocate stack space */
62
+ sub $sp, $r2 /* Allocate stack space */
63
63
  mov $r0, $sp /* We can stomp over $r0 */
64
64
  /* $r1 is already set up */
65
65
  jsra ffi_prep_args
@@ -1,5 +1,5 @@
1
1
  /* -----------------------------------------------------------------------
2
- ffi.c - Copyright (C) 2012, 2013 Anthony Green
2
+ ffi.c - Copyright (C) 2012, 2013, 2018 Anthony Green
3
3
 
4
4
  Moxie Foreign Function Interface
5
5
 
@@ -159,7 +159,7 @@ void ffi_closure_eabi (unsigned arg1, unsigned arg2, unsigned arg3,
159
159
  unsigned arg4, unsigned arg5, unsigned arg6)
160
160
  {
161
161
  /* This function is called by a trampoline. The trampoline stows a
162
- pointer to the ffi_closure object in $r7. We must save this
162
+ pointer to the ffi_closure object in $r12. We must save this
163
163
  pointer in a place that will persist while we do our work. */
164
164
  register ffi_closure *creg __asm__ ("$r12");
165
165
  ffi_closure *closure = creg;
@@ -215,7 +215,18 @@ void ffi_closure_eabi (unsigned arg1, unsigned arg2, unsigned arg3,
215
215
  break;
216
216
  default:
217
217
  /* This is an 8-byte value. */
218
- avalue[i] = ptr;
218
+ if (ptr == (char *) &register_args[5])
219
+ {
220
+ /* The value is split across two locations */
221
+ unsigned *ip = alloca(8);
222
+ avalue[i] = ip;
223
+ ip[0] = *(unsigned *) ptr;
224
+ ip[1] = *(unsigned *) stack_args;
225
+ }
226
+ else
227
+ {
228
+ avalue[i] = ptr;
229
+ }
219
230
  ptr += 4;
220
231
  break;
221
232
  }
@@ -223,8 +234,10 @@ void ffi_closure_eabi (unsigned arg1, unsigned arg2, unsigned arg3,
223
234
 
224
235
  /* If we've handled more arguments than fit in registers,
225
236
  start looking at the those passed on the stack. */
226
- if (ptr == &register_args[6])
237
+ if (ptr == (char *) &register_args[6])
227
238
  ptr = stack_args;
239
+ else if (ptr == (char *) &register_args[7])
240
+ ptr = stack_args + 4;
228
241
  }
229
242
 
230
243
  /* Invoke the closure. */
@@ -257,7 +270,7 @@ ffi_prep_closure_loc (ffi_closure* closure,
257
270
 
258
271
  fn = (unsigned long) ffi_closure_eabi;
259
272
 
260
- tramp[0] = 0x01e0; /* ldi.l $r7, .... */
273
+ tramp[0] = 0x01e0; /* ldi.l $r12, .... */
261
274
  tramp[1] = cls >> 16;
262
275
  tramp[2] = cls & 0xffff;
263
276
  tramp[3] = 0x1a00; /* jmpa .... */
@@ -62,7 +62,6 @@ ffi_prep_types_linux64 (ffi_abi abi)
62
62
  #endif
63
63
 
64
64
 
65
- #if _CALL_ELF == 2
66
65
  static unsigned int
67
66
  discover_homogeneous_aggregate (const ffi_type *t, unsigned int *elnum)
68
67
  {
@@ -86,8 +85,13 @@ discover_homogeneous_aggregate (const ffi_type *t, unsigned int *elnum)
86
85
  return 0;
87
86
  base_elt = el_elt;
88
87
  total_elnum += el_elnum;
88
+ #if _CALL_ELF == 2
89
89
  if (total_elnum > 8)
90
90
  return 0;
91
+ #else
92
+ if (total_elnum > 1)
93
+ return 0;
94
+ #endif
91
95
  el++;
92
96
  }
93
97
  *elnum = total_elnum;
@@ -98,7 +102,6 @@ discover_homogeneous_aggregate (const ffi_type *t, unsigned int *elnum)
98
102
  return 0;
99
103
  }
100
104
  }
101
- #endif
102
105
 
103
106
 
104
107
  /* Perform machine dependent cif processing */
@@ -109,9 +112,7 @@ ffi_prep_cif_linux64_core (ffi_cif *cif)
109
112
  unsigned bytes;
110
113
  unsigned i, fparg_count = 0, intarg_count = 0;
111
114
  unsigned flags = cif->flags;
112
- #if _CALL_ELF == 2
113
115
  unsigned int elt, elnum;
114
- #endif
115
116
 
116
117
  #if FFI_TYPE_LONGDOUBLE == FFI_TYPE_DOUBLE
117
118
  /* If compiled without long double support.. */
@@ -157,6 +158,7 @@ ffi_prep_cif_linux64_core (ffi_cif *cif)
157
158
  /* Fall through. */
158
159
  case FFI_TYPE_UINT64:
159
160
  case FFI_TYPE_SINT64:
161
+ case FFI_TYPE_POINTER:
160
162
  flags |= FLAG_RETURNS_64BITS;
161
163
  break;
162
164
 
@@ -222,7 +224,6 @@ ffi_prep_cif_linux64_core (ffi_cif *cif)
222
224
  intarg_count = FFI_ALIGN (intarg_count, align);
223
225
  }
224
226
  intarg_count += ((*ptr)->size + 7) / 8;
225
- #if _CALL_ELF == 2
226
227
  elt = discover_homogeneous_aggregate (*ptr, &elnum);
227
228
  if (elt)
228
229
  {
@@ -231,7 +232,6 @@ ffi_prep_cif_linux64_core (ffi_cif *cif)
231
232
  flags |= FLAG_ARG_NEEDS_PSAVE;
232
233
  }
233
234
  else
234
- #endif
235
235
  {
236
236
  if (intarg_count > NUM_GPR_ARG_REGISTERS64)
237
237
  flags |= FLAG_ARG_NEEDS_PSAVE;
@@ -449,9 +449,7 @@ ffi_prep_args64 (extended_cif *ecif, unsigned long *const stack)
449
449
  i < nargs;
450
450
  i++, ptr++, p_argv.v++)
451
451
  {
452
- #if _CALL_ELF == 2
453
452
  unsigned int elt, elnum;
454
- #endif
455
453
 
456
454
  switch ((*ptr)->type)
457
455
  {
@@ -494,6 +492,7 @@ ffi_prep_args64 (extended_cif *ecif, unsigned long *const stack)
494
492
  /* Fall through. */
495
493
  #endif
496
494
  case FFI_TYPE_DOUBLE:
495
+ do_double:
497
496
  double_tmp = **p_argv.d;
498
497
  if (fparg_count < NUM_FPR_ARG_REGISTERS64 && i < nfixedargs)
499
498
  {
@@ -512,17 +511,30 @@ ffi_prep_args64 (extended_cif *ecif, unsigned long *const stack)
512
511
  break;
513
512
 
514
513
  case FFI_TYPE_FLOAT:
514
+ do_float:
515
515
  double_tmp = **p_argv.f;
516
516
  if (fparg_count < NUM_FPR_ARG_REGISTERS64 && i < nfixedargs)
517
517
  {
518
518
  *fpr_base.d++ = double_tmp;
519
519
  #if _CALL_ELF != 2
520
520
  if ((flags & FLAG_COMPAT) != 0)
521
- *next_arg.f = (float) double_tmp;
521
+ {
522
+ # ifndef __LITTLE_ENDIAN__
523
+ next_arg.f[1] = (float) double_tmp;
524
+ # else
525
+ next_arg.f[0] = (float) double_tmp;
526
+ # endif
527
+ }
522
528
  #endif
523
529
  }
524
530
  else
525
- *next_arg.f = (float) double_tmp;
531
+ {
532
+ # ifndef __LITTLE_ENDIAN__
533
+ next_arg.f[1] = (float) double_tmp;
534
+ # else
535
+ next_arg.f[0] = (float) double_tmp;
536
+ # endif
537
+ }
526
538
  if (++next_arg.ul == gpr_end.ul)
527
539
  next_arg.ul = rest.ul;
528
540
  fparg_count++;
@@ -538,10 +550,10 @@ ffi_prep_args64 (extended_cif *ecif, unsigned long *const stack)
538
550
  if (align > 1)
539
551
  next_arg.p = FFI_ALIGN (next_arg.p, align);
540
552
  }
541
- #if _CALL_ELF == 2
542
553
  elt = discover_homogeneous_aggregate (*ptr, &elnum);
543
554
  if (elt)
544
555
  {
556
+ #if _CALL_ELF == 2
545
557
  union {
546
558
  void *v;
547
559
  float *f;
@@ -583,9 +595,14 @@ ffi_prep_args64 (extended_cif *ecif, unsigned long *const stack)
583
595
  fparg_count++;
584
596
  }
585
597
  while (--elnum != 0);
598
+ #else
599
+ if (elt == FFI_TYPE_FLOAT)
600
+ goto do_float;
601
+ else
602
+ goto do_double;
603
+ #endif
586
604
  }
587
605
  else
588
- #endif
589
606
  {
590
607
  words = ((*ptr)->size + 7) / 8;
591
608
  if (next_arg.ul >= gpr_base.ul && next_arg.ul + words > gpr_end.ul)
@@ -796,12 +813,10 @@ ffi_closure_helper_LINUX64 (ffi_cif *cif,
796
813
  if (align > 1)
797
814
  pst = (unsigned long *) FFI_ALIGN ((size_t) pst, align);
798
815
  }
799
- elt = 0;
800
- #if _CALL_ELF == 2
801
816
  elt = discover_homogeneous_aggregate (arg_types[i], &elnum);
802
- #endif
803
817
  if (elt)
804
818
  {
819
+ #if _CALL_ELF == 2
805
820
  union {
806
821
  void *v;
807
822
  unsigned long *ul;
@@ -853,6 +868,12 @@ ffi_closure_helper_LINUX64 (ffi_cif *cif,
853
868
  }
854
869
  while (--elnum != 0);
855
870
  }
871
+ #else
872
+ if (elt == FFI_TYPE_FLOAT)
873
+ goto do_float;
874
+ else
875
+ goto do_double;
876
+ #endif
856
877
  }
857
878
  else
858
879
  {
@@ -894,6 +915,7 @@ ffi_closure_helper_LINUX64 (ffi_cif *cif,
894
915
  /* Fall through. */
895
916
  #endif
896
917
  case FFI_TYPE_DOUBLE:
918
+ do_double:
897
919
  /* On the outgoing stack all values are aligned to 8 */
898
920
  /* there are 13 64bit floating point registers */
899
921
 
@@ -908,6 +930,7 @@ ffi_closure_helper_LINUX64 (ffi_cif *cif,
908
930
  break;
909
931
 
910
932
  case FFI_TYPE_FLOAT:
933
+ do_float:
911
934
  if (pfr < end_pfr && i < nfixedargs)
912
935
  {
913
936
  /* Float values are stored as doubles in the
@@ -917,7 +940,13 @@ ffi_closure_helper_LINUX64 (ffi_cif *cif,
917
940
  pfr++;
918
941
  }
919
942
  else
920
- avalue[i] = pst;
943
+ {
944
+ #ifndef __LITTLE_ENDIAN__
945
+ avalue[i] = (char *) pst + 4;
946
+ #else
947
+ avalue[i] = pst;
948
+ #endif
949
+ }
921
950
  pst++;
922
951
  break;
923
952
 
@@ -0,0 +1,445 @@
1
+ /* -----------------------------------------------------------------------
2
+ ffi.c - Copyright (c) 2015 Michael Knyszek <mknyszek@berkeley.edu>
3
+ 2015 Andrew Waterman <waterman@cs.berkeley.edu>
4
+ 2018 Stef O'Rear <sorear2@gmail.com>
5
+ Based on MIPS N32/64 port
6
+
7
+ RISC-V Foreign Function Interface
8
+
9
+ Permission is hereby granted, free of charge, to any person obtaining
10
+ a copy of this software and associated documentation files (the
11
+ ``Software''), to deal in the Software without restriction, including
12
+ without limitation the rights to use, copy, modify, merge, publish,
13
+ distribute, sublicense, and/or sell copies of the Software, and to
14
+ permit persons to whom the Software is furnished to do so, subject to
15
+ the following conditions:
16
+
17
+ The above copyright notice and this permission notice shall be included
18
+ in all copies or substantial portions of the Software.
19
+
20
+ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
21
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
24
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
25
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27
+ DEALINGS IN THE SOFTWARE.
28
+ ----------------------------------------------------------------------- */
29
+
30
+ #include <ffi.h>
31
+ #include <ffi_common.h>
32
+
33
+ #include <stdlib.h>
34
+ #include <stdint.h>
35
+
36
+ #if __riscv_float_abi_double
37
+ #define ABI_FLEN 64
38
+ #define ABI_FLOAT double
39
+ #elif __riscv_float_abi_single
40
+ #define ABI_FLEN 32
41
+ #define ABI_FLOAT float
42
+ #endif
43
+
44
+ #define NARGREG 8
45
+ #define STKALIGN 16
46
+ #define MAXCOPYARG (2 * sizeof(double))
47
+
48
+ typedef struct call_context
49
+ {
50
+ #if ABI_FLEN
51
+ ABI_FLOAT fa[8];
52
+ #endif
53
+ size_t a[8];
54
+ /* used by the assembly code to in-place construct its own stack frame */
55
+ char frame[16];
56
+ } call_context;
57
+
58
+ typedef struct call_builder
59
+ {
60
+ call_context *aregs;
61
+ int used_integer;
62
+ int used_float;
63
+ size_t *used_stack;
64
+ } call_builder;
65
+
66
+ /* integer (not pointer) less than ABI XLEN */
67
+ /* FFI_TYPE_INT does not appear to be used */
68
+ #if __SIZEOF_POINTER__ == 8
69
+ #define IS_INT(type) ((type) >= FFI_TYPE_UINT8 && (type) <= FFI_TYPE_SINT64)
70
+ #else
71
+ #define IS_INT(type) ((type) >= FFI_TYPE_UINT8 && (type) <= FFI_TYPE_SINT32)
72
+ #endif
73
+
74
+ #if ABI_FLEN
75
+ typedef struct {
76
+ char as_elements, type1, offset2, type2;
77
+ } float_struct_info;
78
+
79
+ #if ABI_FLEN >= 64
80
+ #define IS_FLOAT(type) ((type) >= FFI_TYPE_FLOAT && (type) <= FFI_TYPE_DOUBLE)
81
+ #else
82
+ #define IS_FLOAT(type) ((type) == FFI_TYPE_FLOAT)
83
+ #endif
84
+
85
+ static ffi_type **flatten_struct(ffi_type *in, ffi_type **out, ffi_type **out_end) {
86
+ int i;
87
+ if (out == out_end) return out;
88
+ if (in->type != FFI_TYPE_STRUCT) {
89
+ *(out++) = in;
90
+ } else {
91
+ for (i = 0; in->elements[i]; i++)
92
+ out = flatten_struct(in->elements[i], out, out_end);
93
+ }
94
+ return out;
95
+ }
96
+
97
+ /* Structs with at most two fields after flattening, one of which is of
98
+ floating point type, are passed in multiple registers if sufficient
99
+ registers are available. */
100
+ static float_struct_info struct_passed_as_elements(call_builder *cb, ffi_type *top) {
101
+ float_struct_info ret = {0, 0, 0, 0};
102
+ ffi_type *fields[3];
103
+ int num_floats, num_ints;
104
+ int num_fields = flatten_struct(top, fields, fields + 3) - fields;
105
+
106
+ if (num_fields == 1) {
107
+ if (IS_FLOAT(fields[0]->type)) {
108
+ ret.as_elements = 1;
109
+ ret.type1 = fields[0]->type;
110
+ }
111
+ } else if (num_fields == 2) {
112
+ num_floats = IS_FLOAT(fields[0]->type) + IS_FLOAT(fields[1]->type);
113
+ num_ints = IS_INT(fields[0]->type) + IS_INT(fields[1]->type);
114
+ if (num_floats == 0 || num_floats + num_ints != 2)
115
+ return ret;
116
+ if (cb->used_float + num_floats > NARGREG || cb->used_integer + (2 - num_floats) > NARGREG)
117
+ return ret;
118
+ if (!IS_FLOAT(fields[0]->type) && !IS_FLOAT(fields[1]->type))
119
+ return ret;
120
+
121
+ ret.type1 = fields[0]->type;
122
+ ret.type2 = fields[1]->type;
123
+ ret.offset2 = FFI_ALIGN(fields[0]->size, fields[1]->alignment);
124
+ ret.as_elements = 1;
125
+ }
126
+
127
+ return ret;
128
+ }
129
+ #endif
130
+
131
+ /* allocates a single register, float register, or XLEN-sized stack slot to a datum */
132
+ static void marshal_atom(call_builder *cb, int type, void *data) {
133
+ size_t value = 0;
134
+ switch (type) {
135
+ case FFI_TYPE_UINT8: value = *(uint8_t *)data; break;
136
+ case FFI_TYPE_SINT8: value = *(int8_t *)data; break;
137
+ case FFI_TYPE_UINT16: value = *(uint16_t *)data; break;
138
+ case FFI_TYPE_SINT16: value = *(int16_t *)data; break;
139
+ /* 32-bit quantities are always sign-extended in the ABI */
140
+ case FFI_TYPE_UINT32: value = *(int32_t *)data; break;
141
+ case FFI_TYPE_SINT32: value = *(int32_t *)data; break;
142
+ #if __SIZEOF_POINTER__ == 8
143
+ case FFI_TYPE_UINT64: value = *(uint64_t *)data; break;
144
+ case FFI_TYPE_SINT64: value = *(int64_t *)data; break;
145
+ #endif
146
+ case FFI_TYPE_POINTER: value = *(size_t *)data; break;
147
+
148
+ /* float values may be recoded in an implementation-defined way
149
+ by hardware conforming to 2.1 or earlier, so use asm to
150
+ reinterpret floats as doubles */
151
+ #if ABI_FLEN >= 32
152
+ case FFI_TYPE_FLOAT:
153
+ asm("" : "=f"(cb->aregs->fa[cb->used_float++]) : "0"(*(float *)data));
154
+ return;
155
+ #endif
156
+ #if ABI_FLEN >= 64
157
+ case FFI_TYPE_DOUBLE:
158
+ asm("" : "=f"(cb->aregs->fa[cb->used_float++]) : "0"(*(double *)data));
159
+ return;
160
+ #endif
161
+ default: FFI_ASSERT(0); break;
162
+ }
163
+
164
+ if (cb->used_integer == NARGREG) {
165
+ *cb->used_stack++ = value;
166
+ } else {
167
+ cb->aregs->a[cb->used_integer++] = value;
168
+ }
169
+ }
170
+
171
+ static void unmarshal_atom(call_builder *cb, int type, void *data) {
172
+ size_t value;
173
+ switch (type) {
174
+ #if ABI_FLEN >= 32
175
+ case FFI_TYPE_FLOAT:
176
+ asm("" : "=f"(*(float *)data) : "0"(cb->aregs->fa[cb->used_float++]));
177
+ return;
178
+ #endif
179
+ #if ABI_FLEN >= 64
180
+ case FFI_TYPE_DOUBLE:
181
+ asm("" : "=f"(*(double *)data) : "0"(cb->aregs->fa[cb->used_float++]));
182
+ return;
183
+ #endif
184
+ }
185
+
186
+ if (cb->used_integer == NARGREG) {
187
+ value = *cb->used_stack++;
188
+ } else {
189
+ value = cb->aregs->a[cb->used_integer++];
190
+ }
191
+
192
+ switch (type) {
193
+ case FFI_TYPE_UINT8: *(uint8_t *)data = value; break;
194
+ case FFI_TYPE_SINT8: *(uint8_t *)data = value; break;
195
+ case FFI_TYPE_UINT16: *(uint16_t *)data = value; break;
196
+ case FFI_TYPE_SINT16: *(uint16_t *)data = value; break;
197
+ case FFI_TYPE_UINT32: *(uint32_t *)data = value; break;
198
+ case FFI_TYPE_SINT32: *(uint32_t *)data = value; break;
199
+ #if __SIZEOF_POINTER__ == 8
200
+ case FFI_TYPE_UINT64: *(uint64_t *)data = value; break;
201
+ case FFI_TYPE_SINT64: *(uint64_t *)data = value; break;
202
+ #endif
203
+ case FFI_TYPE_POINTER: *(size_t *)data = value; break;
204
+ default: FFI_ASSERT(0); break;
205
+ }
206
+ }
207
+
208
+ /* adds an argument to a call, or a not by reference return value */
209
+ static void marshal(call_builder *cb, ffi_type *type, int var, void *data) {
210
+ size_t realign[2];
211
+
212
+ #if ABI_FLEN
213
+ if (!var && type->type == FFI_TYPE_STRUCT) {
214
+ float_struct_info fsi = struct_passed_as_elements(cb, type);
215
+ if (fsi.as_elements) {
216
+ marshal_atom(cb, fsi.type1, data);
217
+ if (fsi.offset2)
218
+ marshal_atom(cb, fsi.type2, ((char*)data) + fsi.offset2);
219
+ return;
220
+ }
221
+ }
222
+
223
+ if (!var && cb->used_float < NARGREG && IS_FLOAT(type->type)) {
224
+ marshal_atom(cb, type->type, data);
225
+ return;
226
+ }
227
+ #endif
228
+
229
+ if (type->size > 2 * __SIZEOF_POINTER__) {
230
+ /* pass by reference */
231
+ marshal_atom(cb, FFI_TYPE_POINTER, &data);
232
+ } else if (IS_INT(type->type) || type->type == FFI_TYPE_POINTER) {
233
+ marshal_atom(cb, type->type, data);
234
+ } else {
235
+ /* overlong integers, soft-float floats, and structs without special
236
+ float handling are treated identically from this point on */
237
+
238
+ /* variadics are aligned even in registers */
239
+ if (type->alignment > __SIZEOF_POINTER__) {
240
+ if (var)
241
+ cb->used_integer = FFI_ALIGN(cb->used_integer, 2);
242
+ cb->used_stack = (size_t *)FFI_ALIGN(cb->used_stack, 2*__SIZEOF_POINTER__);
243
+ }
244
+
245
+ memcpy(realign, data, type->size);
246
+ if (type->size > 0)
247
+ marshal_atom(cb, FFI_TYPE_POINTER, realign);
248
+ if (type->size > __SIZEOF_POINTER__)
249
+ marshal_atom(cb, FFI_TYPE_POINTER, realign + 1);
250
+ }
251
+ }
252
+
253
+ /* for arguments passed by reference returns the pointer, otherwise the arg is copied (up to MAXCOPYARG bytes) */
254
+ static void *unmarshal(call_builder *cb, ffi_type *type, int var, void *data) {
255
+ size_t realign[2];
256
+ void *pointer;
257
+
258
+ #if ABI_FLEN
259
+ if (!var && type->type == FFI_TYPE_STRUCT) {
260
+ float_struct_info fsi = struct_passed_as_elements(cb, type);
261
+ if (fsi.as_elements) {
262
+ unmarshal_atom(cb, fsi.type1, data);
263
+ if (fsi.offset2)
264
+ unmarshal_atom(cb, fsi.type2, ((char*)data) + fsi.offset2);
265
+ return data;
266
+ }
267
+ }
268
+
269
+ if (!var && cb->used_float < NARGREG && IS_FLOAT(type->type)) {
270
+ unmarshal_atom(cb, type->type, data);
271
+ return data;
272
+ }
273
+ #endif
274
+
275
+ if (type->size > 2 * __SIZEOF_POINTER__) {
276
+ /* pass by reference */
277
+ unmarshal_atom(cb, FFI_TYPE_POINTER, (char*)&pointer);
278
+ return pointer;
279
+ } else if (IS_INT(type->type) || type->type == FFI_TYPE_POINTER) {
280
+ unmarshal_atom(cb, type->type, data);
281
+ return data;
282
+ } else {
283
+ /* overlong integers, soft-float floats, and structs without special
284
+ float handling are treated identically from this point on */
285
+
286
+ /* variadics are aligned even in registers */
287
+ if (type->alignment > __SIZEOF_POINTER__) {
288
+ if (var)
289
+ cb->used_integer = FFI_ALIGN(cb->used_integer, 2);
290
+ cb->used_stack = (size_t *)FFI_ALIGN(cb->used_stack, 2*__SIZEOF_POINTER__);
291
+ }
292
+
293
+ if (type->size > 0)
294
+ unmarshal_atom(cb, FFI_TYPE_POINTER, realign);
295
+ if (type->size > __SIZEOF_POINTER__)
296
+ unmarshal_atom(cb, FFI_TYPE_POINTER, realign + 1);
297
+ memcpy(data, realign, type->size);
298
+ return data;
299
+ }
300
+ }
301
+
302
+ static int passed_by_ref(call_builder *cb, ffi_type *type, int var) {
303
+ #if ABI_FLEN
304
+ if (!var && type->type == FFI_TYPE_STRUCT) {
305
+ float_struct_info fsi = struct_passed_as_elements(cb, type);
306
+ if (fsi.as_elements) return 0;
307
+ }
308
+ #endif
309
+
310
+ return type->size > 2 * __SIZEOF_POINTER__;
311
+ }
312
+
313
+ /* Perform machine dependent cif processing */
314
+ ffi_status ffi_prep_cif_machdep(ffi_cif *cif) {
315
+ cif->riscv_nfixedargs = cif->nargs;
316
+ return FFI_OK;
317
+ }
318
+
319
+ /* Perform machine dependent cif processing when we have a variadic function */
320
+
321
+ ffi_status ffi_prep_cif_machdep_var(ffi_cif *cif, unsigned int nfixedargs, unsigned int ntotalargs) {
322
+ cif->riscv_nfixedargs = nfixedargs;
323
+ return FFI_OK;
324
+ }
325
+
326
+ /* Low level routine for calling functions */
327
+ extern void ffi_call_asm(void *stack, struct call_context *regs, void (*fn)(void)) FFI_HIDDEN;
328
+
329
+ void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
330
+ {
331
+ /* this is a conservative estimate, assuming a complex return value and
332
+ that all remaining arguments are long long / __int128 */
333
+ size_t arg_bytes = cif->nargs <= 3 ? 0 :
334
+ FFI_ALIGN(2 * sizeof(size_t) * (cif->nargs - 3), STKALIGN);
335
+ size_t rval_bytes = 0;
336
+ if (rvalue == NULL && cif->rtype->size > 2*__SIZEOF_POINTER__)
337
+ rval_bytes = FFI_ALIGN(cif->rtype->size, STKALIGN);
338
+ size_t alloc_size = arg_bytes + rval_bytes + sizeof(call_context);
339
+
340
+ /* the assembly code will deallocate all stack data at lower addresses
341
+ than the argument region, so we need to allocate the frame and the
342
+ return value after the arguments in a single allocation */
343
+ size_t alloc_base;
344
+ /* Argument region must be 16-byte aligned */
345
+ if (_Alignof(max_align_t) >= STKALIGN) {
346
+ /* since sizeof long double is normally 16, the compiler will
347
+ guarantee alloca alignment to at least that much */
348
+ alloc_base = (size_t)alloca(alloc_size);
349
+ } else {
350
+ alloc_base = FFI_ALIGN(alloca(alloc_size + STKALIGN - 1), STKALIGN);
351
+ }
352
+
353
+ if (rval_bytes)
354
+ rvalue = (void*)(alloc_base + arg_bytes);
355
+
356
+ call_builder cb;
357
+ cb.used_float = cb.used_integer = 0;
358
+ cb.aregs = (call_context*)(alloc_base + arg_bytes + rval_bytes);
359
+ cb.used_stack = (void*)alloc_base;
360
+
361
+ int return_by_ref = passed_by_ref(&cb, cif->rtype, 0);
362
+ if (return_by_ref)
363
+ marshal(&cb, &ffi_type_pointer, 0, &rvalue);
364
+
365
+ int i;
366
+ for (i = 0; i < cif->nargs; i++)
367
+ marshal(&cb, cif->arg_types[i], i >= cif->riscv_nfixedargs, avalue[i]);
368
+
369
+ ffi_call_asm((void*)alloc_base, cb.aregs, fn);
370
+
371
+ cb.used_float = cb.used_integer = 0;
372
+ if (!return_by_ref && rvalue)
373
+ unmarshal(&cb, cif->rtype, 0, rvalue);
374
+ }
375
+
376
+ extern void ffi_closure_asm(void) FFI_HIDDEN;
377
+
378
+ ffi_status ffi_prep_closure_loc(ffi_closure *closure, ffi_cif *cif, void (*fun)(ffi_cif*,void*,void**,void*), void *user_data, void *codeloc)
379
+ {
380
+ uint32_t *tramp = (uint32_t *) &closure->tramp[0];
381
+ uint64_t fn = (uint64_t) (uintptr_t) ffi_closure_asm;
382
+
383
+ if (cif->abi <= FFI_FIRST_ABI || cif->abi >= FFI_LAST_ABI)
384
+ return FFI_BAD_ABI;
385
+
386
+ /* we will call ffi_closure_inner with codeloc, not closure, but as long
387
+ as the memory is readable it should work */
388
+
389
+ tramp[0] = 0x00000317; /* auipc t1, 0 (i.e. t0 <- codeloc) */
390
+ #if __SIZEOF_POINTER__ == 8
391
+ tramp[1] = 0x01033383; /* ld t2, 16(t1) */
392
+ #else
393
+ tramp[1] = 0x01032383; /* lw t2, 16(t1) */
394
+ #endif
395
+ tramp[2] = 0x00038067; /* jr t2 */
396
+ tramp[3] = 0x00000013; /* nop */
397
+ tramp[4] = fn;
398
+ tramp[5] = fn >> 32;
399
+
400
+ closure->cif = cif;
401
+ closure->fun = fun;
402
+ closure->user_data = user_data;
403
+
404
+ __builtin___clear_cache(codeloc, codeloc + FFI_TRAMPOLINE_SIZE);
405
+
406
+ return FFI_OK;
407
+ }
408
+
409
+ /* Called by the assembly code with aregs pointing to saved argument registers
410
+ and stack pointing to the stacked arguments. Return values passed in
411
+ registers will be reloaded from aregs. */
412
+ void FFI_HIDDEN ffi_closure_inner(size_t *stack, call_context *aregs, ffi_closure *closure) {
413
+ ffi_cif *cif = closure->cif;
414
+ void **avalue = alloca(cif->nargs * sizeof(void*));
415
+ /* storage for arguments which will be copied by unmarshal(). We could
416
+ theoretically avoid the copies in many cases and use at most 128 bytes
417
+ of memory, but allocating disjoint storage for each argument is
418
+ simpler. */
419
+ char *astorage = alloca(cif->nargs * MAXCOPYARG);
420
+ void *rvalue;
421
+ call_builder cb;
422
+ int return_by_ref;
423
+ int i;
424
+
425
+ cb.aregs = aregs;
426
+ cb.used_integer = cb.used_float = 0;
427
+ cb.used_stack = stack;
428
+
429
+ return_by_ref = passed_by_ref(&cb, cif->rtype, 0);
430
+ if (return_by_ref)
431
+ unmarshal(&cb, &ffi_type_pointer, 0, &rvalue);
432
+ else
433
+ rvalue = alloca(cif->rtype->size);
434
+
435
+ for (i = 0; i < cif->nargs; i++)
436
+ avalue[i] = unmarshal(&cb, cif->arg_types[i],
437
+ i >= cif->riscv_nfixedargs, astorage + i*MAXCOPYARG);
438
+
439
+ (closure->fun)(cif, rvalue, avalue, closure->user_data);
440
+
441
+ if (!return_by_ref && cif->rtype->type != FFI_TYPE_VOID) {
442
+ cb.used_integer = cb.used_float = 0;
443
+ marshal(&cb, cif->rtype, 0, rvalue);
444
+ }
445
+ }