github.com/llvm-mirror/llgo@v0.0.0-20190322182713-bf6f0a60fce1/third_party/gofrontend/libgo/runtime/go-reflect-call.c (about)

     1  /* go-reflect-call.c -- call reflection support for Go.
     2  
     3     Copyright 2009 The Go Authors. All rights reserved.
     4     Use of this source code is governed by a BSD-style
     5     license that can be found in the LICENSE file.  */
     6  
     7  #include <stdio.h>
     8  #include <stdint.h>
     9  #include <stdlib.h>
    10  
    11  #include "runtime.h"
    12  #include "go-alloc.h"
    13  #include "go-assert.h"
    14  #include "go-type.h"
    15  #include "go-ffi.h"
    16  
    17  #if defined(USE_LIBFFI) && FFI_GO_CLOSURES
    18  
    19  /* The functions in this file are only called from reflect_call.  As
    20     reflect_call calls a libffi function, which will be compiled
    21     without -fsplit-stack, it will always run with a large stack.  */
    22  
    23  static size_t go_results_size (const struct __go_func_type *)
    24    __attribute__ ((no_split_stack));
    25  static void go_set_results (const struct __go_func_type *, unsigned char *,
    26  			    void **)
    27    __attribute__ ((no_split_stack));
    28  
    29  /* Get the total size required for the result parameters of a
    30     function.  */
    31  
    32  static size_t
    33  go_results_size (const struct __go_func_type *func)
    34  {
    35    int count;
    36    const struct __go_type_descriptor **types;
    37    size_t off;
    38    size_t maxalign;
    39    int i;
    40  
    41    count = func->__out.__count;
    42    if (count == 0)
    43      return 0;
    44  
    45    types = (const struct __go_type_descriptor **) func->__out.__values;
    46  
    47    /* A single integer return value is always promoted to a full
    48       word.  */
    49    if (count == 1)
    50      {
    51        switch (types[0]->__code & GO_CODE_MASK)
    52  	{
    53  	case GO_BOOL:
    54  	case GO_INT8:
    55  	case GO_INT16:
    56  	case GO_INT32:
    57  	case GO_UINT8:
    58  	case GO_UINT16:
    59  	case GO_UINT32:
    60  	case GO_INT:
    61  	case GO_UINT:
    62  	  return sizeof (ffi_arg);
    63  
    64  	default:
    65  	  break;
    66  	}
    67      }
    68  
    69    off = 0;
    70    maxalign = 0;
    71    for (i = 0; i < count; ++i)
    72      {
    73        size_t align;
    74  
    75        align = types[i]->__field_align;
    76        if (align > maxalign)
    77  	maxalign = align;
    78        off = (off + align - 1) & ~ (align - 1);
    79        off += types[i]->__size;
    80      }
    81  
    82    off = (off + maxalign - 1) & ~ (maxalign - 1);
    83  
    84    // The libffi library doesn't understand a struct with no fields.
    85    // We generate a struct with a single field of type void.  When used
    86    // as a return value, libffi will think that requires a byte.
    87    if (off == 0)
    88      off = 1;
    89  
    90    return off;
    91  }
    92  
    93  /* Copy the results of calling a function via FFI from CALL_RESULT
    94     into the addresses in RESULTS.  */
    95  
    96  static void
    97  go_set_results (const struct __go_func_type *func, unsigned char *call_result,
    98  		void **results)
    99  {
   100    int count;
   101    const struct __go_type_descriptor **types;
   102    size_t off;
   103    int i;
   104  
   105    count = func->__out.__count;
   106    if (count == 0)
   107      return;
   108  
   109    types = (const struct __go_type_descriptor **) func->__out.__values;
   110  
   111    /* A single integer return value is always promoted to a full
   112       word.  */
   113    if (count == 1)
   114      {
   115        switch (types[0]->__code & GO_CODE_MASK)
   116  	{
   117  	case GO_BOOL:
   118  	case GO_INT8:
   119  	case GO_INT16:
   120  	case GO_INT32:
   121  	case GO_UINT8:
   122  	case GO_UINT16:
   123  	case GO_UINT32:
   124  	case GO_INT:
   125  	case GO_UINT:
   126  	  {
   127  	    union
   128  	    {
   129  	      unsigned char buf[sizeof (ffi_arg)];
   130  	      ffi_arg v;
   131  	    } u;
   132  	    ffi_arg v;
   133  
   134  	    __builtin_memcpy (&u.buf, call_result, sizeof (ffi_arg));
   135  	    v = u.v;
   136  
   137  	    switch (types[0]->__size)
   138  	      {
   139  	      case 1:
   140  		{
   141  		  uint8_t b;
   142  
   143  		  b = (uint8_t) v;
   144  		  __builtin_memcpy (results[0], &b, 1);
   145  		}
   146  		break;
   147  
   148  	      case 2:
   149  		{
   150  		  uint16_t s;
   151  
   152  		  s = (uint16_t) v;
   153  		  __builtin_memcpy (results[0], &s, 2);
   154  		}
   155  		break;
   156  
   157  	      case 4:
   158  		{
   159  		  uint32_t w;
   160  
   161  		  w = (uint32_t) v;
   162  		  __builtin_memcpy (results[0], &w, 4);
   163  		}
   164  		break;
   165  
   166  	      case 8:
   167  		{
   168  		  uint64_t d;
   169  
   170  		  d = (uint64_t) v;
   171  		  __builtin_memcpy (results[0], &d, 8);
   172  		}
   173  		break;
   174  
   175  	      default:
   176  		abort ();
   177  	      }
   178  	  }
   179  	  return;
   180  
   181  	default:
   182  	  break;
   183  	}
   184      }
   185  
   186    off = 0;
   187    for (i = 0; i < count; ++i)
   188      {
   189        size_t align;
   190        size_t size;
   191  
   192        align = types[i]->__field_align;
   193        size = types[i]->__size;
   194        off = (off + align - 1) & ~ (align - 1);
   195        __builtin_memcpy (results[i], call_result + off, size);
   196        off += size;
   197      }
   198  }
   199  
   200  /* Call a function.  The type of the function is FUNC_TYPE, and the
   201     closure is FUNC_VAL.  PARAMS is an array of parameter addresses.
   202     RESULTS is an array of result addresses.
   203  
   204     If IS_INTERFACE is true this is a call to an interface method and
   205     the first argument is the receiver, which is always a pointer.
   206     This argument, the receiver, is not described in FUNC_TYPE.
   207  
   208     If IS_METHOD is true this is a call to a method expression.  The
   209     first argument is the receiver.  It is described in FUNC_TYPE, but
   210     regardless of FUNC_TYPE, it is passed as a pointer.  */
   211  
   212  void
   213  reflect_call (const struct __go_func_type *func_type, FuncVal *func_val,
   214  	      _Bool is_interface, _Bool is_method, void **params,
   215  	      void **results)
   216  {
   217    ffi_cif cif;
   218    unsigned char *call_result;
   219  
   220    __go_assert ((func_type->__common.__code & GO_CODE_MASK) == GO_FUNC);
   221    __go_func_to_cif (func_type, is_interface, is_method, &cif);
   222  
   223    call_result = (unsigned char *) malloc (go_results_size (func_type));
   224  
   225    ffi_call_go (&cif, func_val->fn, call_result, params, func_val);
   226  
   227    /* Some day we may need to free result values if RESULTS is
   228       NULL.  */
   229    if (results != NULL)
   230      go_set_results (func_type, call_result, results);
   231  
   232    free (call_result);
   233  }
   234  
   235  #else /* !defined(USE_LIBFFI) */
   236  
   237  void
   238  reflect_call (const struct __go_func_type *func_type __attribute__ ((unused)),
   239  	      FuncVal *func_val __attribute__ ((unused)),
   240  	      _Bool is_interface __attribute__ ((unused)),
   241  	      _Bool is_method __attribute__ ((unused)),
   242  	      void **params __attribute__ ((unused)),
   243  	      void **results __attribute__ ((unused)))
   244  {
   245    /* Without FFI there is nothing we can do.  */
   246    runtime_throw("libgo built without FFI does not support "
   247  		"reflect.Call or runtime.SetFinalizer");
   248  }
   249  
   250  #endif /* !defined(USE_LIBFFI) */