From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 9656 invoked by alias); 28 Oct 2014 19:46:45 -0000 Mailing-List: contact libffi-discuss-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libffi-discuss-owner@sourceware.org Received: (qmail 9485 invoked by uid 89); 28 Oct 2014 19:46:45 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.3 required=5.0 tests=AWL,BAYES_00,FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM,RCVD_IN_DNSWL_LOW,SPF_PASS autolearn=ham version=3.3.2 X-HELO: mail-qg0-f54.google.com Received: from mail-qg0-f54.google.com (HELO mail-qg0-f54.google.com) (209.85.192.54) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-SHA encrypted) ESMTPS; Tue, 28 Oct 2014 19:46:42 +0000 Received: by mail-qg0-f54.google.com with SMTP id q108so1106518qgd.41 for ; Tue, 28 Oct 2014 12:46:40 -0700 (PDT) X-Received: by 10.224.166.207 with SMTP id n15mr8455137qay.13.1414525600374; Tue, 28 Oct 2014 12:46:40 -0700 (PDT) Received: from anchor.com (50-194-63-110-static.hfc.comcastbusiness.net. [50.194.63.110]) by mx.google.com with ESMTPSA id 11sm2042715qgj.34.2014.10.28.12.46.38 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 28 Oct 2014 12:46:39 -0700 (PDT) From: Richard Henderson To: libffi-discuss@sourceware.org Cc: davem@davemloft.net Subject: [PATCH 8/8] sparc: Re-add abi compliant structure support Date: Tue, 28 Oct 2014 19:46:00 -0000 Message-Id: <1414525555-21256-9-git-send-email-rth@twiddle.net> In-Reply-To: <1414525555-21256-1-git-send-email-rth@twiddle.net> References: <1414525555-21256-1-git-send-email-rth@twiddle.net> X-SW-Source: 2014/txt/msg00157.txt.bz2 The original code, removed in the "rewrite" patch, was incorrect for large structures, and required dynamic allocation of a trampoline on every ffi_call. Instead, allocate a 4k entry table of all possible structure returns. The table is 80k, but is read-only and dynamically paged, which ought to be better than allocating the trampoline. This is difficult to test with gcc. One can only use -O0 at present. See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63668. --- src/sparc/ffi.c | 19 +++++++++++++------ src/sparc/ffi64.c | 2 +- src/sparc/internal.h | 2 +- src/sparc/v8.S | 29 ++++++++++++++++++++++------- src/sparc/v9.S | 2 +- 5 files changed, 38 insertions(+), 16 deletions(-) diff --git a/src/sparc/ffi.c b/src/sparc/ffi.c index 19c3586..d5212d8 100644 --- a/src/sparc/ffi.c +++ b/src/sparc/ffi.c @@ -66,7 +66,8 @@ ffi_prep_cif_machdep(ffi_cif *cif) break; case FFI_TYPE_LONGDOUBLE: case FFI_TYPE_STRUCT: - flags = SPARC_RET_STRUCT; + flags = (rtype->size & 0xfff) << SPARC_SIZEMASK_SHIFT; + flags |= SPARC_RET_STRUCT; break; case FFI_TYPE_SINT8: flags = SPARC_RET_SINT8; @@ -187,7 +188,7 @@ ffi_prep_args_v8(ffi_cif *cif, unsigned long *argp, void *rvalue, void **avalue) if (rvalue == NULL) { - if (flags == SPARC_RET_STRUCT) + if ((flags & SPARC_FLAG_RET_MASK) == SPARC_RET_STRUCT) { /* Since we pass the pointer to the callee, we need a value. We allowed for this space in ffi_call, before ffi_call_v8 @@ -290,7 +291,8 @@ ffi_call_int (ffi_cif *cif, void (*fn)(void), void *rvalue, /* If we've not got a return value, we need to create one if we've got to pass the return value to the callee. Otherwise ignore it. */ - if (rvalue == NULL && cif->flags == SPARC_RET_STRUCT) + if (rvalue == NULL + && (cif->flags & SPARC_FLAG_RET_MASK) == SPARC_RET_STRUCT) bytes += ALIGN (cif->rtype->size, 8); ffi_call_v8(cif, fn, rvalue, avalue, -bytes, closure); @@ -382,9 +384,14 @@ ffi_closure_sparc_inner_v8(ffi_cif *cif, avalue = alloca(nargs * sizeof(void *)); /* Copy the caller's structure return address so that the closure - returns the data directly to the caller. */ - if (flags == SPARC_RET_STRUCT) - rvalue = (void *)*argp; + returns the data directly to the caller. Also install it so we + can return the address in %o0. */ + if ((flags & SPARC_FLAG_RET_MASK) == SPARC_RET_STRUCT) + { + void *new_rvalue = (void *)*argp; + *(void **)rvalue = new_rvalue; + rvalue = new_rvalue; + } /* Always skip the structure return address. */ argp++; diff --git a/src/sparc/ffi64.c b/src/sparc/ffi64.c index 02f3d75..a4e41d2 100644 --- a/src/sparc/ffi64.c +++ b/src/sparc/ffi64.c @@ -197,7 +197,7 @@ ffi_prep_cif_machdep(ffi_cif *cif) int all_mask = (1 << word_size) - 1; int fp_mask = size_mask >> 8; - flags = (size_mask << SPARC_FLTMASK_SHIFT) | SPARC_RET_STRUCT; + flags = (size_mask << SPARC_SIZEMASK_SHIFT) | SPARC_RET_STRUCT; /* For special cases of all-int or all-fp, we can return the value directly without popping through a struct copy. */ diff --git a/src/sparc/internal.h b/src/sparc/internal.h index f9387d4..0a66472 100644 --- a/src/sparc/internal.h +++ b/src/sparc/internal.h @@ -23,4 +23,4 @@ #define SPARC_FLAG_RET_IN_MEM 32 #define SPARC_FLAG_FP_ARGS 64 -#define SPARC_FLTMASK_SHIFT 8 +#define SPARC_SIZEMASK_SHIFT 8 diff --git a/src/sparc/v8.S b/src/sparc/v8.S index 66cf76f..3a811ef 100644 --- a/src/sparc/v8.S +++ b/src/sparc/v8.S @@ -91,6 +91,7 @@ C(ffi_call_v8): add %sp, 32, %sp ! deallocate prep frame and %o0, SPARC_FLAG_RET_MASK, %l0 ! save return type + srl %o0, SPARC_SIZEMASK_SHIFT, %l1 ! save return size ld [%sp+64+4], %o0 ! load all argument registers ld [%sp+64+8], %o1 ld [%sp+64+12], %o2 @@ -182,22 +183,35 @@ E SPARC_RET_F_1 ret restore - ! Struct returning functions expect and skip the unimp here. .align 8 -8: call %i1 - mov %i5, %g2 ! load static chain - unimp 4 +9: sth %o0, [%i2] ret restore - .align 8 -9: sth %o0, [%i2] +10: stb %o0, [%i2] ret restore + + ! Struct returning functions expect and skip the unimp here. + ! To make it worse, conforming callees examine the unimp and + ! make sure the low 12 bits of the unimp match the size of + ! the struct being returned. .align 8 -10: stb %o0, [%i2] +8: call 1f ! load pc in %o7 + sll %l1, 2, %l0 ! size * 4 +1: sll %l1, 4, %l1 ! size * 16 + add %l0, %l1, %l0 ! size * 20 + add %o7, %l0, %o7 ! o7 = 0b + size*20 + jmp %o7+(2f-8b) + mov %i5, %g2 ! load static chain +2: +.rept 0x1000 + call %i1 + nop + unimp (. - 2b) / 20 ret restore +.endr cfi_endproc .size C(ffi_call_v8),. - C(ffi_call_v8) @@ -275,6 +289,7 @@ E SPARC_RET_VOID ret restore E SPARC_RET_STRUCT + ld [%i2], %i0 jmp %i7+12 restore E SPARC_RET_UINT8 diff --git a/src/sparc/v9.S b/src/sparc/v9.S index d848f9a..52732d3 100644 --- a/src/sparc/v9.S +++ b/src/sparc/v9.S @@ -188,7 +188,7 @@ E SPARC_RET_F_1 std %f6, [%l2+56] ! Copy the structure into place. - srl %l0, SPARC_FLTMASK_SHIFT, %o0 ! load size_mask + srl %l0, SPARC_SIZEMASK_SHIFT, %o0 ! load size_mask mov %i2, %o1 ! load dst mov %l2, %o2 ! load src_gp call C(ffi_struct_float_copy) -- 1.9.3