xref: /aosp_15_r20/external/libffi/src/raw_api.c (revision 1fd5a2e1d639cd1ddf29dd0c484c123bbd850c21)
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