1/* Area: closure_call (thiscall convention) 2 Purpose: Check handling when caller expects thiscall callee 3 Limitations: none. 4 PR: none. 5 Originator: <ktietz@redhat.com> */ 6 7/* { dg-do run { target i?86-*-cygwin* i?86-*-mingw* } } */ 8#include "ffitest.h" 9 10static void 11closure_test_thiscall(ffi_cif* cif __UNUSED__, void* resp, void** args, 12 void* userdata) 13{ 14 *(ffi_arg*)resp = 15 (int)*(int *)args[0] + (int)(*(int *)args[1]) 16 + (int)(*(int *)args[2]) + (int)(*(int *)args[3]) 17 + (int)(intptr_t)userdata; 18 19 printf("%d %d %d %d: %d\n", 20 (int)*(int *)args[0], (int)(*(int *)args[1]), 21 (int)(*(int *)args[2]), (int)(*(int *)args[3]), 22 (int)*(ffi_arg *)resp); 23 24} 25 26typedef int (__thiscall *closure_test_type0)(int, int, int, int); 27 28int main (void) 29{ 30 ffi_cif cif; 31 void *code; 32 ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); 33 ffi_type * cl_arg_types[17]; 34 int res; 35 void* sp_pre; 36 void* sp_post; 37 char buf[1024]; 38 39 cl_arg_types[0] = &ffi_type_uint; 40 cl_arg_types[1] = &ffi_type_uint; 41 cl_arg_types[2] = &ffi_type_uint; 42 cl_arg_types[3] = &ffi_type_uint; 43 cl_arg_types[4] = NULL; 44 45 /* Initialize the cif */ 46 CHECK(ffi_prep_cif(&cif, FFI_THISCALL, 4, 47 &ffi_type_sint, cl_arg_types) == FFI_OK); 48 49 CHECK(ffi_prep_closure_loc(pcl, &cif, closure_test_thiscall, 50 (void *) 3 /* userdata */, code) == FFI_OK); 51 52#ifdef _MSC_VER 53 __asm { mov sp_pre, esp } 54#else 55 asm volatile (" movl %%esp,%0" : "=g" (sp_pre)); 56#endif 57 res = (*(closure_test_type0)code)(0, 1, 2, 3); 58#ifdef _MSC_VER 59 __asm { mov sp_post, esp } 60#else 61 asm volatile (" movl %%esp,%0" : "=g" (sp_post)); 62#endif 63 /* { dg-output "0 1 2 3: 9" } */ 64 65 printf("res: %d\n",res); 66 /* { dg-output "\nres: 9" } */ 67 68 sprintf(buf, "mismatch: pre=%p vs post=%p", sp_pre, sp_post); 69 printf("stack pointer %s\n", (sp_pre == sp_post ? "match" : buf)); 70 /* { dg-output "\nstack pointer match" } */ 71 exit(0); 72} 73