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