ยปCore Development>Code coverage>Modules/_ctypes/libffi_arm_wince/ffi.c

Python code coverage for Modules/_ctypes/libffi_arm_wince/ffi.c

#countcontent
1n/a/* -----------------------------------------------------------------------
2n/a ffi.c - Copyright (c) 1998 Red Hat, Inc.
3n/a
4n/a ARM Foreign Function Interface
5n/a
6n/a Permission is hereby granted, free of charge, to any person obtaining
7n/a a copy of this software and associated documentation files (the
8n/a ``Software''), to deal in the Software without restriction, including
9n/a without limitation the rights to use, copy, modify, merge, publish,
10n/a distribute, sublicense, and/or sell copies of the Software, and to
11n/a permit persons to whom the Software is furnished to do so, subject to
12n/a the following conditions:
13n/a
14n/a The above copyright notice and this permission notice shall be included
15n/a in all copies or substantial portions of the Software.
16n/a
17n/a THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
18n/a OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19n/a MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20n/a IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21n/a OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22n/a ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23n/a OTHER DEALINGS IN THE SOFTWARE.
24n/a ----------------------------------------------------------------------- */
25n/a
26n/a#include <ffi.h>
27n/a#include <ffi_common.h>
28n/a
29n/a#include <stdlib.h>
30n/a
31n/a#ifdef _WIN32_WCE
32n/a#pragma warning (disable : 4142) /* benign redefinition of type */
33n/a#include <windows.h>
34n/a#endif
35n/a
36n/a/* ffi_prep_args is called by the assembly routine once stack space
37n/a has been allocated for the function's arguments */
38n/a
39n/a/*@-exportheader@*/
40n/avoid ffi_prep_args(char *stack, extended_cif *ecif)
41n/a/*@=exportheader@*/
42n/a{
43n/a register unsigned int i;
44n/a register void **p_argv;
45n/a register char *argp;
46n/a register ffi_type **p_arg;
47n/a
48n/a argp = stack;
49n/a
50n/a if ( ecif->cif->rtype->type == FFI_TYPE_STRUCT ) {
51n/a *(void **) argp = ecif->rvalue;
52n/a argp += 4;
53n/a }
54n/a
55n/a p_argv = ecif->avalue;
56n/a
57n/a for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
58n/a (i != 0);
59n/a i--, p_arg++)
60n/a {
61n/a size_t z;
62n/a size_t argalign = (*p_arg)->alignment;
63n/a
64n/a#ifdef _WIN32_WCE
65n/a if (argalign > 4)
66n/a argalign = 4;
67n/a#endif
68n/a /* Align if necessary */
69n/a if ((argalign - 1) & (unsigned) argp) {
70n/a argp = (char *) ALIGN(argp, argalign);
71n/a }
72n/a
73n/a z = (*p_arg)->size;
74n/a if (z < sizeof(int))
75n/a {
76n/a z = sizeof(int);
77n/a switch ((*p_arg)->type)
78n/a {
79n/a case FFI_TYPE_SINT8:
80n/a *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
81n/a break;
82n/a
83n/a case FFI_TYPE_UINT8:
84n/a *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
85n/a break;
86n/a
87n/a case FFI_TYPE_SINT16:
88n/a *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
89n/a break;
90n/a
91n/a case FFI_TYPE_UINT16:
92n/a *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
93n/a break;
94n/a
95n/a case FFI_TYPE_STRUCT:
96n/a /* *p_argv may not be aligned for a UINT32 */
97n/a memcpy(argp, *p_argv, z);
98n/a break;
99n/a
100n/a default:
101n/a FFI_ASSERT(0);
102n/a }
103n/a }
104n/a else if (z == sizeof(int))
105n/a {
106n/a *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
107n/a }
108n/a else
109n/a {
110n/a memcpy(argp, *p_argv, z);
111n/a }
112n/a p_argv++;
113n/a argp += z;
114n/a }
115n/a
116n/a return;
117n/a}
118n/a
119n/a/* Perform machine dependent cif processing */
120n/affi_status ffi_prep_cif_machdep(ffi_cif *cif)
121n/a{
122n/a /* Set the return type flag */
123n/a switch (cif->rtype->type)
124n/a {
125n/a case FFI_TYPE_VOID:
126n/a case FFI_TYPE_STRUCT:
127n/a case FFI_TYPE_FLOAT:
128n/a case FFI_TYPE_DOUBLE:
129n/a case FFI_TYPE_SINT64:
130n/a cif->flags = (unsigned) cif->rtype->type;
131n/a break;
132n/a
133n/a case FFI_TYPE_UINT64:
134n/a cif->flags = FFI_TYPE_SINT64;
135n/a break;
136n/a
137n/a default:
138n/a cif->flags = FFI_TYPE_INT;
139n/a break;
140n/a }
141n/a
142n/a return FFI_OK;
143n/a}
144n/a
145n/a/*@-declundef@*/
146n/a/*@-exportheader@*/
147n/aextern void ffi_call_SYSV(void (*)(char *, extended_cif *),
148n/a /*@out@*/ extended_cif *,
149n/a unsigned, unsigned,
150n/a /*@out@*/ unsigned *,
151n/a void (*fn)());
152n/a/*@=declundef@*/
153n/a/*@=exportheader@*/
154n/a
155n/a/* Return type changed from void for ctypes */
156n/aint ffi_call(/*@dependent@*/ ffi_cif *cif,
157n/a void (*fn)(),
158n/a /*@out@*/ void *rvalue,
159n/a /*@dependent@*/ void **avalue)
160n/a{
161n/a extended_cif ecif;
162n/a
163n/a ecif.cif = cif;
164n/a ecif.avalue = avalue;
165n/a
166n/a /* If the return value is a struct and we don't have a return */
167n/a /* value address then we need to make one */
168n/a
169n/a if ((rvalue == NULL) &&
170n/a (cif->rtype->type == FFI_TYPE_STRUCT))
171n/a {
172n/a /*@-sysunrecog@*/
173n/a ecif.rvalue = alloca(cif->rtype->size);
174n/a /*@=sysunrecog@*/
175n/a }
176n/a else
177n/a ecif.rvalue = rvalue;
178n/a
179n/a
180n/a switch (cif->abi)
181n/a {
182n/a case FFI_SYSV:
183n/a /*@-usedef@*/
184n/a ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes,
185n/a cif->flags, ecif.rvalue, fn);
186n/a /*@=usedef@*/
187n/a break;
188n/a default:
189n/a FFI_ASSERT(0);
190n/a break;
191n/a }
192n/a /* I think calculating the real stack pointer delta is not useful
193n/a because stdcall is not supported */
194n/a return 0;
195n/a}
196n/a
197n/a/** private members **/
198n/a
199n/astatic void ffi_prep_incoming_args_SYSV (char *stack, void **ret,
200n/a void** args, ffi_cif* cif);
201n/a
202n/a/* This function is called by ffi_closure_SYSV in sysv.asm */
203n/a
204n/aunsigned int
205n/affi_closure_SYSV_inner (ffi_closure *closure, char *in_args, void *rvalue)
206n/a{
207n/a ffi_cif *cif = closure->cif;
208n/a void **out_args;
209n/a
210n/a out_args = (void **) alloca(cif->nargs * sizeof (void *));
211n/a
212n/a /* this call will initialize out_args, such that each
213n/a * element in that array points to the corresponding
214n/a * value on the stack; and if the function returns
215n/a * a structure, it will re-set rvalue to point to the
216n/a * structure return address. */
217n/a
218n/a ffi_prep_incoming_args_SYSV(in_args, &rvalue, out_args, cif);
219n/a
220n/a (closure->fun)(cif, rvalue, out_args, closure->user_data);
221n/a
222n/a /* Tell ffi_closure_SYSV what the returntype is */
223n/a return cif->flags;
224n/a}
225n/a
226n/a/*@-exportheader@*/
227n/astatic void
228n/affi_prep_incoming_args_SYSV(char *stack, void **rvalue,
229n/a void **avalue, ffi_cif *cif)
230n/a/*@=exportheader@*/
231n/a{
232n/a unsigned int i;
233n/a void **p_argv;
234n/a char *argp;
235n/a ffi_type **p_arg;
236n/a
237n/a argp = stack;
238n/a
239n/a if ( cif->rtype->type == FFI_TYPE_STRUCT ) {
240n/a *rvalue = *(void **) argp;
241n/a argp += 4;
242n/a }
243n/a
244n/a p_argv = avalue;
245n/a
246n/a for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++)
247n/a {
248n/a size_t z;
249n/a size_t argalign = (*p_arg)->alignment;
250n/a
251n/a#ifdef _WIN32_WCE
252n/a if (argalign > 4)
253n/a argalign = 4;
254n/a#endif
255n/a /* Align if necessary */
256n/a if ((argalign - 1) & (unsigned) argp) {
257n/a argp = (char *) ALIGN(argp, argalign);
258n/a }
259n/a
260n/a z = (*p_arg)->size;
261n/a if (z < sizeof(int))
262n/a z = sizeof(int);
263n/a
264n/a *p_argv = (void*) argp;
265n/a
266n/a p_argv++;
267n/a argp += z;
268n/a }
269n/a}
270n/a
271n/a/*
272n/a add ip, pc, #-8 ; ip = address of this trampoline == address of ffi_closure
273n/a ldr pc, [pc, #-4] ; jump to __fun
274n/a DCD __fun
275n/a*/
276n/a#define FFI_INIT_TRAMPOLINE(TRAMP,FUN) \
277n/a{ \
278n/a unsigned int *__tramp = (unsigned int *)(TRAMP); \
279n/a __tramp[0] = 0xe24fc008; /* add ip, pc, #-8 */ \
280n/a __tramp[1] = 0xe51ff004; /* ldr pc, [pc, #-4] */ \
281n/a __tramp[2] = (unsigned int)(FUN); \
282n/a }
283n/a
284n/a/* the cif must already be prep'ed */
285n/a
286n/a/* defined in sysv.asm */
287n/avoid ffi_closure_SYSV(void);
288n/a
289n/affi_status
290n/affi_prep_closure (ffi_closure* closure,
291n/a ffi_cif* cif,
292n/a void (*fun)(ffi_cif*,void*,void**,void*),
293n/a void *user_data)
294n/a{
295n/a FFI_ASSERT (cif->abi == FFI_SYSV);
296n/a
297n/a FFI_INIT_TRAMPOLINE (&closure->tramp[0], &ffi_closure_SYSV);
298n/a
299n/a closure->cif = cif;
300n/a closure->user_data = user_data;
301n/a closure->fun = fun;
302n/a
303n/a#ifdef _WIN32_WCE
304n/a /* This is important to allow calling the trampoline safely */
305n/a FlushInstructionCache(GetCurrentProcess(), 0, 0);
306n/a#endif
307n/a
308n/a return FFI_OK;
309n/a}
310n/a