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

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

#countcontent
1n/a/* -----------------------------------------------------------------------
2n/a ffi.c - Copyright (c) 1996, 1998, 1999, 2001 Red Hat, Inc.
3n/a Copyright (c) 2002 Ranjit Mathew
4n/a Copyright (c) 2002 Bo Thorsen
5n/a Copyright (c) 2002 Roger Sayle
6n/a
7n/a x86 Foreign Function Interface
8n/a
9n/a Permission is hereby granted, free of charge, to any person obtaining
10n/a a copy of this software and associated documentation files (the
11n/a ``Software''), to deal in the Software without restriction, including
12n/a without limitation the rights to use, copy, modify, merge, publish,
13n/a distribute, sublicense, and/or sell copies of the Software, and to
14n/a permit persons to whom the Software is furnished to do so, subject to
15n/a the following conditions:
16n/a
17n/a The above copyright notice and this permission notice shall be included
18n/a in all copies or substantial portions of the Software.
19n/a
20n/a THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
21n/a OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22n/a MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23n/a IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
24n/a OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
25n/a ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
26n/a OTHER DEALINGS IN THE SOFTWARE.
27n/a ----------------------------------------------------------------------- */
28n/a
29n/a#include <ffi.h>
30n/a#include <ffi_common.h>
31n/a
32n/a#include <stdlib.h>
33n/a
34n/a/* ffi_prep_args is called by the assembly routine once stack space
35n/a has been allocated for the function's arguments */
36n/a
37n/aextern void Py_FatalError(const char *msg);
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 if (ecif->cif->rtype->type == FFI_TYPE_STRUCT)
50n/a {
51n/a *(void **) argp = ecif->rvalue;
52n/a argp += sizeof(void *);
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
63n/a /* Align if necessary */
64n/a if ((sizeof(void *) - 1) & (size_t) argp)
65n/a argp = (char *) ALIGN(argp, sizeof(void *));
66n/a
67n/a z = (*p_arg)->size;
68n/a if (z < sizeof(intptr_t))
69n/a {
70n/a z = sizeof(intptr_t);
71n/a switch ((*p_arg)->type)
72n/a {
73n/a case FFI_TYPE_SINT8:
74n/a *(intptr_t *) argp = (intptr_t)*(SINT8 *)(* p_argv);
75n/a break;
76n/a
77n/a case FFI_TYPE_UINT8:
78n/a *(uintptr_t *) argp = (uintptr_t)*(UINT8 *)(* p_argv);
79n/a break;
80n/a
81n/a case FFI_TYPE_SINT16:
82n/a *(intptr_t *) argp = (intptr_t)*(SINT16 *)(* p_argv);
83n/a break;
84n/a
85n/a case FFI_TYPE_UINT16:
86n/a *(uintptr_t *) argp = (uintptr_t)*(UINT16 *)(* p_argv);
87n/a break;
88n/a
89n/a case FFI_TYPE_SINT32:
90n/a *(intptr_t *) argp = (intptr_t)*(SINT32 *)(* p_argv);
91n/a break;
92n/a
93n/a case FFI_TYPE_UINT32:
94n/a *(uintptr_t *) argp = (uintptr_t)*(UINT32 *)(* p_argv);
95n/a break;
96n/a
97n/a case FFI_TYPE_FLOAT:
98n/a *(uintptr_t *) argp = 0;
99n/a *(float *) argp = *(float *)(* p_argv);
100n/a break;
101n/a
102n/a // 64-bit value cases should never be used for x86 and AMD64 builds
103n/a case FFI_TYPE_SINT64:
104n/a *(intptr_t *) argp = (intptr_t)*(SINT64 *)(* p_argv);
105n/a break;
106n/a
107n/a case FFI_TYPE_UINT64:
108n/a *(uintptr_t *) argp = (uintptr_t)*(UINT64 *)(* p_argv);
109n/a break;
110n/a
111n/a case FFI_TYPE_STRUCT:
112n/a *(uintptr_t *) argp = (uintptr_t)*(UINT32 *)(* p_argv);
113n/a break;
114n/a
115n/a case FFI_TYPE_DOUBLE:
116n/a *(uintptr_t *) argp = 0;
117n/a *(double *) argp = *(double *)(* p_argv);
118n/a break;
119n/a
120n/a default:
121n/a FFI_ASSERT(0);
122n/a }
123n/a }
124n/a#ifdef _WIN64
125n/a else if (z > 8)
126n/a {
127n/a /* On Win64, if a single argument takes more than 8 bytes,
128n/a then it is always passed by reference. */
129n/a *(void **)argp = *p_argv;
130n/a z = 8;
131n/a }
132n/a#endif
133n/a else
134n/a {
135n/a memcpy(argp, *p_argv, z);
136n/a }
137n/a p_argv++;
138n/a argp += z;
139n/a }
140n/a
141n/a if (argp >= stack && (unsigned)(argp - stack) > ecif->cif->bytes)
142n/a {
143n/a Py_FatalError("FFI BUG: not enough stack space for arguments");
144n/a }
145n/a return;
146n/a}
147n/a
148n/a/* Perform machine dependent cif processing */
149n/affi_status ffi_prep_cif_machdep(ffi_cif *cif)
150n/a{
151n/a /* Set the return type flag */
152n/a switch (cif->rtype->type)
153n/a {
154n/a case FFI_TYPE_VOID:
155n/a case FFI_TYPE_SINT64:
156n/a case FFI_TYPE_FLOAT:
157n/a case FFI_TYPE_DOUBLE:
158n/a case FFI_TYPE_LONGDOUBLE:
159n/a cif->flags = (unsigned) cif->rtype->type;
160n/a break;
161n/a
162n/a case FFI_TYPE_STRUCT:
163n/a /* MSVC returns small structures in registers. Put in cif->flags
164n/a the value FFI_TYPE_STRUCT only if the structure is big enough;
165n/a otherwise, put the 4- or 8-bytes integer type. */
166n/a if (cif->rtype->size <= 4)
167n/a cif->flags = FFI_TYPE_INT;
168n/a else if (cif->rtype->size <= 8)
169n/a cif->flags = FFI_TYPE_SINT64;
170n/a else
171n/a cif->flags = FFI_TYPE_STRUCT;
172n/a break;
173n/a
174n/a case FFI_TYPE_UINT64:
175n/a#ifdef _WIN64
176n/a case FFI_TYPE_POINTER:
177n/a#endif
178n/a cif->flags = FFI_TYPE_SINT64;
179n/a break;
180n/a
181n/a default:
182n/a cif->flags = FFI_TYPE_INT;
183n/a break;
184n/a }
185n/a
186n/a return FFI_OK;
187n/a}
188n/a
189n/a#ifdef _WIN32
190n/aextern int
191n/affi_call_x86(void (*)(char *, extended_cif *),
192n/a /*@out@*/ extended_cif *,
193n/a unsigned, unsigned,
194n/a /*@out@*/ unsigned *,
195n/a void (*fn)());
196n/a#endif
197n/a
198n/a#ifdef _WIN64
199n/aextern int
200n/affi_call_AMD64(void (*)(char *, extended_cif *),
201n/a /*@out@*/ extended_cif *,
202n/a unsigned, unsigned,
203n/a /*@out@*/ unsigned *,
204n/a void (*fn)());
205n/a#endif
206n/a
207n/aint
208n/affi_call(/*@dependent@*/ ffi_cif *cif,
209n/a void (*fn)(),
210n/a /*@out@*/ void *rvalue,
211n/a /*@dependent@*/ void **avalue)
212n/a{
213n/a extended_cif ecif;
214n/a
215n/a ecif.cif = cif;
216n/a ecif.avalue = avalue;
217n/a
218n/a /* If the return value is a struct and we don't have a return */
219n/a /* value address then we need to make one */
220n/a
221n/a if ((rvalue == NULL) &&
222n/a (cif->rtype->type == FFI_TYPE_STRUCT))
223n/a {
224n/a /*@-sysunrecog@*/
225n/a ecif.rvalue = alloca(cif->rtype->size);
226n/a /*@=sysunrecog@*/
227n/a }
228n/a else
229n/a ecif.rvalue = rvalue;
230n/a
231n/a
232n/a switch (cif->abi)
233n/a {
234n/a#if !defined(_WIN64)
235n/a case FFI_SYSV:
236n/a case FFI_STDCALL:
237n/a return ffi_call_x86(ffi_prep_args, &ecif, cif->bytes,
238n/a cif->flags, ecif.rvalue, fn);
239n/a break;
240n/a#else
241n/a case FFI_SYSV:
242n/a /*@-usedef@*/
243n/a return ffi_call_AMD64(ffi_prep_args, &ecif, cif->bytes,
244n/a cif->flags, ecif.rvalue, fn);
245n/a /*@=usedef@*/
246n/a break;
247n/a#endif
248n/a
249n/a default:
250n/a FFI_ASSERT(0);
251n/a break;
252n/a }
253n/a return -1; /* theller: Hrm. */
254n/a}
255n/a
256n/a
257n/a/** private members **/
258n/a
259n/astatic void ffi_prep_incoming_args_SYSV (char *stack, void **ret,
260n/a void** args, ffi_cif* cif);
261n/a/* This function is jumped to by the trampoline */
262n/a
263n/a#ifdef _WIN64
264n/avoid *
265n/a#else
266n/astatic void __fastcall
267n/a#endif
268n/affi_closure_SYSV (ffi_closure *closure, char *argp)
269n/a{
270n/a // this is our return value storage
271n/a long double res;
272n/a
273n/a // our various things...
274n/a ffi_cif *cif;
275n/a void **arg_area;
276n/a unsigned short rtype;
277n/a void *resp = (void*)&res;
278n/a void *args = argp + sizeof(void*);
279n/a
280n/a cif = closure->cif;
281n/a arg_area = (void**) alloca (cif->nargs * sizeof (void*));
282n/a
283n/a /* this call will initialize ARG_AREA, such that each
284n/a * element in that array points to the corresponding
285n/a * value on the stack; and if the function returns
286n/a * a structure, it will re-set RESP to point to the
287n/a * structure return address. */
288n/a
289n/a ffi_prep_incoming_args_SYSV(args, (void**)&resp, arg_area, cif);
290n/a
291n/a (closure->fun) (cif, resp, arg_area, closure->user_data);
292n/a
293n/a rtype = cif->flags;
294n/a
295n/a#if defined(_WIN32) && !defined(_WIN64)
296n/a#ifdef _MSC_VER
297n/a /* now, do a generic return based on the value of rtype */
298n/a if (rtype == FFI_TYPE_INT)
299n/a {
300n/a _asm mov eax, resp ;
301n/a _asm mov eax, [eax] ;
302n/a }
303n/a else if (rtype == FFI_TYPE_FLOAT)
304n/a {
305n/a _asm mov eax, resp ;
306n/a _asm fld DWORD PTR [eax] ;
307n/a// asm ("flds (%0)" : : "r" (resp) : "st" );
308n/a }
309n/a else if (rtype == FFI_TYPE_DOUBLE)
310n/a {
311n/a _asm mov eax, resp ;
312n/a _asm fld QWORD PTR [eax] ;
313n/a// asm ("fldl (%0)" : : "r" (resp) : "st", "st(1)" );
314n/a }
315n/a else if (rtype == FFI_TYPE_LONGDOUBLE)
316n/a {
317n/a// asm ("fldt (%0)" : : "r" (resp) : "st", "st(1)" );
318n/a }
319n/a else if (rtype == FFI_TYPE_SINT64)
320n/a {
321n/a _asm mov edx, resp ;
322n/a _asm mov eax, [edx] ;
323n/a _asm mov edx, [edx + 4] ;
324n/a// asm ("movl 0(%0),%%eax;"
325n/a// "movl 4(%0),%%edx"
326n/a// : : "r"(resp)
327n/a// : "eax", "edx");
328n/a }
329n/a#else
330n/a /* now, do a generic return based on the value of rtype */
331n/a if (rtype == FFI_TYPE_INT)
332n/a {
333n/a asm ("movl (%0),%%eax" : : "r" (resp) : "eax");
334n/a }
335n/a else if (rtype == FFI_TYPE_FLOAT)
336n/a {
337n/a asm ("flds (%0)" : : "r" (resp) : "st" );
338n/a }
339n/a else if (rtype == FFI_TYPE_DOUBLE)
340n/a {
341n/a asm ("fldl (%0)" : : "r" (resp) : "st", "st(1)" );
342n/a }
343n/a else if (rtype == FFI_TYPE_LONGDOUBLE)
344n/a {
345n/a asm ("fldt (%0)" : : "r" (resp) : "st", "st(1)" );
346n/a }
347n/a else if (rtype == FFI_TYPE_SINT64)
348n/a {
349n/a asm ("movl 0(%0),%%eax;"
350n/a "movl 4(%0),%%edx"
351n/a : : "r"(resp)
352n/a : "eax", "edx");
353n/a }
354n/a#endif
355n/a#endif
356n/a
357n/a#ifdef _WIN64
358n/a /* The result is returned in rax. This does the right thing for
359n/a result types except for floats; we have to 'mov xmm0, rax' in the
360n/a caller to correct this.
361n/a */
362n/a return *(void **)resp;
363n/a#endif
364n/a}
365n/a
366n/a/*@-exportheader@*/
367n/astatic void
368n/affi_prep_incoming_args_SYSV(char *stack, void **rvalue,
369n/a void **avalue, ffi_cif *cif)
370n/a/*@=exportheader@*/
371n/a{
372n/a register unsigned int i;
373n/a register void **p_argv;
374n/a register char *argp;
375n/a register ffi_type **p_arg;
376n/a
377n/a argp = stack;
378n/a
379n/a if ( cif->rtype->type == FFI_TYPE_STRUCT ) {
380n/a *rvalue = *(void **) argp;
381n/a argp += sizeof(void *);
382n/a }
383n/a
384n/a p_argv = avalue;
385n/a
386n/a for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++)
387n/a {
388n/a size_t z;
389n/a
390n/a /* Align if necessary */
391n/a if ((sizeof(char *) - 1) & (size_t) argp) {
392n/a argp = (char *) ALIGN(argp, sizeof(char*));
393n/a }
394n/a
395n/a z = (*p_arg)->size;
396n/a
397n/a /* because we're little endian, this is what it turns into. */
398n/a
399n/a#ifdef _WIN64
400n/a if (z > 8) {
401n/a /* On Win64, if a single argument takes more than 8 bytes,
402n/a * then it is always passed by reference.
403n/a */
404n/a *p_argv = *((void**) argp);
405n/a z = 8;
406n/a }
407n/a else
408n/a#endif
409n/a *p_argv = (void*) argp;
410n/a
411n/a p_argv++;
412n/a argp += z;
413n/a }
414n/a
415n/a return;
416n/a}
417n/a
418n/a/* the cif must already be prep'ed */
419n/aextern void ffi_closure_OUTER();
420n/a
421n/affi_status
422n/affi_prep_closure_loc (ffi_closure* closure,
423n/a ffi_cif* cif,
424n/a void (*fun)(ffi_cif*,void*,void**,void*),
425n/a void *user_data,
426n/a void *codeloc)
427n/a{
428n/a short bytes;
429n/a char *tramp;
430n/a#ifdef _WIN64
431n/a int mask = 0;
432n/a#endif
433n/a FFI_ASSERT (cif->abi == FFI_SYSV);
434n/a
435n/a if (cif->abi == FFI_SYSV)
436n/a bytes = 0;
437n/a#if !defined(_WIN64)
438n/a else if (cif->abi == FFI_STDCALL)
439n/a bytes = cif->bytes;
440n/a#endif
441n/a else
442n/a return FFI_BAD_ABI;
443n/a
444n/a tramp = &closure->tramp[0];
445n/a
446n/a#define BYTES(text) memcpy(tramp, text, sizeof(text)), tramp += sizeof(text)-1
447n/a#define POINTER(x) *(void**)tramp = (void*)(x), tramp += sizeof(void*)
448n/a#define SHORT(x) *(short*)tramp = x, tramp += sizeof(short)
449n/a#define INT(x) *(int*)tramp = x, tramp += sizeof(int)
450n/a
451n/a#ifdef _WIN64
452n/a if (cif->nargs >= 1 &&
453n/a (cif->arg_types[0]->type == FFI_TYPE_FLOAT
454n/a || cif->arg_types[0]->type == FFI_TYPE_DOUBLE))
455n/a mask |= 1;
456n/a if (cif->nargs >= 2 &&
457n/a (cif->arg_types[1]->type == FFI_TYPE_FLOAT
458n/a || cif->arg_types[1]->type == FFI_TYPE_DOUBLE))
459n/a mask |= 2;
460n/a if (cif->nargs >= 3 &&
461n/a (cif->arg_types[2]->type == FFI_TYPE_FLOAT
462n/a || cif->arg_types[2]->type == FFI_TYPE_DOUBLE))
463n/a mask |= 4;
464n/a if (cif->nargs >= 4 &&
465n/a (cif->arg_types[3]->type == FFI_TYPE_FLOAT
466n/a || cif->arg_types[3]->type == FFI_TYPE_DOUBLE))
467n/a mask |= 8;
468n/a
469n/a /* 41 BB ---- mov r11d,mask */
470n/a BYTES("\x41\xBB"); INT(mask);
471n/a
472n/a /* 48 B8 -------- mov rax, closure */
473n/a BYTES("\x48\xB8"); POINTER(closure);
474n/a
475n/a /* 49 BA -------- mov r10, ffi_closure_OUTER */
476n/a BYTES("\x49\xBA"); POINTER(ffi_closure_OUTER);
477n/a
478n/a /* 41 FF E2 jmp r10 */
479n/a BYTES("\x41\xFF\xE2");
480n/a
481n/a#else
482n/a
483n/a /* mov ecx, closure */
484n/a BYTES("\xb9"); POINTER(closure);
485n/a
486n/a /* mov edx, esp */
487n/a BYTES("\x8b\xd4");
488n/a
489n/a /* call ffi_closure_SYSV */
490n/a BYTES("\xe8"); POINTER((char*)&ffi_closure_SYSV - (tramp + 4));
491n/a
492n/a /* ret bytes */
493n/a BYTES("\xc2");
494n/a SHORT(bytes);
495n/a
496n/a#endif
497n/a
498n/a if (tramp - &closure->tramp[0] > FFI_TRAMPOLINE_SIZE)
499n/a Py_FatalError("FFI_TRAMPOLINE_SIZE too small in " __FILE__);
500n/a
501n/a closure->cif = cif;
502n/a closure->user_data = user_data;
503n/a closure->fun = fun;
504n/a return FFI_OK;
505n/a}