gcc/libgo/go/reflect/makefunc_ffi_c.c
Ian Lance Taylor 9d1e3afb54 runtime: rewrite panic/defer code from C to Go
The actual stack unwind code is still in C, but the rest of the code,
    notably all the memory allocation, is now in Go.  The names are changed
    to the names used in the Go 1.7 runtime, but the code is necessarily
    somewhat different.
    
    The __go_makefunc_can_recover function is dropped, as the uses of it
    were removed in https://golang.org/cl/198770044.
    
    Reviewed-on: https://go-review.googlesource.com/33414

From-SVN: r242715
2016-11-22 17:58:04 +00:00

101 lines
2.5 KiB
C

// 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"
#ifdef USE_LIBFFI
#include "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(void *cif, 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. */
extern void FFICallbackGo(void *result, void **args, ffi_go_closure *closure)
__asm__ (GOSYM_PREFIX "reflect.FFICallbackGo");
extern void makefuncfficanrecover(Slice)
__asm__ (GOSYM_PREFIX "runtime.makefuncfficanrecover");
extern void makefuncreturning(void)
__asm__ (GOSYM_PREFIX "runtime.makefuncreturning");
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)
{
Slice s;
s.__values = (void *) &locs[i];
s.__count = n - i;
s.__capacity = n - i;
makefuncfficanrecover (s);
}
FFICallbackGo(results, args, closure);
if (i < n)
makefuncreturning ();
}
/* Allocate an FFI closure and arrange to call ffi_callback. */
void
makeFuncFFI(void *cif, void *impl)
{
ffi_prep_go_closure(impl, (ffi_cif*)cif, ffi_callback);
}
#else /* !defined(USE_LIBFFI_CLOSURES) */
void
makeFuncFFI(void *cif __attribute__ ((unused)),
void *impl __attribute__ ((unused)))
{
runtime_panicstring ("libgo built without FFI does not support "
"reflect.MakeFunc");
}
#endif