111
|
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 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 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 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 */
|