diff --git a/src/ia64/unix.S b/src/ia64/unix.S index 4733377..e2547e0 100644 --- a/src/ia64/unix.S +++ b/src/ia64/unix.S @@ -175,7 +175,6 @@ ffi_call_unix: ;; .Lst_small_struct: - add sp = -16, sp cmp.lt p6, p0 = 8, in3 cmp.lt p7, p0 = 16, in3 cmp.lt p8, p0 = 24, in3 @@ -191,6 +190,12 @@ ffi_call_unix: (p8) st8 [r18] = r11 mov out1 = sp mov out2 = in3 + ;; + // ia64 software calling convention requires + // top 16 bytes of stack to be scratch space + // PLT resolver uses that scratch space at + // 'memcpy' symbol reolution time + add sp = -16, sp br.call.sptk.many b0 = memcpy# ;; mov ar.pfs = loc0 diff --git a/testsuite/Makefile.am b/testsuite/Makefile.am index 5eecc57..b367b46 100644 --- a/testsuite/Makefile.am +++ b/testsuite/Makefile.am @@ -68,6 +68,7 @@ libffi.call/float4.c \ libffi.call/return_ldl.c \ libffi.call/closure_fn5.c \ libffi.call/struct6.c libffi.call/return_ll.c libffi.call/struct9.c \ +libffi.call/struct10.c \ libffi.call/return_sc.c libffi.call/struct7.c \ libffi.call/cls_align_uint64.c libffi.call/cls_4byte.c \ libffi.call/cls_6_1_byte.c \ diff --git a/testsuite/libffi.call/struct10.c b/testsuite/libffi.call/struct10.c new file mode 100644 index 0000000..17b1377 --- /dev/null +++ b/testsuite/libffi.call/struct10.c @@ -0,0 +1,57 @@ +/* Area: ffi_call + Purpose: Check structures. + Limitations: none. + PR: none. + Originator: Sergei Trofimovich + + The test originally discovered in ruby's bindings + for ffi in https://bugs.gentoo.org/634190 */ + +/* { dg-do run } */ +#include "ffitest.h" + +struct s { + int s32; + float f32; + signed char s8; +}; + +struct s make_s(void) { + struct s r; + r.s32 = 0x1234; + r.f32 = 7.0; + r.s8 = 0x78; + return r; +} + +int main() { + ffi_cif cif; + struct s r; + ffi_type rtype; + ffi_type* s_fields[] = { + &ffi_type_sint, + &ffi_type_float, + &ffi_type_schar, + NULL, + }; + + rtype.size = 0; + rtype.alignment = 0, + rtype.type = FFI_TYPE_STRUCT, + rtype.elements = s_fields, + + r.s32 = 0xbad; + r.f32 = 999.999; + r.s8 = 0x51; + + // Here we emulate the following call: + //r = make_s(); + + CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 0, &rtype, NULL) == FFI_OK); + ffi_call(&cif, FFI_FN(make_s), &r, NULL); + + CHECK(r.s32 == 0x1234); + CHECK(r.f32 == 7.0); + CHECK(r.s8 == 0x78); + exit(0); +}