Makefile.am (EXTRA_DIST): Bring up to date.
[gcc.git] / libffi / src / java_raw_api.c
1 /* -----------------------------------------------------------------------
2 java_raw_api.c - Copyright (c) 1999, 2007 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, EXPRESS
23 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
25 IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
26 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
27 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
28 OTHER DEALINGS IN THE SOFTWARE.
29 ----------------------------------------------------------------------- */
30
31 /* This defines a Java- and 64-bit specific variant of the raw API. */
32 /* It assumes that "raw" argument blocks look like Java stacks on a */
33 /* 64-bit machine. Arguments that can be stored in a single stack */
34 /* stack slots (longs, doubles) occupy 128 bits, but only the first */
35 /* 64 bits are actually used. */
36
37 #include <ffi.h>
38 #include <ffi_common.h>
39 #include <stdlib.h>
40
41 #if !defined(NO_JAVA_RAW_API) && !defined(FFI_NO_RAW_API)
42
43 size_t
44 ffi_java_raw_size (ffi_cif *cif)
45 {
46 size_t result = 0;
47 int i;
48
49 ffi_type **at = cif->arg_types;
50
51 for (i = cif->nargs-1; i >= 0; i--, at++)
52 {
53 switch((*at) -> type) {
54 case FFI_TYPE_UINT64:
55 case FFI_TYPE_SINT64:
56 case FFI_TYPE_DOUBLE:
57 result += 2 * FFI_SIZEOF_ARG;
58 break;
59 case FFI_TYPE_STRUCT:
60 /* No structure parameters in Java. */
61 abort();
62 default:
63 result += FFI_SIZEOF_ARG;
64 }
65 }
66
67 return result;
68 }
69
70
71 void
72 ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args)
73 {
74 unsigned i;
75 ffi_type **tp = cif->arg_types;
76
77 #if WORDS_BIGENDIAN
78
79 for (i = 0; i < cif->nargs; i++, tp++, args++)
80 {
81 switch ((*tp)->type)
82 {
83 case FFI_TYPE_UINT8:
84 case FFI_TYPE_SINT8:
85 *args = (void*) ((char*)(raw++) + 3);
86 break;
87
88 case FFI_TYPE_UINT16:
89 case FFI_TYPE_SINT16:
90 *args = (void*) ((char*)(raw++) + 2);
91 break;
92
93 #if FFI_SIZEOF_ARG == 8
94 case FFI_TYPE_UINT64:
95 case FFI_TYPE_SINT64:
96 case FFI_TYPE_DOUBLE:
97 *args = (void *)raw;
98 raw += 2;
99 break;
100 #endif
101
102 case FFI_TYPE_POINTER:
103 *args = (void*) &(raw++)->ptr;
104 break;
105
106 default:
107 *args = raw;
108 raw += ALIGN ((*tp)->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
109 }
110 }
111
112 #else /* WORDS_BIGENDIAN */
113
114 #if !PDP
115
116 /* then assume little endian */
117 for (i = 0; i < cif->nargs; i++, tp++, args++)
118 {
119 #if FFI_SIZEOF_ARG == 8
120 switch((*tp)->type) {
121 case FFI_TYPE_UINT64:
122 case FFI_TYPE_SINT64:
123 case FFI_TYPE_DOUBLE:
124 *args = (void*) raw;
125 raw += 2;
126 break;
127 default:
128 *args = (void*) raw++;
129 }
130 #else /* FFI_SIZEOF_ARG != 8 */
131 *args = (void*) raw;
132 raw += ALIGN ((*tp)->size, sizeof (void*)) / sizeof (void*);
133 #endif /* FFI_SIZEOF_ARG == 8 */
134 }
135
136 #else
137 #error "pdp endian not supported"
138 #endif /* ! PDP */
139
140 #endif /* WORDS_BIGENDIAN */
141 }
142
143 void
144 ffi_java_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw)
145 {
146 unsigned i;
147 ffi_type **tp = cif->arg_types;
148
149 for (i = 0; i < cif->nargs; i++, tp++, args++)
150 {
151 switch ((*tp)->type)
152 {
153 case FFI_TYPE_UINT8:
154 #if WORDS_BIGENDIAN
155 *(UINT32*)(raw++) = *(UINT8*) (*args);
156 #else
157 (raw++)->uint = *(UINT8*) (*args);
158 #endif
159 break;
160
161 case FFI_TYPE_SINT8:
162 #if WORDS_BIGENDIAN
163 *(SINT32*)(raw++) = *(SINT8*) (*args);
164 #else
165 (raw++)->sint = *(SINT8*) (*args);
166 #endif
167 break;
168
169 case FFI_TYPE_UINT16:
170 #if WORDS_BIGENDIAN
171 *(UINT32*)(raw++) = *(UINT16*) (*args);
172 #else
173 (raw++)->uint = *(UINT16*) (*args);
174 #endif
175 break;
176
177 case FFI_TYPE_SINT16:
178 #if WORDS_BIGENDIAN
179 *(SINT32*)(raw++) = *(SINT16*) (*args);
180 #else
181 (raw++)->sint = *(SINT16*) (*args);
182 #endif
183 break;
184
185 case FFI_TYPE_UINT32:
186 #if WORDS_BIGENDIAN
187 *(UINT32*)(raw++) = *(UINT32*) (*args);
188 #else
189 (raw++)->uint = *(UINT32*) (*args);
190 #endif
191 break;
192
193 case FFI_TYPE_SINT32:
194 #if WORDS_BIGENDIAN
195 *(SINT32*)(raw++) = *(SINT32*) (*args);
196 #else
197 (raw++)->sint = *(SINT32*) (*args);
198 #endif
199 break;
200
201 case FFI_TYPE_FLOAT:
202 (raw++)->flt = *(FLOAT32*) (*args);
203 break;
204
205 #if FFI_SIZEOF_ARG == 8
206 case FFI_TYPE_UINT64:
207 case FFI_TYPE_SINT64:
208 case FFI_TYPE_DOUBLE:
209 raw->uint = *(UINT64*) (*args);
210 raw += 2;
211 break;
212 #endif
213
214 case FFI_TYPE_POINTER:
215 (raw++)->ptr = **(void***) args;
216 break;
217
218 default:
219 #if FFI_SIZEOF_ARG == 8
220 FFI_ASSERT(0); /* Should have covered all cases */
221 #else
222 memcpy ((void*) raw->data, (void*)*args, (*tp)->size);
223 raw += ALIGN ((*tp)->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
224 #endif
225 }
226 }
227 }
228
229 #if !FFI_NATIVE_RAW_API
230
231 static void
232 ffi_java_rvalue_to_raw (ffi_cif *cif, void *rvalue)
233 {
234 #if WORDS_BIGENDIAN && FFI_SIZEOF_ARG == 8
235 switch (cif->rtype->type)
236 {
237 case FFI_TYPE_UINT8:
238 case FFI_TYPE_UINT16:
239 case FFI_TYPE_UINT32:
240 *(UINT64 *)rvalue <<= 32;
241 break;
242
243 case FFI_TYPE_SINT8:
244 case FFI_TYPE_SINT16:
245 case FFI_TYPE_SINT32:
246 case FFI_TYPE_INT:
247 *(SINT64 *)rvalue <<= 32;
248 break;
249
250 default:
251 break;
252 }
253 #endif
254 }
255
256 static void
257 ffi_java_raw_to_rvalue (ffi_cif *cif, void *rvalue)
258 {
259 #if WORDS_BIGENDIAN && FFI_SIZEOF_ARG == 8
260 switch (cif->rtype->type)
261 {
262 case FFI_TYPE_UINT8:
263 case FFI_TYPE_UINT16:
264 case FFI_TYPE_UINT32:
265 *(UINT64 *)rvalue >>= 32;
266 break;
267
268 case FFI_TYPE_SINT8:
269 case FFI_TYPE_SINT16:
270 case FFI_TYPE_SINT32:
271 case FFI_TYPE_INT:
272 *(SINT64 *)rvalue >>= 32;
273 break;
274
275 default:
276 break;
277 }
278 #endif
279 }
280
281 /* This is a generic definition of ffi_raw_call, to be used if the
282 * native system does not provide a machine-specific implementation.
283 * Having this, allows code to be written for the raw API, without
284 * the need for system-specific code to handle input in that format;
285 * these following couple of functions will handle the translation forth
286 * and back automatically. */
287
288 void ffi_java_raw_call (ffi_cif *cif, void (*fn)(), void *rvalue, ffi_raw *raw)
289 {
290 void **avalue = (void**) alloca (cif->nargs * sizeof (void*));
291 ffi_java_raw_to_ptrarray (cif, raw, avalue);
292 ffi_call (cif, fn, rvalue, avalue);
293 ffi_java_rvalue_to_raw (cif, rvalue);
294 }
295
296 #if FFI_CLOSURES /* base system provides closures */
297
298 static void
299 ffi_java_translate_args (ffi_cif *cif, void *rvalue,
300 void **avalue, void *user_data)
301 {
302 ffi_raw *raw = (ffi_raw*)alloca (ffi_java_raw_size (cif));
303 ffi_raw_closure *cl = (ffi_raw_closure*)user_data;
304
305 ffi_java_ptrarray_to_raw (cif, avalue, raw);
306 (*cl->fun) (cif, rvalue, raw, cl->user_data);
307 ffi_java_raw_to_rvalue (cif, rvalue);
308 }
309
310 ffi_status
311 ffi_prep_java_raw_closure_loc (ffi_raw_closure* cl,
312 ffi_cif *cif,
313 void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
314 void *user_data,
315 void *codeloc)
316 {
317 ffi_status status;
318
319 status = ffi_prep_closure_loc ((ffi_closure*) cl,
320 cif,
321 &ffi_java_translate_args,
322 codeloc,
323 codeloc);
324 if (status == FFI_OK)
325 {
326 cl->fun = fun;
327 cl->user_data = user_data;
328 }
329
330 return status;
331 }
332
333 /* Again, here is the generic version of ffi_prep_raw_closure, which
334 * will install an intermediate "hub" for translation of arguments from
335 * the pointer-array format, to the raw format */
336
337 ffi_status
338 ffi_prep_java_raw_closure (ffi_raw_closure* cl,
339 ffi_cif *cif,
340 void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
341 void *user_data)
342 {
343 return ffi_prep_java_raw_closure_loc (cl, cif, fun, user_data, cl);
344 }
345
346 #endif /* FFI_CLOSURES */
347 #endif /* !FFI_NATIVE_RAW_API */
348 #endif /* !FFI_NO_RAW_API */