• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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) && !defined(FFI_NO_RAW_API)
43 
44 size_t
ffi_java_raw_size(ffi_cif * cif)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
ffi_java_raw_to_ptrarray(ffi_cif * cif,ffi_java_raw * raw,void ** args)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
ffi_java_ptrarray_to_raw(ffi_cif * cif,void ** args,ffi_java_raw * raw)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
ffi_java_rvalue_to_raw(ffi_cif * cif,void * rvalue)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
ffi_java_raw_to_rvalue(ffi_cif * cif,void * rvalue)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 
ffi_java_raw_call(ffi_cif * cif,void (* fn)(void),void * rvalue,ffi_java_raw * raw)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
ffi_java_translate_args(ffi_cif * cif,void * rvalue,void ** avalue,void * user_data)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
ffi_prep_java_raw_closure_loc(ffi_java_raw_closure * cl,ffi_cif * cif,void (* fun)(ffi_cif *,void *,ffi_java_raw *,void *),void * user_data,void * codeloc)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
ffi_prep_java_raw_closure(ffi_java_raw_closure * cl,ffi_cif * cif,void (* fun)(ffi_cif *,void *,ffi_java_raw *,void *),void * user_data)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