public inbox for libffi-discuss@sourceware.org
 help / color / mirror / Atom feed
* Incorrect data detected in the nested float struct with x86/libffi on Linux/64bit
@ 2021-06-09 16:41 Cheng Jin
  2021-06-09 16:50 ` Anthony Green
                   ` (2 more replies)
  0 siblings, 3 replies; 10+ messages in thread
From: Cheng Jin @ 2021-06-09 16:41 UTC (permalink / raw)
  To: libffi-discuss



Hi,

We found that the nested struct [[float, float], float] works good with
x86/libffi (at https://github.com/libffi/libffi/tree/master/src/x86)
on Linux/64bit (verified on Ubuntu 19) while a variant of it like
[float,[float,float]] was messed up at the 3rd element when invoking
ffi_call() in the following test:


typedef struct stru_Nested_F stru_Nested_F;

struct stru_FF {
	float elem1;
	float elem2;
};

struct stru_Nested_F {
	float elem1;
	stru_FF elem2;
};

static float testNestedFloatStruct(float arg1, stru_Nested_F arg2)
{
	float floatSum = arg1 + arg2.elem1 + arg2.elem2.elem1 +
arg2.elem2.elem2;
	return floatSum;
}

int main() {
	  float returnValue = 0;
	  ffi_cif cif_temp;
	  UDATA structElemNum = 2;
	  UDATA nestedStructElemNum = 2;
	  UDATA argNum = 2;
	  ffi_type **cls_struct_fields1 = (ffi_type **)malloc(sizeof(ffi_type
*) * (structElemNum + 1));
	  ffi_type **cls_struct_fields2 = (ffi_type **)malloc(sizeof(ffi_type
*) * (nestedStructElemNum + 1));
	  ffi_type **dbl_arg_types = (ffi_type **)malloc(sizeof(ffi_type *) *
(argNum + 1));
	  void **args_db = (void **)malloc(sizeof(void *) * (argNum + 1));
	  ffi_type cls_struct_type1, cls_struct_type2;
	  ffi_type *retType = &ffi_type_float;
	  float arg1;
	  float *arg2 = (float *)malloc(sizeof(stru_Nested_F));

	  cls_struct_fields2[0] = &ffi_type_float;
	  cls_struct_fields2[1] = &ffi_type_float;
	  cls_struct_fields2[2] = NULL;

	  cls_struct_type2.size = 0;
	  cls_struct_type2.alignment = 0;
	  cls_struct_type2.type = FFI_TYPE_STRUCT;
	  cls_struct_type2.elements = cls_struct_fields2;

	  cls_struct_fields1[0] = &ffi_type_float;
	  cls_struct_fields1[1] = &cls_struct_type2;
	  cls_struct_fields1[2] = NULL;

	  cls_struct_type1.size = 0;
	  cls_struct_type1.alignment = 0;
	  cls_struct_type1.type = FFI_TYPE_STRUCT;
	  cls_struct_type1.elements = cls_struct_fields1;

	  dbl_arg_types[0] = &ffi_type_float;
	  dbl_arg_types[1] = &cls_struct_type1;
	  dbl_arg_types[2] = NULL;

	 ffi_prep_cif(&cif_temp, FFI_DEFAULT_ABI, 2, retType, dbl_arg_types);
	 arg1 = 37.88;
	 arg2[0] = 31.22;
	 arg2[1] = 33.44;
	 arg2[2] = 35.66;
	 args_db[0] = &arg1;
	 args_db[1] = arg2;
	 args_db[2] = NULL;

	ffi_call(&cif_temp, FFI_FN(testNestedFloatStruct), &returnValue,
args_db);

	free(cls_struct_fields1);
	free(cls_struct_fields2);
	free(dbl_arg_types);
	free(args_db);

     return 0;
}

with the debugging output as follows:

(gdb) p arg2[0]
$1 = 31.2199993
(gdb) p arg2[1]
$2 = 33.4399986
(gdb) p arg2[2]
$3 = 35.6599998
(gdb) x/10x  arg2
0x7ffff025b540:	0x41f9c28f	0x4205c28f	0x420ea3d7	0xdddddddd
0x7ffff025b550:	0xb7654321	0x475d4352	0x0000000c	0x00000000
0x7ffff025b560:	0xf749c970	0x00007fff


(gdb) bt
#0  testNestedFloatStruct(arg1=37.8800011, arg2=...) at main.c:xxx
#1  0x00007ffff746e4e0 in ffi_call_unix64 () at x86/unix64.S:xxx
#2  0x00007ffff746dac8 in ffi_call (cif=0x7ffff7d44e90, fn=0x7ffff7f9e060,
rvalue=0x16818, avalue=0x7ffff7d44f30) at x86/ffi64.c:xxx

Thread 2 "main" hit Breakpoint 2, testNestedFloatStruct(arg1=37.8800011,
arg2=...) at main.c
		float floatSum = arg1 + arg2.elem1 + arg2.elem2.elem1 +
arg2.elem2.elem2;
(gdb) p arg2
$4 = {
  elem1 = 31.2199993,
  elem2 = {
    elem1 = 33.4399986,
    elem2 = 4.20389539e-45  <------------------ messed up
  }
}

(gdb) x/10x  &arg2
0x7ffff7d44458:	0x41f9c28f	0x4205c28f	0x00000003	0x00007fff
0x7ffff7d44468:	0xf70cf1e6	0x4217851f	0xf7d44510	0x00007fff
0x7ffff7d44478:	0xf7d44660	0x00007fff


-------------------------------------------

It looks like there is something wrong in dealing with the nested stuct on
Linux/64bit in x86/libffi as the test above works good on Windows/64bit.


Thanks and Best Regards
Cheng Jin


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Incorrect data detected in the nested float struct with x86/libffi on Linux/64bit
  2021-06-09 16:41 Incorrect data detected in the nested float struct with x86/libffi on Linux/64bit Cheng Jin
