ffi 1.10.0 → 1.11.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -0
  3. data/.gitmodules +2 -1
  4. data/.travis.yml +17 -18
  5. data/CHANGELOG.md +33 -0
  6. data/Gemfile +1 -1
  7. data/README.md +20 -17
  8. data/Rakefile +10 -83
  9. data/appveyor.yml +6 -1
  10. data/ext/ffi_c/Call.c +16 -33
  11. data/ext/ffi_c/Call.h +2 -5
  12. data/ext/ffi_c/Function.c +24 -108
  13. data/ext/ffi_c/Platform.c +0 -47
  14. data/ext/ffi_c/Thread.c +6 -222
  15. data/ext/ffi_c/Thread.h +2 -13
  16. data/ext/ffi_c/Type.c +0 -18
  17. data/ext/ffi_c/Type.h +0 -1
  18. data/ext/ffi_c/Variadic.c +9 -15
  19. data/ext/ffi_c/extconf.rb +34 -20
  20. data/ext/ffi_c/ffi.c +3 -8
  21. data/ext/ffi_c/libffi/configure.ac +5 -1
  22. data/ext/ffi_c/libffi/include/ffi_common.h +1 -1
  23. data/ext/ffi_c/libffi/src/aarch64/ffi.c +2 -2
  24. data/ext/ffi_c/libffi/src/frv/ffi.c +1 -1
  25. data/ext/ffi_c/libffi/src/metag/ffi.c +1 -1
  26. data/ext/ffi_c/libffi/src/moxie/ffi.c +1 -1
  27. data/ext/ffi_c/libffi/src/riscv/ffi.c +42 -6
  28. data/ext/ffi_c/libffi/src/riscv/ffitarget.h +1 -0
  29. data/ext/ffi_c/libffi/src/riscv/sysv.S +86 -7
  30. data/ext/ffi_c/libffi/src/x86/ffi.c +2 -1
  31. data/ext/ffi_c/libffi/src/x86/ffiw64.c +1 -1
  32. data/ext/ffi_c/libffi/src/x86/sysv.S +88 -2
  33. data/ext/ffi_c/libffi/src/x86/unix64.S +41 -0
  34. data/ext/ffi_c/rbffi.h +0 -2
  35. data/ffi.gemspec +11 -4
  36. data/lib/ffi/data_converter.rb +67 -0
  37. data/lib/ffi/ffi.rb +1 -0
  38. data/lib/ffi/platform.rb +2 -0
  39. data/lib/ffi/pointer.rb +1 -1
  40. data/lib/ffi/struct.rb +3 -63
  41. data/lib/ffi/struct_by_reference.rb +72 -0
  42. data/lib/ffi/struct_layout.rb +96 -0
  43. data/lib/ffi/tools/const_generator.rb +5 -4
  44. data/lib/ffi/tools/generator.rb +47 -2
  45. data/lib/ffi/tools/generator_task.rb +13 -17
  46. data/lib/ffi/tools/struct_generator.rb +4 -4
  47. data/lib/ffi/types.rb +1 -1
  48. data/lib/ffi/version.rb +1 -1
  49. metadata +18 -13
  50. data/ext/ffi_c/DataConverter.c +0 -91
  51. data/ext/ffi_c/StructByReference.c +0 -190
  52. data/ext/ffi_c/StructByReference.h +0 -50
@@ -66,7 +66,9 @@ typedef struct rbffi_frame {
66
66
  struct thread_data* td;
67
67
  #endif
68
68
  struct rbffi_frame* prev;
69
+ #ifndef HAVE_RUBY_THREAD_HAS_GVL_P
69
70
  bool has_gvl;
71
+ #endif
70
72
  VALUE exc;
71
73
  } rbffi_frame_t;
72
74
 
@@ -74,19 +76,6 @@ rbffi_frame_t* rbffi_frame_current(void);
74
76
  void rbffi_frame_push(rbffi_frame_t* frame);
75
77
  void rbffi_frame_pop(rbffi_frame_t* frame);
76
78
 
