makefunc_ffi_c.c 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. // Copyright 2014 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. #include "runtime.h"
  5. #include "go-type.h"
  6. #include "go-panic.h"
  7. #ifdef USE_LIBFFI
  8. #include "go-ffi.h"
  9. #if FFI_GO_CLOSURES
  10. #define USE_LIBFFI_CLOSURES
  11. #endif
  12. #endif /* defined(USE_LIBFFI) */
  13. /* Declare C functions with the names used to call from Go. */
  14. void makeFuncFFI(const struct __go_func_type *ftyp, void *impl)
  15. __asm__ (GOSYM_PREFIX "reflect.makeFuncFFI");
  16. #ifdef USE_LIBFFI_CLOSURES
  17. /* The function that we pass to ffi_prep_closure_loc. This calls the Go
  18. function ffiCall with the pointer to the arguments, the results area,
  19. and the closure structure. */
  20. void FFICallbackGo(void *result, void **args, ffi_go_closure *closure)
  21. __asm__ (GOSYM_PREFIX "reflect.FFICallbackGo");
  22. static void ffi_callback (ffi_cif *, void *, void **, void *)
  23. __asm__ ("reflect.ffi_callback");
  24. static void
  25. ffi_callback (ffi_cif* cif __attribute__ ((unused)), void *results,
  26. void **args, void *closure)
  27. {
  28. Location locs[8];
  29. int n;
  30. int i;
  31. /* This function is called from some series of FFI closure functions
  32. called by a Go function. We want to see whether the caller of
  33. the closure functions can recover. Look up the stack and skip
  34. the FFI functions. */
  35. n = runtime_callers (1, &locs[0], sizeof locs / sizeof locs[0], true);
  36. for (i = 0; i < n; i++)
  37. {
  38. const byte *name;
  39. if (locs[i].function.len == 0)
  40. continue;
  41. if (locs[i].function.len < 4)
  42. break;
  43. name = locs[i].function.str;
  44. if (name[0] != 'f' || name[1] != 'f' || name[2] != 'i' || name[3] != '_')
  45. break;
  46. }
  47. if (i < n)
  48. __go_makefunc_ffi_can_recover (locs + i, n - i);
  49. FFICallbackGo(results, args, closure);
  50. if (i < n)
  51. __go_makefunc_returning ();
  52. }
  53. /* Allocate an FFI closure and arrange to call ffi_callback. */
  54. void
  55. makeFuncFFI(const struct __go_func_type *ftyp, void *impl)
  56. {
  57. ffi_cif *cif;
  58. cif = (ffi_cif *) __go_alloc (sizeof (ffi_cif));
  59. __go_func_to_cif (ftyp, 0, 0, cif);
  60. ffi_prep_go_closure(impl, cif, ffi_callback);
  61. }
  62. #else /* !defined(USE_LIBFFI_CLOSURES) */
  63. void
  64. makeFuncFFI(const struct __go_func_type *ftyp __attribute__ ((unused)),
  65. void *impl __attribute__ ((unused)))
  66. {
  67. runtime_panicstring ("libgo built without FFI does not support "
  68. "reflect.MakeFunc");
  69. }
  70. #endif