1*1fd5a2e1SPrashanth Swaminathan /* -----------------------------------------------------------------------
2*1fd5a2e1SPrashanth Swaminathan raw_api.c - Copyright (c) 1999, 2008 Red Hat, Inc.
3*1fd5a2e1SPrashanth Swaminathan
4*1fd5a2e1SPrashanth Swaminathan Author: Kresten Krab Thorup <[email protected]>
5*1fd5a2e1SPrashanth Swaminathan
6*1fd5a2e1SPrashanth Swaminathan Permission is hereby granted, free of charge, to any person obtaining
7*1fd5a2e1SPrashanth Swaminathan a copy of this software and associated documentation files (the
8*1fd5a2e1SPrashanth Swaminathan ``Software''), to deal in the Software without restriction, including
9*1fd5a2e1SPrashanth Swaminathan without limitation the rights to use, copy, modify, merge, publish,
10*1fd5a2e1SPrashanth Swaminathan distribute, sublicense, and/or sell copies of the Software, and to
11*1fd5a2e1SPrashanth Swaminathan permit persons to whom the Software is furnished to do so, subject to
12*1fd5a2e1SPrashanth Swaminathan the following conditions:
13*1fd5a2e1SPrashanth Swaminathan
14*1fd5a2e1SPrashanth Swaminathan The above copyright notice and this permission notice shall be included
15*1fd5a2e1SPrashanth Swaminathan in all copies or substantial portions of the Software.
16*1fd5a2e1SPrashanth Swaminathan
17*1fd5a2e1SPrashanth Swaminathan THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
18*1fd5a2e1SPrashanth Swaminathan EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19*1fd5a2e1SPrashanth Swaminathan MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20*1fd5a2e1SPrashanth Swaminathan NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
21*1fd5a2e1SPrashanth Swaminathan HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22*1fd5a2e1SPrashanth Swaminathan WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23*1fd5a2e1SPrashanth Swaminathan OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24*1fd5a2e1SPrashanth Swaminathan DEALINGS IN THE SOFTWARE.
25*1fd5a2e1SPrashanth Swaminathan ----------------------------------------------------------------------- */
26*1fd5a2e1SPrashanth Swaminathan
27*1fd5a2e1SPrashanth Swaminathan /* This file defines generic functions for use with the raw api. */
28*1fd5a2e1SPrashanth Swaminathan
29*1fd5a2e1SPrashanth Swaminathan #include <ffi.h>
30*1fd5a2e1SPrashanth Swaminathan #include <ffi_common.h>
31*1fd5a2e1SPrashanth Swaminathan
32*1fd5a2e1SPrashanth Swaminathan #if !FFI_NO_RAW_API
33*1fd5a2e1SPrashanth Swaminathan
34*1fd5a2e1SPrashanth Swaminathan size_t
ffi_raw_size(ffi_cif * cif)35*1fd5a2e1SPrashanth Swaminathan ffi_raw_size (ffi_cif *cif)
36*1fd5a2e1SPrashanth Swaminathan {
37*1fd5a2e1SPrashanth Swaminathan size_t result = 0;
38*1fd5a2e1SPrashanth Swaminathan int i;
39*1fd5a2e1SPrashanth Swaminathan
40*1fd5a2e1SPrashanth Swaminathan ffi_type **at = cif->arg_types;
41*1fd5a2e1SPrashanth Swaminathan
42*1fd5a2e1SPrashanth Swaminathan for (i = cif->nargs-1; i >= 0; i--, at++)
43*1fd5a2e1SPrashanth Swaminathan {
44*1fd5a2e1SPrashanth Swaminathan #if !FFI_NO_STRUCTS
45*1fd5a2e1SPrashanth Swaminathan if ((*at)->type == FFI_TYPE_STRUCT)
46*1fd5a2e1SPrashanth Swaminathan result += FFI_ALIGN (sizeof (void*), FFI_SIZEOF_ARG);
47*1fd5a2e1SPrashanth Swaminathan else
48*1fd5a2e1SPrashanth Swaminathan #endif
49*1fd5a2e1SPrashanth Swaminathan result += FFI_ALIGN ((*at)->size, FFI_SIZEOF_ARG);
50*1fd5a2e1SPrashanth Swaminathan }
51*1fd5a2e1SPrashanth Swaminathan
52*1fd5a2e1SPrashanth Swaminathan return result;
53*1fd5a2e1SPrashanth Swaminathan }
54*1fd5a2e1SPrashanth Swaminathan
55*1fd5a2e1SPrashanth Swaminathan
56*1fd5a2e1SPrashanth Swaminathan void
ffi_raw_to_ptrarray(ffi_cif * cif,ffi_raw * raw,void ** args)57*1fd5a2e1SPrashanth Swaminathan ffi_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args)
58*1fd5a2e1SPrashanth Swaminathan {
59*1fd5a2e1SPrashanth Swaminathan unsigned i;
60*1fd5a2e1SPrashanth Swaminathan ffi_type **tp = cif->arg_types;
61*1fd5a2e1SPrashanth Swaminathan
62*1fd5a2e1SPrashanth Swaminathan #if WORDS_BIGENDIAN
63*1fd5a2e1SPrashanth Swaminathan
64*1fd5a2e1SPrashanth Swaminathan for (i = 0; i < cif->nargs; i++, tp++, args++)
65*1fd5a2e1SPrashanth Swaminathan {
66*1fd5a2e1SPrashanth Swaminathan switch ((*tp)->type)
67*1fd5a2e1SPrashanth Swaminathan {
68*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT8:
69*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT8:
70*1fd5a2e1SPrashanth Swaminathan *args = (void*) ((char*)(raw++) + FFI_SIZEOF_ARG - 1);
71*1fd5a2e1SPrashanth Swaminathan break;
72*1fd5a2e1SPrashanth Swaminathan
73*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT16:
74*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT16:
75*1fd5a2e1SPrashanth Swaminathan *args = (void*) ((char*)(raw++) + FFI_SIZEOF_ARG - 2);
76*1fd5a2e1SPrashanth Swaminathan break;
77*1fd5a2e1SPrashanth Swaminathan
78*1fd5a2e1SPrashanth Swaminathan #if FFI_SIZEOF_ARG >= 4
79*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT32:
80*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT32:
81*1fd5a2e1SPrashanth Swaminathan *args = (void*) ((char*)(raw++) + FFI_SIZEOF_ARG - 4);
82*1fd5a2e1SPrashanth Swaminathan break;
83*1fd5a2e1SPrashanth Swaminathan #endif
84*1fd5a2e1SPrashanth Swaminathan
85*1fd5a2e1SPrashanth Swaminathan #if !FFI_NO_STRUCTS
86*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_STRUCT:
87*1fd5a2e1SPrashanth Swaminathan *args = (raw++)->ptr;
88*1fd5a2e1SPrashanth Swaminathan break;
89*1fd5a2e1SPrashanth Swaminathan #endif
90*1fd5a2e1SPrashanth Swaminathan
91*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_COMPLEX:
92*1fd5a2e1SPrashanth Swaminathan *args = (raw++)->ptr;
93*1fd5a2e1SPrashanth Swaminathan break;
94*1fd5a2e1SPrashanth Swaminathan
95*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_POINTER:
96*1fd5a2e1SPrashanth Swaminathan *args = (void*) &(raw++)->ptr;
97*1fd5a2e1SPrashanth Swaminathan break;
98*1fd5a2e1SPrashanth Swaminathan
99*1fd5a2e1SPrashanth Swaminathan default:
100*1fd5a2e1SPrashanth Swaminathan *args = raw;
101*1fd5a2e1SPrashanth Swaminathan raw += FFI_ALIGN ((*tp)->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
102*1fd5a2e1SPrashanth Swaminathan }
103*1fd5a2e1SPrashanth Swaminathan }
104*1fd5a2e1SPrashanth Swaminathan
105*1fd5a2e1SPrashanth Swaminathan #else /* WORDS_BIGENDIAN */
106*1fd5a2e1SPrashanth Swaminathan
107*1fd5a2e1SPrashanth Swaminathan #if !PDP
108*1fd5a2e1SPrashanth Swaminathan
109*1fd5a2e1SPrashanth Swaminathan /* then assume little endian */
110*1fd5a2e1SPrashanth Swaminathan for (i = 0; i < cif->nargs; i++, tp++, args++)
111*1fd5a2e1SPrashanth Swaminathan {
112*1fd5a2e1SPrashanth Swaminathan #if !FFI_NO_STRUCTS
113*1fd5a2e1SPrashanth Swaminathan if ((*tp)->type == FFI_TYPE_STRUCT)
114*1fd5a2e1SPrashanth Swaminathan {
115*1fd5a2e1SPrashanth Swaminathan *args = (raw++)->ptr;
116*1fd5a2e1SPrashanth Swaminathan }
117*1fd5a2e1SPrashanth Swaminathan else
118*1fd5a2e1SPrashanth Swaminathan #endif
119*1fd5a2e1SPrashanth Swaminathan if ((*tp)->type == FFI_TYPE_COMPLEX)
120*1fd5a2e1SPrashanth Swaminathan {
121*1fd5a2e1SPrashanth Swaminathan *args = (raw++)->ptr;
122*1fd5a2e1SPrashanth Swaminathan }
123*1fd5a2e1SPrashanth Swaminathan else
124*1fd5a2e1SPrashanth Swaminathan {
125*1fd5a2e1SPrashanth Swaminathan *args = (void*) raw;
126*1fd5a2e1SPrashanth Swaminathan raw += FFI_ALIGN ((*tp)->size, sizeof (void*)) / sizeof (void*);
127*1fd5a2e1SPrashanth Swaminathan }
128*1fd5a2e1SPrashanth Swaminathan }
129*1fd5a2e1SPrashanth Swaminathan
130*1fd5a2e1SPrashanth Swaminathan #else
131*1fd5a2e1SPrashanth Swaminathan #error "pdp endian not supported"
132*1fd5a2e1SPrashanth Swaminathan #endif /* ! PDP */
133*1fd5a2e1SPrashanth Swaminathan
134*1fd5a2e1SPrashanth Swaminathan #endif /* WORDS_BIGENDIAN */
135*1fd5a2e1SPrashanth Swaminathan }
136*1fd5a2e1SPrashanth Swaminathan
137*1fd5a2e1SPrashanth Swaminathan void
ffi_ptrarray_to_raw(ffi_cif * cif,void ** args,ffi_raw * raw)138*1fd5a2e1SPrashanth Swaminathan ffi_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw)
139*1fd5a2e1SPrashanth Swaminathan {
140*1fd5a2e1SPrashanth Swaminathan unsigned i;
141*1fd5a2e1SPrashanth Swaminathan ffi_type **tp = cif->arg_types;
142*1fd5a2e1SPrashanth Swaminathan
143*1fd5a2e1SPrashanth Swaminathan for (i = 0; i < cif->nargs; i++, tp++, args++)
144*1fd5a2e1SPrashanth Swaminathan {
145*1fd5a2e1SPrashanth Swaminathan switch ((*tp)->type)
146*1fd5a2e1SPrashanth Swaminathan {
147*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT8:
148*1fd5a2e1SPrashanth Swaminathan (raw++)->uint = *(UINT8*) (*args);
149*1fd5a2e1SPrashanth Swaminathan break;
150*1fd5a2e1SPrashanth Swaminathan
151*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT8:
152*1fd5a2e1SPrashanth Swaminathan (raw++)->sint = *(SINT8*) (*args);
153*1fd5a2e1SPrashanth Swaminathan break;
154*1fd5a2e1SPrashanth Swaminathan
155*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT16:
156*1fd5a2e1SPrashanth Swaminathan (raw++)->uint = *(UINT16*) (*args);
157*1fd5a2e1SPrashanth Swaminathan break;
158*1fd5a2e1SPrashanth Swaminathan
159*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT16:
160*1fd5a2e1SPrashanth Swaminathan (raw++)->sint = *(SINT16*) (*args);
161*1fd5a2e1SPrashanth Swaminathan break;
162*1fd5a2e1SPrashanth Swaminathan
163*1fd5a2e1SPrashanth Swaminathan #if FFI_SIZEOF_ARG >= 4
164*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT32:
165*1fd5a2e1SPrashanth Swaminathan (raw++)->uint = *(UINT32*) (*args);
166*1fd5a2e1SPrashanth Swaminathan break;
167*1fd5a2e1SPrashanth Swaminathan
168*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT32:
169*1fd5a2e1SPrashanth Swaminathan (raw++)->sint = *(SINT32*) (*args);
170*1fd5a2e1SPrashanth Swaminathan break;
171*1fd5a2e1SPrashanth Swaminathan #endif
172*1fd5a2e1SPrashanth Swaminathan
173*1fd5a2e1SPrashanth Swaminathan #if !FFI_NO_STRUCTS
174*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_STRUCT:
175*1fd5a2e1SPrashanth Swaminathan (raw++)->ptr = *args;
176*1fd5a2e1SPrashanth Swaminathan break;
177*1fd5a2e1SPrashanth Swaminathan #endif
178*1fd5a2e1SPrashanth Swaminathan
179*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_COMPLEX:
180*1fd5a2e1SPrashanth Swaminathan (raw++)->ptr = *args;
181*1fd5a2e1SPrashanth Swaminathan break;
182*1fd5a2e1SPrashanth Swaminathan
183*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_POINTER:
184*1fd5a2e1SPrashanth Swaminathan (raw++)->ptr = **(void***) args;
185*1fd5a2e1SPrashanth Swaminathan break;
186*1fd5a2e1SPrashanth Swaminathan
187*1fd5a2e1SPrashanth Swaminathan default:
188*1fd5a2e1SPrashanth Swaminathan memcpy ((void*) raw->data, (void*)*args, (*tp)->size);
189*1fd5a2e1SPrashanth Swaminathan raw += FFI_ALIGN ((*tp)->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
190*1fd5a2e1SPrashanth Swaminathan }
191*1fd5a2e1SPrashanth Swaminathan }
192*1fd5a2e1SPrashanth Swaminathan }
193*1fd5a2e1SPrashanth Swaminathan
194*1fd5a2e1SPrashanth Swaminathan #if !FFI_NATIVE_RAW_API
195*1fd5a2e1SPrashanth Swaminathan
196*1fd5a2e1SPrashanth Swaminathan
197*1fd5a2e1SPrashanth Swaminathan /* This is a generic definition of ffi_raw_call, to be used if the
198*1fd5a2e1SPrashanth Swaminathan * native system does not provide a machine-specific implementation.
199*1fd5a2e1SPrashanth Swaminathan * Having this, allows code to be written for the raw API, without
200*1fd5a2e1SPrashanth Swaminathan * the need for system-specific code to handle input in that format;
201*1fd5a2e1SPrashanth Swaminathan * these following couple of functions will handle the translation forth
202*1fd5a2e1SPrashanth Swaminathan * and back automatically. */
203*1fd5a2e1SPrashanth Swaminathan
ffi_raw_call(ffi_cif * cif,void (* fn)(void),void * rvalue,ffi_raw * raw)204*1fd5a2e1SPrashanth Swaminathan void ffi_raw_call (ffi_cif *cif, void (*fn)(void), void *rvalue, ffi_raw *raw)
205*1fd5a2e1SPrashanth Swaminathan {
206*1fd5a2e1SPrashanth Swaminathan void **avalue = (void**) alloca (cif->nargs * sizeof (void*));
207*1fd5a2e1SPrashanth Swaminathan ffi_raw_to_ptrarray (cif, raw, avalue);
208*1fd5a2e1SPrashanth Swaminathan ffi_call (cif, fn, rvalue, avalue);
209*1fd5a2e1SPrashanth Swaminathan }
210*1fd5a2e1SPrashanth Swaminathan
211*1fd5a2e1SPrashanth Swaminathan #if FFI_CLOSURES /* base system provides closures */
212*1fd5a2e1SPrashanth Swaminathan
213*1fd5a2e1SPrashanth Swaminathan static void
ffi_translate_args(ffi_cif * cif,void * rvalue,void ** avalue,void * user_data)214*1fd5a2e1SPrashanth Swaminathan ffi_translate_args (ffi_cif *cif, void *rvalue,
215*1fd5a2e1SPrashanth Swaminathan void **avalue, void *user_data)
216*1fd5a2e1SPrashanth Swaminathan {
217*1fd5a2e1SPrashanth Swaminathan ffi_raw *raw = (ffi_raw*)alloca (ffi_raw_size (cif));
218*1fd5a2e1SPrashanth Swaminathan ffi_raw_closure *cl = (ffi_raw_closure*)user_data;
219*1fd5a2e1SPrashanth Swaminathan
220*1fd5a2e1SPrashanth Swaminathan ffi_ptrarray_to_raw (cif, avalue, raw);
221*1fd5a2e1SPrashanth Swaminathan (*cl->fun) (cif, rvalue, raw, cl->user_data);
222*1fd5a2e1SPrashanth Swaminathan }
223*1fd5a2e1SPrashanth Swaminathan
224*1fd5a2e1SPrashanth Swaminathan ffi_status
ffi_prep_raw_closure_loc(ffi_raw_closure * cl,ffi_cif * cif,void (* fun)(ffi_cif *,void *,ffi_raw *,void *),void * user_data,void * codeloc)225*1fd5a2e1SPrashanth Swaminathan ffi_prep_raw_closure_loc (ffi_raw_closure* cl,
226*1fd5a2e1SPrashanth Swaminathan ffi_cif *cif,
227*1fd5a2e1SPrashanth Swaminathan void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
228*1fd5a2e1SPrashanth Swaminathan void *user_data,
229*1fd5a2e1SPrashanth Swaminathan void *codeloc)
230*1fd5a2e1SPrashanth Swaminathan {
231*1fd5a2e1SPrashanth Swaminathan ffi_status status;
232*1fd5a2e1SPrashanth Swaminathan
233*1fd5a2e1SPrashanth Swaminathan status = ffi_prep_closure_loc ((ffi_closure*) cl,
234*1fd5a2e1SPrashanth Swaminathan cif,
235*1fd5a2e1SPrashanth Swaminathan &ffi_translate_args,
236*1fd5a2e1SPrashanth Swaminathan codeloc,
237*1fd5a2e1SPrashanth Swaminathan codeloc);
238*1fd5a2e1SPrashanth Swaminathan if (status == FFI_OK)
239*1fd5a2e1SPrashanth Swaminathan {
240*1fd5a2e1SPrashanth Swaminathan cl->fun = fun;
241*1fd5a2e1SPrashanth Swaminathan cl->user_data = user_data;
242*1fd5a2e1SPrashanth Swaminathan }
243*1fd5a2e1SPrashanth Swaminathan
244*1fd5a2e1SPrashanth Swaminathan return status;
245*1fd5a2e1SPrashanth Swaminathan }
246*1fd5a2e1SPrashanth Swaminathan
247*1fd5a2e1SPrashanth Swaminathan #endif /* FFI_CLOSURES */
248*1fd5a2e1SPrashanth Swaminathan #endif /* !FFI_NATIVE_RAW_API */
249*1fd5a2e1SPrashanth Swaminathan
250*1fd5a2e1SPrashanth Swaminathan #if FFI_CLOSURES
251*1fd5a2e1SPrashanth Swaminathan
252*1fd5a2e1SPrashanth Swaminathan /* Again, here is the generic version of ffi_prep_raw_closure, which
253*1fd5a2e1SPrashanth Swaminathan * will install an intermediate "hub" for translation of arguments from
254*1fd5a2e1SPrashanth Swaminathan * the pointer-array format, to the raw format */
255*1fd5a2e1SPrashanth Swaminathan
256*1fd5a2e1SPrashanth Swaminathan ffi_status
ffi_prep_raw_closure(ffi_raw_closure * cl,ffi_cif * cif,void (* fun)(ffi_cif *,void *,ffi_raw *,void *),void * user_data)257*1fd5a2e1SPrashanth Swaminathan ffi_prep_raw_closure (ffi_raw_closure* cl,
258*1fd5a2e1SPrashanth Swaminathan ffi_cif *cif,
259*1fd5a2e1SPrashanth Swaminathan void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
260*1fd5a2e1SPrashanth Swaminathan void *user_data)
261*1fd5a2e1SPrashanth Swaminathan {
262*1fd5a2e1SPrashanth Swaminathan return ffi_prep_raw_closure_loc (cl, cif, fun, user_data, cl);
263*1fd5a2e1SPrashanth Swaminathan }
264*1fd5a2e1SPrashanth Swaminathan
265*1fd5a2e1SPrashanth Swaminathan #endif /* FFI_CLOSURES */
266*1fd5a2e1SPrashanth Swaminathan
267*1fd5a2e1SPrashanth Swaminathan #endif /* !FFI_NO_RAW_API */
268