Fix bootstrap/PR63632
[official-gcc.git] / libgo / go / reflect / makefunc_ffi_c.c
bloba3dfd4acd2c3ad1cff08175633f0d52087d4a0b5
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.
5 #include "runtime.h"
6 #include "go-type.h"
7 #include "go-panic.h"
9 #ifdef USE_LIBFFI
11 #include "go-ffi.h"
13 #if FFI_CLOSURES
14 #define USE_LIBFFI_CLOSURES
15 #endif
17 #endif /* defined(USE_LIBFFI) */
19 /* Declare C functions with the names used to call from Go. */
21 struct ffi_ret {
22 void *code;
23 void *data;
24 void *cif;
27 struct ffi_ret ffi(const struct __go_func_type *ftyp, FuncVal *callback)
28 __asm__ (GOSYM_PREFIX "reflect.ffi");
30 void ffiFree(void *data)
31 __asm__ (GOSYM_PREFIX "reflect.ffiFree");
33 #ifdef USE_LIBFFI_CLOSURES
35 /* The function that we pass to ffi_prep_closure_loc. This calls the
36 Go callback function (passed in user_data) with the pointer to the
37 arguments and the results area. */
39 static void ffi_callback (ffi_cif *, void *, void **, void *)
40 __asm__ ("reflect.ffi_callback");
42 static void
43 ffi_callback (ffi_cif* cif __attribute__ ((unused)), void *results,
44 void **args, void *user_data)
46 Location locs[8];
47 int n;
48 int i;
49 FuncVal *fv;
50 void (*f) (void *, void *);
52 /* This function is called from some series of FFI closure functions
53 called by a Go function. We want to see whether the caller of
54 the closure functions can recover. Look up the stack and skip
55 the FFI functions. */
56 n = runtime_callers (1, &locs[0], sizeof locs / sizeof locs[0], true);
57 for (i = 0; i < n; i++)
59 const byte *name;
61 if (locs[i].function.len == 0)
62 continue;
63 if (locs[i].function.len < 4)
64 break;
65 name = locs[i].function.str;
66 if (name[0] != 'f' || name[1] != 'f' || name[2] != 'i' || name[3] != '_')
67 break;
69 if (i < n)
70 __go_makefunc_ffi_can_recover (locs + i, n - i);
72 fv = (FuncVal *) user_data;
73 __go_set_closure (fv);
74 f = (void *) fv->fn;
75 f (args, results);
77 if (i < n)
78 __go_makefunc_returning ();
81 /* Allocate an FFI closure and arrange to call ffi_callback. */
83 struct ffi_ret
84 ffi (const struct __go_func_type *ftyp, FuncVal *callback)
86 ffi_cif *cif;
87 void *code;
88 void *data;
89 struct ffi_ret ret;
91 cif = (ffi_cif *) __go_alloc (sizeof (ffi_cif));
92 __go_func_to_cif (ftyp, 0, 0, cif);
93 data = ffi_closure_alloc (sizeof (ffi_closure), &code);
94 if (data == NULL)
95 runtime_panicstring ("ffi_closure_alloc failed");
96 if (ffi_prep_closure_loc (data, cif, ffi_callback, callback, code)
97 != FFI_OK)
98 runtime_panicstring ("ffi_prep_closure_loc failed");
99 ret.code = code;
100 ret.data = data;
101 ret.cif = cif;
102 return ret;
105 /* Free the FFI closure. */
107 void
108 ffiFree (void *data)
110 ffi_closure_free (data);
113 #else /* !defined(USE_LIBFFI_CLOSURES) */
115 struct ffi_ret
116 ffi(const struct __go_func_type *ftyp, FuncVal *callback)
118 runtime_panicstring ("libgo built without FFI does not support "
119 "reflect.MakeFunc");
122 void ffiFree(void *data)
124 runtime_panicstring ("libgo built without FFI does not support "
125 "reflect.MakeFunc");
128 #endif