OSDN Git Service

* c-typeck.c (set_init_index): Allow array designators that are
[pf3gnuchains/gcc-fork.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_JAVA_RAW;
58           break;
59         case FFI_TYPE_STRUCT:
60           /* No structure parameters in Java.   */
61           abort();
62         default:
63           result += FFI_SIZEOF_JAVA_RAW;
64       }
65     }
66
67   return result;
68 }
69
70
71 void
72 ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_java_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_JAVA_RAW == 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 +=
109             ALIGN ((*tp)->size, sizeof(ffi_java_raw)) / sizeof(ffi_java_raw);
110         }
111     }
112
113 #else /* WORDS_BIGENDIAN */
114
115 #if !PDP
116
117   /* then assume little endian */
118   for (i = 0; i < cif->nargs; i++, tp++, args++)
119     {
120 #if FFI_SIZEOF_JAVA_RAW == 8
121       switch((*tp)->type) {
122         case FFI_TYPE_UINT64:
123         case FFI_TYPE_SINT64:
124         case FFI_TYPE_DOUBLE:
125           *args = (void*) raw;
126           raw += 2;
127           break;
128         default:
129           *args = (void*) raw++;
130       }
131 #else /* FFI_SIZEOF_JAVA_RAW != 8 */
132         *args = (void*) raw;
133         raw +=
134           ALIGN ((*tp)->size, sizeof(ffi_java_raw)) / sizeof(ffi_java_raw);
135 #endif /* FFI_SIZEOF_JAVA_RAW == 8 */
136     }
137
138 #else
139 #error "pdp endian not supported"
140 #endif /* ! PDP */
141
142 #endif /* WORDS_BIGENDIAN */
143 }
144
145 void
146 ffi_java_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_java_raw *raw)
147 {
148   unsigned i;
149   ffi_type **tp = cif->arg_types;
150
151   for (i = 0; i < cif->nargs; i++, tp++, args++)
152     {
153       switch ((*tp)->type)
154         {
155         case FFI_TYPE_UINT8:
156 #if WORDS_BIGENDIAN
157           *(UINT32*)(raw++) = *(UINT8*) (*args);
158 #else
159           (raw++)->uint = *(UINT8*) (*args);
160 #endif
161           break;
162
163         case FFI_TYPE_SINT8:
164 #if WORDS_BIGENDIAN
165           *(SINT32*)(raw++) = *(SINT8*) (*args);
166 #else
167           (raw++)->sint = *(SINT8*) (*args);
168 #endif
169           break;
170
171         case FFI_TYPE_UINT16:
172 #if WORDS_BIGENDIAN
173           *(UINT32*)(raw++) = *(UINT16*) (*args);
174 #else
175           (raw++)->uint = *(UINT16*) (*args);
176 #endif
177           break;
178
179         case FFI_TYPE_SINT16:
180 #if WORDS_BIGENDIAN
181           *(SINT32*)(raw++) = *(SINT16*) (*args);
182 #else
183           (raw++)->sint = *(SINT16*) (*args);
184 #endif
185           break;
186
187         case FFI_TYPE_UINT32:
188 #if WORDS_BIGENDIAN
189           *(UINT32*)(raw++) = *(UINT32*) (*args);
190 #else
191           (raw++)->uint = *(UINT32*) (*args);
192 #endif
193           break;
194
195         case FFI_TYPE_SINT32:
196 #if WORDS_BIGENDIAN
197           *(SINT32*)(raw++) = *(SINT32*) (*args);
198 #else
199           (raw++)->sint = *(SINT32*) (*args);
200 #endif
201           break;
202
203         case FFI_TYPE_FLOAT:
204           (raw++)->flt = *(FLOAT32*) (*args);
205           break;
206
207 #if FFI_SIZEOF_JAVA_RAW == 8
208         case FFI_TYPE_UINT64:
209         case FFI_TYPE_SINT64:
210         case FFI_TYPE_DOUBLE:
211           raw->uint = *(UINT64*) (*args);
212           raw += 2;
213           break;
214 #endif
215
216         case FFI_TYPE_POINTER:
217           (raw++)->ptr = **(void***) args;
218           break;
219
220         default:
221 #if FFI_SIZEOF_JAVA_RAW == 8
222           FFI_ASSERT(0);        /* Should have covered all cases */
223 #else
224           memcpy ((void*) raw->data, (void*)*args, (*tp)->size);
225           raw +=
226             ALIGN ((*tp)->size, sizeof(ffi_java_raw)) / sizeof(ffi_java_raw);
227 #endif
228         }
229     }
230 }
231
232 #if !FFI_NATIVE_RAW_API
233
234 static void
235 ffi_java_rvalue_to_raw (ffi_cif *cif, void *rvalue)
236 {
237 #if WORDS_BIGENDIAN && FFI_SIZEOF_ARG == 8
238   switch (cif->rtype->type)
239     {
240     case FFI_TYPE_UINT8:
241     case FFI_TYPE_UINT16:
242     case FFI_TYPE_UINT32:
243       *(UINT64 *)rvalue <<= 32;
244       break;
245
246     case FFI_TYPE_SINT8:
247     case FFI_TYPE_SINT16:
248     case FFI_TYPE_SINT32:
249     case FFI_TYPE_INT:
250 #if FFI_SIZEOF_JAVA_RAW == 4
251     case FFI_TYPE_POINTER:
252 #endif
253       *(SINT64 *)rvalue <<= 32;
254       break;
255
256     default:
257       break;
258     }
259 #endif
260 }
261
262 static void
263 ffi_java_raw_to_rvalue (ffi_cif *cif, void *rvalue)
264 {
265 #if WORDS_BIGENDIAN && FFI_SIZEOF_ARG == 8
266   switch (cif->rtype->type)
267     {
268     case FFI_TYPE_UINT8:
269     case FFI_TYPE_UINT16:
270     case FFI_TYPE_UINT32:
271       *(UINT64 *)rvalue >>= 32;
272       break;
273
274     case FFI_TYPE_SINT8:
275     case FFI_TYPE_SINT16:
276     case FFI_TYPE_SINT32:
277     case FFI_TYPE_INT:
278 #if FFI_SIZEOF_JAVA_RAW == 4
279     case FFI_TYPE_POINTER:
280 #endif
281       *(SINT64 *)rvalue >>= 32;
282       break;
283
284     default:
285       break;
286     }
287 #endif
288 }
289
290 /* This is a generic definition of ffi_raw_call, to be used if the
291  * native system does not provide a machine-specific implementation.
292  * Having this, allows code to be written for the raw API, without
293  * the need for system-specific code to handle input in that format;
294  * these following couple of functions will handle the translation forth
295  * and back automatically. */
296
297 void ffi_java_raw_call (ffi_cif *cif, void (*fn)(), void *rvalue,
298                         ffi_java_raw *raw)
299 {
300   void **avalue = (void**) alloca (cif->nargs * sizeof (void*));
301   ffi_java_raw_to_ptrarray (cif, raw, avalue);
302   ffi_call (cif, fn, rvalue, avalue);
303   ffi_java_rvalue_to_raw (cif, rvalue);
304 }
305
306 #if FFI_CLOSURES                /* base system provides closures */
307
308 static void
309 ffi_java_translate_args (ffi_cif *cif, void *rvalue,
310                     void **avalue, void *user_data)
311 {
312   ffi_java_raw *raw = (ffi_java_raw*)alloca (ffi_java_raw_size (cif));
313   ffi_raw_closure *cl = (ffi_raw_closure*)user_data;
314
315   ffi_java_ptrarray_to_raw (cif, avalue, raw);
316   (*cl->fun) (cif, rvalue, raw, cl->user_data);
317   ffi_java_raw_to_rvalue (cif, rvalue);
318 }
319
320 ffi_status
321 ffi_prep_java_raw_closure_loc (ffi_java_raw_closure* cl,
322                                ffi_cif *cif,
323                                void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*),
324                                void *user_data,
325                                void *codeloc)
326 {
327   ffi_status status;
328
329   status = ffi_prep_closure_loc ((ffi_closure*) cl,
330                                  cif,
331                                  &ffi_java_translate_args,
332                                  codeloc,
333                                  codeloc);
334   if (status == FFI_OK)
335     {
336       cl->fun       = fun;
337       cl->user_data = user_data;
338     }
339
340   return status;
341 }
342
343 /* Again, here is the generic version of ffi_prep_raw_closure, which
344  * will install an intermediate "hub" for translation of arguments from
345  * the pointer-array format, to the raw format */
346
347 ffi_status
348 ffi_prep_java_raw_closure (ffi_java_raw_closure* cl,
349                            ffi_cif *cif,
350                            void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*),
351                            void *user_data)
352 {
353   return ffi_prep_java_raw_closure_loc (cl, cif, fun, user_data, cl);
354 }
355
356 #endif /* FFI_CLOSURES */
357 #endif /* !FFI_NATIVE_RAW_API */
358 #endif /* !FFI_NO_RAW_API */