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

     1  /* go-ffi.c -- convert Go type description to libffi.
     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  
    16  #ifdef USE_LIBFFI
    17  
    18  #include "ffi.h"
    19  
    20  /* The functions in this file are only called from reflect_call and
    21     reflect.ffi.  As these functions call libffi functions, which will
    22     be compiled without -fsplit-stack, they will always run with a
    23     large stack.  */
    24  
    25  static ffi_type *go_array_to_ffi (const struct __go_array_type *)
    26    __attribute__ ((no_split_stack));
    27  static ffi_type *go_slice_to_ffi (const struct __go_slice_type *)
    28    __attribute__ ((no_split_stack));
    29  static ffi_type *go_struct_to_ffi (const struct __go_struct_type *)
    30    __attribute__ ((no_split_stack));
    31  static ffi_type *go_string_to_ffi (void) __attribute__ ((no_split_stack));
    32  static ffi_type *go_interface_to_ffi (void) __attribute__ ((no_split_stack));
    33  static ffi_type *go_type_to_ffi (const struct __go_type_descriptor *)
    34    __attribute__ ((no_split_stack));
    35  static ffi_type *go_func_return_ffi (const struct __go_func_type *)
    36    __attribute__ ((no_split_stack));
    37  
    38  /* Return an ffi_type for a Go array type.  The libffi library does
    39     not have any builtin support for passing arrays as values.  We work
    40     around this by pretending that the array is a struct.  */
    41  
    42  static ffi_type *
    43  go_array_to_ffi (const struct __go_array_type *descriptor)
    44  {
    45    ffi_type *ret;
    46    uintptr_t len;
    47    ffi_type *element;
    48    uintptr_t i;
    49  
    50    ret = (ffi_type *) __go_alloc (sizeof (ffi_type));
    51    ret->type = FFI_TYPE_STRUCT;
    52    len = descriptor->__len;
    53    if (len == 0)
    54      {
    55        /* The libffi library won't accept an empty struct.  */
    56        ret->elements = (ffi_type **) __go_alloc (2 * sizeof (ffi_type *));
    57        ret->elements[0] = &ffi_type_void;
    58        ret->elements[1] = NULL;
    59        return ret;
    60      }
    61    ret->elements = (ffi_type **) __go_alloc ((len + 1) * sizeof (ffi_type *));
    62    element = go_type_to_ffi (descriptor->__element_type);
    63    for (i = 0; i < len; ++i)
    64      ret->elements[i] = element;
    65    ret->elements[len] = NULL;
    66    return ret;
    67  }
    68  
    69  /* Return an ffi_type for a Go slice type.  This describes the
    70     __go_open_array type defines in array.h.  */
    71  
    72  static ffi_type *
    73  go_slice_to_ffi (
    74      const struct __go_slice_type *descriptor __attribute__ ((unused)))
    75  {
    76    ffi_type *ret;
    77    ffi_type *ffi_intgo;
    78  
    79    ret = (ffi_type *) __go_alloc (sizeof (ffi_type));
    80    ret->type = FFI_TYPE_STRUCT;
    81    ret->elements = (ffi_type **) __go_alloc (4 * sizeof (ffi_type *));
    82    ret->elements[0] = &ffi_type_pointer;
    83    ffi_intgo = sizeof (intgo) == 4 ? &ffi_type_sint32 : &ffi_type_sint64;
    84    ret->elements[1] = ffi_intgo;
    85    ret->elements[2] = ffi_intgo;
    86    ret->elements[3] = NULL;
    87    return ret;
    88  }
    89  
    90  /* Return an ffi_type for a Go struct type.  */
    91  
    92  static ffi_type *
    93  go_struct_to_ffi (const struct __go_struct_type *descriptor)
    94  {
    95    ffi_type *ret;
    96    int field_count;
    97    const struct __go_struct_field *fields;
    98    int i;
    99  
   100    field_count = descriptor->__fields.__count;
   101    ret = (ffi_type *) __go_alloc (sizeof (ffi_type));
   102    ret->type = FFI_TYPE_STRUCT;
   103    if (field_count == 0)
   104      {
   105        /* The libffi library won't accept an empty struct.  */
   106        ret->elements = (ffi_type **) __go_alloc (2 * sizeof (ffi_type *));
   107        ret->elements[0] = &ffi_type_void;
   108        ret->elements[1] = NULL;
   109        return ret;
   110      }
   111    fields = (const struct __go_struct_field *) descriptor->__fields.__values;
   112    ret->elements = (ffi_type **) __go_alloc ((field_count + 1)
   113  					    * sizeof (ffi_type *));
   114    for (i = 0; i < field_count; ++i)
   115      ret->elements[i] = go_type_to_ffi (fields[i].__type);
   116    ret->elements[field_count] = NULL;
   117    return ret;
   118  }
   119  
   120  /* Return an ffi_type for a Go string type.  This describes the String
   121     struct.  */
   122  
   123  static ffi_type *
   124  go_string_to_ffi (void)
   125  {
   126    ffi_type *ret;
   127    ffi_type *ffi_intgo;
   128  
   129    ret = (ffi_type *) __go_alloc (sizeof (ffi_type));
   130    ret->type = FFI_TYPE_STRUCT;
   131    ret->elements = (ffi_type **) __go_alloc (3 * sizeof (ffi_type *));
   132    ret->elements[0] = &ffi_type_pointer;
   133    ffi_intgo = sizeof (intgo) == 4 ? &ffi_type_sint32 : &ffi_type_sint64;
   134    ret->elements[1] = ffi_intgo;
   135    ret->elements[2] = NULL;
   136    return ret;
   137  }
   138  
   139  /* Return an ffi_type for a Go interface type.  This describes the
   140     __go_interface and __go_empty_interface structs.  */
   141  
   142  static ffi_type *
   143  go_interface_to_ffi (void)
   144  {
   145    ffi_type *ret;
   146  
   147    ret = (ffi_type *) __go_alloc (sizeof (ffi_type));
   148    ret->type = FFI_TYPE_STRUCT;
   149    ret->elements = (ffi_type **) __go_alloc (3 * sizeof (ffi_type *));
   150    ret->elements[0] = &ffi_type_pointer;
   151    ret->elements[1] = &ffi_type_pointer;
   152    ret->elements[2] = NULL;
   153    return ret;
   154  }
   155  
   156  
   157  #ifndef FFI_TARGET_HAS_COMPLEX_TYPE
   158  /* If libffi hasn't been updated for this target to support complex,
   159     pretend complex is a structure.  Warning: This does not work for
   160     all ABIs.  Eventually libffi should be updated for all targets
   161     and this should go away.  */
   162  
   163  static ffi_type *go_complex_to_ffi (ffi_type *)
   164    __attribute__ ((no_split_stack));
   165  
   166  static ffi_type *
   167  go_complex_to_ffi (ffi_type *float_type)
   168  {
   169    ffi_type *ret;
   170  
   171    ret = (ffi_type *) __go_alloc (sizeof (ffi_type));
   172    ret->type = FFI_TYPE_STRUCT;
   173    ret->elements = (ffi_type **) __go_alloc (3 * sizeof (ffi_type *));
   174    ret->elements[0] = float_type;
   175    ret->elements[1] = float_type;
   176    ret->elements[2] = NULL;
   177    return ret;
   178  }
   179  #endif
   180  
   181  /* Return an ffi_type for a type described by a
   182     __go_type_descriptor.  */
   183  
   184  static ffi_type *
   185  go_type_to_ffi (const struct __go_type_descriptor *descriptor)
   186  {
   187    switch (descriptor->__code & GO_CODE_MASK)
   188      {
   189      case GO_BOOL:
   190        if (sizeof (_Bool) == 1)
   191  	return &ffi_type_uint8;
   192        else if (sizeof (_Bool) == sizeof (int))
   193  	return &ffi_type_uint;
   194        abort ();
   195      case GO_FLOAT32:
   196        if (sizeof (float) == 4)
   197  	return &ffi_type_float;
   198        abort ();
   199      case GO_FLOAT64:
   200        if (sizeof (double) == 8)
   201  	return &ffi_type_double;
   202        abort ();
   203      case GO_COMPLEX64:
   204        if (sizeof (float) == 4)
   205  	{
   206  #ifdef FFI_TARGET_HAS_COMPLEX_TYPE
   207  	  return &ffi_type_complex_float;
   208  #else
   209  	  return go_complex_to_ffi (&ffi_type_float);
   210  #endif
   211  	}
   212        abort ();
   213      case GO_COMPLEX128:
   214        if (sizeof (double) == 8)
   215  	{
   216  #ifdef FFI_TARGET_HAS_COMPLEX_TYPE
   217  	  return &ffi_type_complex_double;
   218  #else
   219  	  return go_complex_to_ffi (&ffi_type_double);
   220  #endif
   221  	}
   222        abort ();
   223      case GO_INT16:
   224        return &ffi_type_sint16;
   225      case GO_INT32:
   226        return &ffi_type_sint32;
   227      case GO_INT64:
   228        return &ffi_type_sint64;
   229      case GO_INT8:
   230        return &ffi_type_sint8;
   231      case GO_INT:
   232        return sizeof (intgo) == 4 ? &ffi_type_sint32 : &ffi_type_sint64;
   233      case GO_UINT16:
   234        return &ffi_type_uint16;
   235      case GO_UINT32:
   236        return &ffi_type_uint32;
   237      case GO_UINT64:
   238        return &ffi_type_uint64;
   239      case GO_UINT8:
   240        return &ffi_type_uint8;
   241      case GO_UINT:
   242        return sizeof (uintgo) == 4 ? &ffi_type_uint32 : &ffi_type_uint64;
   243      case GO_UINTPTR:
   244        if (sizeof (void *) == 2)
   245  	return &ffi_type_uint16;
   246        else if (sizeof (void *) == 4)
   247  	return &ffi_type_uint32;
   248        else if (sizeof (void *) == 8)
   249  	return &ffi_type_uint64;
   250        abort ();
   251      case GO_ARRAY:
   252        return go_array_to_ffi ((const struct __go_array_type *) descriptor);
   253      case GO_SLICE:
   254        return go_slice_to_ffi ((const struct __go_slice_type *) descriptor);
   255      case GO_STRUCT:
   256        return go_struct_to_ffi ((const struct __go_struct_type *) descriptor);
   257      case GO_STRING:
   258        return go_string_to_ffi ();
   259      case GO_INTERFACE:
   260        return go_interface_to_ffi ();
   261      case GO_CHAN:
   262      case GO_FUNC:
   263      case GO_MAP:
   264      case GO_PTR:
   265      case GO_UNSAFE_POINTER:
   266        /* These types are always pointers, and for FFI purposes nothing
   267  	 else matters.  */
   268        return &ffi_type_pointer;
   269      default:
   270        abort ();
   271      }
   272  }
   273  
   274  /* Return the return type for a function, given the number of out
   275     parameters and their types.  */
   276  
   277  static ffi_type *
   278  go_func_return_ffi (const struct __go_func_type *func)
   279  {
   280    int count;
   281    const struct __go_type_descriptor **types;
   282    ffi_type *ret;
   283    int i;
   284  
   285    count = func->__out.__count;
   286    if (count == 0)
   287      return &ffi_type_void;
   288  
   289    types = (const struct __go_type_descriptor **) func->__out.__values;
   290  
   291    if (count == 1)
   292      return go_type_to_ffi (types[0]);
   293  
   294    ret = (ffi_type *) __go_alloc (sizeof (ffi_type));
   295    ret->type = FFI_TYPE_STRUCT;
   296    ret->elements = (ffi_type **) __go_alloc ((count + 1) * sizeof (ffi_type *));
   297    for (i = 0; i < count; ++i)
   298      ret->elements[i] = go_type_to_ffi (types[i]);
   299    ret->elements[count] = NULL;
   300    return ret;
   301  }
   302  
   303  /* Build an ffi_cif structure for a function described by a
   304     __go_func_type structure.  */
   305  
   306  void
   307  __go_func_to_cif (const struct __go_func_type *func, _Bool is_interface,
   308  		_Bool is_method, ffi_cif *cif)
   309  {
   310    int num_params;
   311    const struct __go_type_descriptor **in_types;
   312    size_t num_args;
   313    ffi_type **args;
   314    int off;
   315    int i;
   316    ffi_type *rettype;
   317    ffi_status status;
   318  
   319    num_params = func->__in.__count;
   320    in_types = ((const struct __go_type_descriptor **)
   321  	      func->__in.__values);
   322  
   323    num_args = num_params + (is_interface ? 1 : 0);
   324    args = (ffi_type **) __go_alloc (num_args * sizeof (ffi_type *));
   325    i = 0;
   326    off = 0;
   327    if (is_interface)
   328      {
   329        args[0] = &ffi_type_pointer;
   330        off = 1;
   331      }
   332    else if (is_method)
   333      {
   334        args[0] = &ffi_type_pointer;
   335        i = 1;
   336      }
   337    for (; i < num_params; ++i)
   338      args[i + off] = go_type_to_ffi (in_types[i]);
   339  
   340    rettype = go_func_return_ffi (func);
   341  
   342    status = ffi_prep_cif (cif, FFI_DEFAULT_ABI, num_args, rettype, args);
   343    __go_assert (status == FFI_OK);
   344  }
   345  
   346  #endif /* defined(USE_LIBFFI) */