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 #if FFI_SIZEOF_JAVA_RAW == 4
    280     case FFI_TYPE_POINTER:
    281 #endif
    282       *(SINT64 *)rvalue >>= 32;
    283       break;
    284 
    285     default:
    286       break;
    287     }
    288 #endif
    289 }
    290 
    291 /* This is a generic definition of ffi_raw_call, to be used if the
    292  * native system does not provide a machine-specific implementation.
    293  * Having this, allows code to be written for the raw API, without
    294  * the need for system-specific code to handle input in that format;
    295  * these following couple of functions will handle the translation forth
    296  * and back automatically. */
    297 
    298 void ffi_java_raw_call (ffi_cif *cif, void (*fn)(void), void *rvalue,
    299 			ffi_java_raw *raw)
    300 {
    301   void **avalue = (void**) alloca (cif->nargs * sizeof (void*));
    302   ffi_java_raw_to_ptrarray (cif, raw, avalue);
    303   ffi_call (cif, fn, rvalue, avalue);
    304   ffi_java_rvalue_to_raw (cif, rvalue);
    305 }
    306 
    307 #if FFI_CLOSURES		/* base system provides closures */
    308 
    309 static void
    310 ffi_java_translate_args (ffi_cif *cif, void *rvalue,
    311 		    void **avalue, void *user_data)
    312 {
    313   ffi_java_raw *raw = (ffi_java_raw*)alloca (ffi_java_raw_size (cif));
    314   ffi_raw_closure *cl = (ffi_raw_closure*)user_data;
    315 
    316   ffi_java_ptrarray_to_raw (cif, avalue, raw);
    317   (*cl->fun) (cif, rvalue, raw, cl->user_data);
    318   ffi_java_raw_to_rvalue (cif, rvalue);
    319 }
    320 
    321 ffi_status
    322 ffi_prep_java_raw_closure_loc (ffi_java_raw_closure* cl,
    323 			       ffi_cif *cif,
    324 			       void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*),
    325 			       void *user_data,
    326 			       void *codeloc)
    327 {
    328   ffi_status status;
    329 
    330   status = ffi_prep_closure_loc ((ffi_closure*) cl,
    331 				 cif,
    332 				 &ffi_java_translate_args,
    333 				 codeloc,
    334 				 codeloc);
    335   if (status == FFI_OK)
    336     {
    337       cl->fun       = fun;
    338       cl->user_data = user_data;
    339     }
    340 
    341   return status;
    342 }
    343 
    344 /* Again, here is the generic version of ffi_prep_raw_closure, which
    345  * will install an intermediate "hub" for translation of arguments from
    346  * the pointer-array format, to the raw format */
    347 
    348 ffi_status
    349 ffi_prep_java_raw_closure (ffi_java_raw_closure* cl,
    350 			   ffi_cif *cif,
    351 			   void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*),
    352 			   void *user_data)
    353 {
    354   return ffi_prep_java_raw_closure_loc (cl, cif, fun, user_data, cl);
    355 }
    356 
    357 #endif /* FFI_CLOSURES */
    358 #endif /* !FFI_NATIVE_RAW_API */
    359 #endif /* !FFI_NO_RAW_API */
    360