12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394 |
- // Copyright 2014 The Go Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style
- // license that can be found in the LICENSE file.
- #include "runtime.h"
- #include "go-type.h"
- #include "go-panic.h"
- #ifdef USE_LIBFFI
- #include "go-ffi.h"
- #if FFI_GO_CLOSURES
- #define USE_LIBFFI_CLOSURES
- #endif
- #endif /* defined(USE_LIBFFI) */
- /* Declare C functions with the names used to call from Go. */
- void makeFuncFFI(const struct __go_func_type *ftyp, void *impl)
- __asm__ (GOSYM_PREFIX "reflect.makeFuncFFI");
- #ifdef USE_LIBFFI_CLOSURES
- /* The function that we pass to ffi_prep_closure_loc. This calls the Go
- function ffiCall with the pointer to the arguments, the results area,
- and the closure structure. */
- void FFICallbackGo(void *result, void **args, ffi_go_closure *closure)
- __asm__ (GOSYM_PREFIX "reflect.FFICallbackGo");
- static void ffi_callback (ffi_cif *, void *, void **, void *)
- __asm__ ("reflect.ffi_callback");
- static void
- ffi_callback (ffi_cif* cif __attribute__ ((unused)), void *results,
- void **args, void *closure)
- {
- Location locs[8];
- int n;
- int i;
- /* This function is called from some series of FFI closure functions
- called by a Go function. We want to see whether the caller of
- the closure functions can recover. Look up the stack and skip
- the FFI functions. */
- n = runtime_callers (1, &locs[0], sizeof locs / sizeof locs[0], true);
- for (i = 0; i < n; i++)
- {
- const byte *name;
- if (locs[i].function.len == 0)
- continue;
- if (locs[i].function.len < 4)
- break;
- name = locs[i].function.str;
- if (name[0] != 'f' || name[1] != 'f' || name[2] != 'i' || name[3] != '_')
- break;
- }
- if (i < n)
- __go_makefunc_ffi_can_recover (locs + i, n - i);
- FFICallbackGo(results, args, closure);
- if (i < n)
- __go_makefunc_returning ();
- }
- /* Allocate an FFI closure and arrange to call ffi_callback. */
- void
- makeFuncFFI(const struct __go_func_type *ftyp, void *impl)
- {
- ffi_cif *cif;
- cif = (ffi_cif *) __go_alloc (sizeof (ffi_cif));
- __go_func_to_cif (ftyp, 0, 0, cif);
- ffi_prep_go_closure(impl, cif, ffi_callback);
- }
- #else /* !defined(USE_LIBFFI_CLOSURES) */
- void
- makeFuncFFI(const struct __go_func_type *ftyp __attribute__ ((unused)),
- void *impl __attribute__ ((unused)))
- {
- runtime_panicstring ("libgo built without FFI does not support "
- "reflect.MakeFunc");
- }
- #endif
|