From patchwork Fri May 4 10:10:20 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alan Modra X-Patchwork-Id: 908647 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-477225-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="bElBraYV"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40cnpr5m8vz9s1d for ; Fri, 4 May 2018 20:11:15 +1000 (AEST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:cc:subject:message-id:mime-version:content-type; q=dns; s=default; b=Kf9aGNgj/UJGJceUOvRSTYjcq3YOh4fxjChcO3u8pU44vnPwwx Dn6B5AoLerhryIhleCbXtnmBTHLejkbOtBlBr+gZ5yoYlUZauIl1QkubzYGyt1Vp pcy9Y+OaH/+zE1pIiKGVjlbMX5PVUgBUcg4L6vHN7yRYHQQYVAl9fCHU4= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:cc:subject:message-id:mime-version:content-type; s= default; bh=XEOUx7ph1R++UVkrU+Cw+BZ1w5s=; b=bElBraYVfu6iYTw5mIfX jGBxI02wipRTyDPvrYGDdLZ87G8Pu4rySsfGViympL0/Evl30+zKxRMrI/5v0Ud1 ZG5JY78rqj+obbZJ2SN+3iEEG65a8LO3w+pV8VgWGmHDzU0nWb8AwL+nMVgLoBmQ jAYppksDPt2QBn9kmTjH91Q= Received: (qmail 19518 invoked by alias); 4 May 2018 10:10:31 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 19440 invoked by uid 89); 4 May 2018 10:10:30 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-25.4 required=5.0 tests=AWL, BAYES_00, FREEMAIL_FROM, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RCVD_IN_DNSWL_NONE, SPF_PASS autolearn=ham version=3.3.2 spammy=cif, wrapped, Fall, aggregates X-HELO: mail-pg0-f53.google.com Received: from mail-pg0-f53.google.com (HELO mail-pg0-f53.google.com) (74.125.83.53) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 04 May 2018 10:10:26 +0000 Received: by mail-pg0-f53.google.com with SMTP id g20-v6so8469803pgv.1 for ; Fri, 04 May 2018 03:10:26 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:mime-version :content-disposition:user-agent; bh=wRXaAvQS+CE1tMyJwTLUFOZsQK46jN63/i5m0XmbJEs=; b=B6xopZJG+ygU/rHRrAEVzm4B20EZsVRdnLl7Q/LTC7r+4azFaORRSng9QIONUxLFpb hRjIbrvGZgNjR796N0bpQxg4n0v1Klzyo9CyrvhhL9RxIaPe2bsiAL5l2Hq2Ega6cvkm By9b4Q2JeOIQnJ52lQL1NWcti4VpZBsGtCt3EGL392PAS1GXQdTeSlPTYKz5V8o7hTy0 tYgi/TQS7HuSjqs8UtAiTtdYkgT2T2XO0BxtvGfo9SIx4YvU/cGtJoyjxnhg45+eFDti xA4vbjtIePE3+p6y4UkIlO36qrMY03dmRnEyV5+qYjVVwDiybibroIQnz7Rsj+lcNlKC J2Aw== X-Gm-Message-State: ALQs6tB5cKPH4BzniHB+td69K3Qr05USYBwfJuaRITsQZkppMj0Mf1/v fPNPJ/GJ/wT24JNAp+ElWbIVdg== X-Google-Smtp-Source: AB8JxZqJKMiPsdxZvR9bFgE4HyOuKB92UmskTlbtj8cY7ODoMylXxHUZoaKk0j+I7wfZrsEgdeEdtQ== X-Received: by 2002:a17:902:8a81:: with SMTP id p1-v6mr4292947plo.33.1525428624801; Fri, 04 May 2018 03:10:24 -0700 (PDT) Received: from bubble.grove.modra.org (CPE-58-175-241-133.hdcz1.win.bigpond.net.au. [58.175.241.133]) by smtp.gmail.com with ESMTPSA id o88sm33845571pfk.91.2018.05.04.03.10.23 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Fri, 04 May 2018 03:10:23 -0700 (PDT) Received: by bubble.grove.modra.org (Postfix, from userid 1000) id 3A1EA87DE8; Fri, 4 May 2018 19:40:20 +0930 (ACST) Date: Fri, 4 May 2018 19:40:20 +0930 From: Alan Modra To: gcc-patches@gcc.gnu.org Cc: Segher Boessenkool Subject: libffi PowerPC64 ELFv1 fp arg fixes Message-ID: <20180504101020.GI28782@bubble.grove.modra.org> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.9.4 (2018-02-28) X-IsSubscribed: yes The attached patch has been accepted into upstream libffi. It fixes powerpc64-linux problems shown up by Bruno Haible's new libffi testsuite tests. Bootstrapped and regression tested powerpc64-linux and powerpc64le-linux. OK mainline and active branches? From a3b6c9db017d3f142031636a9dd6088c5478ca28 Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Wed, 2 May 2018 19:10:53 +0930 Subject: [PATCH] libffi PowerPC64 ELFv1 fp arg fixes The ELFv1 ABI says: "Single precision floating point values are mapped to the second word in a single doubleword" and also "Floating point registers f1 through f13 are used consecutively to pass up to 13 floating point values, one member aggregates passed by value containing a floating point value, and to pass complex floating point values". libffi wasn't expecting float args in the second word, and wasn't passing one member aggregates in fp registers. This patch fixes those problems, making use of the existing ELFv2 homogeneous aggregate support since a one element fp struct is a special case of an homogeneous aggregate. I've also set a flag when returning pointers that might be used one day. This is just a tidy since the ppc64 assembly support code currently doesn't test FLAG_RETURNS_64BITS for integer types.. * src/powerpc/ffi_linux64.c (discover_homogeneous_aggregate): Compile for ELFv1 too, handling single element aggregates. (ffi_prep_cif_linux64_core): Call discover_homogeneous_aggregate for ELFv1. Set FLAG_RETURNS_64BITS for FFI_TYPE_POINTER return. (ffi_prep_args64): Call discover_homogeneous_aggregate for ELFv1, and handle single element structs containing float or double as if the element wasn't wrapped in a struct. Store floats in second word of doubleword slot when big-endian. (ffi_closure_helper_LINUX64): Similarly. diff --git a/libffi/src/powerpc/ffi_linux64.c b/libffi/src/powerpc/ffi_linux64.c index b84b91fb237..ef0361b24ee 100644 --- a/libffi/src/powerpc/ffi_linux64.c +++ b/libffi/src/powerpc/ffi_linux64.c @@ -62,7 +62,6 @@ ffi_prep_types_linux64 (ffi_abi abi) #endif -#if _CALL_ELF == 2 static unsigned int discover_homogeneous_aggregate (const ffi_type *t, unsigned int *elnum) { @@ -86,8 +85,13 @@ discover_homogeneous_aggregate (const ffi_type *t, unsigned int *elnum) return 0; base_elt = el_elt; total_elnum += el_elnum; +#if _CALL_ELF == 2 if (total_elnum > 8) return 0; +#else + if (total_elnum > 1) + return 0; +#endif el++; } *elnum = total_elnum; @@ -98,7 +102,6 @@ discover_homogeneous_aggregate (const ffi_type *t, unsigned int *elnum) return 0; } } -#endif /* Perform machine dependent cif processing */ @@ -109,9 +112,7 @@ ffi_prep_cif_linux64_core (ffi_cif *cif) unsigned bytes; unsigned i, fparg_count = 0, intarg_count = 0; unsigned flags = cif->flags; -#if _CALL_ELF == 2 unsigned int elt, elnum; -#endif #if FFI_TYPE_LONGDOUBLE == FFI_TYPE_DOUBLE /* If compiled without long double support.. */ @@ -157,6 +158,7 @@ ffi_prep_cif_linux64_core (ffi_cif *cif) /* Fall through. */ case FFI_TYPE_UINT64: case FFI_TYPE_SINT64: + case FFI_TYPE_POINTER: flags |= FLAG_RETURNS_64BITS; break; @@ -222,7 +224,6 @@ ffi_prep_cif_linux64_core (ffi_cif *cif) intarg_count = ALIGN (intarg_count, align); } intarg_count += ((*ptr)->size + 7) / 8; -#if _CALL_ELF == 2 elt = discover_homogeneous_aggregate (*ptr, &elnum); if (elt) { @@ -231,7 +232,6 @@ ffi_prep_cif_linux64_core (ffi_cif *cif) flags |= FLAG_ARG_NEEDS_PSAVE; } else -#endif { if (intarg_count > NUM_GPR_ARG_REGISTERS64) flags |= FLAG_ARG_NEEDS_PSAVE; @@ -449,9 +449,7 @@ ffi_prep_args64 (extended_cif *ecif, unsigned long *const stack) i < nargs; i++, ptr++, p_argv.v++) { -#if _CALL_ELF == 2 unsigned int elt, elnum; -#endif switch ((*ptr)->type) { @@ -494,6 +492,7 @@ ffi_prep_args64 (extended_cif *ecif, unsigned long *const stack) /* Fall through. */ #endif case FFI_TYPE_DOUBLE: + do_double: double_tmp = **p_argv.d; if (fparg_count < NUM_FPR_ARG_REGISTERS64 && i < nfixedargs) { @@ -512,17 +511,30 @@ ffi_prep_args64 (extended_cif *ecif, unsigned long *const stack) break; case FFI_TYPE_FLOAT: + do_float: double_tmp = **p_argv.f; if (fparg_count < NUM_FPR_ARG_REGISTERS64 && i < nfixedargs) { *fpr_base.d++ = double_tmp; #if _CALL_ELF != 2 if ((flags & FLAG_COMPAT) != 0) - *next_arg.f = (float) double_tmp; + { +# ifndef __LITTLE_ENDIAN__ + next_arg.f[1] = (float) double_tmp; +# else + next_arg.f[0] = (float) double_tmp; +# endif + } #endif } else - *next_arg.f = (float) double_tmp; + { +# ifndef __LITTLE_ENDIAN__ + next_arg.f[1] = (float) double_tmp; +# else + next_arg.f[0] = (float) double_tmp; +# endif + } if (++next_arg.ul == gpr_end.ul) next_arg.ul = rest.ul; fparg_count++; @@ -538,10 +550,10 @@ ffi_prep_args64 (extended_cif *ecif, unsigned long *const stack) if (align > 1) next_arg.p = ALIGN (next_arg.p, align); } -#if _CALL_ELF == 2 elt = discover_homogeneous_aggregate (*ptr, &elnum); if (elt) { +#if _CALL_ELF == 2 union { void *v; float *f; @@ -583,9 +595,14 @@ ffi_prep_args64 (extended_cif *ecif, unsigned long *const stack) fparg_count++; } while (--elnum != 0); +#else + if (elt == FFI_TYPE_FLOAT) + goto do_float; + else + goto do_double; +#endif } else -#endif { words = ((*ptr)->size + 7) / 8; if (next_arg.ul >= gpr_base.ul && next_arg.ul + words > gpr_end.ul) @@ -796,12 +813,10 @@ ffi_closure_helper_LINUX64 (ffi_cif *cif, if (align > 1) pst = (unsigned long *) ALIGN ((size_t) pst, align); } - elt = 0; -#if _CALL_ELF == 2 elt = discover_homogeneous_aggregate (arg_types[i], &elnum); -#endif if (elt) { +#if _CALL_ELF == 2 union { void *v; unsigned long *ul; @@ -853,6 +868,12 @@ ffi_closure_helper_LINUX64 (ffi_cif *cif, } while (--elnum != 0); } +#else + if (elt == FFI_TYPE_FLOAT) + goto do_float; + else + goto do_double; +#endif } else { @@ -894,6 +915,7 @@ ffi_closure_helper_LINUX64 (ffi_cif *cif, /* Fall through. */ #endif case FFI_TYPE_DOUBLE: + do_double: /* On the outgoing stack all values are aligned to 8 */ /* there are 13 64bit floating point registers */ @@ -908,6 +930,7 @@ ffi_closure_helper_LINUX64 (ffi_cif *cif, break; case FFI_TYPE_FLOAT: + do_float: if (pfr < end_pfr && i < nfixedargs) { /* Float values are stored as doubles in the @@ -917,7 +940,13 @@ ffi_closure_helper_LINUX64 (ffi_cif *cif, pfr++; } else - avalue[i] = pst; + { +#ifndef __LITTLE_ENDIAN__ + avalue[i] = (char *) pst + 4; +#else + avalue[i] = pst; +#endif + } pst++; break;