Exemplo n.º 1
0
int main (void)
{
  ffi_cif cif;
  ffi_type *args[MAX_ARGS];
  void *values[MAX_ARGS];
  float f;
  long double ld;

  args[0] = &ffi_type_float;
  values[0] = &f;
  
  /* Initialize the cif */
  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, 
		     &ffi_type_longdouble, args) == FFI_OK);
  
  f = 3.14159;
  
#if 1 
  /* This is ifdef'd out for now. long double support under SunOS/gcc
     is pretty much non-existent.  You'll get the odd bus error in library
     routines like printf().  */
  printf ("%Lf\n", ldblit(f));
#endif
  ld = 666;
  ffi_call(&cif, FFI_FN(ldblit), &ld, values);
  
#if 1 
  /* This is ifdef'd out for now. long double support under SunOS/gcc
     is pretty much non-existent.  You'll get the odd bus error in library
     routines like printf().  */
  printf ("%Lf, %Lf, %Lf, %Lf\n", ld, ldblit(f), ld - ldblit(f), LDBL_EPSILON);
#endif
  
  /* These are not always the same!! Check for a reasonable delta */
  /*@-realcompare@*/
  if (ld - ldblit(f) < LDBL_EPSILON)
    /*@=realcompare@*/
    puts("long double return value tests ok!");
  else
    CHECK(0);

  exit(0);
}
Exemplo n.º 2
0
Arquivo: ffitest.c Projeto: aosm/gcc3
int main(/*@unused@*/ int argc, /*@unused@*/ char *argv[])
{
  ffi_cif cif;
  ffi_type *args[MAX_ARGS];
  void *values[MAX_ARGS];
  char *s;
  signed char sc;
  unsigned char uc;
  signed short ss;
  unsigned short us;
  unsigned long ul;
  long long ll;
  float f;
  double d;
  long double ld;
  signed int si1;
  signed int si2;

  ffi_arg rint;
  long long rlonglong;

  ffi_type ts1_type;
  ffi_type ts2_type;
  ffi_type ts3_type;
  ffi_type ts4_type;  
  ffi_type ts5_type;
  ffi_type *ts1_type_elements[4];
  ffi_type *ts2_type_elements[3];
  ffi_type *ts3_type_elements[2];
  ffi_type *ts4_type_elements[4];
  ffi_type *ts5_type_elements[3];

  ts1_type.size = 0;
  ts1_type.alignment = 0;
  ts1_type.type = FFI_TYPE_STRUCT;

  ts2_type.size = 0;
  ts2_type.alignment = 0;
  ts2_type.type = FFI_TYPE_STRUCT;

  ts3_type.size = 0;
  ts3_type.alignment = 0;
  ts3_type.type = FFI_TYPE_STRUCT;

  ts4_type.size = 0;
  ts4_type.alignment = 0;
  ts4_type.type = FFI_TYPE_STRUCT;

  ts5_type.size = 0;
  ts5_type.alignment = 0;
  ts5_type.type = FFI_TYPE_STRUCT;

  /*@-immediatetrans@*/
  ts1_type.elements = ts1_type_elements;
  ts2_type.elements = ts2_type_elements;
  ts3_type.elements = ts3_type_elements;
  ts4_type.elements = ts4_type_elements;
  ts5_type.elements = ts5_type_elements;
  /*@=immediatetrans@*/
  
  ts1_type_elements[0] = &ffi_type_uchar;
  ts1_type_elements[1] = &ffi_type_double;
  ts1_type_elements[2] = &ffi_type_uint;
  ts1_type_elements[3] = NULL;
  
  ts2_type_elements[0] = &ffi_type_double;
  ts2_type_elements[1] = &ffi_type_double;
  ts2_type_elements[2] = NULL;

  ts3_type_elements[0] = &ffi_type_sint;
  ts3_type_elements[1] = NULL;

  ts4_type_elements[0] = &ffi_type_uint;
  ts4_type_elements[1] = &ffi_type_uint;
  ts4_type_elements[2] = &ffi_type_uint;
  ts4_type_elements[3] = NULL;

  ts5_type_elements[0] = &ffi_type_schar;
  ts5_type_elements[1] = &ffi_type_schar;
  ts5_type_elements[2] = NULL;

  ul = 0;

  /* return value tests */
  {
#if defined(MIPS) /* || defined(ARM) */
    puts ("long long tests not run. This is a known bug on this architecture.");
#else
    args[0] = &ffi_type_sint64;
    values[0] = &ll;
    
    /* Initialize the cif */
    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, 
		       &ffi_type_sint64, args) == FFI_OK);

    for (ll = 0LL; ll < 100LL; ll++)
      {
	ul++;
	ffi_call(&cif, FFI_FN(return_ll), &rlonglong, values);
	CHECK(rlonglong == ll);
      }

    for (ll = 55555555555000LL; ll < 55555555555100LL; ll++)
      {
	ul++;
	ffi_call(&cif, FFI_FN(return_ll), &rlonglong, values);
	CHECK(rlonglong == ll);
      }
