(root)/
gcc-13.2.0/
libffi/
src/
java_raw_api.c
       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  	    FFI_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  	  FFI_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  	    FFI_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 */