ยปCore Development>Code coverage>Modules/_ctypes/libffi/src/tile/ffi.c

Python code coverage for Modules/_ctypes/libffi/src/tile/ffi.c

#countcontent
1n/a/* -----------------------------------------------------------------------
2n/a ffi.c - Copyright (c) 2012 Tilera Corp.
3n/a
4n/a TILE 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,
18n/a EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19n/a MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20n/a NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
21n/a HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22n/a WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23n/a OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24n/a DEALINGS IN THE SOFTWARE.
25n/a ----------------------------------------------------------------------- */
26n/a
27n/a#include <ffi.h>
28n/a#include <ffi_common.h>
29n/a#include <stdlib.h>
30n/a#include <stdint.h>
31n/a#include <unistd.h>
32n/a#include <arch/abi.h>
33n/a#include <arch/icache.h>
34n/a#include <arch/opcode.h>
35n/a
36n/a
37n/a/* The first 10 registers are used to pass arguments and return values. */
38n/a#define NUM_ARG_REGS 10
39n/a
40n/a/* Performs a raw function call with the given NUM_ARG_REGS register arguments
41n/a and the specified additional stack arguments (if any). */
42n/aextern void ffi_call_tile(ffi_sarg reg_args[NUM_ARG_REGS],
43n/a const ffi_sarg *stack_args,
44n/a size_t stack_args_bytes,
45n/a void (*fnaddr)(void))
46n/a FFI_HIDDEN;
47n/a
48n/a/* This handles the raw call from the closure stub, cleaning up the
49n/a parameters and delegating to ffi_closure_tile_inner. */
50n/aextern void ffi_closure_tile(void) FFI_HIDDEN;
51n/a
52n/a
53n/affi_status
54n/affi_prep_cif_machdep(ffi_cif *cif)
55n/a{
56n/a /* We always allocate room for all registers. Even if we don't
57n/a use them as parameters, they get returned in the same array
58n/a as struct return values so we need to make room. */
59n/a if (cif->bytes < NUM_ARG_REGS * FFI_SIZEOF_ARG)
60n/a cif->bytes = NUM_ARG_REGS * FFI_SIZEOF_ARG;
61n/a
62n/a if (cif->rtype->size > NUM_ARG_REGS * FFI_SIZEOF_ARG)
63n/a cif->flags = FFI_TYPE_STRUCT;
64n/a else
65n/a cif->flags = FFI_TYPE_INT;
66n/a
67n/a /* Nothing to do. */
68n/a return FFI_OK;
69n/a}
70n/a
71n/a
72n/astatic long
73n/aassign_to_ffi_arg(ffi_sarg *out, void *in, const ffi_type *type,
74n/a int write_to_reg)
75n/a{
76n/a switch (type->type)
77n/a {
78n/a case FFI_TYPE_SINT8:
79n/a *out = *(SINT8 *)in;
80n/a return 1;
81n/a
82n/a case FFI_TYPE_UINT8:
83n/a *out = *(UINT8 *)in;
84n/a return 1;
85n/a
86n/a case FFI_TYPE_SINT16:
87n/a *out = *(SINT16 *)in;
88n/a return 1;
89n/a
90n/a case FFI_TYPE_UINT16:
91n/a *out = *(UINT16 *)in;
92n/a return 1;
93n/a
94n/a case FFI_TYPE_SINT32:
95n/a case FFI_TYPE_UINT32:
96n/a#ifndef __LP64__
97n/a case FFI_TYPE_POINTER:
98n/a#endif
99n/a /* Note that even unsigned 32-bit quantities are sign extended
100n/a on tilegx when stored in a register. */
101n/a *out = *(SINT32 *)in;
102n/a return 1;
103n/a
104n/a case FFI_TYPE_FLOAT:
105n/a#ifdef __tilegx__
106n/a if (write_to_reg)
107n/a {
108n/a /* Properly sign extend the value. */
109n/a union { float f; SINT32 s32; } val;
110n/a val.f = *(float *)in;
111n/a *out = val.s32;
112n/a }
113n/a else
114n/a#endif
115n/a {
116n/a *(float *)out = *(float *)in;
117n/a }
118n/a return 1;
119n/a
120n/a case FFI_TYPE_SINT64:
121n/a case FFI_TYPE_UINT64:
122n/a case FFI_TYPE_DOUBLE:
123n/a#ifdef __LP64__
124n/a case FFI_TYPE_POINTER:
125n/a#endif
126n/a *(UINT64 *)out = *(UINT64 *)in;
127n/a return sizeof(UINT64) / FFI_SIZEOF_ARG;
128n/a
129n/a case FFI_TYPE_STRUCT:
130n/a memcpy(out, in, type->size);
131n/a return (type->size + FFI_SIZEOF_ARG - 1) / FFI_SIZEOF_ARG;
132n/a
133n/a case FFI_TYPE_VOID:
134n/a /* Must be a return type. Nothing to do. */
135n/a return 0;
136n/a
137n/a default:
138n/a FFI_ASSERT(0);
139n/a return -1;
140n/a }
141n/a}
142n/a
143n/a
144n/avoid
145n/affi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
146n/a{
147n/a ffi_sarg * const arg_mem = alloca(cif->bytes);
148n/a ffi_sarg * const reg_args = arg_mem;
149n/a ffi_sarg * const stack_args = &reg_args[NUM_ARG_REGS];
150n/a ffi_sarg *argp = arg_mem;
151n/a ffi_type ** const arg_types = cif->arg_types;
152n/a const long num_args = cif->nargs;
153n/a long i;
154n/a
155n/a if (cif->flags == FFI_TYPE_STRUCT)
156n/a {
157n/a /* Pass a hidden pointer to the return value. We make sure there
158n/a is scratch space for the callee to store the return value even if
159n/a our caller doesn't care about it. */
160n/a *argp++ = (intptr_t)(rvalue ? rvalue : alloca(cif->rtype->size));
161n/a
162n/a /* No more work needed to return anything. */
163n/a rvalue = NULL;
164n/a }
165n/a
166n/a for (i = 0; i < num_args; i++)
167n/a {
168n/a ffi_type *type = arg_types[i];
169n/a void * const arg_in = avalue[i];
170n/a ptrdiff_t arg_word = argp - arg_mem;
171n/a
172n/a#ifndef __tilegx__
173n/a /* Doubleword-aligned values are always in an even-number register
174n/a pair, or doubleword-aligned stack slot if out of registers. */
175n/a long align = arg_word & (type->alignment > FFI_SIZEOF_ARG);
176n/a argp += align;
177n/a arg_word += align;
178n/a#endif
179n/a
180n/a if (type->type == FFI_TYPE_STRUCT)
181n/a {
182n/a const size_t arg_size_in_words =
183n/a (type->size + FFI_SIZEOF_ARG - 1) / FFI_SIZEOF_ARG;
184n/a
185n/a if (arg_word < NUM_ARG_REGS &&
186n/a arg_word + arg_size_in_words > NUM_ARG_REGS)
187n/a {
188n/a /* Args are not allowed to span registers and the stack. */
189n/a argp = stack_args;
190n/a }
191n/a
192n/a memcpy(argp, arg_in, type->size);
193n/a argp += arg_size_in_words;
194n/a }
195n/a else
196n/a {
197n/a argp += assign_to_ffi_arg(argp, arg_in, arg_types[i], 1);
198n/a }
199n/a }
200n/a
201n/a /* Actually do the call. */
202n/a ffi_call_tile(reg_args, stack_args,
203n/a cif->bytes - (NUM_ARG_REGS * FFI_SIZEOF_ARG), fn);
204n/a
205n/a if (rvalue != NULL)
206n/a assign_to_ffi_arg(rvalue, reg_args, cif->rtype, 0);
207n/a}
208n/a
209n/a
210n/a/* Template code for closure. */
211n/aextern const UINT64 ffi_template_tramp_tile[] FFI_HIDDEN;
212n/a
213n/a
214n/affi_status
215n/affi_prep_closure_loc (ffi_closure *closure,
216n/a ffi_cif *cif,
217n/a void (*fun)(ffi_cif*, void*, void**, void*),
218n/a void *user_data,
219n/a void *codeloc)
220n/a{
221n/a#ifdef __tilegx__
222n/a /* TILE-Gx */
223n/a SINT64 c;
224n/a SINT64 h;
225n/a int s;
226n/a UINT64 *out;
227n/a
228n/a if (cif->abi != FFI_UNIX)
229n/a return FFI_BAD_ABI;
230n/a
231n/a out = (UINT64 *)closure->tramp;
232n/a
233n/a c = (intptr_t)closure;
234n/a h = (intptr_t)ffi_closure_tile;
235n/a s = 0;
236n/a
237n/a /* Find the smallest shift count that doesn't lose information
238n/a (i.e. no need to explicitly insert high bits of the address that
239n/a are just the sign extension of the low bits). */
240n/a while ((c >> s) != (SINT16)(c >> s) || (h >> s) != (SINT16)(h >> s))
241n/a s += 16;
242n/a
243n/a#define OPS(a, b, shift) \
244n/a (create_Imm16_X0((a) >> (shift)) | create_Imm16_X1((b) >> (shift)))
245n/a
246n/a /* Emit the moveli. */
247n/a *out++ = ffi_template_tramp_tile[0] | OPS(c, h, s);
248n/a for (s -= 16; s >= 0; s -= 16)
249n/a *out++ = ffi_template_tramp_tile[1] | OPS(c, h, s);
250n/a
251n/a#undef OPS
252n/a
253n/a *out++ = ffi_template_tramp_tile[2];
254n/a
255n/a#else
256n/a /* TILEPro */
257n/a UINT64 *out;
258n/a intptr_t delta;
259n/a
260n/a if (cif->abi != FFI_UNIX)
261n/a return FFI_BAD_ABI;
262n/a
263n/a out = (UINT64 *)closure->tramp;
264n/a delta = (intptr_t)ffi_closure_tile - (intptr_t)codeloc;
265n/a
266n/a *out++ = ffi_template_tramp_tile[0] | create_JOffLong_X1(delta >> 3);
267n/a#endif
268n/a
269n/a closure->cif = cif;
270n/a closure->fun = fun;
271n/a closure->user_data = user_data;
272n/a
273n/a invalidate_icache(closure->tramp, (char *)out - closure->tramp,
274n/a getpagesize());
275n/a
276n/a return FFI_OK;
277n/a}
278n/a
279n/a
280n/a/* This is called by the assembly wrapper for closures. This does
281n/a all of the work. On entry reg_args[0] holds the values the registers
282n/a had when the closure was invoked. On return reg_args[1] holds the register
283n/a values to be returned to the caller (many of which may be garbage). */
284n/avoid FFI_HIDDEN
285n/affi_closure_tile_inner(ffi_closure *closure,
286n/a ffi_sarg reg_args[2][NUM_ARG_REGS],
287n/a ffi_sarg *stack_args)
288n/a{
289n/a ffi_cif * const cif = closure->cif;
290n/a void ** const avalue = alloca(cif->nargs * sizeof(void *));
291n/a void *rvalue;
292n/a ffi_type ** const arg_types = cif->arg_types;
293n/a ffi_sarg * const reg_args_in = reg_args[0];
294n/a ffi_sarg * const reg_args_out = reg_args[1];
295n/a ffi_sarg * argp;
296n/a long i, arg_word, nargs = cif->nargs;
297n/a /* Use a union to guarantee proper alignment for double. */
298n/a union { ffi_sarg arg[NUM_ARG_REGS]; double d; UINT64 u64; } closure_ret;
299n/a
300n/a /* Start out reading register arguments. */
301n/a argp = reg_args_in;
302n/a
303n/a /* Copy the caller's structure return address to that the closure
304n/a returns the data directly to the caller. */
305n/a if (cif->flags == FFI_TYPE_STRUCT)
306n/a {
307n/a /* Return by reference via hidden pointer. */
308n/a rvalue = (void *)(intptr_t)*argp++;
309n/a arg_word = 1;
310n/a }
311n/a else
312n/a {
313n/a /* Return the value in registers. */
314n/a rvalue = &closure_ret;
315n/a arg_word = 0;
316n/a }
317n/a
318n/a /* Grab the addresses of the arguments. */
319n/a for (i = 0; i < nargs; i++)
320n/a {
321n/a ffi_type * const type = arg_types[i];
322n/a const size_t arg_size_in_words =
323n/a (type->size + FFI_SIZEOF_ARG - 1) / FFI_SIZEOF_ARG;
324n/a
325n/a#ifndef __tilegx__
326n/a /* Doubleword-aligned values are always in an even-number register
327n/a pair, or doubleword-aligned stack slot if out of registers. */
328n/a long align = arg_word & (type->alignment > FFI_SIZEOF_ARG);
329n/a argp += align;
330n/a arg_word += align;
331n/a#endif
332n/a
333n/a if (arg_word == NUM_ARG_REGS ||
334n/a (arg_word < NUM_ARG_REGS &&
335n/a arg_word + arg_size_in_words > NUM_ARG_REGS))
336n/a {
337n/a /* Switch to reading arguments from the stack. */
338n/a argp = stack_args;
339n/a arg_word = NUM_ARG_REGS;
340n/a }
341n/a
342n/a avalue[i] = argp;
343n/a argp += arg_size_in_words;
344n/a arg_word += arg_size_in_words;
345n/a }
346n/a
347n/a /* Invoke the closure. */
348n/a closure->fun(cif, rvalue, avalue, closure->user_data);
349n/a
350n/a if (cif->flags != FFI_TYPE_STRUCT)
351n/a {
352n/a /* Canonicalize for register representation. */
353n/a assign_to_ffi_arg(reg_args_out, &closure_ret, cif->rtype, 1);
354n/a }
355n/a}