1/* Area: closure_call (stdcall convention) 2 Purpose: Check handling when caller expects stdcall callee 3 Limitations: none. 4 PR: none. 5 Originator: <twalljava@dev.java.net> */ 6 7/* { dg-do run { target i?86-*-cygwin* i?86-*-mingw* } } */ 8#include "ffitest.h" 9 10static void 11closure_test_stdcall(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)(long)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 (__stdcall *closure_test_type0)(int, int, int, int); 27 28int main (void) 29{ 30 ffi_cif cif; 31#ifndef USING_MMAP 32 static ffi_closure cl; 33#endif 34 ffi_closure *pcl; 35 ffi_type * cl_arg_types[17]; 36 int res; 37 void* sp_pre; 38 void* sp_post; 39 char buf[1024]; 40 41#ifdef USING_MMAP 42 pcl = allocate_mmap (sizeof(ffi_closure)); 43#else 44 pcl = &cl; 45#endif 46 47 cl_arg_types[0] = &ffi_type_uint; 48 cl_arg_types[1] = &ffi_type_uint; 49 cl_arg_types[2] = &ffi_type_uint; 50 cl_arg_types[3] = &ffi_type_uint; 51 cl_arg_types[4] = NULL; 52 53 /* Initialize the cif */ 54 CHECK(ffi_prep_cif(&cif, FFI_STDCALL, 4, 55 &ffi_type_sint, cl_arg_types) == FFI_OK); 56 57 CHECK(ffi_prep_closure(pcl, &cif, closure_test_stdcall, 58 (void *) 3 /* userdata */) == FFI_OK); 59 60 asm volatile (" movl %%esp,%0" : "=g" (sp_pre)); 61 res = (*(closure_test_type0)pcl)(0, 1, 2, 3); 62 asm volatile (" movl %%esp,%0" : "=g" (sp_post)); 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