Home | History | Annotate | Download | only in src
      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 (at) gnu.org>
      7    Java_raw_api.c author: Hans-J. Boehm <hboehm (at) 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) && !defined(FFI_NO_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 	default:
     64 	  result += FFI_SIZEOF_JAVA_RAW;
     65       }
     66     }
     67 
     68   return result;
     69 }
     70 
     71 
     72 void
     73 ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_java_raw *raw, void **args)
     74 {
     75   unsigned i;
     76   ffi_type **tp = cif->arg_types;
     77 
     78 #if WORDS_BIGENDIAN
     79 
     80   for (i = 0; i < cif->nargs; i++, tp++, args++)
     81     {
     82       switch ((*tp)->type)
     83 	{
     84 	case FFI_TYPE_UINT8:
     85 	case FFI_TYPE_SINT8:
     86 	  *args = (void*) ((char*)(raw++) + 3);
     87 	  break;
     88 
     89 	case FFI_TYPE_UINT16:
     90 	case FFI_TYPE_SINT16:
     91 	  *args = (void*) ((char*)(raw++) + 2);
     92 	  break;
     93 
     94 #if FFI_SIZEOF_JAVA_RAW == 8
     95 	case FFI_TYPE_UINT64:
     96 	case FFI_TYPE_SINT64:
     97 	case FFI_TYPE_DOUBLE:
     98 	  *args = (void *)raw;
     99 	  raw += 2;
    100 	  break;
    101 #endif
    102 
    103 	case FFI_TYPE_POINTER:
    104 	  *args = (void*) &(raw++)->ptr;
    105 	  break;
    106 
    107 	default:
    108 	  *args = raw;
    109 	  raw +=
    110 	    ALIGN ((*tp)->size, sizeof(ffi_java_raw)) / sizeof(ffi_java_raw);
    111 	}
    112     }
    113 
    114 #else /* WORDS_BIGENDIAN */
    115 
    116 #if !PDP
    117 
    118   /* then assume little endian */
    119   for (i = 0; i < cif->nargs; i++, tp++, args++)
    120     {
    121 #if FFI_SIZEOF_JAVA_RAW == 8
    122       switch((*tp)->type) {
    123 	case FFI_TYPE_UINT64:
    124 	case FFI_TYPE_SINT64:
    125 	case FFI_TYPE_DOUBLE:
    126 	  *args = (void*) raw;
    127 	  raw += 2;
    128 	  break;
    129 	default:
    130 	  *args = (void*) raw++;
    131       }
    132 #else /* FFI_SIZEOF_JAVA_RAW != 8 */
    133 	*args = (void*) raw;
    134 	raw +=
    135 	  ALIGN ((*tp)->size, sizeof(ffi_java_raw)) / sizeof(ffi_java_raw);
    136 #endif /* FFI_SIZEOF_JAVA_RAW == 8 */
    137     }
    138 
    139 #else
    140 #error "pdp endian not supported"
    141 #endif /* ! PDP */
    142 
    143 #endif /* WORDS_BIGENDIAN */
    144 }
    145 
    146 void
    147 ffi_java_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_java_raw *raw)
    148 {
    149   unsigned i;
    150   ffi_type **tp = cif->arg_types;
    151 
    152   for (i = 0; i < cif->nargs; i++, tp++, args++)
    153     {
    154       switch ((*tp)->type)
    155 	{
    156 	case FFI_TYPE_UINT8:
    157 #if WORDS_BIGENDIAN
    158 	  *(UINT32*)(raw++) = *(UINT8*) (*args);
    159 #else
    160 	  (raw++)->uint = *(UINT8*) (*args);
    161 #endif
    162 	  break;
    163 
    164 	case FFI_TYPE_SINT8:
    165 #if WORDS_BIGENDIAN
    166 	  *(SINT32*)(raw++) = *(SINT8*) (*args);
    167 #else
    168 	  (raw++)->sint = *(SINT8*) (*args);
    169 #endif
    170 	  break;
    171 
    172 	case FFI_TYPE_UINT16:
    173 #if WORDS_BIGENDIAN
    174 	  *(UINT32*)(raw++) = *(UINT16*) (*args);
    175 #else
    176 	  (raw++)->uint = *(UINT16*) (*args);
    177 #endif
    178 	  break;
    179 
    180 	case FFI_TYPE_SINT16:
    181 #if WORDS_BIGENDIAN
    182 	  *(SINT32*)(raw++) = *(SINT16*) (*args);
    183 #else
    184 	  (raw++)->sint = *(SINT16*) (*args);
    185 #endif
    186 	  break;
    187 
    188 	case FFI_TYPE_UINT32:
    189 #if WORDS_BIGENDIAN
    190 	  *(UINT32*)(raw++) = *(UINT32*) (*args);
    191 #else
    192 	  (raw++)->uint = *(UINT32*) (*args);
    193 #endif
    194 	  break;
    195 
    196 	case FFI_TYPE_SINT32:
    197 #if WORDS_BIGENDIAN
    198 	  *(SINT32*)(raw++) = *(SINT32*) (*args);
    199 #else
    200 	  (raw++)->sint = *(SINT32*) (*args);
    201 #endif
    202 	  break;
    203 
    204 	case FFI_TYPE_FLOAT:
    205 	  (raw++)->flt = *(FLOAT32*) (*args);
    206 	  break;
    207 
    208 #if FFI_SIZEOF_JAVA_RAW == 8
    209 	case FFI_TYPE_UINT64:
    210 	case FFI_TYPE_SINT64:
    211 	case FFI_TYPE_DOUBLE:
    212 	  raw->uint = *(UINT64*) (*args);
    213 	  raw += 2;
    214 	  break;
    215 #endif
    216 
    217 	case FFI_TYPE_POINTER:
    218 	  (raw++)->ptr = **(void***) args;
    219 	  break;
    220 
    221 	default:
    222 #if FFI_SIZEOF_JAVA_RAW == 8
    223 	  FFI_ASSERT(0);	/* Should have covered all cases */
    224 #else
    225 	  memcpy ((void*) raw->data, (void*)*args, (*tp)->size);
    226 	  raw +=
    227 	    ALIGN ((*tp)->size, sizeof(ffi_java_raw)) / sizeof(ffi_java_raw);
    228 #endif
    229 	}
    230     }
    231 }
    232 
    233 #if !FFI_NATIVE_RAW_API
    234 
    235 static void
    236 ffi_java_rvalue_to_raw (ffi_cif *cif, void *rvalue)
    237 {
    238 #if WORDS_BIGENDIAN && FFI_SIZEOF_ARG == 8
    239   switch (cif->rtype->type)
    240     {
    241     case FFI_TYPE_UINT8:
    242     case FFI_TYPE_UINT16:
    243     case FFI_TYPE_UINT32:
    244       *(UINT64 *)rvalue <<= 32;
    245       break;
    246 
    247     case FFI_TYPE_SINT8:
    248     case FFI_TYPE_SINT16:
    249     case FFI_TYPE_SINT32:
    250     case FFI_TYPE_INT:
    251 #if FFI_SIZEOF_JAVA_RAW == 4
    252     case FFI_TYPE_POINTER:
    253 #endif
    254       *(SINT64 *)rvalue <<= 32;
    255       break;
    256 
    257     default:
    258       break;
    259     }
    260 #endif
    261 }
    262 
    263 static void
    264 ffi_java_raw_to_rvalue (ffi_cif *cif, void *rvalue)
    265 {
    266 #if WORDS_BIGENDIAN && FFI_SIZEOF_ARG == 8
    267   switch (cif->rtype->type)
    268     {
    269     case FFI_TYPE_UINT8:
    270     case FFI_TYPE_UINT16:
    271     case FFI_TYPE_UINT32:
    272       *(UINT64 *)rvalue >>= 32;
    273       break;
    274 
    275     case FFI_TYPE_SINT8:
    276     case FFI_TYPE_SINT16:
    277     case FFI_TYPE_SINT32:
    278     case FFI_TYPE_INT:
    279       *(SINT64 *)rvalue >>= 32;
    280       break;
    281 
    282     default:
    283       break;
    284     }
    285 #endif
    286 }
    287 
    288 /* This is a generic definition of ffi_raw_call, to be used if the
    289  * native system does not provide a machine-specific implementation.
    290  * Having this, allows code to be written for the raw API, without
    291  * the need for system-specific code to handle input in that format;
    292  * these following couple of functions will handle the translation forth
    293  * and back automatically. */
    294 
    295 void ffi_java_raw_call (ffi_cif *cif, void (*fn)(void), void *rvalue,
    296 			ffi_java_raw *raw)
    297 {
    298   void **avalue = (void**) alloca (cif->nargs * sizeof (void*));
    299   ffi_java_raw_to_ptrarray (cif, raw, avalue);
    300   ffi_call (cif, fn, rvalue, avalue);
    301   ffi_java_rvalue_to_raw (cif, rvalue);
    302 }
    303 
    304 #if FFI_CLOSURES		/* base system provides closures */
    305 
    306 static void
    307 ffi_java_translate_args (ffi_cif *cif, void *rvalue,
    308 		    void **avalue, void *user_data)
    309 {
    310   ffi_java_raw *raw = (ffi_java_raw*)alloca (ffi_java_raw_size (cif));
    311   ffi_raw_closure *cl = (ffi_raw_closure*)user_data;
    312 
    313   ffi_java_ptrarray_to_raw (cif, avalue, raw);
    314   (*cl->fun) (cif, rvalue, (ffi_raw*)raw, cl->user_data);
    315   ffi_java_raw_to_rvalue (cif, rvalue);
    316 }
    317 
    318 ffi_status
    319 ffi_prep_java_raw_closure_loc (ffi_java_raw_closure* cl,
    320 			       ffi_cif *cif,
    321 			       void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*),
    322 			       void *user_data,
    323 			       void *codeloc)
    324 {
    325   ffi_status status;
    326 
    327   status = ffi_prep_closure_loc ((ffi_closure*) cl,
    328 				 cif,
    329 				 &ffi_java_translate_args,
    330 				 codeloc,
    331 				 codeloc);
    332   if (status == FFI_OK)
    333     {
    334       cl->fun       = fun;
    335       cl->user_data = user_data;
    336     }
    337 
    338   return status;
    339 }
    340 
    341 /* Again, here is the generic version of ffi_prep_raw_closure, which
    342  * will install an intermediate "hub" for translation of arguments from
    343  * the pointer-array format, to the raw format */
    344 
    345 ffi_status
    346 ffi_prep_java_raw_closure (ffi_java_raw_closure* cl,
    347 			   ffi_cif *cif,
    348 			   void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*),
    349 			   void *user_data)
    350 {
    351   return ffi_prep_java_raw_closure_loc (cl, cif, fun, user_data, cl);
    352 }
    353 
    354 #endif /* FFI_CLOSURES */
    355 #endif /* !FFI_NATIVE_RAW_API */
    356 #endif /* !FFI_NO_RAW_API */
    357