ffi.c, [...]: New files.
[platform/upstream/gcc.git] / libffi / src / java_raw_api.c
1 /* -----------------------------------------------------------------------
2    java_raw_api.c - Copyright (c) 1999  Cygnus Solutions
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
40 #if !defined(NO_JAVA_RAW_API) && !defined(FFI_NO_RAW_API)
41
42 size_t
43 ffi_java_raw_size (ffi_cif *cif)
44 {
45   size_t result = 0;
46   int i;
47
48   ffi_type **at = cif->arg_types;
49
50   for (i = cif->nargs-1; i >= 0; i--, at++)
51     {
52       switch((*at) -> type) {
53         case FFI_TYPE_UINT64:
54         case FFI_TYPE_SINT64:
55           result += 2 * SIZEOF_ARG;
56           break;
57         case FFI_TYPE_STRUCT:
58           /* No structure parameters in Java.   */
59           abort();
60         default:
61           result += SIZEOF_ARG;
62       }
63     }
64
65   return result;
66 }
67
68
69 void
70 ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args)
71 {
72   unsigned i;
73   ffi_type **tp = cif->arg_types;
74
75 #if WORDS_BIGENDIAN
76
77   for (i = 0; i < cif->nargs; i++, tp++, args++)
78     {     
79       switch ((*tp)->type)
80         {
81         case FFI_TYPE_UINT8:
82         case FFI_TYPE_SINT8:
83           *args = (void*) ((char*)(raw++) + SIZEOF_ARG - 1);
84           break;
85           
86         case FFI_TYPE_UINT16:
87         case FFI_TYPE_SINT16:
88           *args = (void*) ((char*)(raw++) + SIZEOF_ARG - 2);
89           break;
90
91 #if SIZEOF_ARG >= 4       
92         case FFI_TYPE_UINT32:
93         case FFI_TYPE_SINT32:
94           *args = (void*) ((char*)(raw++) + SIZEOF_ARG - 4);
95           break;
96 #endif
97         
98 #if SIZEOF_ARG == 8       
99         case FFI_TYPE_UINT64:
100         case FFI_TYPE_SINT64:
101         case FFI_TYPE_DOUBLE:
102           *args = (void *)raw;
103           raw += 2;
104           break;
105 #endif
106
107         case FFI_TYPE_POINTER:
108           *args = (void*) &(raw++)->ptr;
109           break;
110           
111         default:
112           *args = raw;
113           raw += ALIGN ((*tp)->size, SIZEOF_ARG) / SIZEOF_ARG;
114         }
115     }
116
117 #else /* WORDS_BIGENDIAN */
118
119 #if !PDP
120
121   /* then assume little endian */
122   for (i = 0; i < cif->nargs; i++, tp++, args++)
123     {
124 #if SIZEOF_ARG == 8
125       switch((*tp)->type) {
126         case FFI_TYPE_UINT64:
127         case FFI_TYPE_SINT64:
128         case FFI_TYPE_DOUBLE:
129           *args = (void*) raw;
130           raw += 2;
131           break;
132         default:
133           *args = (void*) raw++;
134       }
135 #else /* SIZEOF_ARG != 8 */
136         *args = (void*) raw;
137         raw += ALIGN ((*tp)->size, sizeof (void*)) / sizeof (void*);
138 #endif /* SIZEOF_ARG == 8 */
139     }
140
141 #else
142 #error "pdp endian not supported"
143 #endif /* ! PDP */
144
145 #endif /* WORDS_BIGENDIAN */
146 }
147
148 void
149 ffi_java_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw)
150 {
151   unsigned i;
152   ffi_type **tp = cif->arg_types;
153
154   for (i = 0; i < cif->nargs; i++, tp++, args++)
155     {     
156       switch ((*tp)->type)
157         {
158         case FFI_TYPE_UINT8:
159           (raw++)->uint = *(UINT8*) (*args);
160           break;
161
162         case FFI_TYPE_SINT8:
163           (raw++)->sint = *(SINT8*) (*args);
164           break;
165
166         case FFI_TYPE_UINT16:
167           (raw++)->uint = *(UINT16*) (*args);
168           break;
169
170         case FFI_TYPE_SINT16:
171           (raw++)->sint = *(SINT16*) (*args);
172           break;
173
174 #if SIZEOF_ARG >= 4
175         case FFI_TYPE_UINT32:
176           (raw++)->uint = *(UINT32*) (*args);
177           break;
178
179         case FFI_TYPE_SINT32:
180           (raw++)->sint = *(SINT32*) (*args);
181           break;
182 #endif
183         case FFI_TYPE_FLOAT:
184           (raw++)->flt = *(FLOAT32*) (*args);
185           break;
186
187 #if SIZEOF_ARG == 8
188         case FFI_TYPE_UINT64:
189         case FFI_TYPE_SINT64:
190         case FFI_TYPE_DOUBLE:
191           raw->uint = *(UINT64*) (*args);
192           raw += 2;
193           break;
194 #endif
195
196         case FFI_TYPE_POINTER:
197           (raw++)->ptr = **(void***) args;
198           break;
199
200         default:
201 #if SIZEOF_ARG == 8
202           FFI_ASSERT(FALSE);    /* Should have covered all cases */
203 #else   
204           memcpy ((void*) raw->data, (void*)*args, (*tp)->size);
205           raw += ALIGN ((*tp)->size, SIZEOF_ARG) / SIZEOF_ARG;
206 #endif
207         }
208     }
209 }
210
211 #if !FFI_NATIVE_RAW_API
212
213
214 /* This is a generic definition of ffi_raw_call, to be used if the
215  * native system does not provide a machine-specific implementation.
216  * Having this, allows code to be written for the raw API, without
217  * the need for system-specific code to handle input in that format;
218  * these following couple of functions will handle the translation forth
219  * and back automatically. */
220
221 void ffi_java_raw_call (/*@dependent@*/ ffi_cif *cif, 
222                    void (*fn)(), 
223                    /*@out@*/ void *rvalue, 
224                    /*@dependent@*/ ffi_raw *raw)
225 {
226   void **avalue = (void**) alloca (cif->nargs * sizeof (void*));
227   ffi_java_raw_to_ptrarray (cif, raw, avalue);
228   ffi_call (cif, fn, rvalue, avalue);
229 }
230
231 #if FFI_CLOSURES                /* base system provides closures */
232
233 static void 
234 ffi_java_translate_args (ffi_cif *cif, void *rvalue,
235                     void **avalue, void *user_data)
236 {
237   ffi_raw *raw = (ffi_raw*)alloca (ffi_java_raw_size (cif));
238   ffi_raw_closure *cl = (ffi_raw_closure*)user_data;
239
240   ffi_java_ptrarray_to_raw (cif, avalue, raw);
241   (*cl->fun) (cif, rvalue, raw, cl->user_data);
242 }
243
244 /* Again, here is the generic version of ffi_prep_raw_closure, which
245  * will install an intermediate "hub" for translation of arguments from
246  * the pointer-array format, to the raw format */
247
248 ffi_status
249 ffi_prep_java_raw_closure (ffi_raw_closure* cl,
250                       ffi_cif *cif,
251                       void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
252                       void *user_data)
253 {
254   ffi_status status;
255
256   status = ffi_prep_closure ((ffi_closure*) cl, 
257                              cif,
258                              &ffi_java_translate_args,
259                              (void*)cl);
260   if (status == FFI_OK)
261     {
262       cl->fun       = fun;
263       cl->user_data = user_data;
264     }
265
266   return status;
267 }
268
269 #endif /* FFI_CLOSURES */
270 #endif /* !FFI_NATIVE_RAW_API */
271 #endif /* !FFI_NO_RAW_API */