1  /* Area:		ffi_call, closure_call
       2     Purpose:		Check pointer arguments across multiple hideous stack frames.
       3     Limitations:	none.
       4     PR:			none.
       5     Originator:	Blake Chaffin 6/7/2007	*/
       6  
       7  /* { dg-do run { xfail strongarm*-*-* xscale*-*-* } } */
       8  #include "ffitest.h"
       9  
      10  static	long dummyVar;
      11  
      12  long dummy_func(
      13  	long double a1, char b1,
      14  	long double a2, char b2,
      15  	long double a3, char b3,
      16  	long double a4, char b4)
      17  {
      18  	return a1 + b1 + a2 + b2 + a3 + b3 + a4 + b4;
      19  }
      20  
      21  void* cls_pointer_fn2(void* a1, void* a2)
      22  {
      23  	long double	trample1	= (intptr_t)a1 + (intptr_t)a2;
      24  	char		trample2	= ((char*)&a1)[0] + ((char*)&a2)[0];
      25  	long double	trample3	= (intptr_t)trample1 + (intptr_t)a1;
      26  	char		trample4	= trample2 + ((char*)&a1)[1];
      27  	long double	trample5	= (intptr_t)trample3 + (intptr_t)a2;
      28  	char		trample6	= trample4 + ((char*)&a2)[1];
      29  	long double	trample7	= (intptr_t)trample5 + (intptr_t)trample1;
      30  	char		trample8	= trample6 + trample2;
      31  	void*		result;
      32  
      33  	dummyVar	= dummy_func(trample1, trample2, trample3, trample4,
      34  		trample5, trample6, trample7, trample8);
      35  
      36  	result	= (void*)((intptr_t)a1 + (intptr_t)a2);
      37  
      38  	printf("0x%08x 0x%08x: 0x%08x\n", 
      39  	       (unsigned int)(uintptr_t) a1,
      40                 (unsigned int)(uintptr_t) a2,
      41                 (unsigned int)(uintptr_t) result);
      42  
      43  	return result;
      44  }
      45  
      46  void* cls_pointer_fn1(void* a1, void* a2)
      47  {
      48  	long double	trample1	= (intptr_t)a1 + (intptr_t)a2;
      49  	char		trample2	= ((char*)&a1)[0] + ((char*)&a2)[0];
      50  	long double	trample3	= (intptr_t)trample1 + (intptr_t)a1;
      51  	char		trample4	= trample2 + ((char*)&a1)[1];
      52  	long double	trample5	= (intptr_t)trample3 + (intptr_t)a2;
      53  	char		trample6	= trample4 + ((char*)&a2)[1];
      54  	long double	trample7	= (intptr_t)trample5 + (intptr_t)trample1;
      55  	char		trample8	= trample6 + trample2;
      56  	void*		result;
      57  
      58  	dummyVar	= dummy_func(trample1, trample2, trample3, trample4,
      59  		trample5, trample6, trample7, trample8);
      60  
      61  	result	= (void*)((intptr_t)a1 + (intptr_t)a2);
      62  
      63  	printf("0x%08x 0x%08x: 0x%08x\n",
      64                 (unsigned int)(intptr_t) a1,
      65                 (unsigned int)(intptr_t) a2,
      66                 (unsigned int)(intptr_t) result);
      67  
      68  	result	= cls_pointer_fn2(result, a1);
      69  
      70  	return result;
      71  }
      72  
      73  static void
      74  cls_pointer_gn(ffi_cif* cif __UNUSED__, void* resp, 
      75  	       void** args, void* userdata __UNUSED__)
      76  {
      77  	void*	a1	= *(void**)(args[0]);
      78  	void*	a2	= *(void**)(args[1]);
      79  
      80  	long double	trample1	= (intptr_t)a1 + (intptr_t)a2;
      81  	char		trample2	= ((char*)&a1)[0] + ((char*)&a2)[0];
      82  	long double	trample3	= (intptr_t)trample1 + (intptr_t)a1;
      83  	char		trample4	= trample2 + ((char*)&a1)[1];
      84  	long double	trample5	= (intptr_t)trample3 + (intptr_t)a2;
      85  	char		trample6	= trample4 + ((char*)&a2)[1];
      86  	long double	trample7	= (intptr_t)trample5 + (intptr_t)trample1;
      87  	char		trample8	= trample6 + trample2;
      88  
      89  	dummyVar	= dummy_func(trample1, trample2, trample3, trample4,
      90  		trample5, trample6, trample7, trample8);
      91  
      92  	*(void**)resp = cls_pointer_fn1(a1, a2);
      93  }
      94  
      95  int main (void)
      96  {
      97  	ffi_cif	cif;
      98          void *code;
      99  	ffi_closure*	pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
     100  	void*			args[3];
     101  	/*	ffi_type		cls_pointer_type; */
     102  	ffi_type*		arg_types[3];
     103  
     104  /*	cls_pointer_type.size = sizeof(void*);
     105  	cls_pointer_type.alignment = 0;
     106  	cls_pointer_type.type = FFI_TYPE_POINTER;
     107  	cls_pointer_type.elements = NULL;*/
     108  
     109  	void*	arg1	= (void*)0x01234567;
     110  	void*	arg2	= (void*)0x89abcdef;
     111  	ffi_arg	res		= 0;
     112  
     113  	arg_types[0] = &ffi_type_pointer;
     114  	arg_types[1] = &ffi_type_pointer;
     115  	arg_types[2] = NULL;
     116  
     117  	CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &ffi_type_pointer,
     118  		arg_types) == FFI_OK);
     119  
     120  	args[0] = &arg1;
     121  	args[1] = &arg2;
     122  	args[2] = NULL;
     123  
     124  	printf("\n");
     125  	ffi_call(&cif, FFI_FN(cls_pointer_fn1), &res, args);
     126  
     127  	printf("res: 0x%08x\n", (unsigned int) res);
     128  	/* { dg-output "\n0x01234567 0x89abcdef: 0x8acf1356" } */
     129  	/* { dg-output "\n0x8acf1356 0x01234567: 0x8bf258bd" } */
     130  	/* { dg-output "\nres: 0x8bf258bd" } */
     131  
     132  	CHECK(ffi_prep_closure_loc(pcl, &cif, cls_pointer_gn, NULL, code) == FFI_OK);
     133  
     134  	res = (ffi_arg)(uintptr_t)((void*(*)(void*, void*))(code))(arg1, arg2);
     135  
     136  	printf("res: 0x%08x\n", (unsigned int) res);
     137  	/* { dg-output "\n0x01234567 0x89abcdef: 0x8acf1356" } */
     138  	/* { dg-output "\n0x8acf1356 0x01234567: 0x8bf258bd" } */
     139  	/* { dg-output "\nres: 0x8bf258bd" } */
     140  
     141  	exit(0);
     142  }