ffi 1.10.0 → 1.11.1
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
- data/.gitignore +3 -0
- data/.gitmodules +2 -1
- data/.travis.yml +17 -18
- data/CHANGELOG.md +33 -0
- data/Gemfile +1 -1
- data/README.md +20 -17
- data/Rakefile +10 -83
- data/appveyor.yml +6 -1
- data/ext/ffi_c/Call.c +16 -33
- data/ext/ffi_c/Call.h +2 -5
- data/ext/ffi_c/Function.c +24 -108
- data/ext/ffi_c/Platform.c +0 -47
- data/ext/ffi_c/Thread.c +6 -222
- data/ext/ffi_c/Thread.h +2 -13
- data/ext/ffi_c/Type.c +0 -18
- data/ext/ffi_c/Type.h +0 -1
- data/ext/ffi_c/Variadic.c +9 -15
- data/ext/ffi_c/extconf.rb +34 -20
- data/ext/ffi_c/ffi.c +3 -8
- data/ext/ffi_c/libffi/configure.ac +5 -1
- data/ext/ffi_c/libffi/include/ffi_common.h +1 -1
- data/ext/ffi_c/libffi/src/aarch64/ffi.c +2 -2
- data/ext/ffi_c/libffi/src/frv/ffi.c +1 -1
- data/ext/ffi_c/libffi/src/metag/ffi.c +1 -1
- data/ext/ffi_c/libffi/src/moxie/ffi.c +1 -1
- data/ext/ffi_c/libffi/src/riscv/ffi.c +42 -6
- data/ext/ffi_c/libffi/src/riscv/ffitarget.h +1 -0
- data/ext/ffi_c/libffi/src/riscv/sysv.S +86 -7
- data/ext/ffi_c/libffi/src/x86/ffi.c +2 -1
- data/ext/ffi_c/libffi/src/x86/ffiw64.c +1 -1
- data/ext/ffi_c/libffi/src/x86/sysv.S +88 -2
- data/ext/ffi_c/libffi/src/x86/unix64.S +41 -0
- data/ext/ffi_c/rbffi.h +0 -2
- data/ffi.gemspec +11 -4
- data/lib/ffi/data_converter.rb +67 -0
- data/lib/ffi/ffi.rb +1 -0
- data/lib/ffi/platform.rb +2 -0
- data/lib/ffi/pointer.rb +1 -1
- data/lib/ffi/struct.rb +3 -63
- data/lib/ffi/struct_by_reference.rb +72 -0
- data/lib/ffi/struct_layout.rb +96 -0
- data/lib/ffi/tools/const_generator.rb +5 -4
- data/lib/ffi/tools/generator.rb +47 -2
- data/lib/ffi/tools/generator_task.rb +13 -17
- data/lib/ffi/tools/struct_generator.rb +4 -4
- data/lib/ffi/types.rb +1 -1
- data/lib/ffi/version.rb +1 -1
- metadata +18 -13
- data/ext/ffi_c/DataConverter.c +0 -91
- data/ext/ffi_c/StructByReference.c +0 -190
- data/ext/ffi_c/StructByReference.h +0 -50
data/ext/ffi_c/Thread.h
CHANGED
@@ -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
|
data/ext/ffi_c/Type.c
CHANGED
@@ -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
|
{
|
data/ext/ffi_c/Type.h
CHANGED
data/ext/ffi_c/Variadic.c
CHANGED
@@ -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
|
-
|
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
|
-
|
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
|
}
|
data/ext/ffi_c/extconf.rb
CHANGED
@@ -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
|
-
|
16
|
-
|
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
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
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
|
-
|
30
|
-
have_func('
|
31
|
-
|
32
|
-
|
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
|
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 !
|
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
|
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"
|
data/ext/ffi_c/ffi.c
CHANGED
@@ -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
|
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
|
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, #
|
353
|
+
" ldp q18, q19, [%3, #32]\n"
|
354
354
|
" b 4f\n"
|
355
355
|
" ldp q16, q17, [%3]\n" /* Q3 */
|
356
|
-
" ldr q18, [%3, #
|
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 :
|
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 *)
|
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 :
|
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,
|
327
|
+
extern void ffi_call_asm (void *stack, struct call_context *regs,
|
328
|
+
void (*fn) (void), void *closure) FFI_HIDDEN;
|
328
329
|
|
329
|
-
|
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
|
413
|
-
|
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
|
-
|
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
|
-
|
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(
|
149
|
-
|
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
|
-
|
191
|
-
|
192
|
-
|
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
|