1 | /* -----------------------------------------------------------------------
|
---|
2 | prep_cif.c - Copyright (c) 1996, 1998 Cygnus Solutions
|
---|
3 |
|
---|
4 | Permission is hereby granted, free of charge, to any person obtaining
|
---|
5 | a copy of this software and associated documentation files (the
|
---|
6 | ``Software''), to deal in the Software without restriction, including
|
---|
7 | without limitation the rights to use, copy, modify, merge, publish,
|
---|
8 | distribute, sublicense, and/or sell copies of the Software, and to
|
---|
9 | permit persons to whom the Software is furnished to do so, subject to
|
---|
10 | the following conditions:
|
---|
11 |
|
---|
12 | The above copyright notice and this permission notice shall be included
|
---|
13 | in all copies or substantial portions of the Software.
|
---|
14 |
|
---|
15 | THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
---|
16 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
---|
17 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
---|
18 | IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
---|
19 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
---|
20 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
---|
21 | OTHER DEALINGS IN THE SOFTWARE.
|
---|
22 | ----------------------------------------------------------------------- */
|
---|
23 |
|
---|
24 | #include <ffi.h>
|
---|
25 | #include <ffi_common.h>
|
---|
26 | #include <stdlib.h>
|
---|
27 |
|
---|
28 |
|
---|
29 | /* Round up to SIZEOF_ARG. */
|
---|
30 |
|
---|
31 | #define STACK_ARG_SIZE(x) ALIGN(x, SIZEOF_ARG)
|
---|
32 |
|
---|
33 | /* Perform machine independent initialization of aggregate type
|
---|
34 | specifications. */
|
---|
35 |
|
---|
36 | static ffi_status initialize_aggregate(/*@out@*/ ffi_type *arg)
|
---|
37 | {
|
---|
38 | ffi_type **ptr;
|
---|
39 |
|
---|
40 | FFI_ASSERT(arg != NULL);
|
---|
41 |
|
---|
42 | /*@-usedef@*/
|
---|
43 |
|
---|
44 | FFI_ASSERT(arg->elements != NULL);
|
---|
45 | FFI_ASSERT(arg->size == 0);
|
---|
46 | FFI_ASSERT(arg->alignment == 0);
|
---|
47 |
|
---|
48 | ptr = &(arg->elements[0]);
|
---|
49 |
|
---|
50 | while ((*ptr) != NULL)
|
---|
51 | {
|
---|
52 | if (((*ptr)->size == 0) && (initialize_aggregate((*ptr)) != FFI_OK))
|
---|
53 | return FFI_BAD_TYPEDEF;
|
---|
54 |
|
---|
55 | /* Perform a sanity check on the argument type */
|
---|
56 | FFI_ASSERT(ffi_type_test((*ptr)));
|
---|
57 |
|
---|
58 | arg->size = ALIGN(arg->size, (*ptr)->alignment);
|
---|
59 | arg->size += (*ptr)->size;
|
---|
60 |
|
---|
61 | arg->alignment = (arg->alignment > (*ptr)->alignment) ?
|
---|
62 | arg->alignment : (*ptr)->alignment;
|
---|
63 |
|
---|
64 | ptr++;
|
---|
65 | }
|
---|
66 |
|
---|
67 | if (arg->size == 0)
|
---|
68 | return FFI_BAD_TYPEDEF;
|
---|
69 | else
|
---|
70 | return FFI_OK;
|
---|
71 |
|
---|
72 | /*@=usedef@*/
|
---|
73 | }
|
---|
74 |
|
---|
75 | /* Perform machine independent ffi_cif preparation, then call
|
---|
76 | machine dependent routine. */
|
---|
77 |
|
---|
78 | ffi_status ffi_prep_cif(/*@out@*/ /*@partial@*/ ffi_cif *cif,
|
---|
79 | ffi_abi abi, unsigned int nargs,
|
---|
80 | /*@dependent@*/ /*@out@*/ /*@partial@*/ ffi_type *rtype,
|
---|
81 | /*@dependent@*/ ffi_type **atypes)
|
---|
82 | {
|
---|
83 | unsigned bytes = 0;
|
---|
84 | unsigned int i;
|
---|
85 | ffi_type **ptr;
|
---|
86 |
|
---|
87 | FFI_ASSERT(cif != NULL);
|
---|
88 | FFI_ASSERT((abi > FFI_FIRST_ABI) && (abi < FFI_LAST_ABI));
|
---|
89 |
|
---|
90 | cif->abi = abi;
|
---|
91 | cif->arg_types = atypes;
|
---|
92 | cif->nargs = nargs;
|
---|
93 | cif->rtype = rtype;
|
---|
94 |
|
---|
95 | cif->flags = 0;
|
---|
96 |
|
---|
97 | /* Initialize the return type if necessary */
|
---|
98 | /*@-usedef@*/
|
---|
99 | if ((cif->rtype->size == 0) && (initialize_aggregate(cif->rtype) != FFI_OK))
|
---|
100 | return FFI_BAD_TYPEDEF;
|
---|
101 | /*@=usedef@*/
|
---|
102 |
|
---|
103 | /* Perform a sanity check on the return type */
|
---|
104 | FFI_ASSERT(ffi_type_test(cif->rtype));
|
---|
105 |
|
---|
106 | /* x86-64 and s390 stack space allocation is handled in prep_machdep. */
|
---|
107 | #if !defined M68K && !defined __x86_64__ && !defined S390
|
---|
108 | /* Make space for the return structure pointer */
|
---|
109 | if (cif->rtype->type == FFI_TYPE_STRUCT
|
---|
110 | #ifdef SPARC
|
---|
111 | && (cif->abi != FFI_V9 || cif->rtype->size > 32)
|
---|
112 | #endif
|
---|
113 | )
|
---|
114 | bytes = STACK_ARG_SIZE(sizeof(void*));
|
---|
115 | #endif
|
---|
116 |
|
---|
117 | for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
|
---|
118 | {
|
---|
119 | /* Perform a sanity check on the argument type */
|
---|
120 | FFI_ASSERT(ffi_type_test(*ptr));
|
---|
121 |
|
---|
122 | /* Initialize any uninitialized aggregate type definitions */
|
---|
123 | if (((*ptr)->size == 0) && (initialize_aggregate((*ptr)) != FFI_OK))
|
---|
124 | return FFI_BAD_TYPEDEF;
|
---|
125 |
|
---|
126 | #if !defined __x86_64__ && !defined S390
|
---|
127 | #ifdef SPARC
|
---|
128 | if (((*ptr)->type == FFI_TYPE_STRUCT
|
---|
129 | && ((*ptr)->size > 16 || cif->abi != FFI_V9))
|
---|
130 | || ((*ptr)->type == FFI_TYPE_LONGDOUBLE
|
---|
131 | && cif->abi != FFI_V9))
|
---|
132 | bytes += sizeof(void*);
|
---|
133 | else
|
---|
134 | #endif
|
---|
135 | {
|
---|
136 | /* Add any padding if necessary */
|
---|
137 | if (((*ptr)->alignment - 1) & bytes)
|
---|
138 | bytes = ALIGN(bytes, (*ptr)->alignment);
|
---|
139 |
|
---|
140 | bytes += STACK_ARG_SIZE((*ptr)->size);
|
---|
141 | }
|
---|
142 | #endif
|
---|
143 | }
|
---|
144 |
|
---|
145 | cif->bytes = bytes;
|
---|
146 |
|
---|
147 | /* Perform machine dependent cif processing */
|
---|
148 | return ffi_prep_cif_machdep(cif);
|
---|
149 | }
|
---|