github.com/llvm-mirror/llgo@v0.0.0-20190322182713-bf6f0a60fce1/third_party/gofrontend/libgo/go/reflect/makefunc_ffi_c.c (about) 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 5 #include "runtime.h" 6 #include "go-type.h" 7 #include "go-panic.h" 8 9 #ifdef USE_LIBFFI 10 11 #include "go-ffi.h" 12 13 #if FFI_GO_CLOSURES 14 #define USE_LIBFFI_CLOSURES 15 #endif 16 17 #endif /* defined(USE_LIBFFI) */ 18 19 /* Declare C functions with the names used to call from Go. */ 20 21 void makeFuncFFI(const struct __go_func_type *ftyp, void *impl) 22 __asm__ (GOSYM_PREFIX "reflect.makeFuncFFI"); 23 24 #ifdef USE_LIBFFI_CLOSURES 25 26 /* The function that we pass to ffi_prep_closure_loc. This calls the Go 27 function ffiCall with the pointer to the arguments, the results area, 28 and the closure structure. */ 29 30 void FFICallbackGo(void *result, void **args, ffi_go_closure *closure) 31 __asm__ (GOSYM_PREFIX "reflect.FFICallbackGo"); 32 33 static void ffi_callback (ffi_cif *, void *, void **, void *) 34 __asm__ ("reflect.ffi_callback"); 35 36 static void 37 ffi_callback (ffi_cif* cif __attribute__ ((unused)), void *results, 38 void **args, void *closure) 39 { 40 Location locs[8]; 41 int n; 42 int i; 43 44 /* This function is called from some series of FFI closure functions 45 called by a Go function. We want to see whether the caller of 46 the closure functions can recover. Look up the stack and skip 47 the FFI functions. */ 48 n = runtime_callers (1, &locs[0], sizeof locs / sizeof locs[0], true); 49 for (i = 0; i < n; i++) 50 { 51 const byte *name; 52 53 if (locs[i].function.len == 0) 54 continue; 55 if (locs[i].function.len < 4) 56 break; 57 name = locs[i].function.str; 58 if (name[0] != 'f' || name[1] != 'f' || name[2] != 'i' || name[3] != '_') 59 break; 60 } 61 if (i < n) 62 __go_makefunc_ffi_can_recover (locs + i, n - i); 63 64 FFICallbackGo(results, args, closure); 65 66 if (i < n) 67 __go_makefunc_returning (); 68 } 69 70 /* Allocate an FFI closure and arrange to call ffi_callback. */ 71 72 void 73 makeFuncFFI(const struct __go_func_type *ftyp, void *impl) 74 { 75 ffi_cif *cif; 76 77 cif = (ffi_cif *) __go_alloc (sizeof (ffi_cif)); 78 __go_func_to_cif (ftyp, 0, 0, cif); 79 80 ffi_prep_go_closure(impl, cif, ffi_callback); 81 } 82 83 #else /* !defined(USE_LIBFFI_CLOSURES) */ 84 85 void 86 makeFuncFFI(const struct __go_func_type *ftyp __attribute__ ((unused)), 87 void *impl __attribute__ ((unused))) 88 { 89 runtime_panicstring ("libgo built without FFI does not support " 90 "reflect.MakeFunc"); 91 } 92 93 #endif