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