]>
Commit | Line | Data |
---|---|---|
63e5e3e0 | 1 | /* ----------------------------------------------------------------------- |
1450eb7a | 2 | raw_api.c - Copyright (c) 1999 Red Hat, Inc. |
63e5e3e0 AG |
3 | |
4 | Author: Kresten Krab Thorup <krab@gnu.org> | |
5 | ||
6 | $Id $ | |
7 | ||
8 | Permission is hereby granted, free of charge, to any person obtaining | |
9 | a copy of this software and associated documentation files (the | |
10 | ``Software''), to deal in the Software without restriction, including | |
11 | without limitation the rights to use, copy, modify, merge, publish, | |
12 | distribute, sublicense, and/or sell copies of the Software, and to | |
13 | permit persons to whom the Software is furnished to do so, subject to | |
14 | the following conditions: | |
15 | ||
16 | The above copyright notice and this permission notice shall be included | |
17 | in all copies or substantial portions of the Software. | |
18 | ||
19 | THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS | |
20 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
21 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | |
22 | IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR | |
23 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | |
24 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | |
25 | OTHER DEALINGS IN THE SOFTWARE. | |
26 | ----------------------------------------------------------------------- */ | |
27 | ||
28 | /* This file defines generic functions for use with the raw api. */ | |
29 | ||
30 | #include <ffi.h> | |
31 | #include <ffi_common.h> | |
32 | ||
33 | #if !FFI_NO_RAW_API | |
34 | ||
35 | size_t | |
36 | ffi_raw_size (ffi_cif *cif) | |
37 | { | |
38 | size_t result = 0; | |
39 | int i; | |
40 | ||
41 | ffi_type **at = cif->arg_types; | |
42 | ||
43 | for (i = cif->nargs-1; i >= 0; i--, at++) | |
44 | { | |
45 | #if !FFI_NO_STRUCTS | |
46 | if ((*at)->type == FFI_TYPE_STRUCT) | |
1450eb7a | 47 | result += ALIGN (sizeof (void*), FFI_SIZEOF_ARG); |
63e5e3e0 AG |
48 | else |
49 | #endif | |
1450eb7a | 50 | result += ALIGN ((*at)->size, FFI_SIZEOF_ARG); |
63e5e3e0 AG |
51 | } |
52 | ||
53 | return result; | |
54 | } | |
55 | ||
56 | ||
57 | void | |
58 | ffi_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args) | |
59 | { | |
60 | unsigned i; | |
61 | ffi_type **tp = cif->arg_types; | |
62 | ||
63 | #if WORDS_BIGENDIAN | |
64 | ||
65 | for (i = 0; i < cif->nargs; i++, tp++, args++) | |
66 | { | |
67 | switch ((*tp)->type) | |
68 | { | |
69 | case FFI_TYPE_UINT8: | |
70 | case FFI_TYPE_SINT8: | |
1450eb7a | 71 | *args = (void*) ((char*)(raw++) + FFI_SIZEOF_ARG - 1); |
63e5e3e0 AG |
72 | break; |
73 | ||
74 | case FFI_TYPE_UINT16: | |
75 | case FFI_TYPE_SINT16: | |
1450eb7a | 76 | *args = (void*) ((char*)(raw++) + FFI_SIZEOF_ARG - 2); |
63e5e3e0 AG |
77 | break; |
78 | ||
1450eb7a | 79 | #if FFI_SIZEOF_ARG >= 4 |
63e5e3e0 AG |
80 | case FFI_TYPE_UINT32: |
81 | case FFI_TYPE_SINT32: | |
1450eb7a | 82 | *args = (void*) ((char*)(raw++) + FFI_SIZEOF_ARG - 4); |
63e5e3e0 AG |
83 | break; |
84 | #endif | |
85 | ||
86 | #if !FFI_NO_STRUCTS | |
87 | case FFI_TYPE_STRUCT: | |
88 | *args = (raw++)->ptr; | |
89 | break; | |
90 | #endif | |
91 | ||
92 | case FFI_TYPE_POINTER: | |
93 | *args = (void*) &(raw++)->ptr; | |
94 | break; | |
95 | ||
96 | default: | |
97 | *args = raw; | |
1450eb7a | 98 | raw += ALIGN ((*tp)->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG; |
63e5e3e0 AG |
99 | } |
100 | } | |
101 | ||
102 | #else /* WORDS_BIGENDIAN */ | |
103 | ||
104 | #if !PDP | |
105 | ||
106 | /* then assume little endian */ | |
107 | for (i = 0; i < cif->nargs; i++, tp++, args++) | |
108 | { | |
109 | #if !FFI_NO_STRUCTS | |
110 | if ((*tp)->type == FFI_TYPE_STRUCT) | |
111 | { | |
112 | *args = (raw++)->ptr; | |
113 | } | |
114 | else | |
115 | #endif | |
116 | { | |
117 | *args = (void*) raw; | |
118 | raw += ALIGN ((*tp)->size, sizeof (void*)) / sizeof (void*); | |
119 | } | |
120 | } | |
121 | ||
122 | #else | |
123 | #error "pdp endian not supported" | |
124 | #endif /* ! PDP */ | |
125 | ||
126 | #endif /* WORDS_BIGENDIAN */ | |
127 | } | |
128 | ||
129 | void | |
130 | ffi_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw) | |
131 | { | |
132 | unsigned i; | |
133 | ffi_type **tp = cif->arg_types; | |
134 | ||
135 | for (i = 0; i < cif->nargs; i++, tp++, args++) | |
136 | { | |
137 | switch ((*tp)->type) | |
138 | { | |
139 | case FFI_TYPE_UINT8: | |
140 | (raw++)->uint = *(UINT8*) (*args); | |
141 | break; | |
142 | ||
143 | case FFI_TYPE_SINT8: | |
144 | (raw++)->sint = *(SINT8*) (*args); | |
145 | break; | |
146 | ||
147 | case FFI_TYPE_UINT16: | |
148 | (raw++)->uint = *(UINT16*) (*args); | |
149 | break; | |
150 | ||
151 | case FFI_TYPE_SINT16: | |
152 | (raw++)->sint = *(SINT16*) (*args); | |
153 | break; | |
154 | ||
1450eb7a | 155 | #if FFI_SIZEOF_ARG >= 4 |
63e5e3e0 AG |
156 | case FFI_TYPE_UINT32: |
157 | (raw++)->uint = *(UINT32*) (*args); | |
158 | break; | |
159 | ||
160 | case FFI_TYPE_SINT32: | |
161 | (raw++)->sint = *(SINT32*) (*args); | |
162 | break; | |
163 | #endif | |
164 | ||
165 | #if !FFI_NO_STRUCTS | |
166 | case FFI_TYPE_STRUCT: | |
167 | (raw++)->ptr = *args; | |
168 | break; | |
169 | #endif | |
170 | ||
171 | case FFI_TYPE_POINTER: | |
172 | (raw++)->ptr = **(void***) args; | |
173 | break; | |
174 | ||
175 | default: | |
176 | memcpy ((void*) raw->data, (void*)*args, (*tp)->size); | |
1450eb7a | 177 | raw += ALIGN ((*tp)->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG; |
63e5e3e0 AG |
178 | } |
179 | } | |
180 | } | |
181 | ||
182 | #if !FFI_NATIVE_RAW_API | |
183 | ||
184 | ||
185 | /* This is a generic definition of ffi_raw_call, to be used if the | |
186 | * native system does not provide a machine-specific implementation. | |
187 | * Having this, allows code to be written for the raw API, without | |
188 | * the need for system-specific code to handle input in that format; | |
189 | * these following couple of functions will handle the translation forth | |
190 | * and back automatically. */ | |
191 | ||
ac6ed182 | 192 | void ffi_raw_call (ffi_cif *cif, void (*fn)(), void *rvalue, ffi_raw *raw) |
63e5e3e0 AG |
193 | { |
194 | void **avalue = (void**) alloca (cif->nargs * sizeof (void*)); | |
195 | ffi_raw_to_ptrarray (cif, raw, avalue); | |
196 | ffi_call (cif, fn, rvalue, avalue); | |
197 | } | |
198 | ||
199 | #if FFI_CLOSURES /* base system provides closures */ | |
200 | ||
ac6ed182 | 201 | static void |
dc5de370 | 202 | ffi_translate_args (ffi_cif *cif, void *rvalue, |
63e5e3e0 AG |
203 | void **avalue, void *user_data) |
204 | { | |
205 | ffi_raw *raw = (ffi_raw*)alloca (ffi_raw_size (cif)); | |
63e5e3e0 | 206 | ffi_raw_closure *cl = (ffi_raw_closure*)user_data; |
dc5de370 HB |
207 | |
208 | ffi_ptrarray_to_raw (cif, avalue, raw); | |
63e5e3e0 AG |
209 | (*cl->fun) (cif, rvalue, raw, cl->user_data); |
210 | } | |
211 | ||
63e5e3e0 | 212 | ffi_status |
18fa3240 AO |
213 | ffi_prep_raw_closure_loc (ffi_raw_closure* cl, |
214 | ffi_cif *cif, | |
215 | void (*fun)(ffi_cif*,void*,ffi_raw*,void*), | |
216 | void *user_data, | |
217 | void *codeloc) | |
63e5e3e0 AG |
218 | { |
219 | ffi_status status; | |
220 | ||
18fa3240 AO |
221 | status = ffi_prep_closure_loc ((ffi_closure*) cl, |
222 | cif, | |
223 | &ffi_translate_args, | |
224 | codeloc, | |
225 | codeloc); | |
63e5e3e0 AG |
226 | if (status == FFI_OK) |
227 | { | |
228 | cl->fun = fun; | |
229 | cl->user_data = user_data; | |
230 | } | |
231 | ||
232 | return status; | |
233 | } | |
234 | ||
235 | #endif /* FFI_CLOSURES */ | |
236 | #endif /* !FFI_NATIVE_RAW_API */ | |
18fa3240 AO |
237 | |
238 | #if FFI_CLOSURES | |
239 | ||
240 | /* Again, here is the generic version of ffi_prep_raw_closure, which | |
241 | * will install an intermediate "hub" for translation of arguments from | |
242 | * the pointer-array format, to the raw format */ | |
243 | ||
244 | ffi_status | |
245 | ffi_prep_raw_closure (ffi_raw_closure* cl, | |
246 | ffi_cif *cif, | |
247 | void (*fun)(ffi_cif*,void*,ffi_raw*,void*), | |
248 | void *user_data) | |
249 | { | |
250 | return ffi_prep_raw_closure_loc (cl, cif, fun, user_data, cl); | |
251 | } | |
252 | ||
253 | #endif /* FFI_CLOSURES */ | |
254 | ||
63e5e3e0 | 255 | #endif /* !FFI_NO_RAW_API */ |