github.com/llvm-mirror/llgo@v0.0.0-20190322182713-bf6f0a60fce1/third_party/gofrontend/libffi/src/raw_api.c (about)

     1  /* -----------------------------------------------------------------------
     2     raw_api.c - Copyright (c) 1999, 2008  Red Hat, Inc.
     3  
     4     Author: Kresten Krab Thorup <krab@gnu.org>
     5  
     6     Permission is hereby granted, free of charge, to any person obtaining
     7     a copy of this software and associated documentation files (the
     8     ``Software''), to deal in the Software without restriction, including
     9     without limitation the rights to use, copy, modify, merge, publish,
    10     distribute, sublicense, and/or sell copies of the Software, and to
    11     permit persons to whom the Software is furnished to do so, subject to
    12     the following conditions:
    13  
    14     The above copyright notice and this permission notice shall be included
    15     in all copies or substantial portions of the Software.
    16  
    17     THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
    18     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    19     MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    20     NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
    21     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
    22     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    23     OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
    24     DEALINGS IN THE SOFTWARE.
    25     ----------------------------------------------------------------------- */
    26  
    27  /* This file defines generic functions for use with the raw api. */
    28  
    29  #include <ffi.h>
    30  #include <ffi_common.h>
    31  
    32  #if !FFI_NO_RAW_API
    33  
    34  size_t
    35  ffi_raw_size (ffi_cif *cif)
    36  {
    37    size_t result = 0;
    38    int i;
    39  
    40    ffi_type **at = cif->arg_types;
    41  
    42    for (i = cif->nargs-1; i >= 0; i--, at++)
    43      {
    44  #if !FFI_NO_STRUCTS
    45        if ((*at)->type == FFI_TYPE_STRUCT)
    46  	result += ALIGN (sizeof (void*), FFI_SIZEOF_ARG);
    47        else
    48  #endif
    49  	result += ALIGN ((*at)->size, FFI_SIZEOF_ARG);
    50      }
    51  
    52    return result;
    53  }
    54  
    55  
    56  void
    57  ffi_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args)
    58  {
    59    unsigned i;
    60    ffi_type **tp = cif->arg_types;
    61  
    62  #if WORDS_BIGENDIAN
    63  
    64    for (i = 0; i < cif->nargs; i++, tp++, args++)
    65      {	  
    66        switch ((*tp)->type)
    67  	{
    68  	case FFI_TYPE_UINT8:
    69  	case FFI_TYPE_SINT8:
    70  	  *args = (void*) ((char*)(raw++) + FFI_SIZEOF_ARG - 1);
    71  	  break;
    72  	  
    73  	case FFI_TYPE_UINT16:
    74  	case FFI_TYPE_SINT16:
    75  	  *args = (void*) ((char*)(raw++) + FFI_SIZEOF_ARG - 2);
    76  	  break;
    77  
    78  #if FFI_SIZEOF_ARG >= 4	  
    79  	case FFI_TYPE_UINT32:
    80  	case FFI_TYPE_SINT32:
    81  	  *args = (void*) ((char*)(raw++) + FFI_SIZEOF_ARG - 4);
    82  	  break;
    83  #endif
    84  	
    85  #if !FFI_NO_STRUCTS  
    86  	case FFI_TYPE_STRUCT:
    87  	  *args = (raw++)->ptr;
    88  	  break;
    89  #endif
    90  
    91  	case FFI_TYPE_COMPLEX:
    92  	  *args = (raw++)->ptr;
    93  	  break;
    94  
    95  	case FFI_TYPE_POINTER:
    96  	  *args = (void*) &(raw++)->ptr;
    97  	  break;
    98  	  
    99  	default:
   100  	  *args = raw;
   101  	  raw += ALIGN ((*tp)->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
   102  	}
   103      }
   104  
   105  #else /* WORDS_BIGENDIAN */
   106  
   107  #if !PDP
   108  
   109    /* then assume little endian */
   110    for (i = 0; i < cif->nargs; i++, tp++, args++)
   111      {	  
   112  #if !FFI_NO_STRUCTS
   113        if ((*tp)->type == FFI_TYPE_STRUCT)
   114  	{
   115  	  *args = (raw++)->ptr;
   116  	}
   117        else
   118  #endif
   119        if ((*tp)->type == FFI_TYPE_COMPLEX)
   120  	{
   121  	  *args = (raw++)->ptr;
   122  	}
   123        else
   124  	{
   125  	  *args = (void*) raw;
   126  	  raw += ALIGN ((*tp)->size, sizeof (void*)) / sizeof (void*);
   127  	}
   128      }
   129  
   130  #else
   131  #error "pdp endian not supported"
   132  #endif /* ! PDP */
   133  
   134  #endif /* WORDS_BIGENDIAN */
   135  }
   136  
   137  void
   138  ffi_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw)
   139  {
   140    unsigned i;
   141    ffi_type **tp = cif->arg_types;
   142  
   143    for (i = 0; i < cif->nargs; i++, tp++, args++)
   144      {	  
   145        switch ((*tp)->type)
   146  	{
   147  	case FFI_TYPE_UINT8:
   148  	  (raw++)->uint = *(UINT8*) (*args);
   149  	  break;
   150  
   151  	case FFI_TYPE_SINT8:
   152  	  (raw++)->sint = *(SINT8*) (*args);
   153  	  break;
   154  
   155  	case FFI_TYPE_UINT16:
   156  	  (raw++)->uint = *(UINT16*) (*args);
   157  	  break;
   158  
   159  	case FFI_TYPE_SINT16:
   160  	  (raw++)->sint = *(SINT16*) (*args);
   161  	  break;
   162  
   163  #if FFI_SIZEOF_ARG >= 4
   164  	case FFI_TYPE_UINT32:
   165  	  (raw++)->uint = *(UINT32*) (*args);
   166  	  break;
   167  
   168  	case FFI_TYPE_SINT32:
   169  	  (raw++)->sint = *(SINT32*) (*args);
   170  	  break;
   171  #endif
   172  
   173  #if !FFI_NO_STRUCTS
   174  	case FFI_TYPE_STRUCT:
   175  	  (raw++)->ptr = *args;
   176  	  break;
   177  #endif
   178  
   179  	case FFI_TYPE_COMPLEX:
   180  	  (raw++)->ptr = *args;
   181  	  break;
   182  
   183  	case FFI_TYPE_POINTER:
   184  	  (raw++)->ptr = **(void***) args;
   185  	  break;
   186  
   187  	default:
   188  	  memcpy ((void*) raw->data, (void*)*args, (*tp)->size);
   189  	  raw += ALIGN ((*tp)->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
   190  	}
   191      }
   192  }
   193  
   194  #if !FFI_NATIVE_RAW_API
   195  
   196  
   197  /* This is a generic definition of ffi_raw_call, to be used if the
   198   * native system does not provide a machine-specific implementation.
   199   * Having this, allows code to be written for the raw API, without
   200   * the need for system-specific code to handle input in that format;
   201   * these following couple of functions will handle the translation forth
   202   * and back automatically. */
   203  
   204  void ffi_raw_call (ffi_cif *cif, void (*fn)(void), void *rvalue, ffi_raw *raw)
   205  {
   206    void **avalue = (void**) alloca (cif->nargs * sizeof (void*));
   207    ffi_raw_to_ptrarray (cif, raw, avalue);
   208    ffi_call (cif, fn, rvalue, avalue);
   209  }
   210  
   211  #if FFI_CLOSURES		/* base system provides closures */
   212  
   213  static void
   214  ffi_translate_args (ffi_cif *cif, void *rvalue,
   215  		    void **avalue, void *user_data)
   216  {
   217    ffi_raw *raw = (ffi_raw*)alloca (ffi_raw_size (cif));
   218    ffi_raw_closure *cl = (ffi_raw_closure*)user_data;
   219  
   220    ffi_ptrarray_to_raw (cif, avalue, raw);
   221    (*cl->fun) (cif, rvalue, raw, cl->user_data);
   222  }
   223  
   224  ffi_status
   225  ffi_prep_raw_closure_loc (ffi_raw_closure* cl,
   226  			  ffi_cif *cif,
   227  			  void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
   228  			  void *user_data,
   229  			  void *codeloc)
   230  {
   231    ffi_status status;
   232  
   233    status = ffi_prep_closure_loc ((ffi_closure*) cl,
   234  				 cif,
   235  				 &ffi_translate_args,
   236  				 codeloc,
   237  				 codeloc);
   238    if (status == FFI_OK)
   239      {
   240        cl->fun       = fun;
   241        cl->user_data = user_data;
   242      }
   243  
   244    return status;
   245  }
   246  
   247  #endif /* FFI_CLOSURES */
   248  #endif /* !FFI_NATIVE_RAW_API */
   249  
   250  #if FFI_CLOSURES
   251  
   252  /* Again, here is the generic version of ffi_prep_raw_closure, which
   253   * will install an intermediate "hub" for translation of arguments from
   254   * the pointer-array format, to the raw format */
   255  
   256  ffi_status
   257  ffi_prep_raw_closure (ffi_raw_closure* cl,
   258  		      ffi_cif *cif,
   259  		      void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
   260  		      void *user_data)
   261  {
   262    return ffi_prep_raw_closure_loc (cl, cif, fun, user_data, cl);
   263  }
   264  
   265  #endif /* FFI_CLOSURES */
   266  
   267  #endif /* !FFI_NO_RAW_API */