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