1/* Area: ffi_call, closure_call 2 Purpose: Check structure passing with different structure size. 3 Contains structs as parameter of the struct itself. 4 Sample taken from Alan Modras patch to src/prep_cif.c. 5 Limitations: none. 6 PR: none. 7 Originator: <andreast@gcc.gnu.org> 20030911 */ 8 9/* { dg-do run { xfail mips*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */ 10#include "ffitest.h" 11 12#if LONG_MAX == 2147483647 13#define ffi_type_mylong ffi_type_uint32 14#else 15#if LONG_MAX == 9223372036854775807 16#define ffi_type_mylong ffi_type_uint64 17#else 18#error "Error, size LONG not defined as expected" 19#endif 20#endif 21 22typedef struct A { 23 unsigned long a; 24 unsigned char b; 25} A; 26 27typedef struct B { 28 struct A x; 29 unsigned char y; 30} B; 31 32B B_fn(struct A b0, struct B b1) 33{ 34 struct B result; 35 36 result.x.a = b0.a + b1.x.a; 37 result.x.b = b0.b + b1.x.b + b1.y; 38 result.y = b0.b + b1.x.b; 39 40 printf("%d %d %d %d %d: %d %d %d\n", b0.a, b0.b, b1.x.a, b1.x.b, b1.y, 41 result.x.a, result.x.b, result.y); 42 43 return result; 44} 45 46static void 47B_gn(ffi_cif* cif, void* resp, void** args, void* userdata) 48{ 49 struct A b0; 50 struct B b1; 51 52 b0 = *(struct A*)(args[0]); 53 b1 = *(struct B*)(args[1]); 54 55 *(B*)resp = B_fn(b0, b1); 56} 57 58int main (void) 59{ 60 ffi_cif cif; 61#ifndef USING_MMAP 62 static ffi_closure cl; 63#endif 64 ffi_closure *pcl; 65 void* args_dbl[3]; 66 ffi_type* cls_struct_fields[3]; 67 ffi_type* cls_struct_fields1[3]; 68 ffi_type cls_struct_type, cls_struct_type1; 69 ffi_type* dbl_arg_types[3]; 70 71#ifdef USING_MMAP 72 pcl = allocate_mmap (sizeof(ffi_closure)); 73#else 74 pcl = &cl; 75#endif 76 77 cls_struct_type.size = 0; 78 cls_struct_type.alignment = 0; 79 cls_struct_type.type = FFI_TYPE_STRUCT; 80 cls_struct_type.elements = cls_struct_fields; 81 82 cls_struct_type1.size = 0; 83 cls_struct_type1.alignment = 0; 84 cls_struct_type1.type = FFI_TYPE_STRUCT; 85 cls_struct_type1.elements = cls_struct_fields1; 86 87 struct A e_dbl = { 1, 7}; 88 struct B f_dbl = {{12 , 127}, 99}; 89 90 struct B res_dbl; 91 92 cls_struct_fields[0] = &ffi_type_mylong; 93 cls_struct_fields[1] = &ffi_type_uchar; 94 cls_struct_fields[2] = NULL; 95 96 cls_struct_fields1[0] = &cls_struct_type; 97 cls_struct_fields1[1] = &ffi_type_uchar; 98 cls_struct_fields1[2] = NULL; 99 100 101 dbl_arg_types[0] = &cls_struct_type; 102 dbl_arg_types[1] = &cls_struct_type1; 103 dbl_arg_types[2] = NULL; 104 105 CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type1, 106 dbl_arg_types) == FFI_OK); 107 108 args_dbl[0] = &e_dbl; 109 args_dbl[1] = &f_dbl; 110 args_dbl[2] = NULL; 111 112 ffi_call(&cif, FFI_FN(B_fn), &res_dbl, args_dbl); 113 /* { dg-output "1 7 12 127 99: 13 233 134" } */ 114 CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a)); 115 CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y)); 116 CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b)); 117 118 119 CHECK(ffi_prep_closure(pcl, &cif, B_gn, NULL) == FFI_OK); 120 121 res_dbl = ((B(*)(A, B))(pcl))(e_dbl, f_dbl); 122 /* { dg-output "\n1 7 12 127 99: 13 233 134" } */ 123 CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a)); 124 CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y)); 125 CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b)); 126 exit(0); 127} 128