@ 2021-06-09 16:50 ` Anthony Green
  2021-06-09 17:53   ` Cheng Jin
  2021-06-15 18:02   ` Jakub Jelinek
  2021-06-09 23:48 ` Kaz Kylheku (libffi)
  2021-06-10  2:05 ` Kaz Kylheku (libffi)
  2 siblings, 2 replies; 10+ messages in thread
From: Anthony Green @ 2021-06-09 16:50 UTC (permalink / raw)
  To: Cheng Jin; +Cc: libffi-discuss

Thank you, Cheng.  Are you able to submit this test case as a github pull
request?  The resulting CI testing will give us a broader picture of where
we have problems.

Thanks,

AG


On Wed, Jun 9, 2021 at 12:41 PM Cheng Jin via Libffi-discuss <
libffi-discuss@sourceware.org> wrote:

>
>
> Hi,
>
> We found that the nested struct [[float, float], float] works good with
> x86/libffi (at https://github.com/libffi/libffi/tree/master/src/x86)
> on Linux/64bit (verified on Ubuntu 19) while a variant of it like
> [float,[float,float]] was messed up at the 3rd element when invoking
> ffi_call() in the following test:
>
>
> typedef struct stru_Nested_F stru_Nested_F;
>
> struct stru_FF {
>         float elem1;
>         float elem2;
> };
>
> struct stru_Nested_F {
>         float elem1;
>         stru_FF elem2;
> };
>
> static float testNestedFloatStruct(float arg1, stru_Nested_F arg2)
> {
>         float floatSum = arg1 + arg2.elem1 + arg2.elem2.elem1 +
> arg2.elem2.elem2;
>         return floatSum;
> }
>
> int main() {
>           float returnValue = 0;
>           ffi_cif cif_temp;
>           UDATA structElemNum = 2;
>           UDATA nestedStructElemNum = 2;
>           UDATA argNum = 2;
>           ffi_type **cls_struct_fields1 = (ffi_type
> **)malloc(sizeof(ffi_type
> *) * (structElemNum + 1));
>           ffi_type **cls_struct_fields2 = (ffi_type
> **)malloc(sizeof(ffi_type
> *) * (nestedStructElemNum + 1));
>           ffi_type **dbl_arg_types = (ffi_type **)malloc(sizeof(ffi_type
> *) *
> (argNum + 1));
>           void **args_db = (void **)malloc(sizeof(void *) * (argNum + 1));
>           ffi_type cls_struct_type1, cls_struct_type2;
>           ffi_type *retType = &ffi_type_float;
>           float arg1;
>           float *arg2 = (float *)malloc(sizeof(stru_Nested_F));
>
>           cls_struct_fields2[0] = &ffi_type_float;
>           cls_struct_fields2[1] = &ffi_type_float;
>           cls_struct_fields2[2] = NULL;
>
>           cls_struct_type2.size = 0;
>           cls_struct_type2.alignment = 0;
>           cls_struct_type2.type = FFI_TYPE_STRUCT;
>           cls_struct_type2.elements = cls_struct_fields2;
>
>           cls_struct_fields1[0] = &ffi_type_float;
>           cls_struct_fields1[1] = &cls_struct_type2;
>           cls_struct_fields1[2] = NULL;
>
>           cls_struct_type1.size = 0;
>           cls_struct_type1.alignment = 0;
>           cls_struct_type1.type = FFI_TYPE_STRUCT;
>           cls_struct_type1.elements = cls_struct_fields1;
>
>           dbl_arg_types[0] = &ffi_type_float;
>           dbl_arg_types[1] = &cls_struct_type1;
>           dbl_arg_types[2] = NULL;
>
>          ffi_prep_cif(&cif_temp, FFI_DEFAULT_ABI, 2, retType,
> dbl_arg_types);
>          arg1 = 37.88;
>          arg2[0] = 31.22;
>          arg2[1] = 33.44;
>          arg2[2] = 35.66;
>          args_db[0] = &arg1;
>          args_db[1] = arg2;
>          args_db[2] = NULL;
>
>         ffi_call(&cif_temp, FFI_FN(testNestedFloatStruct), &returnValue,
> args_db);
>
>         free(cls_struct_fields1);
>         free(cls_struct_fields2);
>         free(dbl_arg_types);
>         free(args_db);
>
>      return 0;
> }
>
> with the debugging output as follows:
>
> (gdb) p arg2[0]
> $1 = 31.2199993
> (gdb) p arg2[1]
> $2 = 33.4399986
> (gdb) p arg2[2]
> $3 = 35.6599998
> (gdb) x/10x  arg2
> 0x7ffff025b540: 0x41f9c28f      0x4205c28f      0x420ea3d7      0xdddddddd
> 0x7ffff025b550: 0xb7654321      0x475d4352      0x0000000c      0x00000000
> 0x7ffff025b560: 0xf749c970      0x00007fff
>
>
> (gdb) bt
> #0  testNestedFloatStruct(arg1=37.8800011, arg2=...) at main.c:xxx
> #1  0x00007ffff746e4e0 in ffi_call_unix64 () at x86/unix64.S:xxx
> #2  0x00007ffff746dac8 in ffi_call (cif=0x7ffff7d44e90, fn=0x7ffff7f9e060,
> rvalue=0x16818, avalue=0x7ffff7d44f30) at x86/ffi64.c:xxx
>
> Thread 2 "main" hit Breakpoint 2, testNestedFloatStruct(arg1=37.8800011,
> arg2=...) at main.c
>                 float floatSum = arg1 + arg2.elem1 + arg2.elem2.elem1 +
> arg2.elem2.elem2;
> (gdb) p arg2
> $4 = {
>   elem1 = 31.2199993,
>   elem2 = {
>     elem1 = 33.4399986,
>     elem2 = 4.20389539e-45  <------------------ messed up
>   }
> }
>
> (gdb) x/10x  &arg2
> 0x7ffff7d44458: 0x41f9c28f      0x4205c28f      0x00000003      0x00007fff
> 0x7ffff7d44468: 0xf70cf1e6      0x4217851f      0xf7d44510      0x00007fff
> 0x7ffff7d44478: 0xf7d44660      0x00007fff
>
>
> -------------------------------------------
>
> It looks like there is something wrong in dealing with the nested stuct on
> Linux/64bit in x86/libffi as the test above works good on Windows/64bit.
>
>
> Thanks and Best Regards
> Cheng Jin
>
>

^ permalink raw reply	[flat|nested] 10+ messages in thread

* RE: Incorrect data detected in the nested float struct with x86/libffi on Linux/64bit
  2021-06-09 16:50 ` Anthony Green
@ 2021-06-09 17:53   ` Cheng Jin
  2021-06-15 18:02   ` Jakub Jelinek
  1 sibling, 0 replies; 10+ messages in thread
From: Cheng Jin @ 2021-06-09 17:53 UTC (permalink / raw)
  To: Anthony Green; +Cc: libffi-discuss

