Back to index

plt-scheme  4.2.1
java_raw_api.c
Go to the documentation of this file.
00001 /* -----------------------------------------------------------------------
00002    java_raw_api.c - Copyright (c) 1999, 2007  Red Hat, Inc.
00003 
00004    Cloned from raw_api.c
00005 
00006    Raw_api.c author: Kresten Krab Thorup <krab@gnu.org>
00007    Java_raw_api.c author: Hans-J. Boehm <hboehm@hpl.hp.com>
00008 
00009    $Id $
00010 
00011    Permission is hereby granted, free of charge, to any person obtaining
00012    a copy of this software and associated documentation files (the
00013    ``Software''), to deal in the Software without restriction, including
00014    without limitation the rights to use, copy, modify, merge, publish,
00015    distribute, sublicense, and/or sell copies of the Software, and to
00016    permit persons to whom the Software is furnished to do so, subject to
00017    the following conditions:
00018 
00019    The above copyright notice and this permission notice shall be included
00020    in all copies or substantial portions of the Software.
00021 
00022    THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
00023    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00024    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
00025    IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
00026    OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
00027    ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
00028    OTHER DEALINGS IN THE SOFTWARE.
00029    ----------------------------------------------------------------------- */
00030 
00031 /* This defines a Java- and 64-bit specific variant of the raw API.   */
00032 /* It assumes that "raw" argument blocks look like Java stacks on a   */
00033 /* 64-bit machine.  Arguments that can be stored in a single stack    */
00034 /* stack slots (longs, doubles) occupy 128 bits, but only the first   */
00035 /* 64 bits are actually used.                                         */
00036 
00037 #include <ffi.h>
00038 #include <ffi_common.h>
00039 #include <stdlib.h>
00040 
00041 #if !defined(NO_JAVA_RAW_API) && !defined(FFI_NO_RAW_API)
00042 
00043 size_t
00044 ffi_java_raw_size (ffi_cif *cif)
00045 {
00046   size_t result = 0;
00047   int i;
00048 
00049   ffi_type **at = cif->arg_types;
00050 
00051   for (i = cif->nargs-1; i >= 0; i--, at++)
00052     {
00053       switch((*at) -> type) {
00054        case FFI_TYPE_UINT64:
00055        case FFI_TYPE_SINT64:
00056        case FFI_TYPE_DOUBLE:
00057          result += 2 * FFI_SIZEOF_JAVA_RAW;
00058          break;
00059        case FFI_TYPE_STRUCT:
00060          /* No structure parameters in Java.     */
00061          abort();
00062        default:
00063          result += FFI_SIZEOF_JAVA_RAW;
00064       }
00065     }
00066 
00067   return result;
00068 }
00069 
00070 
00071 void
00072 ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_java_raw *raw, void **args)
00073 {
00074   unsigned i;
00075   ffi_type **tp = cif->arg_types;
00076 
00077 #if WORDS_BIGENDIAN
00078 
00079   for (i = 0; i < cif->nargs; i++, tp++, args++)
00080     {
00081       switch ((*tp)->type)
00082        {
00083        case FFI_TYPE_UINT8:
00084        case FFI_TYPE_SINT8:
00085          *args = (void*) ((char*)(raw++) + 3);
00086          break;
00087 
00088        case FFI_TYPE_UINT16:
00089        case FFI_TYPE_SINT16:
00090          *args = (void*) ((char*)(raw++) + 2);
00091          break;
00092 
00093 #if FFI_SIZEOF_JAVA_RAW == 8
00094        case FFI_TYPE_UINT64:
00095        case FFI_TYPE_SINT64:
00096        case FFI_TYPE_DOUBLE:
00097          *args = (void *)raw;
00098          raw += 2;
00099          break;
00100 #endif
00101 
00102        case FFI_TYPE_POINTER:
00103          *args = (void*) &(raw++)->ptr;
00104          break;
00105 
00106        default:
00107          *args = raw;
00108          raw +=
00109            ALIGN ((*tp)->size, sizeof(ffi_java_raw)) / sizeof(ffi_java_raw);
00110        }
00111     }
00112 
00113 #else /* WORDS_BIGENDIAN */
00114 
00115 #if !PDP
00116 
00117   /* then assume little endian */
00118   for (i = 0; i < cif->nargs; i++, tp++, args++)
00119     {
00120 #if FFI_SIZEOF_JAVA_RAW == 8
00121       switch((*tp)->type) {
00122        case FFI_TYPE_UINT64:
00123        case FFI_TYPE_SINT64:
00124        case FFI_TYPE_DOUBLE:
00125          *args = (void*) raw;
00126          raw += 2;
00127          break;
00128        default:
00129          *args = (void*) raw++;
00130       }
00131 #else /* FFI_SIZEOF_JAVA_RAW != 8 */
00132        *args = (void*) raw;
00133        raw +=
00134          ALIGN ((*tp)->size, sizeof(ffi_java_raw)) / sizeof(ffi_java_raw);
00135 #endif /* FFI_SIZEOF_JAVA_RAW == 8 */
00136     }
00137 
00138 #else
00139 #error "pdp endian not supported"
00140 #endif /* ! PDP */
00141 
00142 #endif /* WORDS_BIGENDIAN */
00143 }
00144 
00145 void
00146 ffi_java_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_java_raw *raw)
00147 {
00148   unsigned i;
00149   ffi_type **tp = cif->arg_types;
00150 
00151   for (i = 0; i < cif->nargs; i++, tp++, args++)
00152     {
00153       switch ((*tp)->type)
00154        {
00155        case FFI_TYPE_UINT8:
00156 #if WORDS_BIGENDIAN
00157          *(UINT32*)(raw++) = *(UINT8*) (*args);
00158 #else
00159          (raw++)->uint = *(UINT8*) (*args);
00160 #endif
00161          break;
00162 
00163        case FFI_TYPE_SINT8:
00164 #if WORDS_BIGENDIAN
00165          *(SINT32*)(raw++) = *(SINT8*) (*args);
00166 #else
00167          (raw++)->sint = *(SINT8*) (*args);
00168 #endif
00169          break;
00170 
00171        case FFI_TYPE_UINT16:
00172 #if WORDS_BIGENDIAN
00173          *(UINT32*)(raw++) = *(UINT16*) (*args);
00174 #else
00175          (raw++)->uint = *(UINT16*) (*args);
00176 #endif
00177          break;
00178 
00179        case FFI_TYPE_SINT16:
00180 #if WORDS_BIGENDIAN
00181          *(SINT32*)(raw++) = *(SINT16*) (*args);
00182 #else
00183          (raw++)->sint = *(SINT16*) (*args);
00184 #endif
00185          break;
00186 
00187        case FFI_TYPE_UINT32:
00188 #if WORDS_BIGENDIAN
00189          *(UINT32*)(raw++) = *(UINT32*) (*args);
00190 #else
00191          (raw++)->uint = *(UINT32*) (*args);
00192 #endif
00193          break;
00194 
00195        case FFI_TYPE_SINT32:
00196 #if WORDS_BIGENDIAN
00197          *(SINT32*)(raw++) = *(SINT32*) (*args);
00198 #else
00199          (raw++)->sint = *(SINT32*) (*args);
00200 #endif
00201          break;
00202 
00203        case FFI_TYPE_FLOAT:
00204          (raw++)->flt = *(FLOAT32*) (*args);
00205          break;
00206 
00207 #if FFI_SIZEOF_JAVA_RAW == 8
00208        case FFI_TYPE_UINT64:
00209        case FFI_TYPE_SINT64:
00210        case FFI_TYPE_DOUBLE:
00211          raw->uint = *(UINT64*) (*args);
00212          raw += 2;
00213          break;
00214 #endif
00215 
00216        case FFI_TYPE_POINTER:
00217          (raw++)->ptr = **(void***) args;
00218          break;
00219 
00220        default:
00221 #if FFI_SIZEOF_JAVA_RAW == 8
00222          FFI_ASSERT(0);     /* Should have covered all cases */
00223 #else
00224          memcpy ((void*) raw->data, (void*)*args, (*tp)->size);
00225          raw +=
00226            ALIGN ((*tp)->size, sizeof(ffi_java_raw)) / sizeof(ffi_java_raw);
00227 #endif
00228        }
00229     }
00230 }
00231 
00232 #if !FFI_NATIVE_RAW_API
00233 
00234 static void
00235 ffi_java_rvalue_to_raw (ffi_cif *cif, void *rvalue)
00236 {
00237 #if WORDS_BIGENDIAN && FFI_SIZEOF_ARG == 8
00238   switch (cif->rtype->type)
00239     {
00240     case FFI_TYPE_UINT8:
00241     case FFI_TYPE_UINT16:
00242     case FFI_TYPE_UINT32:
00243       *(UINT64 *)rvalue <<= 32;
00244       break;
00245 
00246     case FFI_TYPE_SINT8:
00247     case FFI_TYPE_SINT16:
00248     case FFI_TYPE_SINT32:
00249     case FFI_TYPE_INT:
00250 #if FFI_SIZEOF_JAVA_RAW == 4
00251     case FFI_TYPE_POINTER:
00252 #endif
00253       *(SINT64 *)rvalue <<= 32;
00254       break;
00255 
00256     default:
00257       break;
00258     }
00259 #endif
00260 }
00261 
00262 static void
00263 ffi_java_raw_to_rvalue (ffi_cif *cif, void *rvalue)
00264 {
00265 #if WORDS_BIGENDIAN && FFI_SIZEOF_ARG == 8
00266   switch (cif->rtype->type)
00267     {
00268     case FFI_TYPE_UINT8:
00269     case FFI_TYPE_UINT16:
00270     case FFI_TYPE_UINT32:
00271       *(UINT64 *)rvalue >>= 32;
00272       break;
00273 
00274     case FFI_TYPE_SINT8:
00275     case FFI_TYPE_SINT16:
00276     case FFI_TYPE_SINT32:
00277     case FFI_TYPE_INT:
00278 #if FFI_SIZEOF_JAVA_RAW == 4
00279     case FFI_TYPE_POINTER:
00280 #endif
00281       *(SINT64 *)rvalue >>= 32;
00282       break;
00283 
00284     default:
00285       break;
00286     }
00287 #endif
00288 }
00289 
00290 /* This is a generic definition of ffi_raw_call, to be used if the
00291  * native system does not provide a machine-specific implementation.
00292  * Having this, allows code to be written for the raw API, without
00293  * the need for system-specific code to handle input in that format;
00294  * these following couple of functions will handle the translation forth
00295  * and back automatically. */
00296 
00297 void ffi_java_raw_call (ffi_cif *cif, void (*fn)(), void *rvalue,
00298                      ffi_java_raw *raw)
00299 {
00300   void **avalue = (void**) alloca (cif->nargs * sizeof (void*));
00301   ffi_java_raw_to_ptrarray (cif, raw, avalue);
00302   ffi_call (cif, fn, rvalue, avalue);
00303   ffi_java_rvalue_to_raw (cif, rvalue);
00304 }
00305 
00306 #if FFI_CLOSURES            /* base system provides closures */
00307 
00308 static void
00309 ffi_java_translate_args (ffi_cif *cif, void *rvalue,
00310                   void **avalue, void *user_data)
00311 {
00312   ffi_java_raw *raw = (ffi_java_raw*)alloca (ffi_java_raw_size (cif));
00313   ffi_raw_closure *cl = (ffi_raw_closure*)user_data;
00314 
00315   ffi_java_ptrarray_to_raw (cif, avalue, raw);
00316   (*cl->fun) (cif, rvalue, raw, cl->user_data);
00317   ffi_java_raw_to_rvalue (cif, rvalue);
00318 }
00319 
00320 ffi_status
00321 ffi_prep_java_raw_closure_loc (ffi_java_raw_closure* cl,
00322                             ffi_cif *cif,
00323                             void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*),
00324                             void *user_data,
00325                             void *codeloc)
00326 {
00327   ffi_status status;
00328 
00329   status = ffi_prep_closure_loc ((ffi_closure*) cl,
00330                              cif,
00331                              &ffi_java_translate_args,
00332                              codeloc,
00333                              codeloc);
00334   if (status == FFI_OK)
00335     {
00336       cl->fun       = fun;
00337       cl->user_data = user_data;
00338     }
00339 
00340   return status;
00341 }
00342 
00343 /* Again, here is the generic version of ffi_prep_raw_closure, which
00344  * will install an intermediate "hub" for translation of arguments from
00345  * the pointer-array format, to the raw format */
00346 
00347 ffi_status
00348 ffi_prep_java_raw_closure (ffi_java_raw_closure* cl,
00349                         ffi_cif *cif,
00350                         void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*),
00351                         void *user_data)
00352 {
00353   return ffi_prep_java_raw_closure_loc (cl, cif, fun, user_data, cl);
00354 }
00355 
00356 #endif /* FFI_CLOSURES */
00357 #endif /* !FFI_NATIVE_RAW_API */
00358 #endif /* !FFI_NO_RAW_API */