github.com/prattmic/llgo-embedded@v0.0.0-20150820070356-41cfecea0e1e/third_party/gofrontend/libffi/src/java_raw_api.c (about)

     1  /* -----------------------------------------------------------------------
     2     java_raw_api.c - Copyright (c) 1999, 2007, 2008  Red Hat, Inc.
     3  
     4     Cloned from raw_api.c
     5  
     6     Raw_api.c author: Kresten Krab Thorup <krab@gnu.org>
     7     Java_raw_api.c author: Hans-J. Boehm <hboehm@hpl.hp.com>
     8  
     9     $Id $
    10  
    11     Permission is hereby granted, free of charge, to any person obtaining
    12     a copy of this software and associated documentation files (the
    13     ``Software''), to deal in the Software without restriction, including
    14     without limitation the rights to use, copy, modify, merge, publish,
    15     distribute, sublicense, and/or sell copies of the Software, and to
    16     permit persons to whom the Software is furnished to do so, subject to
    17     the following conditions:
    18  
    19     The above copyright notice and this permission notice shall be included
    20     in all copies or substantial portions of the Software.
    21  
    22     THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
    23     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    24     MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    25     NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
    26     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
    27     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    28     OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
    29     DEALINGS IN THE SOFTWARE.
    30     ----------------------------------------------------------------------- */
    31  
    32  /* This defines a Java- and 64-bit specific variant of the raw API.	*/
    33  /* It assumes that "raw" argument blocks look like Java stacks on a	*/
    34  /* 64-bit machine.  Arguments that can be stored in a single stack	*/
    35  /* stack slots (longs, doubles) occupy 128 bits, but only the first	*/
    36  /* 64 bits are actually used.						*/
    37  
    38  #include <ffi.h>
    39  #include <ffi_common.h>
    40  #include <stdlib.h>
    41  
    42  #if !defined(NO_JAVA_RAW_API)
    43  
    44  size_t
    45  ffi_java_raw_size (ffi_cif *cif)
    46  {
    47    size_t result = 0;
    48    int i;
    49  
    50    ffi_type **at = cif->arg_types;
    51  
    52    for (i = cif->nargs-1; i >= 0; i--, at++)
    53      {
    54        switch((*at) -> type) {
    55  	case FFI_TYPE_UINT64:
    56  	case FFI_TYPE_SINT64:
    57  	case FFI_TYPE_DOUBLE:
    58  	  result += 2 * FFI_SIZEOF_JAVA_RAW;
    59  	  break;
    60  	case FFI_TYPE_STRUCT:
    61  	  /* No structure parameters in Java.	*/
    62  	  abort();
    63  	case FFI_TYPE_COMPLEX:
    64  	  /* Not supported yet.  */
    65  	  abort();
    66  	default:
    67  	  result += FFI_SIZEOF_JAVA_RAW;
    68        }
    69      }
    70  
    71    return result;
    72  }
    73  
    74  
    75  void
    76  ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_java_raw *raw, void **args)
    77  {
    78    unsigned i;
    79    ffi_type **tp = cif->arg_types;
    80  
    81  #if WORDS_BIGENDIAN
    82  
    83    for (i = 0; i < cif->nargs; i++, tp++, args++)
    84      {
    85        switch ((*tp)->type)
    86  	{
    87  	case FFI_TYPE_UINT8:
    88  	case FFI_TYPE_SINT8:
    89  	  *args = (void*) ((char*)(raw++) + 3);
    90  	  break;
    91  
    92  	case FFI_TYPE_UINT16:
    93  	case FFI_TYPE_SINT16:
    94  	  *args = (void*) ((char*)(raw++) + 2);
    95  	  break;
    96  
    97  #if FFI_SIZEOF_JAVA_RAW == 8
    98  	case FFI_TYPE_UINT64:
    99  	case FFI_TYPE_SINT64:
   100  	case FFI_TYPE_DOUBLE:
   101  	  *args = (void *)raw;
   102  	  raw += 2;
   103  	  break;
   104  #endif
   105  
   106  	case FFI_TYPE_POINTER:
   107  	  *args = (void*) &(raw++)->ptr;
   108  	  break;
   109  
   110  	case FFI_TYPE_COMPLEX:
   111  	  /* Not supported yet.  */
   112  	  abort();
   113  
   114  	default:
   115  	  *args = raw;
   116  	  raw +=
   117  	    ALIGN ((*tp)->size, sizeof(ffi_java_raw)) / sizeof(ffi_java_raw);
   118  	}
   119      }
   120  
   121  #else /* WORDS_BIGENDIAN */
   122  
   123  #if !PDP
   124  
   125    /* then assume little endian */
   126    for (i = 0; i < cif->nargs; i++, tp++, args++)
   127      {
   128  #if FFI_SIZEOF_JAVA_RAW == 8
   129        switch((*tp)->type) {
   130  	case FFI_TYPE_UINT64:
   131  	case FFI_TYPE_SINT64:
   132  	case FFI_TYPE_DOUBLE:
   133  	  *args = (void*) raw;
   134  	  raw += 2;
   135  	  break;
   136  	case FFI_TYPE_COMPLEX:
   137  	  /* Not supported yet.  */
   138  	  abort();
   139  	default:
   140  	  *args = (void*) raw++;
   141        }
   142  #else /* FFI_SIZEOF_JAVA_RAW != 8 */
   143  	*args = (void*) raw;
   144  	raw +=
   145  	  ALIGN ((*tp)->size, sizeof(ffi_java_raw)) / sizeof(ffi_java_raw);
   146  #endif /* FFI_SIZEOF_JAVA_RAW == 8 */
   147      }
   148  
   149  #else
   150  #error "pdp endian not supported"
   151  #endif /* ! PDP */
   152  
   153  #endif /* WORDS_BIGENDIAN */
   154  }
   155  
   156  void
   157  ffi_java_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_java_raw *raw)
   158  {
   159    unsigned i;
   160    ffi_type **tp = cif->arg_types;
   161  
   162    for (i = 0; i < cif->nargs; i++, tp++, args++)
   163      {
   164        switch ((*tp)->type)
   165  	{
   166  	case FFI_TYPE_UINT8:
   167  #if WORDS_BIGENDIAN
   168  	  *(UINT32*)(raw++) = *(UINT8*) (*args);
   169  #else
   170  	  (raw++)->uint = *(UINT8*) (*args);
   171  #endif
   172  	  break;
   173  
   174  	case FFI_TYPE_SINT8:
   175  #if WORDS_BIGENDIAN
   176  	  *(SINT32*)(raw++) = *(SINT8*) (*args);
   177  #else
   178  	  (raw++)->sint = *(SINT8*) (*args);
   179  #endif
   180  	  break;
   181  
   182  	case FFI_TYPE_UINT16:
   183  #if WORDS_BIGENDIAN
   184  	  *(UINT32*)(raw++) = *(UINT16*) (*args);
   185  #else
   186  	  (raw++)->uint = *(UINT16*) (*args);
   187  #endif
   188  	  break;
   189  
   190  	case FFI_TYPE_SINT16:
   191  #if WORDS_BIGENDIAN
   192  	  *(SINT32*)(raw++) = *(SINT16*) (*args);
   193  #else
   194  	  (raw++)->sint = *(SINT16*) (*args);
   195  #endif
   196  	  break;
   197  
   198  	case FFI_TYPE_UINT32:
   199  #if WORDS_BIGENDIAN
   200  	  *(UINT32*)(raw++) = *(UINT32*) (*args);
   201  #else
   202  	  (raw++)->uint = *(UINT32*) (*args);
   203  #endif
   204  	  break;
   205  
   206  	case FFI_TYPE_SINT32:
   207  #if WORDS_BIGENDIAN
   208  	  *(SINT32*)(raw++) = *(SINT32*) (*args);
   209  #else
   210  	  (raw++)->sint = *(SINT32*) (*args);
   211  #endif
   212  	  break;
   213  
   214  	case FFI_TYPE_FLOAT:
   215  	  (raw++)->flt = *(FLOAT32*) (*args);
   216  	  break;
   217  
   218  #if FFI_SIZEOF_JAVA_RAW == 8
   219  	case FFI_TYPE_UINT64:
   220  	case FFI_TYPE_SINT64:
   221  	case FFI_TYPE_DOUBLE:
   222  	  raw->uint = *(UINT64*) (*args);
   223  	  raw += 2;
   224  	  break;
   225  #endif
   226  
   227  	case FFI_TYPE_POINTER:
   228  	  (raw++)->ptr = **(void***) args;
   229  	  break;
   230  
   231  	default:
   232  #if FFI_SIZEOF_JAVA_RAW == 8
   233  	  FFI_ASSERT(0);	/* Should have covered all cases */
   234  #else
   235  	  memcpy ((void*) raw->data, (void*)*args, (*tp)->size);
   236  	  raw +=
   237  	    ALIGN ((*tp)->size, sizeof(ffi_java_raw)) / sizeof(ffi_java_raw);
   238  #endif
   239  	}
   240      }
   241  }
   242  
   243  #if !FFI_NATIVE_RAW_API
   244  
   245  static void
   246  ffi_java_rvalue_to_raw (ffi_cif *cif, void *rvalue)
   247  {
   248  #if WORDS_BIGENDIAN && FFI_SIZEOF_ARG == 8
   249    switch (cif->rtype->type)
   250      {
   251      case FFI_TYPE_UINT8:
   252      case FFI_TYPE_UINT16:
   253      case FFI_TYPE_UINT32:
   254        *(UINT64 *)rvalue <<= 32;
   255        break;
   256  
   257      case FFI_TYPE_SINT8:
   258      case FFI_TYPE_SINT16:
   259      case FFI_TYPE_SINT32:
   260      case FFI_TYPE_INT:
   261  #if FFI_SIZEOF_JAVA_RAW == 4
   262      case FFI_TYPE_POINTER:
   263  #endif
   264        *(SINT64 *)rvalue <<= 32;
   265        break;
   266  
   267      case FFI_TYPE_COMPLEX:
   268        /* Not supported yet.  */
   269        abort();
   270  
   271      default:
   272        break;
   273      }
   274  #endif
   275  }
   276  
   277  static void
   278  ffi_java_raw_to_rvalue (ffi_cif *cif, void *rvalue)
   279  {
   280  #if WORDS_BIGENDIAN && FFI_SIZEOF_ARG == 8
   281    switch (cif->rtype->type)
   282      {
   283      case FFI_TYPE_UINT8:
   284      case FFI_TYPE_UINT16:
   285      case FFI_TYPE_UINT32:
   286        *(UINT64 *)rvalue >>= 32;
   287        break;
   288  
   289      case FFI_TYPE_SINT8:
   290      case FFI_TYPE_SINT16:
   291      case FFI_TYPE_SINT32:
   292      case FFI_TYPE_INT:
   293        *(SINT64 *)rvalue >>= 32;
   294        break;
   295  
   296      case FFI_TYPE_COMPLEX:
   297        /* Not supported yet.  */
   298        abort();
   299  
   300      default:
   301        break;
   302      }
   303  #endif
   304  }
   305  
   306  /* This is a generic definition of ffi_raw_call, to be used if the
   307   * native system does not provide a machine-specific implementation.
   308   * Having this, allows code to be written for the raw API, without
   309   * the need for system-specific code to handle input in that format;
   310   * these following couple of functions will handle the translation forth
   311   * and back automatically. */
   312  
   313  void ffi_java_raw_call (ffi_cif *cif, void (*fn)(void), void *rvalue,
   314  			ffi_java_raw *raw)
   315  {
   316    void **avalue = (void**) alloca (cif->nargs * sizeof (void*));
   317    ffi_java_raw_to_ptrarray (cif, raw, avalue);
   318    ffi_call (cif, fn, rvalue, avalue);
   319    ffi_java_rvalue_to_raw (cif, rvalue);
   320  }
   321  
   322  #if FFI_CLOSURES		/* base system provides closures */
   323  
   324  static void
   325  ffi_java_translate_args (ffi_cif *cif, void *rvalue,
   326  		    void **avalue, void *user_data)
   327  {
   328    ffi_java_raw *raw = (ffi_java_raw*)alloca (ffi_java_raw_size (cif));
   329    ffi_raw_closure *cl = (ffi_raw_closure*)user_data;
   330  
   331    ffi_java_ptrarray_to_raw (cif, avalue, raw);
   332    (*cl->fun) (cif, rvalue, (ffi_raw*)raw, cl->user_data);
   333    ffi_java_raw_to_rvalue (cif, rvalue);
   334  }
   335  
   336  ffi_status
   337  ffi_prep_java_raw_closure_loc (ffi_java_raw_closure* cl,
   338  			       ffi_cif *cif,
   339  			       void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*),
   340  			       void *user_data,
   341  			       void *codeloc)
   342  {
   343    ffi_status status;
   344  
   345    status = ffi_prep_closure_loc ((ffi_closure*) cl,
   346  				 cif,
   347  				 &ffi_java_translate_args,
   348  				 codeloc,
   349  				 codeloc);
   350    if (status == FFI_OK)
   351      {
   352        cl->fun       = fun;
   353        cl->user_data = user_data;
   354      }
   355  
   356    return status;
   357  }
   358  
   359  /* Again, here is the generic version of ffi_prep_raw_closure, which
   360   * will install an intermediate "hub" for translation of arguments from
   361   * the pointer-array format, to the raw format */
   362  
   363  ffi_status
   364  ffi_prep_java_raw_closure (ffi_java_raw_closure* cl,
   365  			   ffi_cif *cif,
   366  			   void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*),
   367  			   void *user_data)
   368  {
   369    return ffi_prep_java_raw_closure_loc (cl, cif, fun, user_data, cl);
   370  }
   371  
   372  #endif /* FFI_CLOSURES */
   373  #endif /* !FFI_NATIVE_RAW_API */
   374  #endif /* !NO_JAVA_RAW_API */