[-- Attachment #1: Type: text/plain, Size: 5628 bytes --]




Hi Anthony,

Many thanks for the quick response. The PR has been created at
https://github.com/libffi/libffi/pull/640 as requested.

Thanks and Best Regards
Cheng Jin




From:	Anthony Green <green@moxielogic.com>
To:	Cheng Jin <jincheng@ca.ibm.com>
Cc:	libffi-discuss <libffi-discuss@sourceware.org>
Date:	2021-06-09 12:50 PM
Subject:	[EXTERNAL] Re: Incorrect data detected in the nested float
            struct with x86/libffi on Linux/64bit



Thank you, Cheng.  Are you able to submit this test case as a github pull
request?  The resulting CI testing will give us a broader picture of where
we have problems. Thanks, AG On Wed, Jun 9, 2021 at 12:41 PM Cheng Jin via
Libffi-discuss < ZjQcmQRYFpfptBannerStart
This Message Is From an External Sender
This message came from outside your organization.
ZjQcmQRYFpfptBannerEnd
Thank you, Cheng.  Are you able to submit this test case as a github pull
request?  The resulting CI testing will give us a broader picture of where
we have problems.

Thanks,

AG


On Wed, Jun 9, 2021 at 12:41 PM Cheng Jin via Libffi-discuss <
libffi-discuss@sourceware.org> wrote:


  Hi,

  We found that the nested struct [[float, float], float] works good with
  x86/libffi (at https://github.com/libffi/libffi/tree/master/src/x86)
  on Linux/64bit (verified on Ubuntu 19) while a variant of it like
  [float,[float,float]] was messed up at the 3rd element when invoking
  ffi_call() in the following test:


  typedef struct stru_Nested_F stru_Nested_F;

  struct stru_FF {
          float elem1;
          float elem2;
  };

  struct stru_Nested_F {
          float elem1;
          stru_FF elem2;
  };

  static float testNestedFloatStruct(float arg1, stru_Nested_F arg2)
  {
          float floatSum = arg1 + arg2.elem1 + arg2.elem2.elem1 +
  arg2.elem2.elem2;
          return floatSum;
  }

  int main() {
            float returnValue = 0;
            ffi_cif cif_temp;
            UDATA structElemNum = 2;
            UDATA nestedStructElemNum = 2;
            UDATA argNum = 2;
            ffi_type **cls_struct_fields1 = (ffi_type
  **)malloc(sizeof(ffi_type
  *) * (structElemNum + 1));
            ffi_type **cls_struct_fields2 = (ffi_type
  **)malloc(sizeof(ffi_type
  *) * (nestedStructElemNum + 1));
            ffi_type **dbl_arg_types = (ffi_type **)malloc(sizeof(ffi_type
  *) *
  (argNum + 1));
            void **args_db = (void **)malloc(sizeof(void *) * (argNum +
  1));
            ffi_type cls_struct_type1, cls_struct_type2;
            ffi_type *retType = &ffi_type_float;
            float arg1;
            float *arg2 = (float *)malloc(sizeof(stru_Nested_F));

            cls_struct_fields2[0] = &ffi_type_float;
            cls_struct_fields2[1] = &ffi_type_float;
            cls_struct_fields2[2] = NULL;

            cls_struct_type2.size = 0;
            cls_struct_type2.alignment = 0;
            cls_struct_type2.type = FFI_TYPE_STRUCT;
            cls_struct_type2.elements = cls_struct_fields2;

            cls_struct_fields1[0] = &ffi_type_float;
            cls_struct_fields1[1] = &cls_struct_type2;
            cls_struct_fields1[2] = NULL;

            cls_struct_type1.size = 0;
            cls_struct_type1.alignment = 0;
            cls_struct_type1.type = FFI_TYPE_STRUCT;
            cls_struct_type1.elements = cls_struct_fields1;

            dbl_arg_types[0] = &ffi_type_float;
            dbl_arg_types[1] = &cls_struct_type1;
            dbl_arg_types[2] = NULL;

           ffi_prep_cif(&cif_temp, FFI_DEFAULT_ABI, 2, retType,
  dbl_arg_types);
           arg1 = 37.88;
           arg2[0] = 31.22;
           arg2[1] = 33.44;
           arg2[2] = 35.66;
           args_db[0] = &arg1;
           args_db[1] = arg2;
           args_db[2] = NULL;

          ffi_call(&cif_temp, FFI_FN(testNestedFloatStruct), &returnValue,
  args_db);

          free(cls_struct_fields1);
          free(cls_struct_fields2);
          free(dbl_arg_types);
          free(args_db);

       return 0;
  }

  with the debugging output as follows:

  (gdb) p arg2[0]
  $1 = 31.2199993
  (gdb) p arg2[1]
  $2 = 33.4399986
  (gdb) p arg2[2]
  $3 = 35.6599998
  (gdb) x/10x  arg2
  0x7ffff025b540: 0x41f9c28f      0x4205c28f      0x420ea3d7
  0xdddddddd
  0x7ffff025b550: 0xb7654321      0x475d4352      0x0000000c
  0x00000000
  0x7ffff025b560: 0xf749c970      0x00007fff


  (gdb) bt
  #0  testNestedFloatStruct(arg1=37.8800011, arg2=...) at main.c:xxx
  #1  0x00007ffff746e4e0 in ffi_call_unix64 () at x86/unix64.S:xxx
  #2  0x00007ffff746dac8 in ffi_call (cif=0x7ffff7d44e90,
  fn=0x7ffff7f9e060,
  rvalue=0x16818, avalue=0x7ffff7d44f30) at x86/ffi64.c:xxx

  Thread 2 "main" hit Breakpoint 2, testNestedFloatStruct(arg1=37.8800011,
  arg2=...) at main.c
                  float floatSum = arg1 + arg2.elem1 + arg2.elem2.elem1 +
  arg2.elem2.elem2;
  (gdb) p arg2
  $4 = {
    elem1 = 31.2199993,
    elem2 = {
      elem1 = 33.4399986,
      elem2 = 4.20389539e-45  <------------------ messed up
    }
  }

  (gdb) x/10x  &arg2
  0x7ffff7d44458: 0x41f9c28f      0x4205c28f      0x00000003
  0x00007fff
  0x7ffff7d44468: 0xf70cf1e6      0x4217851f      0xf7d44510
  0x00007fff
  0x7ffff7d44478: 0xf7d44660      0x00007fff


  -------------------------------------------

  It looks like there is something wrong in dealing with the nested stuct
  on
  Linux/64bit in x86/libffi as the test above works good on Windows/64bit.


  Thanks and Best Regards
  Cheng Jin



[-- Attachment #2: graycol.gif --]
[-- Type: image/gif, Size: 105 bytes --]

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Incorrect data detected in the nested float struct with x86/libffi on Linux/64bit
  2021-06-09 16:41 Incorrect data detected in the nested float struct with x86/libffi on Linux/64bit Cheng Jin
  2021-06-09 16:50 ` Anthony Green
@ 2021-06-09 23:48 ` Kaz Kylheku (libffi)
  2021-06-10  0:21   ` Cheng Jin
  2021-06-10  2:05 ` Kaz Kylheku (libffi)
  2 siblings, 1 reply; 10+ messages in thread
From: Kaz Kylheku (libffi) @ 2021-06-09 23:48 UTC (permalink / raw)
  To: Cheng Jin; +Cc: libffi-discuss

On 2021-06-09 09:41, Cheng Jin via Libffi-discuss wrote:
> Hi,

Hi Cheng Jin,

A small matter on a tangent.

> 
> 	  cls_struct_fields1[0] = &ffi_type_float;
> 	  cls_struct_fields1[1] = &cls_struct_type2;
> 	  cls_struct_fields1[2] = NULL;

Indeed, the array describing the element types of a structure must be
null terminated, so this is required.

> 	  cls_struct_type1.size = 0;
> 	  cls_struct_type1.alignment = 0;
> 	  cls_struct_type1.type = FFI_TYPE_STRUCT;
> 	  cls_struct_type1.elements = cls_struct_fields1;

Note that here, the size of the object is not indicated. That's why
the extra null pointer is required to infer the size.

> 
> 	  dbl_arg_types[0] = &ffi_type_float;
> 	  dbl_arg_types[1] = &cls_struct_type1;
> 	  dbl_arg_types[2] = NULL;

But, for the argument array of a ffi_cif, no null termination is 
required.

> 	 ffi_prep_cif(&cif_temp, FFI_DEFAULT_ABI, 2, retType, dbl_arg_types);

No requirement for a null terminator is documented or appears in
examples. The 2 argument indicates the number of elements.

There is no harm in it; just pointing it out.

When I looked at your code, I went scrambling through documentation
to see if I was missing a required null terminator. :)

Cheers ...

^ permalink raw reply	[flat|nested] 10+ messages in thread

* RE: Incorrect data detected in the nested float struct with x86/libffi on Linux/64bit
  2021-06-09 23:48 ` Kaz Kylheku (libffi)
@ 2021-06-10  0:21   ` Cheng Jin
  0 siblings, 0 replies; 10+ messages in thread
From: Cheng Jin @ 2021-06-10  0:21 UTC (permalink / raw)
  To: Kaz Kylheku (libffi); +Cc: libffi-discuss

[-- Attachment #1: Type: text/plain, Size: 2007 bytes --]




Hi Kaz,

Many thanks for your comments on the test code.

Actually it is not the test case used in our project but just to verify
whether it works good as expected.
The test code (already merged to the libffi tests at
https://github.com/libffi/libffi/pull/640 as requested by them) was
identified as a bug specific to x86_64 which will be investigated to see
what happens.


Thanks and Best Regards
Cheng Jin




From:	"Kaz Kylheku (libffi)" <382-725-6798@kylheku.com>
To:	Cheng Jin <jincheng@ca.ibm.com>
Cc:	libffi-discuss@sourceware.org
Date:	2021-06-09 07:48 PM
Subject:	[EXTERNAL] Re: Incorrect data detected in the nested float
            struct with  x86/libffi on Linux/64bit



On 2021-06-09 09:41, Cheng Jin via Libffi-discuss wrote:
> Hi,

Hi Cheng Jin,

A small matter on a tangent.

>
> 		   cls_struct_fields1[0] = &ffi_type_float;
> 		   cls_struct_fields1[1] = &cls_struct_type2;
> 		   cls_struct_fields1[2] = NULL;

Indeed, the array describing the element types of a structure must be
null terminated, so this is required.

> 		   cls_struct_type1.size = 0;
> 		   cls_struct_type1.alignment = 0;
> 		   cls_struct_type1.type = FFI_TYPE_STRUCT;
> 		   cls_struct_type1.elements = cls_struct_fields1;

Note that here, the size of the object is not indicated. That's why
the extra null pointer is required to infer the size.

>
> 		   dbl_arg_types[0] = &ffi_type_float;
> 		   dbl_arg_types[1] = &cls_struct_type1;
> 		   dbl_arg_types[2] = NULL;

But, for the argument array of a ffi_cif, no null termination is
required.

> 		  ffi_prep_cif(&cif_temp, FFI_DEFAULT_ABI, 2, retType,
dbl_arg_types);

No requirement for a null terminator is documented or appears in
examples. The 2 argument indicates the number of elements.

There is no harm in it; just pointing it out.

When I looked at your code, I went scrambling through documentation
to see if I was missing a required null terminator. :)

Cheers ...




[-- Attachment #2: graycol.gif --]
[-- Type: image/gif, Size: 105 bytes --]

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Incorrect data detected in the nested float struct with x86/libffi on Linux/64bit
  2021-06-09 16:41 Incorrect data detected in the nested float struct with x86/libffi on Linux/64bit Cheng Jin
  2021-06-09 16:50 ` Anthony Green
  2021-06-09 23:48 ` Kaz Kylheku (libffi)
@ 2021-06-10  2:05 ` Kaz Kylheku (libffi)
  2021-06-10  2:39   ` Cheng Jin
  2 siblings, 1 reply; 10+ messages in thread
From: Kaz Kylheku (libffi) @ 2021-06-10  2:05 UTC (permalink / raw)
  To: Cheng Jin; +Cc: libffi-discuss

On 2021-06-09 09:41, Cheng Jin via Libffi-discuss wrote:
> Hi,
> 
> We found that the nested struct [[float, float], float] works good with
> x86/libffi (at https://github.com/libffi/libffi/tree/master/src/x86)
> on Linux/64bit (verified on Ubuntu 19) while a variant of it like
> [float,[float,float]] was messed up at the 3rd element when invoking
> ffi_call() in the following test:

In the libffi that comes with Ubuntu 18.04 Server, x84-64, your test
case aborts in ffi_call.

I built a similar test case in which I put your function into a shared
lib, and used a libffi-based programming language to call it. Same
thing: abort in ffi_call.

There is some problem in that version of libffi; it doesn't like small
structures. If I add padding to the structure, then there is no abort.

My version of the function looks like this:

float_t testNestedFloatStruct(float_t arg1, stru_Nested_F arg2)
{
   float_t floatSum = arg1 + arg2.elem1 + arg2.elem2.elem1 + 
arg2.elem2.elem2;
   puts("called");
   printf("arg1 = %f, arg2 = { %f, { %f, %f } }\n", arg1, arg2.elem1,
          arg2.elem2.elem1, arg2.elem2.elem2);
   return floatSum;
}

On the FFI side, if I add a uint64's worth of padding to the structure,
the ffi_call proceeds without abort, and the result is like this:

arg1 = 1.000000, arg2 = { 0.000000, { 0.000000, 
-52784298695107543040.000000 } }
-5.27842986951075e19

The second line is the caller printing the return value. As you can
see, complete rubbish.

If I take out the padding and change everything to double (my float_f
typedef lets me do that easily), it looks like this:

arg1 = 1.000000, arg2 = { 2.000000, { 3.000000, 4.000000 } }
10.0

That's the expected behavior; the all-float case should look the same.

Basically with the padding, although the call works, it's using the 
wrong
calling conventions. I think this small structure is supposed to be 
passed
in registers.

If I step over the ffi_prep_cif call to see what args were passed to it
and how the sizes and alignment were set, all looks good:

ffi_make_call_desc (ntotal=<optimized out>, nfixed=<optimized out>,
     rettype=0x7ffff7f97780, argtypes=<optimized out>, name_in=<optimized 
out>)
     at ffi.c:4831
4831      if (ffis != FFI_OK)
(gdb) p args[0]
$5 = (ffi_type *) 0x758c80 <ffi_type_float>
(gdb) p args[1]
$6 = (ffi_type *) 0xc38220
(gdb) p (*args[1])
$7 = {size = 12, alignment = 4, type = 13, elements = 0xc38240}
(gdb) p (*args[1]).elements[0]
$8 = (struct _ffi_type *) 0x758c80 <ffi_type_float>
(gdb) p (*args[1]).elements[1]
$9 = (struct _ffi_type *) 0xb92160
(gdb) p (*(*args[1]).elements[1])
$10 = {size = 8, alignment = 4, type = 13, elements = 0xb92180}
(gdb) p (*(*args[1]).elements[1]).elements[0]
$11 = (struct _ffi_type *) 0x758c80 <ffi_type_float>
(gdb) p (*(*args[1]).elements[1]).elements[1]
$12 = (struct _ffi_type *) 0x758c80 <ffi_type_float>
(gdb) p (*(*args[1]).elements[1]).elements[2]
$13 = (struct _ffi_type *) 0x0
(gdb) p (*args[1]).elements[2]
$14 = (struct _ffi_type *) 0x0


Both elements arrays have two elements and a null terminator. Two floats
at the leaves, and a float + struct at the first level.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* RE: Incorrect data detected in the nested float struct with x86/libffi on Linux/64bit
  2021-06-10  2:05 ` Kaz Kylheku (libffi)
@ 2021-06-10  2:39   ` Cheng Jin
  0 siblings, 0 replies; 10+ messages in thread
From: Cheng Jin @ 2021-06-10  2:39 UTC (permalink / raw)
  To: Kaz Kylheku (libffi); +Cc: libffi-discuss

[-- Attachment #1: Type: text/plain, Size: 4266 bytes --]




Hi Kaz,

It is highly likely that the version of libffi coming with Ubuntu 18 is
outdated (we experienced the same abort with an outdated x86/libffi
integrated in our own project).
Please try the latest version of x86/libffi at
https://github.com/libffi/libffi/tree/master/src/x86.

In addition, adding padding to the nested structure might work but doesn't
make any sense as ffi_prep_cif() will detect/compute the padding
automatically in the code, in which case everything related to padding
should be handled by libffi rather than by users. That's why they need to
investigate why it failed to handle on Linux/64bit given it works good on
other platforms (e.g. Windows/x86_64, Aarch64).


Thanks and Best Regards
Cheng Jin




From:	"Kaz Kylheku (libffi)" <382-725-6798@kylheku.com>
To:	Cheng Jin <jincheng@ca.ibm.com>
Cc:	libffi-discuss@sourceware.org
Date:	2021-06-09 10:05 PM
Subject:	[EXTERNAL] Re: Incorrect data detected in the nested float
            struct with  x86/libffi on Linux/64bit



On 2021-06-09 09:41, Cheng Jin via Libffi-discuss wrote:
> Hi,
>
> We found that the nested struct [[float, float], float] works good with
> x86/libffi (at
https://github.com/libffi/libffi/tree/master/src/x86
 )
> on Linux/64bit (verified on Ubuntu 19) while a variant of it like
> [float,[float,float]] was messed up at the 3rd element when invoking
> ffi_call() in the following test:

In the libffi that comes with Ubuntu 18.04 Server, x84-64, your test
case aborts in ffi_call.

I built a similar test case in which I put your function into a shared
lib, and used a libffi-based programming language to call it. Same
thing: abort in ffi_call.

There is some problem in that version of libffi; it doesn't like small
structures. If I add padding to the structure, then there is no abort.

My version of the function looks like this:

float_t testNestedFloatStruct(float_t arg1, stru_Nested_F arg2)
{
   float_t floatSum = arg1 + arg2.elem1 + arg2.elem2.elem1 +
arg2.elem2.elem2;
   puts("called");
   printf("arg1 = %f, arg2 = { %f, { %f, %f } }\n", arg1, arg2.elem1,
          arg2.elem2.elem1, arg2.elem2.elem2);
   return floatSum;
}

On the FFI side, if I add a uint64's worth of padding to the structure,
the ffi_call proceeds without abort, and the result is like this:

arg1 = 1.000000, arg2 = { 0.000000, { 0.000000,
-52784298695107543040.000000 } }
-5.27842986951075e19

The second line is the caller printing the return value. As you can
see, complete rubbish.

If I take out the padding and change everything to double (my float_f
typedef lets me do that easily), it looks like this:

arg1 = 1.000000, arg2 = { 2.000000, { 3.000000, 4.000000 } }
10.0

That's the expected behavior; the all-float case should look the same.

Basically with the padding, although the call works, it's using the
wrong
calling conventions. I think this small structure is supposed to be
passed
in registers.

If I step over the ffi_prep_cif call to see what args were passed to it
and how the sizes and alignment were set, all looks good:

ffi_make_call_desc (ntotal=<optimized out>, nfixed=<optimized out>,
     rettype=0x7ffff7f97780, argtypes=<optimized out>, name_in=<optimized
out>)
     at ffi.c:4831
4831      if (ffis != FFI_OK)
(gdb) p args[0]
$5 = (ffi_type *) 0x758c80 <ffi_type_float>
(gdb) p args[1]
$6 = (ffi_type *) 0xc38220
(gdb) p (*args[1])
$7 = {size = 12, alignment = 4, type = 13, elements = 0xc38240}
(gdb) p (*args[1]).elements[0]
$8 = (struct _ffi_type *) 0x758c80 <ffi_type_float>
(gdb) p (*args[1]).elements[1]
$9 = (struct _ffi_type *) 0xb92160
(gdb) p (*(*args[1]).elements[1])
$10 = {size = 8, alignment = 4, type = 13, elements = 0xb92180}
(gdb) p (*(*args[1]).elements[1]).elements[0]
$11 = (struct _ffi_type *) 0x758c80 <ffi_type_float>
(gdb) p (*(*args[1]).elements[1]).elements[1]
$12 = (struct _ffi_type *) 0x758c80 <ffi_type_float>
(gdb) p (*(*args[1]).elements[1]).elements[2]
$13 = (struct _ffi_type *) 0x0
(gdb) p (*args[1]).elements[2]
$14 = (struct _ffi_type *) 0x0


Both elements arrays have two elements and a null terminator. Two floats
at the leaves, and a float + struct at the first level.




[-- Attachment #2: graycol.gif --]
[-- Type: image/gif, Size: 105 bytes --]

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Incorrect data detected in the nested float struct with x86/libffi on Linux/64bit
  2021-06-09 16:50 ` Anthony Green
  2021-06-09 17:53   ` Cheng Jin
@ 2021-06-15 18:02   ` Jakub Jelinek
  2021-06-15 19:02     ` Jakub Jelinek
  1 sibling, 1 reply; 10+ messages in thread
From: Jakub Jelinek @ 2021-06-15 18:02 UTC (permalink / raw)
  To: Anthony Green; +Cc: Cheng Jin, libffi-discuss, DJ Delorie

On Wed, Jun 09, 2021 at 12:50:08PM -0400, Anthony Green wrote:
> Thank you, Cheng.  Are you able to submit this test case as a github pull
> request?  The resulting CI testing will give us a broader picture of where
> we have problems.

Comparing gcc/config/i386/ classify_argument and libffi classify_argument,
I found two important differences.

The first one seems the most important one, even GCC 3.2 included the bit
offset (byte offset in libffi) in the calculation of number of words.
And the other change is https://gcc.gnu.org/PR38781.

With this patch the posted testcase works and the testsuite on x86_64-linux
still passes, but haven't done more testing than that.

Haven't tried yet to adapt one of the
libffi/testsuite/libffi.call/nested_struct*.c tests to cover this though.

2021-06-15  Jakub Jelinek  <jakub@redhat.com>

	* src/x86/ffi64.c (classify_argument): For FFI_TYPE_STRUCT set words
	to number of words needed for type->size + byte_offset bytes rather
	than just type->size bytes.  Compute pos before the loop and check
	total size of the structure.

--- libffi/src/x86/ffi64.c.jj	2020-01-14 20:02:48.557583260 +0100
+++ libffi/src/x86/ffi64.c	2021-06-15 19:50:06.059108230 +0200
@@ -217,7 +217,8 @@ classify_argument (ffi_type *type, enum
     case FFI_TYPE_STRUCT:
       {
 	const size_t UNITS_PER_WORD = 8;
-	size_t words = (type->size + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
+	size_t words = (type->size + byte_offset + UNITS_PER_WORD - 1)
+		       / UNITS_PER_WORD;
 	ffi_type **ptr;
 	int i;
 	enum x86_64_reg_class subclasses[MAX_CLASSES];
@@ -241,16 +242,16 @@ classify_argument (ffi_type *type, enum
 	/* Merge the fields of structure.  */
 	for (ptr = type->elements; *ptr != NULL; ptr++)
 	  {
-	    size_t num;
+	    size_t num, pos;
 
 	    byte_offset = ALIGN (byte_offset, (*ptr)->alignment);
 
 	    num = classify_argument (*ptr, subclasses, byte_offset % 8);
 	    if (num == 0)
 	      return 0;
-	    for (i = 0; i < num; i++)
+	    pos = byte_offset / 8;
+	    for (i = 0; i < num && (i + pos) < words; i++)
 	      {
-		size_t pos = byte_offset / 8;
 		classes[i + pos] =
 		  merge_classes (subclasses[i], classes[i + pos]);
 	      }


	Jakub


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Incorrect data detected in the nested float struct with x86/libffi on Linux/64bit
  2021-06-15 18:02   ` Jakub Jelinek
@ 2021-06-15 19:02     ` Jakub Jelinek
  2021-06-15 19:29       ` Anthony Green
  0 siblings, 1 reply; 10+ messages in thread
From: Jakub Jelinek @ 2021-06-15 19:02 UTC (permalink / raw)
  To: Anthony Green, libffi-discuss

On Tue, Jun 15, 2021 at 08:02:56PM +0200, Jakub Jelinek via Libffi-discuss wrote:
> On Wed, Jun 09, 2021 at 12:50:08PM -0400, Anthony Green wrote:
> > Thank you, Cheng.  Are you able to submit this test case as a github pull
> > request?  The resulting CI testing will give us a broader picture of where
> > we have problems.
> 
> Comparing gcc/config/i386/ classify_argument and libffi classify_argument,
> I found two important differences.
> 
> The first one seems the most important one, even GCC 3.2 included the bit
> offset (byte offset in libffi) in the calculation of number of words.
> And the other change is https://gcc.gnu.org/PR38781.
> 
> With this patch the posted testcase works and the testsuite on x86_64-linux
> still passes, but haven't done more testing than that.
> 
> Haven't tried yet to adapt one of the
> libffi/testsuite/libffi.call/nested_struct*.c tests to cover this though.

And here is one with a testcase (modified nested_struct2.c for it).

I'm unsure about the current relationship between the github and gcc
copy of libffi, shall it go to both, or just one of them and be
cherry-picked from there?

Tested on x86_64-linux.

2021-06-15  Jakub Jelinek  <jakub@redhat.com>

	* src/x86/ffi64.c (classify_argument): For FFI_TYPE_STRUCT set words
	to number of words needed for type->size + byte_offset bytes rather
	than just type->size bytes.  Compute pos before the loop and check
	total size of the structure.
	* testsuite/libffi.call/nested_struct12.c: New test.

--- libffi/src/x86/ffi64.c.jj	2020-01-14 20:02:48.557583260 +0100
+++ libffi/src/x86/ffi64.c	2021-06-15 19:50:06.059108230 +0200
@@ -217,7 +217,8 @@ classify_argument (ffi_type *type, enum
     case FFI_TYPE_STRUCT:
       {
 	const size_t UNITS_PER_WORD = 8;
-	size_t words = (type->size + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
+	size_t words = (type->size + byte_offset + UNITS_PER_WORD - 1)
+		       / UNITS_PER_WORD;
 	ffi_type **ptr;
 	int i;
 	enum x86_64_reg_class subclasses[MAX_CLASSES];
@@ -241,16 +242,16 @@ classify_argument (ffi_type *type, enum
 	/* Merge the fields of structure.  */
 	for (ptr = type->elements; *ptr != NULL; ptr++)
 	  {
-	    size_t num;
+	    size_t num, pos;
 
 	    byte_offset = ALIGN (byte_offset, (*ptr)->alignment);
 
 	    num = classify_argument (*ptr, subclasses, byte_offset % 8);
 	    if (num == 0)
 	      return 0;
-	    for (i = 0; i < num; i++)
+	    pos = byte_offset / 8;
+	    for (i = 0; i < num && (i + pos) < words; i++)
 	      {
-		size_t pos = byte_offset / 8;
 		classes[i + pos] =
 		  merge_classes (subclasses[i], classes[i + pos]);
 	      }
--- libffi/testsuite/libffi.call/nested_struct12.c.jj	2021-06-15 20:31:43.327144303 +0200
+++ libffi/testsuite/libffi.call/nested_struct12.c	2021-06-15 20:47:13.129489263 +0200
@@ -0,0 +1,107 @@
+/* Area:	ffi_call, closure_call
+   Purpose:	Check structure passing.
+   Limitations:	none.
+   PR:		none.
+   Originator:	<jincheng@ca.ibm.com> and <jakub@redhat.com> 20210609	 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct A {
+  float a, b;
+} A;
+
+typedef struct B {
+  float x;
+  struct A y;
+} B;
+
+B B_fn(float b0, struct B b1)
+{
+  struct B result;
+
+  result.x = b0 + b1.x;
+  result.y.a = b0 + b1.y.a;
+  result.y.b = b0 + b1.y.b;
+
+  printf("%g %g %g %g: %g %g %g\n", b0, b1.x, b1.y.a, b1.y.b,
+	 result.x, result.y.a, result.y.b);
+
+  return result;
+}
+
+static void
+B_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
+     void* userdata __UNUSED__)
+{
+  float b0;
+  struct B b1;
+
+  b0 = *(float*)(args[0]);
+  b1 = *(struct B*)(args[1]);
+
+  *(B*)resp = B_fn(b0, b1);
+}
+
+int main (void)
+{
+  ffi_cif cif;
+  void *code;
+  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
+  void* args_dbl[3];
+  ffi_type* cls_struct_fields[3];
+  ffi_type* cls_struct_fields1[3];
+  ffi_type cls_struct_type, cls_struct_type1;
+  ffi_type* dbl_arg_types[3];
+
+  float e_dbl = 12.125f;
+  struct B f_dbl = { 24.75f, { 31.625f, 32.25f } };
+
+  struct B res_dbl;
+
+  cls_struct_type.size = 0;
+  cls_struct_type.alignment = 0;
+  cls_struct_type.type = FFI_TYPE_STRUCT;
+  cls_struct_type.elements = cls_struct_fields;
+
+  cls_struct_type1.size = 0;
+  cls_struct_type1.alignment = 0;
+  cls_struct_type1.type = FFI_TYPE_STRUCT;
+  cls_struct_type1.elements = cls_struct_fields1;
+
+  cls_struct_fields[0] = &ffi_type_float;
+  cls_struct_fields[1] = &ffi_type_float;
+  cls_struct_fields[2] = NULL;
+
+  cls_struct_fields1[0] = &ffi_type_float;
+  cls_struct_fields1[1] = &cls_struct_type;
+  cls_struct_fields1[2] = NULL;
+
+
+  dbl_arg_types[0] = &ffi_type_float;
+  dbl_arg_types[1] = &cls_struct_type1;
+  dbl_arg_types[2] = NULL;
+
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type1,
+		     dbl_arg_types) == FFI_OK);
+
+  args_dbl[0] = &e_dbl;
+  args_dbl[1] = &f_dbl;
+  args_dbl[2] = NULL;
+
+  ffi_call(&cif, FFI_FN(B_fn), &res_dbl, args_dbl);
+  /* { dg-output "12.125 24.75 31.625 32.25: 36.875 43.75 44.375" } */
+  CHECK( res_dbl.x == (e_dbl + f_dbl.x));
+  CHECK( res_dbl.y.a == (e_dbl + f_dbl.y.a));
+  CHECK( res_dbl.y.b == (e_dbl + f_dbl.y.b));
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, B_gn, NULL, code) == FFI_OK);
+
+  res_dbl = ((B(*)(float, B))(code))(e_dbl, f_dbl);
+  /* { dg-output "\n12.125 24.75 31.625 32.25: 36.875 43.75 44.375" } */
+  CHECK( res_dbl.x == (e_dbl + f_dbl.x));
+  CHECK( res_dbl.y.a == (e_dbl + f_dbl.y.a));
+  CHECK( res_dbl.y.b == (e_dbl + f_dbl.y.b));
+
+  exit(0);
+}


	Jakub


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Incorrect data detected in the nested float struct with x86/libffi on Linux/64bit
  2021-06-15 19:02     ` Jakub Jelinek
@ 2021-06-15 19:29       ` Anthony Green
  0 siblings, 0 replies; 10+ messages in thread
From: Anthony Green @ 2021-06-15 19:29 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: libffi-discuss

Thank you, Jakub!  This has been committed.

AG

On Tue, Jun 15, 2021 at 3:02 PM Jakub Jelinek <jakub@redhat.com> wrote:

> On Tue, Jun 15, 2021 at 08:02:56PM +0200, Jakub Jelinek via Libffi-discuss
> wrote:
> > On Wed, Jun 09, 2021 at 12:50:08PM -0400, Anthony Green wrote:
> > > Thank you, Cheng.  Are you able to submit this test case as a github
> pull
> > > request?  The resulting CI testing will give us a broader picture of
> where
> > > we have problems.
> >
> > Comparing gcc/config/i386/ classify_argument and libffi
> classify_argument,
> > I found two important differences.
> >
> > The first one seems the most important one, even GCC 3.2 included the bit
> > offset (byte offset in libffi) in the calculation of number of words.
> > And the other change is https://gcc.gnu.org/PR38781.
> >
> > With this patch the posted testcase works and the testsuite on
> x86_64-linux
> > still passes, but haven't done more testing than that.
> >
> > Haven't tried yet to adapt one of the
> > libffi/testsuite/libffi.call/nested_struct*.c tests to cover this though.
>
> And here is one with a testcase (modified nested_struct2.c for it).
>
> I'm unsure about the current relationship between the github and gcc
> copy of libffi, shall it go to both, or just one of them and be
> cherry-picked from there?
>
> Tested on x86_64-linux.
>
> 2021-06-15  Jakub Jelinek  <jakub@redhat.com>
>
>         * src/x86/ffi64.c (classify_argument): For FFI_TYPE_STRUCT set
> words
>         to number of words needed for type->size + byte_offset bytes rather
>         than just type->size bytes.  Compute pos before the loop and check
>         total size of the structure.
>         * testsuite/libffi.call/nested_struct12.c: New test.
>
> --- libffi/src/x86/ffi64.c.jj   2020-01-14 20:02:48.557583260 +0100
> +++ libffi/src/x86/ffi64.c      2021-06-15 19:50:06.059108230 +0200
> @@ -217,7 +217,8 @@ classify_argument (ffi_type *type, enum
>      case FFI_TYPE_STRUCT:
>        {
>         const size_t UNITS_PER_WORD = 8;
> -       size_t words = (type->size + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
> +       size_t words = (type->size + byte_offset + UNITS_PER_WORD - 1)
> +                      / UNITS_PER_WORD;
>         ffi_type **ptr;
>         int i;
>         enum x86_64_reg_class subclasses[MAX_CLASSES];
> @@ -241,16 +242,16 @@ classify_argument (ffi_type *type, enum
>         /* Merge the fields of structure.  */
>         for (ptr = type->elements; *ptr != NULL; ptr++)
>           {
> -           size_t num;
> +           size_t num, pos;
>
>             byte_offset = ALIGN (byte_offset, (*ptr)->alignment);
>
>             num = classify_argument (*ptr, subclasses, byte_offset % 8);
>             if (num == 0)
>               return 0;
> -           for (i = 0; i < num; i++)
> +           pos = byte_offset / 8;
> +           for (i = 0; i < num && (i + pos) < words; i++)
>               {
> -               size_t pos = byte_offset / 8;
>                 classes[i + pos] =
>                   merge_classes (subclasses[i], classes[i + pos]);
>               }
> --- libffi/testsuite/libffi.call/nested_struct12.c.jj   2021-06-15
> 20:31:43.327144303 +0200
> +++ libffi/testsuite/libffi.call/nested_struct12.c      2021-06-15
> 20:47:13.129489263 +0200
> @@ -0,0 +1,107 @@
> +/* Area:       ffi_call, closure_call
> +   Purpose:    Check structure passing.
> +   Limitations:        none.
> +   PR:         none.
> +   Originator: <jincheng@ca.ibm.com> and <jakub@redhat.com> 20210609
> */
> +
> +/* { dg-do run } */
> +#include "ffitest.h"
> +
> +typedef struct A {
> +  float a, b;
> +} A;
> +
> +typedef struct B {
> +  float x;
> +  struct A y;
> +} B;
> +
> +B B_fn(float b0, struct B b1)
> +{
> +  struct B result;
> +
> +  result.x = b0 + b1.x;
> +  result.y.a = b0 + b1.y.a;
> +  result.y.b = b0 + b1.y.b;
> +
> +  printf("%g %g %g %g: %g %g %g\n", b0, b1.x, b1.y.a, b1.y.b,
> +        result.x, result.y.a, result.y.b);
> +
> +  return result;
> +}
> +
> +static void
> +B_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
> +     void* userdata __UNUSED__)
> +{
> +  float b0;
> +  struct B b1;
> +
> +  b0 = *(float*)(args[0]);
> +  b1 = *(struct B*)(args[1]);
> +
> +  *(B*)resp = B_fn(b0, b1);
> +}
> +
> +int main (void)
> +{
> +  ffi_cif cif;
> +  void *code;
> +  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
> +  void* args_dbl[3];
> +  ffi_type* cls_struct_fields[3];
> +  ffi_type* cls_struct_fields1[3];
> +  ffi_type cls_struct_type, cls_struct_type1;
> +  ffi_type* dbl_arg_types[3];
> +
> +  float e_dbl = 12.125f;
> +  struct B f_dbl = { 24.75f, { 31.625f, 32.25f } };
> +
> +  struct B res_dbl;
> +
> +  cls_struct_type.size = 0;
> +  cls_struct_type.alignment = 0;
> +  cls_struct_type.type = FFI_TYPE_STRUCT;
> +  cls_struct_type.elements = cls_struct_fields;
> +
> +  cls_struct_type1.size = 0;
> +  cls_struct_type1.alignment = 0;
> +  cls_struct_type1.type = FFI_TYPE_STRUCT;
> +  cls_struct_type1.elements = cls_struct_fields1;
> +
> +  cls_struct_fields[0] = &ffi_type_float;
> +  cls_struct_fields[1] = &ffi_type_float;
> +  cls_struct_fields[2] = NULL;
> +
> +  cls_struct_fields1[0] = &ffi_type_float;
> +  cls_struct_fields1[1] = &cls_struct_type;
> +  cls_struct_fields1[2] = NULL;
> +
> +
> +  dbl_arg_types[0] = &ffi_type_float;
> +  dbl_arg_types[1] = &cls_struct_type1;
> +  dbl_arg_types[2] = NULL;
> +
> +  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type1,
> +                    dbl_arg_types) == FFI_OK);
> +
> +  args_dbl[0] = &e_dbl;
> +  args_dbl[1] = &f_dbl;
> +  args_dbl[2] = NULL;
> +
> +  ffi_call(&cif, FFI_FN(B_fn), &res_dbl, args_dbl);
> +  /* { dg-output "12.125 24.75 31.625 32.25: 36.875 43.75 44.375" } */
> +  CHECK( res_dbl.x == (e_dbl + f_dbl.x));
> +  CHECK( res_dbl.y.a == (e_dbl + f_dbl.y.a));
> +  CHECK( res_dbl.y.b == (e_dbl + f_dbl.y.b));
> +
> +  CHECK(ffi_prep_closure_loc(pcl, &cif, B_gn, NULL, code) == FFI_OK);
> +
> +  res_dbl = ((B(*)(float, B))(code))(e_dbl, f_dbl);
> +  /* { dg-output "\n12.125 24.75 31.625 32.25: 36.875 43.75 44.375" } */
> +  CHECK( res_dbl.x == (e_dbl + f_dbl.x));
> +  CHECK( res_dbl.y.a == (e_dbl + f_dbl.y.a));
> +  CHECK( res_dbl.y.b == (e_dbl + f_dbl.y.b));
> +
> +  exit(0);
> +}
>
>
>         Jakub
>
>

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2021-06-15 19:29 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-06-09 16:41 Incorrect data detected in the nested float struct with x86/libffi on Linux/64bit Cheng Jin
2021-06-09 16:50 ` Anthony Green
2021-06-09 17:53   ` Cheng Jin
2021-06-15 18:02   ` Jakub Jelinek
2021-06-15 19:02     ` Jakub Jelinek
2021-06-15 19:29       ` Anthony Green
2021-06-09 23:48 ` Kaz Kylheku (libffi)
2021-06-10  0:21   ` Cheng Jin
2021-06-10  2:05 ` Kaz Kylheku (libffi)
2021-06-10  2:39   ` Cheng Jin

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).