ffi 1.10.0 → 1.11.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|