#endif

    args[0] = &ffi_type_schar;
    values[0] = &sc;
    
    /* Initialize the cif */
    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, 
		       &ffi_type_schar, args) == FFI_OK);

    for (sc = (signed char) -127; 
	 sc < (signed char) 127; /*@-type@*/ sc++ /*@=type@*/)
      {
	ul++;
	ffi_call(&cif, FFI_FN(return_sc), &rint, values);
	CHECK(rint == (int) sc);
      }

    args[0] = &ffi_type_uchar;
    values[0] = &uc;
    
    /* Initialize the cif */
    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, 
		       &ffi_type_uchar, args) == FFI_OK);

    for (uc = (unsigned char) '\x00'; 
	 uc < (unsigned char) '\xff'; /*@-type@*/ uc++ /*@=type@*/)
      {
	ul++;
	ffi_call(&cif, FFI_FN(return_uc), &rint, values);
	CHECK(rint == (signed int) uc);
      }

    printf("%lu return value tests run\n", ul);
  }

#ifdef BROKEN_LONG_DOUBLE
  printf ("This architecture has broken `long double' support. No floating point\ntests have been run.\n");
#else
  /* float arg tests */
  {
    args[0] = &ffi_type_float;
    values[0] = &f;

    /* Initialize the cif */
    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, 
		       &ffi_type_longdouble, args) == FFI_OK);

    f = 3.14159;

#if 0
  /* This is ifdef'd out for now. long double support under SunOS/gcc
     is pretty much non-existent.  You'll get the odd bus error in library
     routines like printf().  */
    printf ("%Lf\n", ldblit(f));
#endif
    ld = 666;
    ffi_call(&cif, FFI_FN(ldblit), &ld, values);

#if 0
  /* This is ifdef'd out for now. long double support under SunOS/gcc
     is pretty much non-existent.  You'll get the odd bus error in library
     routines like printf().  */
    printf ("%Lf, %Lf, %Lf, %Lf\n", ld, ldblit(f), ld - ldblit(f), LDBL_EPSILON);
#endif

    /* These are not always the same!! Check for a reasonable delta */
    /*@-realcompare@*/
    if (ld - ldblit(f) < LDBL_EPSILON)
    /*@=realcompare@*/
	puts("long double return value tests ok!");
    else
        CHECK(0);
  }

  /* float arg tests */
  {
    args[0] = &ffi_type_sint;
    values[0] = &si1;
    args[1] = &ffi_type_float;
    values[1] = &f;
    args[2] = &ffi_type_double;
    values[2] = &d;
    args[3] = &ffi_type_longdouble;
    values[3] = &ld;
    args[4] = &ffi_type_sint;
    values[4] = &si2;
    
    /* Initialize the cif */
    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 5,
		       &ffi_type_sint, args) == FFI_OK);

    si1 = 6;
    f = 3.14159;
    d = (double)1.0/(double)3.0;
    ld = 2.71828182846L;
    si2 = 10;

    floating (si1, f, d, ld, si2);

    ffi_call(&cif, FFI_FN(floating), &rint, values);

    printf ("%d vs %d\n", rint, floating (si1, f, d, ld, si2));

    CHECK(rint == floating(si1, f, d, ld, si2));

    printf("float arg tests ok!\n");
  }
