java_raw_api.c (ffi_java_raw_to_ptrarray): Interpret raw data as _Jv_word values...
[gcc.git] / libffi / src / s390 / ffi.c
1 /* -----------------------------------------------------------------------
2 ffi.c - Copyright (c) 2000 Software AG
3
4 S390 Foreign Function Interface
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, EXPRESS
18 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
21 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 OTHER DEALINGS IN THE SOFTWARE.
24 ----------------------------------------------------------------------- */
25 /*====================================================================*/
26 /* Includes */
27 /* -------- */
28 /*====================================================================*/
29
30 #include <ffi.h>
31 #include <ffi_common.h>
32
33 #include <stdlib.h>
34 #include <stdio.h>
35
36 /*====================== End of Includes =============================*/
37
38 /*====================================================================*/
39 /* Defines */
40 /* ------- */
41 /*====================================================================*/
42
43 /* Maximum number of GPRs available for argument passing. */
44 #define MAX_GPRARGS 5
45
46 /* Maximum number of FPRs available for argument passing. */
47 #ifdef __s390x__
48 #define MAX_FPRARGS 4
49 #else
50 #define MAX_FPRARGS 2
51 #endif
52
53 /* Round to multiple of 16. */
54 #define ROUND_SIZE(size) (((size) + 15) & ~15)
55
56 /* If these values change, sysv.S must be adapted! */
57 #define FFI390_RET_VOID 0
58 #define FFI390_RET_STRUCT 1
59 #define FFI390_RET_FLOAT 2
60 #define FFI390_RET_DOUBLE 3
61 #define FFI390_RET_INT32 4
62 #define FFI390_RET_INT64 5
63
64 /*===================== End of Defines ===============================*/
65
66 /*====================================================================*/
67 /* Prototypes */
68 /* ---------- */
69 /*====================================================================*/
70
71 static void ffi_prep_args (unsigned char *, extended_cif *);
72 static int ffi_check_float_struct (ffi_type *);
73 void ffi_closure_helper_SYSV (ffi_closure *, unsigned long *,
74 unsigned long long *, unsigned long *);
75
76 /*====================== End of Prototypes ===========================*/
77
78 /*====================================================================*/
79 /* Externals */
80 /* --------- */
81 /*====================================================================*/
82
83 extern void ffi_call_SYSV(unsigned,
84 extended_cif *,
85 void (*)(unsigned char *, extended_cif *),
86 unsigned,
87 void *,
88 void (*fn)());
89
90 extern void ffi_closure_SYSV(void);
91
92 /*====================== End of Externals ============================*/
93
94 /*====================================================================*/
95 /* */
96 /* Name - ffi_check_struct_type. */
97 /* */
98 /* Function - Determine if a structure can be passed within a */
99 /* general purpose or floating point register. */
100 /* */
101 /*====================================================================*/
102
103 static int
104 ffi_check_struct_type (ffi_type *arg)
105 {
106 size_t size = arg->size;
107
108 /* If the struct has just one element, look at that element
109 to find out whether to consider the struct as floating point. */
110 while (arg->type == FFI_TYPE_STRUCT
111 && arg->elements[0] && !arg->elements[1])
112 arg = arg->elements[0];
113
114 /* Structs of size 1, 2, 4, and 8 are passed in registers,
115 just like the corresponding int/float types. */
116 switch (size)
117 {
118 case 1:
119 return FFI_TYPE_UINT8;
120
121 case 2:
122 return FFI_TYPE_UINT16;
123
124 case 4:
125 if (arg->type == FFI_TYPE_FLOAT)
126 return FFI_TYPE_FLOAT;
127 else
128 return FFI_TYPE_UINT32;
129
130 case 8:
131 if (arg->type == FFI_TYPE_DOUBLE)
132 return FFI_TYPE_DOUBLE;
133 else
134 return FFI_TYPE_UINT64;
135
136 default:
137 break;
138 }
139
140 /* Other structs are passed via a pointer to the data. */
141 return FFI_TYPE_POINTER;
142 }
143
144 /*======================== End of Routine ============================*/
145
146 /*====================================================================*/
147 /* */
148 /* Name - ffi_prep_args. */
149 /* */
150 /* Function - Prepare parameters for call to function. */
151 /* */
152 /* ffi_prep_args is called by the assembly routine once stack space */
153 /* has been allocated for the function's arguments. */
154 /* */
155 /*====================================================================*/
156
157 static void
158 ffi_prep_args (unsigned char *stack, extended_cif *ecif)
159 {
160 /* The stack space will be filled with those areas:
161
162 FPR argument register save area (highest addresses)
163 GPR argument register save area
164 temporary struct copies
165 overflow argument area (lowest addresses)
166
167 We set up the following pointers:
168
169 p_fpr: bottom of the FPR area (growing upwards)
170 p_gpr: bottom of the GPR area (growing upwards)
171 p_ov: bottom of the overflow area (growing upwards)
172 p_struct: top of the struct copy area (growing downwards)
173
174 All areas are kept aligned to twice the word size. */
175
176 int gpr_off = ecif->cif->bytes;
177 int fpr_off = gpr_off + ROUND_SIZE (MAX_GPRARGS * sizeof (long));
178
179 unsigned long long *p_fpr = (unsigned long long *)(stack + fpr_off);
180 unsigned long *p_gpr = (unsigned long *)(stack + gpr_off);
181 unsigned char *p_struct = (unsigned char *)p_gpr;
182 unsigned long *p_ov = (unsigned long *)stack;
183
184 int n_fpr = 0;
185 int n_gpr = 0;
186 int n_ov = 0;
187
188 ffi_type **ptr;
189 void **p_argv = ecif->avalue;
190 int i;
191
192 /* If we returning a structure then we set the first parameter register
193 to the address of where we are returning this structure. */
194
195 if (ecif->cif->flags == FFI390_RET_STRUCT)
196 p_gpr[n_gpr++] = (unsigned long) ecif->rvalue;
197
198 /* Now for the arguments. */
199
200 for (ptr = ecif->cif->arg_types, i = ecif->cif->nargs;
201 i > 0;
202 i--, ptr++, p_argv++)
203 {
204 void *arg = *p_argv;
205 int type = (*ptr)->type;
206
207 /* Check how a structure type is passed. */
208 if (type == FFI_TYPE_STRUCT)
209 {
210 type = ffi_check_struct_type (*ptr);
211
212 /* If we pass the struct via pointer, copy the data. */
213 if (type == FFI_TYPE_POINTER)
214 {
215 p_struct -= ROUND_SIZE ((*ptr)->size);
216 memcpy (p_struct, (char *)arg, (*ptr)->size);
217 arg = &p_struct;
218 }
219 }
220
221 /* Pointers are passed like UINTs of the same size. */
222 if (type == FFI_TYPE_POINTER)
223 #ifdef __s390x__
224 type = FFI_TYPE_UINT64;
225 #else
226 type = FFI_TYPE_UINT32;
227 #endif
228
229 /* Now handle all primitive int/float data types. */
230 switch (type)
231 {
232 case FFI_TYPE_DOUBLE:
233 if (n_fpr < MAX_FPRARGS)
234 p_fpr[n_fpr++] = *(unsigned long long *) arg;
235 else
236 #ifdef __s390x__
237 p_ov[n_ov++] = *(unsigned long *) arg;
238 #else
239 p_ov[n_ov++] = ((unsigned long *) arg)[0],
240 p_ov[n_ov++] = ((unsigned long *) arg)[1];
241 #endif
242 break;
243
244 case FFI_TYPE_FLOAT:
245 if (n_fpr < MAX_FPRARGS)
246 p_fpr[n_fpr++] = (long long) *(unsigned int *) arg << 32;
247 else
248 p_ov[n_ov++] = *(unsigned int *) arg;
249 break;
250
251 case FFI_TYPE_UINT64:
252 case FFI_TYPE_SINT64:
253 #ifdef __s390x__
254 if (n_gpr < MAX_GPRARGS)
255 p_gpr[n_gpr++] = *(unsigned long *) arg;
256 else
257 p_ov[n_ov++] = *(unsigned long *) arg;
258 #else
259 if (n_gpr == MAX_GPRARGS-1)
260 n_gpr = MAX_GPRARGS;
261 if (n_gpr < MAX_GPRARGS)
262 p_gpr[n_gpr++] = ((unsigned long *) arg)[0],
263 p_gpr[n_gpr++] = ((unsigned long *) arg)[1];
264 else
265 p_ov[n_ov++] = ((unsigned long *) arg)[0],
266 p_ov[n_ov++] = ((unsigned long *) arg)[1];
267 #endif
268 break;
269
270 case FFI_TYPE_UINT32:
271 if (n_gpr < MAX_GPRARGS)
272 p_gpr[n_gpr++] = *(unsigned int *) arg;
273 else
274 p_ov[n_ov++] = *(unsigned int *) arg;
275 break;
276
277 case FFI_TYPE_INT:
278 case FFI_TYPE_SINT32:
279 if (n_gpr < MAX_GPRARGS)
280 p_gpr[n_gpr++] = *(signed int *) arg;
281 else
282 p_ov[n_ov++] = *(signed int *) arg;
283 break;
284
285 case FFI_TYPE_UINT16:
286 if (n_gpr < MAX_GPRARGS)
287 p_gpr[n_gpr++] = *(unsigned short *) arg;
288 else
289 p_ov[n_ov++] = *(unsigned short *) arg;
290 break;
291
292 case FFI_TYPE_SINT16:
293 if (n_gpr < MAX_GPRARGS)
294 p_gpr[n_gpr++] = *(signed short *) arg;
295 else
296 p_ov[n_ov++] = *(signed short *) arg;
297 break;
298
299 case FFI_TYPE_UINT8:
300 if (n_gpr < MAX_GPRARGS)
301 p_gpr[n_gpr++] = *(unsigned char *) arg;
302 else
303 p_ov[n_ov++] = *(unsigned char *) arg;
304 break;
305
306 case FFI_TYPE_SINT8:
307 if (n_gpr < MAX_GPRARGS)
308 p_gpr[n_gpr++] = *(signed char *) arg;
309 else
310 p_ov[n_ov++] = *(signed char *) arg;
311 break;
312
313 default:
314 FFI_ASSERT (0);
315 break;
316 }
317 }
318 }
319
320 /*======================== End of Routine ============================*/
321
322 /*====================================================================*/
323 /* */
324 /* Name - ffi_prep_cif_machdep. */
325 /* */
326 /* Function - Perform machine dependent CIF processing. */
327 /* */
328 /*====================================================================*/
329
330 ffi_status
331 ffi_prep_cif_machdep(ffi_cif *cif)
332 {
333 size_t struct_size = 0;
334 int n_gpr = 0;
335 int n_fpr = 0;
336 int n_ov = 0;
337
338 ffi_type **ptr;
339 int i;
340
341 /* Determine return value handling. */
342
343 switch (cif->rtype->type)
344 {
345 /* Void is easy. */
346 case FFI_TYPE_VOID:
347 cif->flags = FFI390_RET_VOID;
348 break;
349
350 /* Structures are returned via a hidden pointer. */
351 case FFI_TYPE_STRUCT:
352 cif->flags = FFI390_RET_STRUCT;
353 n_gpr++; /* We need one GPR to pass the pointer. */
354 break;
355
356 /* Floating point values are returned in fpr 0. */
357 case FFI_TYPE_FLOAT:
358 cif->flags = FFI390_RET_FLOAT;
359 break;
360
361 case FFI_TYPE_DOUBLE:
362 cif->flags = FFI390_RET_DOUBLE;
363 break;
364
365 /* Integer values are returned in gpr 2 (and gpr 3
366 for 64-bit values on 31-bit machines). */
367 case FFI_TYPE_UINT64:
368 case FFI_TYPE_SINT64:
369 cif->flags = FFI390_RET_INT64;
370 break;
371
372 case FFI_TYPE_POINTER:
373 case FFI_TYPE_INT:
374 case FFI_TYPE_UINT32:
375 case FFI_TYPE_SINT32:
376 case FFI_TYPE_UINT16:
377 case FFI_TYPE_SINT16:
378 case FFI_TYPE_UINT8:
379 case FFI_TYPE_SINT8:
380 /* These are to be extended to word size. */
381 #ifdef __s390x__
382 cif->flags = FFI390_RET_INT64;
383 #else
384 cif->flags = FFI390_RET_INT32;
385 #endif
386 break;
387
388 default:
389 FFI_ASSERT (0);
390 break;
391 }
392
393 /* Now for the arguments. */
394
395 for (ptr = cif->arg_types, i = cif->nargs;
396 i > 0;
397 i--, ptr++)
398 {
399 int type = (*ptr)->type;
400
401 /* Check how a structure type is passed. */
402 if (type == FFI_TYPE_STRUCT)
403 {
404 type = ffi_check_struct_type (*ptr);
405
406 /* If we pass the struct via pointer, we must reserve space
407 to copy its data for proper call-by-value semantics. */
408 if (type == FFI_TYPE_POINTER)
409 struct_size += ROUND_SIZE ((*ptr)->size);
410 }
411
412 /* Now handle all primitive int/float data types. */
413 switch (type)
414 {
415 /* The first MAX_FPRARGS floating point arguments
416 go in FPRs, the rest overflow to the stack. */
417
418 case FFI_TYPE_DOUBLE:
419 if (n_fpr < MAX_FPRARGS)
420 n_fpr++;
421 else
422 n_ov += sizeof (double) / sizeof (long);
423 break;
424
425 case FFI_TYPE_FLOAT:
426 if (n_fpr < MAX_FPRARGS)
427 n_fpr++;
428 else
429 n_ov++;
430 break;
431
432 /* On 31-bit machines, 64-bit integers are passed in GPR pairs,
433 if one is still available, or else on the stack. If only one
434 register is free, skip the register (it won't be used for any
435 subsequent argument either). */
436
437 #ifndef __s390x__
438 case FFI_TYPE_UINT64:
439 case FFI_TYPE_SINT64:
440 if (n_gpr == MAX_GPRARGS-1)
441 n_gpr = MAX_GPRARGS;
442 if (n_gpr < MAX_GPRARGS)
443 n_gpr += 2;
444 else
445 n_ov += 2;
446 break;
447 #endif
448
449 /* Everything else is passed in GPRs (until MAX_GPRARGS
450 have been used) or overflows to the stack. */
451
452 default:
453 if (n_gpr < MAX_GPRARGS)
454 n_gpr++;
455 else
456 n_ov++;
457 break;
458 }
459 }
460
461 /* Total stack space as required for overflow arguments
462 and temporary structure copies. */
463
464 cif->bytes = ROUND_SIZE (n_ov * sizeof (long)) + struct_size;
465
466 return FFI_OK;
467 }
468
469 /*======================== End of Routine ============================*/
470
471 /*====================================================================*/
472 /* */
473 /* Name - ffi_call. */
474 /* */
475 /* Function - Call the FFI routine. */
476 /* */
477 /*====================================================================*/
478
479 void
480 ffi_call(ffi_cif *cif,
481 void (*fn)(),
482 void *rvalue,
483 void **avalue)
484 {
485 int ret_type = cif->flags;
486 extended_cif ecif;
487
488 ecif.cif = cif;
489 ecif.avalue = avalue;
490 ecif.rvalue = rvalue;
491
492 /* If we don't have a return value, we need to fake one. */
493 if (rvalue == NULL)
494 {
495 if (ret_type == FFI390_RET_STRUCT)
496 ecif.rvalue = alloca (cif->rtype->size);
497 else
498 ret_type = FFI390_RET_VOID;
499 }
500
501 switch (cif->abi)
502 {
503 case FFI_SYSV:
504 ffi_call_SYSV (cif->bytes, &ecif, ffi_prep_args,
505 ret_type, ecif.rvalue, fn);
506 break;
507
508 default:
509 FFI_ASSERT (0);
510 break;
511 }
512 }
513
514 /*======================== End of Routine ============================*/
515
516 /*====================================================================*/
517 /* */
518 /* Name - ffi_closure_helper_SYSV. */
519 /* */
520 /* Function - Call a FFI closure target function. */
521 /* */
522 /*====================================================================*/
523
524 void
525 ffi_closure_helper_SYSV (ffi_closure *closure,
526 unsigned long *p_gpr,
527 unsigned long long *p_fpr,
528 unsigned long *p_ov)
529 {
530 unsigned long long ret_buffer;
531
532 void *rvalue = &ret_buffer;
533 void **avalue;
534 void **p_arg;
535
536 int n_gpr = 0;
537 int n_fpr = 0;
538 int n_ov = 0;
539
540 ffi_type **ptr;
541 int i;
542
543 /* Allocate buffer for argument list pointers. */
544
545 p_arg = avalue = alloca (closure->cif->nargs * sizeof (void *));
546
547 /* If we returning a structure, pass the structure address
548 directly to the target function. Otherwise, have the target
549 function store the return value to the GPR save area. */
550
551 if (closure->cif->flags == FFI390_RET_STRUCT)
552 rvalue = (void *) p_gpr[n_gpr++];
553
554 /* Now for the arguments. */
555
556 for (ptr = closure->cif->arg_types, i = closure->cif->nargs;
557 i > 0;
558 i--, p_arg++, ptr++)
559 {
560 int deref_struct_pointer = 0;
561 int type = (*ptr)->type;
562
563 /* Check how a structure type is passed. */
564 if (type == FFI_TYPE_STRUCT)
565 {
566 type = ffi_check_struct_type (*ptr);
567
568 /* If we pass the struct via pointer, remember to
569 retrieve the pointer later. */
570 if (type == FFI_TYPE_POINTER)
571 deref_struct_pointer = 1;
572 }
573
574 /* Pointers are passed like UINTs of the same size. */
575 if (type == FFI_TYPE_POINTER)
576 #ifdef __s390x__
577 type = FFI_TYPE_UINT64;
578 #else
579 type = FFI_TYPE_UINT32;
580 #endif
581
582 /* Now handle all primitive int/float data types. */
583 switch (type)
584 {
585 case FFI_TYPE_DOUBLE:
586 if (n_fpr < MAX_FPRARGS)
587 *p_arg = &p_fpr[n_fpr++];
588 else
589 *p_arg = &p_ov[n_ov],
590 n_ov += sizeof (double) / sizeof (long);
591 break;
592
593 case FFI_TYPE_FLOAT:
594 if (n_fpr < MAX_FPRARGS)
595 *p_arg = &p_fpr[n_fpr++];
596 else
597 *p_arg = (char *)&p_ov[n_ov++] + sizeof (long) - 4;
598 break;
599
600 case FFI_TYPE_UINT64:
601 case FFI_TYPE_SINT64:
602 #ifdef __s390x__
603 if (n_gpr < MAX_GPRARGS)
604 *p_arg = &p_gpr[n_gpr++];
605 else
606 *p_arg = &p_ov[n_ov++];
607 #else
608 if (n_gpr == MAX_GPRARGS-1)
609 n_gpr = MAX_GPRARGS;
610 if (n_gpr < MAX_GPRARGS)
611 *p_arg = &p_gpr[n_gpr], n_gpr += 2;
612 else
613 *p_arg = &p_ov[n_ov], n_ov += 2;
614 #endif
615 break;
616
617 case FFI_TYPE_INT:
618 case FFI_TYPE_UINT32:
619 case FFI_TYPE_SINT32:
620 if (n_gpr < MAX_GPRARGS)
621 *p_arg = (char *)&p_gpr[n_gpr++] + sizeof (long) - 4;
622 else
623 *p_arg = (char *)&p_ov[n_ov++] + sizeof (long) - 4;
624 break;
625
626 case FFI_TYPE_UINT16:
627 case FFI_TYPE_SINT16:
628 if (n_gpr < MAX_GPRARGS)
629 *p_arg = (char *)&p_gpr[n_gpr++] + sizeof (long) - 2;
630 else
631 *p_arg = (char *)&p_ov[n_ov++] + sizeof (long) - 2;
632 break;
633
634 case FFI_TYPE_UINT8:
635 case FFI_TYPE_SINT8:
636 if (n_gpr < MAX_GPRARGS)
637 *p_arg = (char *)&p_gpr[n_gpr++] + sizeof (long) - 1;
638 else
639 *p_arg = (char *)&p_ov[n_ov++] + sizeof (long) - 1;
640 break;
641
642 default:
643 FFI_ASSERT (0);
644 break;
645 }
646
647 /* If this is a struct passed via pointer, we need to
648 actually retrieve that pointer. */
649 if (deref_struct_pointer)
650 *p_arg = *(void **)*p_arg;
651 }
652
653
654 /* Call the target function. */
655 (closure->fun) (closure->cif, rvalue, avalue, closure->user_data);
656
657 /* Convert the return value. */
658 switch (closure->cif->rtype->type)
659 {
660 /* Void is easy, and so is struct. */
661 case FFI_TYPE_VOID:
662 case FFI_TYPE_STRUCT:
663 break;
664
665 /* Floating point values are returned in fpr 0. */
666 case FFI_TYPE_FLOAT:
667 p_fpr[0] = (long long) *(unsigned int *) rvalue << 32;
668 break;
669
670 case FFI_TYPE_DOUBLE:
671 p_fpr[0] = *(unsigned long long *) rvalue;
672 break;
673
674 /* Integer values are returned in gpr 2 (and gpr 3
675 for 64-bit values on 31-bit machines). */
676 case FFI_TYPE_UINT64:
677 case FFI_TYPE_SINT64:
678 #ifdef __s390x__
679 p_gpr[0] = *(unsigned long *) rvalue;
680 #else
681 p_gpr[0] = ((unsigned long *) rvalue)[0],
682 p_gpr[1] = ((unsigned long *) rvalue)[1];
683 #endif
684 break;
685
686 case FFI_TYPE_POINTER:
687 case FFI_TYPE_UINT32:
688 case FFI_TYPE_UINT16:
689 case FFI_TYPE_UINT8:
690 p_gpr[0] = *(unsigned long *) rvalue;
691 break;
692
693 case FFI_TYPE_INT:
694 case FFI_TYPE_SINT32:
695 case FFI_TYPE_SINT16:
696 case FFI_TYPE_SINT8:
697 p_gpr[0] = *(signed long *) rvalue;
698 break;
699
700 default:
701 FFI_ASSERT (0);
702 break;
703 }
704 }
705
706 /*======================== End of Routine ============================*/
707
708 /*====================================================================*/
709 /* */
710 /* Name - ffi_prep_closure. */
711 /* */
712 /* Function - Prepare a FFI closure. */
713 /* */
714 /*====================================================================*/
715
716 ffi_status
717 ffi_prep_closure (ffi_closure *closure,
718 ffi_cif *cif,
719 void (*fun) (ffi_cif *, void *, void **, void *),
720 void *user_data)
721 {
722 FFI_ASSERT (cif->abi == FFI_SYSV);
723
724 #ifndef __s390x__
725 *(short *)&closure->tramp [0] = 0x0d10; /* basr %r1,0 */
726 *(short *)&closure->tramp [2] = 0x9801; /* lm %r0,%r1,6(%r1) */
727 *(short *)&closure->tramp [4] = 0x1006;
728 *(short *)&closure->tramp [6] = 0x07f1; /* br %r1 */
729 *(long *)&closure->tramp [8] = (long)closure;
730 *(long *)&closure->tramp[12] = (long)&ffi_closure_SYSV;
731 #else
732 *(short *)&closure->tramp [0] = 0x0d10; /* basr %r1,0 */
733 *(short *)&closure->tramp [2] = 0xeb01; /* lmg %r0,%r1,14(%r1) */
734 *(short *)&closure->tramp [4] = 0x100e;
735 *(short *)&closure->tramp [6] = 0x0004;
736 *(short *)&closure->tramp [8] = 0x07f1; /* br %r1 */
737 *(long *)&closure->tramp[16] = (long)closure;
738 *(long *)&closure->tramp[24] = (long)&ffi_closure_SYSV;
739 #endif
740
741 closure->cif = cif;
742 closure->user_data = user_data;
743 closure->fun = fun;
744
745 return FFI_OK;
746 }
747
748 /*======================== End of Routine ============================*/
749