77
- #ifdef HAVE_RB_THREAD_CALL_WITHOUT_GVL
78
- # define rbffi_thread_blocking_region rb_thread_call_without_gvl
79
-
80
- #elif defined(HAVE_RB_THREAD_BLOCKING_REGION)
81
- # define rbffi_thread_blocking_region rb_thread_blocking_region
82
-
83
- #else
84
-
85
- VALUE rbffi_thread_blocking_region(VALUE (*func)(void *), void *data1, void (*ubf)(void *), void *data2);
86
-
87
- #endif
88
-
89
-
90
79
  #ifdef __cplusplus
91
80
  }
92
81
  #endif
@@ -235,24 +235,6 @@ rbffi_Type_Lookup(VALUE name)
235
235
  return Qnil;
236
236
  }
237
237
 
238
- /**
239
- * rbffi_Type_Find() is like rbffi_Type_Lookup, but an error is raised if the
240
- * type is not found.
241
- */
242
- VALUE
243
- rbffi_Type_Find(VALUE name)
244
- {
245
- VALUE rbType = rbffi_Type_Lookup(name);
246
-
247
- if (!RTEST(rbType)) {
248
- VALUE s = rb_inspect(name);
249
- rb_raise(rb_eTypeError, "invalid type, %s", RSTRING_PTR(s));
250
- RB_GC_GUARD(s);
251
- }
252
-
253
- return rbType;
254
- }
255
-
256
238
  void
257
239
  rbffi_Type_Init(VALUE moduleFFI)