#endif

  /* strlen tests */
  {
    args[0] = &ffi_type_pointer;
    values[0] = (void*) &s;
    
    /* Initialize the cif */
    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, 
		       &ffi_type_sint, args) == FFI_OK);

    s = "a";
    ffi_call(&cif, FFI_FN(my_strlen), &rint, values);
    CHECK(rint == 1);

    s = "1234567";
    ffi_call(&cif, FFI_FN(my_strlen), &rint, values);
    CHECK(rint == 7);

    s = "1234567890123456789012345";
    ffi_call(&cif, FFI_FN(my_strlen), &rint, values);
    CHECK(rint == 25);

    printf("strlen tests passed\n");
  }

  /* float arg tests */
  {
    args[0] = &ffi_type_float;
    values[0] = &f;
    
    /* Initialize the cif */
    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, 
		       &ffi_type_double, args) == FFI_OK);

    f = 3.14159;

    ffi_call(&cif, FFI_FN(dblit), &d, values);

    /* These are not always the same!! Check for a reasonable delta */
    /*@-realcompare@*/
    CHECK(d - dblit(f) < DBL_EPSILON);
    /*@=realcompare@*/

    printf("double return value tests ok!\n");
  }

  /* many arg tests */
  {
    float ff;
    float fa[13];
    
    for (ul = 0; ul < 13; ul++)
      {
	args[ul] = &ffi_type_float;
	values[ul] = &fa[ul];
	fa[ul] = (float) ul;
      }

    /* Initialize the cif */
    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 13, 
		       &ffi_type_float, args) == FFI_OK);

    /*@-usedef@*/
    ff =  many(fa[0], fa[1],
	       fa[2], fa[3],
	       fa[4], fa[5],
	       fa[6], fa[7],
	       fa[8], fa[9],
	       fa[10],fa[11],fa[12]);
    /*@=usedef@*/

    ffi_call(&cif, FFI_FN(many), &f, values);

    /*@-realcompare@*/
    if (f - ff < FLT_EPSILON)
    /*@=realcompare@*/
	printf("many arg tests ok!\n");
    else
#ifdef POWERPC
	printf("many arg tests failed!  This is a gcc bug.\n");
#else
        CHECK(0);
#endif
  }

  /* promotion tests */
  {
    args[0] = &ffi_type_schar;
    args[1] = &ffi_type_sshort;
    args[2] = &ffi_type_uchar;
    args[3] = &ffi_type_ushort;
    values[0] = &sc;
    values[1] = &ss;
    values[2] = &uc;
    values[3] = &us;
    
    /* Initialize the cif */
    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4, 
		       &ffi_type_sint, args) == FFI_OK);

    us = 0;
    ul = 0;

    for (sc = (signed char) -127; 
	 sc <= (signed char) 120; /*@-type@*/ sc += 1 /*@=type@*/)
      for (ss = -30000; ss <= 30000; ss += 10000)
	for (uc = (unsigned char) 0; 
	     uc <= (unsigned char) 200; /*@-type@*/ uc += 20 /*@=type@*/)
	  for (us = 0; us <= 60000; us += 10000)
	    {
	      ul++;
	      ffi_call(&cif, FFI_FN(promotion), &rint, values);
	      CHECK(rint == (int) sc + (int) ss + (int) uc + (int) us);
	    }
    printf("%lu promotion tests run\n", ul);
  }

#ifndef X86_WIN32 /* Structures dont work on Win32 */

  /* struct tests */
  {
    test_structure_1 ts1_arg;
    /* This is a hack to get a properly aligned result buffer */
    test_structure_1 *ts1_result = 
      (test_structure_1 *) malloc (sizeof(test_structure_1));

    args[0] = &ts1_type;
    values[0] = &ts1_arg;
    
    /* Initialize the cif */
    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, 
		       &ts1_type, args) == FFI_OK);

    ts1_arg.uc = '\x01';
    ts1_arg.d = 3.14159;
    ts1_arg.ui = 555;

    ffi_call(&cif, FFI_FN(struct1), ts1_result, values);

    CHECK(ts1_result->ui == 556);
    CHECK(ts1_result->d == 3.14159 - 1);

    puts ("structure test 1 ok!\n");

    free (ts1_result);
  }

  /* struct tests */
  {
    test_structure_2 ts2_arg;

    /* This is a hack to get a properly aligned result buffer */
    test_structure_2 *ts2_result = 
      (test_structure_2 *) malloc (sizeof(test_structure_2));

    args[0] = &ts2_type;
    values[0] = &ts2_arg;
    
    /* Initialize the cif */
    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, 
		       &ts2_type, args) == FFI_OK);

    ts2_arg.d1 = 5.55;
    ts2_arg.d2 = 6.66;

    printf ("%g\n", ts2_result->d1);
    printf ("%g\n", ts2_result->d2);

    ffi_call(&cif, FFI_FN(struct2), ts2_result, values);

    printf ("%g\n", ts2_result->d1);
    printf ("%g\n", ts2_result->d2);
    
    CHECK(ts2_result->d1 == 5.55 - 1);
    CHECK(ts2_result->d2 == 6.66 - 1);

    printf("structure test 2 ok!\n");

    free (ts2_result);
  }

  /* struct tests */
  {
    int compare_value;
    test_structure_3 ts3_arg;
    test_structure_3 *ts3_result = 
      (test_structure_3 *) malloc (sizeof(test_structure_3));

    args[0] = &ts3_type;
    values[0] = &ts3_arg;
    
    /* Initialize the cif */
    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, 
		       &ts3_type, args) == FFI_OK);

    ts3_arg.si = -123;
    compare_value = ts3_arg.si;

    ffi_call(&cif, FFI_FN(struct3), ts3_result, values);

    printf ("%d %d\n", ts3_result->si, -(compare_value*2));

    if (ts3_result->si == -(ts3_arg.si*2))
	puts ("structure test 3 ok!");
    else
      {
	puts ("Structure test 3 found structure passing bug.");
	puts ("  Current versions of GCC are not 100% compliant with the");
	puts ("  n32 ABI.  There is a known problem related to passing");
	puts ("  small structures.  Send a bug report to the gcc maintainers.");
      }

    free (ts3_result);
  }

  /* struct tests */
  {
    test_structure_4 ts4_arg;

    /* This is a hack to get a properly aligned result buffer */
    test_structure_4 *ts4_result = 
      (test_structure_4 *) malloc (sizeof(test_structure_4));

    args[0] = &ts4_type;
    values[0] = &ts4_arg;
    
    /* Initialize the cif */
    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, 
		       &ts4_type, args) == FFI_OK);

    ts4_arg.ui1 = 2;
    ts4_arg.ui2 = 3;
    ts4_arg.ui3 = 4;

    ffi_call (&cif, FFI_FN(struct4), ts4_result, values);
    
    if (ts4_result->ui3 == 2U * 3U * 4U)
      puts ("structure test 4 ok!");
    else
      puts ("Structure test 4 found GCC's structure passing bug.");

    free (ts4_result);
  }

  /* struct tests */
  {
    test_structure_5 ts5_arg1, ts5_arg2;

    /* This is a hack to get a properly aligned result buffer */
    test_structure_5 *ts5_result = 
      (test_structure_5 *) malloc (sizeof(test_structure_5));

    args[0] = &ts5_type;
    args[1] = &ts5_type;
    values[0] = &ts5_arg1;
    values[1] = &ts5_arg2;
    
    /* Initialize the cif */
    CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, 
		       &ts5_type, args) == FFI_OK);

    ts5_arg1.c1 = 2;
    ts5_arg1.c2 = 6;
    ts5_arg2.c1 = 5;
    ts5_arg2.c2 = 3;

    ffi_call (&cif, FFI_FN(struct5), ts5_result, values);
    
    if (ts5_result->c1 == 7 
	&& ts5_result->c2 == 3)
      puts ("structure test 5 ok!");
    else
      puts ("Structure test 5 found GCC's structure passing bug.");

    free (ts5_result);
  }

#else
  printf("Structure passing doesn't work on Win32.\n");
#endif /* X86_WIN32 */

# if FFI_CLOSURES
  /* A simple closure test */
    {
      ffi_closure cl;
      ffi_type * cl_arg_types[3];

      cl_arg_types[0] = &ffi_type_sint;
      cl_arg_types[1] = &ffi_type_float;
      cl_arg_types[2] = NULL;
      
      /* Initialize the cif */
      CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, 
	    	         &ffi_type_sint, cl_arg_types) == FFI_OK);

      CHECK(ffi_prep_closure(&cl, &cif, closure_test_fn,
			     (void *) 3 /* userdata */)
	    == FFI_OK);
      CHECK((*((closure_test_type)(&cl)))(1, 2.0) == 6);
    }
# endif

  /* If we arrived here, all is good */
  (void) puts("\nLooks good. No surprises.\n");

  /*@-compdestroy@*/

  return 0;
}