258
240
  {
@@ -52,7 +52,6 @@ struct Type_ {
52
52
 
53
53
  extern VALUE rbffi_TypeClass;
54
54
  extern VALUE rbffi_Type_Lookup(VALUE type);
55
- extern VALUE rbffi_Type_Find(VALUE type);
56
55
 
57
56
  #ifdef __cplusplus
58
57
  }
@@ -191,7 +191,7 @@ variadic_invoke(VALUE self, VALUE parameterTypes, VALUE parameterValues)
191
191
 
192
192
  for (i = 0; i < paramCount; ++i) {
193
193
  VALUE rbType = rb_ary_entry(parameterTypes, i);
194
-
194
+
195
195
  if (!rb_obj_is_kind_of(rbType, rbffi_TypeClass)) {
196
196
  rb_raise(rb_eTypeError, "wrong type. Expected (FFI::Type)");
197
197
  }
@@ -210,7 +210,7 @@ variadic_invoke(VALUE self, VALUE parameterTypes, VALUE parameterValues)
210
210
  rbType = rb_const_get(rbffi_TypeClass, rb_intern("UINT32"));
211
211
  Data_Get_Struct(rbType, Type, paramTypes[i]);
212
212
  break;
213
-
213
+
214
214
  case NATIVE_FLOAT32:
215
215
  rbType = rb_const_get(rbffi_TypeClass, rb_intern("DOUBLE"));
216
216
  Data_Get_Struct(rbType, Type, paramTypes[i]);
@@ -219,8 +219,8 @@ variadic_invoke(VALUE self, VALUE parameterTypes, VALUE parameterValues)
219
219
  default:
220
220
  break;
221
221
  }
222
-
223
-
222
+
223
+
224
224
  ffiParamTypes[i] = paramTypes[i]->ffiType;
225
225
  if (ffiParamTypes[i] == NULL) {
226
226
  rb_raise(rb_eArgError, "Invalid parameter type #%x", paramTypes[i]->nativeType);
@@ -254,13 +254,9 @@ variadic_invoke(VALUE self, VALUE parameterTypes, VALUE parameterValues)
254
254
 
255
255
  rbffi_SetupCallParams(paramCount, argv, -1, paramTypes, params,
256
256
  ffiValues, NULL, 0, invoker->rbEnums);
257
-
257
+
258
258
  rbffi_frame_push(&frame);
259
- #ifdef HAVE_RB_THREAD_CALL_WITHOUT_GVL
260
- /* In Call.c, blocking: true is supported on older ruby variants
261
- * without rb_thread_call_without_gvl by allocating on the heap instead
262
- * of the stack. Since this functionality is being added later,
263
- * we’re skipping support for old rubies here. */
259
+
264
260
  if(unlikely(invoker->blocking)) {
265
261
  rbffi_blocking_call_t* bc;
266
262
  bc = ALLOCA_N(rbffi_blocking_call_t, 1);
@@ -275,13 +271,11 @@ variadic_invoke(VALUE self, VALUE parameterTypes, VALUE parameterValues)
275
271
  } else {
276
272
  ffi_call(&cif, FFI_FN(invoker->function), retval, ffiValues);
277
273
  }
278
- #else
279
- ffi_call(&cif, FFI_FN(invoker->function), retval, ffiValues);
280
- #endif
274
+
281
275
  rbffi_frame_pop(&frame);
282
-
276
+
283
277
  rbffi_save_errno();
284
-
278
+
285
279
  if (RTEST(frame.exc) && frame.exc != Qnil) {
286
280
  rb_exc_raise(frame.exc);
287
281
  }
@@ -3,6 +3,21 @@
3
3
  if !defined?(RUBY_ENGINE) || RUBY_ENGINE == 'ruby' || RUBY_ENGINE == 'rbx'
4
4
  require 'mkmf'
5
5
  require 'rbconfig'
6
+
7
+ def system_libffi_usable?
8
+ # We need pkg_config or ffi.h
9
+ libffi_ok = pkg_config("libffi") ||
10
+ have_header("ffi.h") ||
11
+ find_header("ffi.h", "/usr/local/include", "/usr/include/ffi")
12
+
13
+ # Ensure we can link to ffi_call
14
+ libffi_ok &&= have_library("ffi", "ffi_call", [ "ffi.h" ]) ||
15
+ have_library("libffi", "ffi_call", [ "ffi.h" ])
16
+
17
+ # And we need a libffi version recent enough to provide ffi_closure_alloc
18
+ libffi_ok &&= have_func("ffi_closure_alloc")
19
+ end
20
+
6
21
  dir_config("ffi_c")
7
22
 
8
23
  # recent versions of ruby add restrictive ansi and warning flags on a whim - kill them all
@@ -12,42 +27,41 @@ if !defined?(RUBY_ENGINE) || RUBY_ENGINE == 'ruby' || RUBY_ENGINE == 'rbx'
12
27
  # solaris 10 needs -c99 for <stdbool.h>
13
28
  $CFLAGS << " -std=c99" if RbConfig::CONFIG['host_os'] =~ /solaris(!?2\.11)/
14
29
 
15
- if ENV['RUBY_CC_VERSION'].nil? && (pkg_config("libffi") ||
16
- have_header("ffi.h") ||
17
- find_header("ffi.h", "/usr/local/include", "/usr/include/ffi"))
30
+ # Check whether we use system libffi
31
+ system_libffi = enable_config('system-libffi', :try)
18
32
 
19
- # We need at least ffi_call and ffi_closure_alloc
20
- libffi_ok = have_library("ffi", "ffi_call", [ "ffi.h" ]) ||
21
- have_library("libffi", "ffi_call", [ "ffi.h" ])
22
- libffi_ok &&= have_func("ffi_closure_alloc")
23
-
24
- # Check if the raw api is available.
25
- $defs << "-DHAVE_RAW_API" if have_func("ffi_raw_call") && have_func("ffi_prep_raw_closure")
33
+ if system_libffi == :try
34
+ system_libffi = ENV['RUBY_CC_VERSION'].nil? && system_libffi_usable?
35
+ elsif system_libffi
36
+ abort "system libffi is not usable" unless system_libffi_usable?
26
37
  end
27
38
 
28
39
  have_header('shlwapi.h')
29
- have_header('ruby/thread.h') # for compat with ruby < 2.0
30
- have_func('rb_thread_blocking_region')
31
- have_func('rb_thread_call_with_gvl')
32
- have_func('rb_thread_call_without_gvl')
40
+ have_func('rb_thread_call_without_gvl') || abort("Ruby C-API function `rb_thread_call_without_gvl` is missing")
41
+ have_func('ruby_native_thread_p')
42
+ if RUBY_VERSION >= "2.3.0"
43
+ # On OSX and Linux ruby_thread_has_gvl_p() is detected but fails at runtime for ruby < 2.3.0
44
+ have_func('ruby_thread_has_gvl_p')
45
+ end
33
46
 
34
- if libffi_ok
47
+ if system_libffi
35
48
  have_func('ffi_prep_cif_var')
49
+ $defs << "-DHAVE_RAW_API" if have_func("ffi_raw_call") && have_func("ffi_prep_raw_closure")
36
50
  else
37
51
  $defs << "-DHAVE_FFI_PREP_CIF_VAR"
52
+ $defs << "-DUSE_INTERNAL_LIBFFI"
38
53
  end
39
54
 
40
55
  $defs << "-DHAVE_EXTCONF_H" if $defs.empty? # needed so create_header works
41
- $defs << "-DUSE_INTERNAL_LIBFFI" unless libffi_ok
42
56
  $defs << "-DRUBY_1_9" if RUBY_VERSION >= "1.9.0"
43
57
  $defs << "-DFFI_BUILDING" if RbConfig::CONFIG['host_os'] =~ /mswin/ # for compatibility with newer libffi
44
58
 
45
59
  create_header
46
-
47
- $LOCAL_LIBS << " ./libffi/.libs/libffi_convenience.lib" if !libffi_ok && RbConfig::CONFIG['host_os'] =~ /mswin/
60
+
61
+ $LOCAL_LIBS << " ./libffi/.libs/libffi_convenience.lib" if !system_libffi && RbConfig::CONFIG['host_os'] =~ /mswin/
48
62
 
49
63
  create_makefile("ffi_c")
50
- unless libffi_ok
64
+ unless system_libffi
51
65
  File.open("Makefile", "a") do |mf|
52
66
  mf.puts "LIBFFI_HOST=--host=#{RbConfig::CONFIG['host_alias']}" if RbConfig::CONFIG.has_key?("host_alias")
53
67
  if RbConfig::CONFIG['host_os'].downcase =~ /darwin/
@@ -63,7 +77,7 @@ if !defined?(RUBY_ENGINE) || RUBY_ENGINE == 'ruby' || RUBY_ENGINE == 'rbx'
63
77
  end
64
78
  end
65
79
  end
66
-
80
+
67
81
  else
68
82
  File.open("Makefile", "w") do |mf|
69
83
  mf.puts "# Dummy makefile for non-mri rubies"
@@ -40,7 +40,6 @@
40
40
  #include "MemoryPointer.h"
41
41
  #include "Struct.h"
42
42
  #include "StructByValue.h"
43
- #include "StructByReference.h"
44
43
  #include "DynamicLibrary.h"
45
44
  #include "Platform.h"
46
45
  #include "Types.h"
@@ -59,9 +58,9 @@ VALUE rbffi_FFIModule = Qnil;
59
58
  static VALUE moduleFFI = Qnil;
60
59
 
61
60
  void
62
- Init_ffi_c(void)
61
+ Init_ffi_c(void)
63
62
  {
64
- /*
63
+ /*
65
64
  * Document-module: FFI
66
65
  *
67
66
  * This module embbed type constants from {FFI::NativeType}.
@@ -70,12 +69,10 @@ Init_ffi_c(void)
70
69
  rb_global_variable(&rbffi_FFIModule);
71
70
 
72
71
  rbffi_Thread_Init(rbffi_FFIModule);
73
-
72
+
74
73
  /* FFI::Type needs to be initialized before most other classes */
75
74
  rbffi_Type_Init(moduleFFI);
76
75
 
77
- rbffi_DataConverter_Init(moduleFFI);
78
-
79
76
  rbffi_ArrayType_Init(moduleFFI);
80
77
  rbffi_LastError_Init(moduleFFI);
81
78
  rbffi_Call_Init(moduleFFI);
@@ -88,11 +85,9 @@ Init_ffi_c(void)
88
85
  rbffi_MemoryPointer_Init(moduleFFI);
89
86
  rbffi_Buffer_Init(moduleFFI);
90
87
  rbffi_StructByValue_Init(moduleFFI);
91
- rbffi_StructByReference_Init(moduleFFI);
92
88
  rbffi_Struct_Init(moduleFFI);
93
89
  rbffi_DynamicLibrary_Init(moduleFFI);
94
90
  rbffi_Variadic_Init(moduleFFI);
95
91
  rbffi_Types_Init(moduleFFI);
96
92
  rbffi_MappedType_Init(moduleFFI);
97
93
  }
98
-
@@ -270,7 +270,7 @@ if test "x$GCC" = "xyes"; then
270
270
  echo 'int __attribute__ ((visibility ("hidden"))) foo (void) { return 1 ; }' > conftest.c
271
271
  libffi_cv_hidden_visibility_attribute=no
272
272
  if AC_TRY_COMMAND(${CC-cc} -Werror -S conftest.c -o conftest.s 1>&AS_MESSAGE_LOG_FD); then
273
- if grep '\.hidden.*foo' conftest.s >/dev/null; then
273
+ if egrep '(\.hidden|\.private_extern).*foo' conftest.s >/dev/null; then
274
274
  libffi_cv_hidden_visibility_attribute=yes
275
275
  fi
276
276
  fi
@@ -292,7 +292,11 @@ AM_CONDITIONAL(BUILD_DOCS, [test x$enable_docs = xyes])
292
292
  AH_BOTTOM([
293
293
  #ifdef HAVE_HIDDEN_VISIBILITY_ATTRIBUTE
294
294
  #ifdef LIBFFI_ASM
295
+ #ifdef __APPLE__
296
+ #define FFI_HIDDEN(name) .private_extern name
297
+ #else
295
298
  #define FFI_HIDDEN(name) .hidden name
299
+ #endif
296
300
  #else
297
301
  #define FFI_HIDDEN __attribute__ ((visibility ("hidden")))
298
302
  #endif
@@ -77,7 +77,7 @@ void ffi_type_test(ffi_type *a, char *file, int line);
77
77
  /* v cast to size_t and aligned up to a multiple of a */
78
78
  #define FFI_ALIGN(v, a) (((((size_t) (v))-1) | ((a)-1))+1)
79
79
  /* v cast to size_t and aligned down to a multiple of a */
80
- #define ALIGN_DOWN(v, a) (((size_t) (v)) & -a)
80
+ #define FFI_ALIGN_DOWN(v, a) (((size_t) (v)) & -a)
81
81
 
82
82
  /* Perform machine dependent cif processing */
83
83
  ffi_status ffi_prep_cif_machdep(ffi_cif *cif);
@@ -350,10 +350,10 @@ extend_hfa_type (void *dest, void *src, int h)
350
350
  " b 1f\n"
351
351
  " nop\n"
352
352
  " ldp q16, q17, [%3]\n" /* Q4 */
353
- " ldp q18, q19, [%3, #16]\n"
353
+ " ldp q18, q19, [%3, #32]\n"
354
354
  " b 4f\n"
355
355
  " ldp q16, q17, [%3]\n" /* Q3 */
356
- " ldr q18, [%3, #16]\n"
356
+ " ldr q18, [%3, #32]\n"
357
357
  " b 3f\n"
358
358
  " ldp q16, q17, [%3]\n" /* Q2 */
359
359
  " b 2f\n"
@@ -107,7 +107,7 @@ void *ffi_prep_args(char *stack, extended_cif *ecif)
107
107
  count += z;
108
108
  }
109
109
 
110
- return (stack + ((count > 24) ? 24 : ALIGN_DOWN(count, 8)));
110
+ return (stack + ((count > 24) ? 24 : FFI_ALIGN_DOWN(count, 8)));
111
111
  }
112
112
 
113
113
  /* Perform machine dependent cif processing */
@@ -61,7 +61,7 @@ unsigned int ffi_prep_args(char *stack, extended_cif *ecif)
61
61
  argp -= z;
62
62
 
63
63
  /* Align if necessary */
64
- argp = (char *) ALIGN_DOWN(ALIGN_DOWN(argp, (*p_arg)->alignment), 4);
64
+ argp = (char *) FFI_ALIGN_DOWN(FFI_ALIGN_DOWN(argp, (*p_arg)->alignment), 4);
65
65
 
66
66
  if (z < sizeof(int)) {
67
67
  z = sizeof(int);
@@ -100,7 +100,7 @@ void *ffi_prep_args(char *stack, extended_cif *ecif)
100
100
  count += z;
101
101
  }
102
102
 
103
- return (stack + ((count > 24) ? 24 : ALIGN_DOWN(count, 8)));
103
+ return (stack + ((count > 24) ? 24 : FFI_ALIGN_DOWN(count, 8)));
104
104
  }
105
105
 
106
106
  /* Perform machine dependent cif processing */
@@ -324,9 +324,12 @@ ffi_status ffi_prep_cif_machdep_var(ffi_cif *cif, unsigned int nfixedargs, unsig
324
324
  }
325
325
 
326
326
  /* Low level routine for calling functions */
327
- extern void ffi_call_asm(void *stack, struct call_context *regs, void (*fn)(void)) FFI_HIDDEN;
327
+ extern void ffi_call_asm (void *stack, struct call_context *regs,
328
+ void (*fn) (void), void *closure) FFI_HIDDEN;
328
329
 
329
- void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
330
+ static void
331
+ ffi_call_int (ffi_cif *cif, void (*fn) (void), void *rvalue, void **avalue,
332
+ void *closure)
330
333
  {
331
334
  /* this is a conservative estimate, assuming a complex return value and
332
335
  that all remaining arguments are long long / __int128 */
@@ -366,13 +369,26 @@ void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
366
369
  for (i = 0; i < cif->nargs; i++)
367
370
  marshal(&cb, cif->arg_types[i], i >= cif->riscv_nfixedargs, avalue[i]);
368
371
 
369
- ffi_call_asm((void*)alloc_base, cb.aregs, fn);
372
+ ffi_call_asm ((void *) alloc_base, cb.aregs, fn, closure);
370
373
 
371
374
  cb.used_float = cb.used_integer = 0;
372
375
  if (!return_by_ref && rvalue)
373
376
  unmarshal(&cb, cif->rtype, 0, rvalue);
374
377
  }
375
378
 
379
+ void
380
+ ffi_call (ffi_cif *cif, void (*fn) (void), void *rvalue, void **avalue)
381
+ {
382
+ ffi_call_int(cif, fn, rvalue, avalue, NULL);
383
+ }
384
+
385
+ void
386
+ ffi_call_go (ffi_cif *cif, void (*fn) (void), void *rvalue,
387
+ void **avalue, void *closure)
388
+ {
389
+ ffi_call_int(cif, fn, rvalue, avalue, closure);
390
+ }
391
+
376
392
  extern void ffi_closure_asm(void) FFI_HIDDEN;
377
393
 
378
394
  ffi_status ffi_prep_closure_loc(ffi_closure *closure, ffi_cif *cif, void (*fun)(ffi_cif*,void*,void**,void*), void *user_data, void *codeloc)
@@ -406,11 +422,31 @@ ffi_status ffi_prep_closure_loc(ffi_closure *closure, ffi_cif *cif, void (*fun)(
406
422
  return FFI_OK;
407
423
  }
408
424
 
425
+ extern void ffi_go_closure_asm (void) FFI_HIDDEN;
426
+
427
+ ffi_status
428
+ ffi_prep_go_closure (ffi_go_closure *closure, ffi_cif *cif,
429
+ void (*fun) (ffi_cif *, void *, void **, void *))
430
+ {
431
+ if (cif->abi <= FFI_FIRST_ABI || cif->abi >= FFI_LAST_ABI)
432
+ return FFI_BAD_ABI;
433
+
434
+ closure->tramp = (void *) ffi_go_closure_asm;
435
+ closure->cif = cif;
436
+ closure->fun = fun;
437
+
438
+ return FFI_OK;
439
+ }
440
+
409
441
  /* Called by the assembly code with aregs pointing to saved argument registers
410
442
  and stack pointing to the stacked arguments. Return values passed in
411
443
  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;
444
+ void FFI_HIDDEN
445
+ ffi_closure_inner (ffi_cif *cif,
446
+ void (*fun) (ffi_cif *, void *, void **, void *),
447
+ void *user_data,
448
+ size_t *stack, call_context *aregs)
449
+ {
414
450
  void **avalue = alloca(cif->nargs * sizeof(void*));
415
451
  /* storage for arguments which will be copied by unmarshal(). We could
416
452
  theoretically avoid the copies in many cases and use at most 128 bytes
@@ -436,7 +472,7 @@ void FFI_HIDDEN ffi_closure_inner(size_t *stack, call_context *aregs, ffi_closur
436
472
  avalue[i] = unmarshal(&cb, cif->arg_types[i],
437
473
  i >= cif->riscv_nfixedargs, astorage + i*MAXCOPYARG);
438
474
 
439
- (closure->fun)(cif, rvalue, avalue, closure->user_data);
475
+ fun (cif, rvalue, avalue, user_data);
440
476
 
441
477
  if (!return_by_ref && cif->rtype->type != FFI_TYPE_VOID) {
442
478
  cb.used_integer = cb.used_float = 0;
@@ -59,6 +59,7 @@ typedef enum ffi_abi {
59
59
  /* ---- Definitions for closures ----------------------------------------- */
60
60
 
61
61
  #define FFI_CLOSURES 1
62
+ #define FFI_GO_CLOSURES 1
62
63
  #define FFI_TRAMPOLINE_SIZE 24
63
64
  #define FFI_NATIVE_RAW_API 0
64
65
  #define FFI_EXTRA_CIF_FIELDS unsigned riscv_nfixedargs; unsigned riscv_unused;
@@ -67,8 +67,8 @@
67
67
  intreg pad[rv32 ? 2 : 0];
68
68
  intreg save_fp, save_ra;
69
69
  }
70
- void ffi_call_asm(size_t *stackargs, struct call_context *regargs,
71
- void (*fn)(void));
70
+ void ffi_call_asm (size_t *stackargs, struct call_context *regargs,
71
+ void (*fn) (void), void *closure);
72
72
  */
73
73
 
74
74
  #define FRAME_LEN (8 * FLTS + 8 * PTRS + 16)
@@ -98,6 +98,7 @@ ffi_call_asm:
98
98
 
99
99
  # Load arguments
100
100
  mv t1, a2
101
+ mv t2, a3
101
102
 
102
103
  #if FLTS
103
104
  FLARG fa0, -FRAME_LEN+0*FLTS(fp)
@@ -145,8 +146,10 @@ ffi_call_asm:
145
146
 
146
147
  /*
147
148
  ffi_closure_asm. Expects address of the passed-in ffi_closure in t1.
148
- void ffi_closure_inner(size_t *stackargs, struct call_context *regargs,
149
- ffi_closure *closure);
149
+ void ffi_closure_inner (ffi_cif *cif,
150
+ void (*fun) (ffi_cif *, void *, void **, void *),
151
+ void *user_data,
152
+ size_t *stackargs, struct call_context *regargs)
150
153
  */
151
154
 
152
155
  .globl ffi_closure_asm
@@ -187,9 +190,11 @@ ffi_closure_asm:
187
190
  SARG a7, 8*FLTS+7*PTRS(sp)
188
191
 
189
192
  /* enter C */
190
- addi a0, sp, FRAME_LEN
191
- mv a1, sp
192
- mv a2, t1
193
+ LARG a0, FFI_TRAMPOLINE_SIZE+0*PTRS(t1)
194
+ LARG a1, FFI_TRAMPOLINE_SIZE+1*PTRS(t1)
195
+ LARG a2, FFI_TRAMPOLINE_SIZE+2*PTRS(t1)
196
+ addi a3, sp, FRAME_LEN
197
+ mv a4, sp
193
198
 
194
199
  call ffi_closure_inner
195
200
 
@@ -212,3 +217,77 @@ ffi_closure_asm:
212
217
  ret
213
218
  .cfi_endproc
214
219
  .size ffi_closure_asm, .-ffi_closure_asm
220
+
221
+ /*
222
+ ffi_go_closure_asm. Expects address of the passed-in ffi_go_closure in t2.
223
+ void ffi_closure_inner (ffi_cif *cif,
224
+ void (*fun) (ffi_cif *, void *, void **, void *),
225
+ void *user_data,
226
+ size_t *stackargs, struct call_context *regargs)
227
+ */
228
+
229
+ .globl ffi_go_closure_asm
230
+ .hidden ffi_go_closure_asm
231
+ .type ffi_go_closure_asm, @function
232
+ ffi_go_closure_asm:
233
+ .cfi_startproc
234
+
235
+ addi sp, sp, -FRAME_LEN
236
+ .cfi_def_cfa_offset FRAME_LEN
237
+
238
+ /* make a frame */
239
+ SARG fp, FRAME_LEN - 2*PTRS(sp)
240
+ .cfi_offset 8, -2*PTRS
241
+ SARG ra, FRAME_LEN - 1*PTRS(sp)
242
+ .cfi_offset 1, -1*PTRS
243
+ addi fp, sp, FRAME_LEN
244
+
245
+ /* save arguments */
246
+ #if FLTS
247
+ FSARG fa0, 0*FLTS(sp)
248
+ FSARG fa1, 1*FLTS(sp)
249
+ FSARG fa2, 2*FLTS(sp)
250
+ FSARG fa3, 3*FLTS(sp)
251
+ FSARG fa4, 4*FLTS(sp)
252
+ FSARG fa5, 5*FLTS(sp)
253
+ FSARG fa6, 6*FLTS(sp)
254
+ FSARG fa7, 7*FLTS(sp)
255
+ #endif
256
+
257
+ SARG a0, 8*FLTS+0*PTRS(sp)
258
+ SARG a1, 8*FLTS+1*PTRS(sp)
259
+ SARG a2, 8*FLTS+2*PTRS(sp)
260
+ SARG a3, 8*FLTS+3*PTRS(sp)
261
+ SARG a4, 8*FLTS+4*PTRS(sp)
262
+ SARG a5, 8*FLTS+5*PTRS(sp)
263
+ SARG a6, 8*FLTS+6*PTRS(sp)
264
+ SARG a7, 8*FLTS+7*PTRS(sp)
265
+
266
+ /* enter C */
267
+ LARG a0, 1*PTRS(t2)
268
+ LARG a1, 2*PTRS(t2)
269
+ mv a2, t2
270
+ addi a3, sp, FRAME_LEN
271
+ mv a4, sp
272
+
273
+ call ffi_closure_inner
274
+
275
+ /* return values */
276
+ #if FLTS
277
+ FLARG fa0, 0*FLTS(sp)
278
+ FLARG fa1, 1*FLTS(sp)
279
+ #endif
280
+
281
+ LARG a0, 8*FLTS+0*PTRS(sp)
282
+ LARG a1, 8*FLTS+1*PTRS(sp)
283
+
284
+ /* restore and return */
285
+ LARG ra, FRAME_LEN-1*PTRS(sp)
286
+ .cfi_restore 1
287
+ LARG fp, FRAME_LEN-2*PTRS(sp)
288
+ .cfi_restore 8
289
+ addi sp, sp, FRAME_LEN
290
+ .cfi_def_cfa_offset 0
291
+ ret
292
+ .cfi_endproc
293
+ .size ffi_go_closure_asm, .-ffi_go_closure_asm