From patchwork Fri May 19 10:19:11 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Jose E. Marchesi" X-Patchwork-Id: 20508 Received: (qmail 125875 invoked by alias); 19 May 2017 10:19:29 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 125841 invoked by uid 89); 19 May 2017 10:19:28 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-25.9 required=5.0 tests=BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_LAZY_DOMAIN_SECURITY, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.2 spammy= X-HELO: aserp1040.oracle.com Received: from aserp1040.oracle.com (HELO aserp1040.oracle.com) (141.146.126.69) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 19 May 2017 10:19:26 +0000 Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id v4JAJJmi022779 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 19 May 2017 10:19:19 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by aserv0021.oracle.com (8.13.8/8.14.4) with ESMTP id v4JAJJjQ016801 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 19 May 2017 10:19:19 GMT Received: from abhmp0016.oracle.com (abhmp0016.oracle.com [141.146.116.22]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id v4JAJItq030055; Fri, 19 May 2017 10:19:18 GMT Received: from termi.oracle.com (/10.175.210.85) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Fri, 19 May 2017 03:19:16 -0700 From: jose.marchesi@oracle.com (Jose E. Marchesi) To: Pedro Alves Cc: vladimir.mezentsev@oracle.com, gdb-patches@sourceware.org Subject: Re: [PATCH] gdb passes and returns incorrect values when dealing with small array on Sparc References: <1494950959-42849-1-git-send-email-vladimir.mezentsev@oracle.com> <87shk1mb99.fsf@oracle.com> Date: Fri, 19 May 2017 12:19:11 +0200 In-Reply-To: (Pedro Alves's message of "Fri, 19 May 2017 10:57:52 +0100") Message-ID: <87o9upkv34.fsf@oracle.com> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/26.0.50 (gnu/linux) MIME-Version: 1.0 X-IsSubscribed: yes On 05/19/2017 10:44 AM, Jose E. Marchesi wrote: > > From: Vladimir Mezentsev > > gdb has a special type (TYPE_CODE_ARRAY) to support the gcc extension > (https://gcc.gnu.org/onlinedocs/gcc/Vector-Extensions.html). > TYPE_CODE_ARRAY is handled incorrectly for both (32- and 64-bit) modes on Sparc machines. > > Tested on sparc64-linux-gnu and sparc-solaris (32- and 64-bit mode). > No regressions. > > gdb/ChangeLog: > 2017-05-12 Vladimir Mezentsev > > * sparc-tdep.c (sparc_structure_return_p) > (sparc_arg_on_registers_p): New functions. > (sparc32_store_arguments): Use them. > * sparc64-tdep.c (sparc64_16_byte_align_p) > (sparc64_store_floating_fields, sparc64_extract_floating_fields): > Handle TYPE_CODE_ARRAY. > > > LGTM. Ok for master? > OK with the commit log tweak mentioned at: https://sourceware.org/ml/gdb-patches/2017-04/msg00509.html Applied as below. Thanks. commit 1933fd8ee01ad2e74a9c6341bc40f54962a8f889 Author: Vladimir Mezentsev Date: Fri May 19 03:06:19 2017 -0700 gdb: fix TYPE_CODE_ARRAY handling in sparc targets gdb has a special type (TYPE_CODE_ARRAY) to support the gcc extension (https://gcc.gnu.org/onlinedocs/gcc/Vector-Extensions.html). TYPE_CODE_ARRAY is handled incorrectly for both (32- and 64-bit) modes on Sparc machines. Tested on sparc64-linux-gnu and sparc-solaris (32- and 64-bit mode). 6 tests ( from gdb/testsuite/gdb.base/gnu_vector.exp) failed on sparc64-Linux and on sparc-Solaris in 32- and 64-bit mode. Now all these tests passed. gdb/testsuite/gdb.base/gnu_vector.exp has 117 different cases for small (and not small) arrays and structures. No regressions. gdb/ChangeLog: 2017-05-19 Vladimir Mezentsev * sparc-tdep.c (sparc_structure_return_p) (sparc_arg_on_registers_p): New functions. (sparc32_store_arguments): Use them. * sparc64-tdep.c (sparc64_16_byte_align_p) (sparc64_store_floating_fields, sparc64_extract_floating_fields): Handle TYPE_CODE_ARRAY. diff --git a/gdb/ChangeLog b/gdb/ChangeLog index fdc2a40..1273ed8 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,12 @@ +2017-05-19 Vladimir Mezentsev + + * sparc-tdep.c (sparc_structure_return_p) + (sparc_arg_on_registers_p): New functions. + (sparc32_store_arguments): Use them. + * sparc64-tdep.c (sparc64_16_byte_align_p) + (sparc64_store_floating_fields, sparc64_extract_floating_fields): + Handle TYPE_CODE_ARRAY. + 2017-05-17 Yao Qi * cli/cli-decode.c (add_alias_cmd): New function. diff --git a/gdb/sparc-tdep.c b/gdb/sparc-tdep.c index d1e64b4..fa0e04e 100644 --- a/gdb/sparc-tdep.c +++ b/gdb/sparc-tdep.c @@ -298,6 +298,43 @@ sparc_structure_or_union_p (const struct type *type) return 0; } +/* Check whether TYPE is returned on registers. */ + +static bool +sparc_structure_return_p (const struct type *type) +{ + if (TYPE_CODE (type) == TYPE_CODE_ARRAY && TYPE_LENGTH (type) <= 8) + { + struct type *t = check_typedef (TYPE_TARGET_TYPE (type)); + + if (sparc_floating_p (t) && TYPE_LENGTH (t) == 8) + return true; + return false; + } + if (sparc_floating_p (type) && TYPE_LENGTH (type) == 16) + return true; + return sparc_structure_or_union_p (type); +} + +/* Check whether TYPE is passed on registers. */ + +static bool +sparc_arg_on_registers_p (const struct type *type) +{ + if (TYPE_CODE (type) == TYPE_CODE_ARRAY && TYPE_LENGTH (type) <= 8) + { + struct type *t = check_typedef (TYPE_TARGET_TYPE (type)); + + if (sparc_floating_p (t) && TYPE_LENGTH (t) == 8) + return false; + return true; + } + if (sparc_structure_or_union_p (type) || sparc_complex_floating_p (type) + || (sparc_floating_p (type) && TYPE_LENGTH (type) == 16)) + return false; + return true; +} + /* Register information. */ #define SPARC32_FPU_REGISTERS \ "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", \ @@ -570,9 +607,7 @@ sparc32_store_arguments (struct regcache *regcache, int nargs, struct type *type = value_type (args[i]); int len = TYPE_LENGTH (type); - if (sparc_structure_or_union_p (type) - || (sparc_floating_p (type) && len == 16) - || sparc_complex_floating_p (type)) + if (!sparc_arg_on_registers_p (type)) { /* Structure, Union and Quad-Precision Arguments. */ sp -= len; @@ -594,11 +629,8 @@ sparc32_store_arguments (struct regcache *regcache, int nargs, else { /* Integral and pointer arguments. */ - gdb_assert (sparc_integral_or_pointer_p (type)); - - if (len < 4) - args[i] = value_cast (builtin_type (gdbarch)->builtin_int32, - args[i]); + gdb_assert (sparc_integral_or_pointer_p (type) + || (TYPE_CODE (type) == TYPE_CODE_ARRAY && len <= 8)); num_elements += ((len + 3) / 4); } } @@ -620,6 +652,15 @@ sparc32_store_arguments (struct regcache *regcache, int nargs, const bfd_byte *valbuf = value_contents (args[i]); struct type *type = value_type (args[i]); int len = TYPE_LENGTH (type); + gdb_byte buf[4]; + + if (len < 4) + { + memset (buf, 0, 4 - len); + memcpy (buf + 4 - len, valbuf, len); + valbuf = buf; + len = 4; + } gdb_assert (len == 4 || len == 8); @@ -1345,10 +1386,10 @@ sparc32_extract_return_value (struct type *type, struct regcache *regcache, int len = TYPE_LENGTH (type); gdb_byte buf[32]; - gdb_assert (!sparc_structure_or_union_p (type)); - gdb_assert (!(sparc_floating_p (type) && len == 16)); + gdb_assert (!sparc_structure_return_p (type)); - if (sparc_floating_p (type) || sparc_complex_floating_p (type)) + if (sparc_floating_p (type) || sparc_complex_floating_p (type) + || TYPE_CODE (type) == TYPE_CODE_ARRAY) { /* Floating return values. */ regcache_cooked_read (regcache, SPARC_F0_REGNUM, buf); @@ -1397,11 +1438,9 @@ sparc32_store_return_value (struct type *type, struct regcache *regcache, const gdb_byte *valbuf) { int len = TYPE_LENGTH (type); - gdb_byte buf[8]; + gdb_byte buf[32]; - gdb_assert (!sparc_structure_or_union_p (type)); - gdb_assert (!(sparc_floating_p (type) && len == 16)); - gdb_assert (len <= 8); + gdb_assert (!sparc_structure_return_p (type)); if (sparc_floating_p (type) || sparc_complex_floating_p (type)) { @@ -1457,8 +1496,7 @@ sparc32_return_value (struct gdbarch *gdbarch, struct value *function, guarantees that we can always find the return value, not just before the function returns. */ - if (sparc_structure_or_union_p (type) - || (sparc_floating_p (type) && TYPE_LENGTH (type) == 16)) + if (sparc_structure_return_p (type)) { ULONGEST sp; CORE_ADDR addr; diff --git a/gdb/sparc64-tdep.c b/gdb/sparc64-tdep.c index 58f5bf0..9e0e6b5 100644 --- a/gdb/sparc64-tdep.c +++ b/gdb/sparc64-tdep.c @@ -669,6 +669,13 @@ static const struct frame_base sparc64_frame_base = static int sparc64_16_byte_align_p (struct type *type) { + if (TYPE_CODE (type) == TYPE_CODE_ARRAY) + { + struct type *t = check_typedef (TYPE_TARGET_TYPE (type)); + + if (sparc64_floating_p (t)) + return 1; + } if (sparc64_floating_p (type) && TYPE_LENGTH (type) == 16) return 1; @@ -703,7 +710,23 @@ sparc64_store_floating_fields (struct regcache *regcache, struct type *type, gdb_assert (element < 16); - if (sparc64_floating_p (type) + if (TYPE_CODE (type) == TYPE_CODE_ARRAY) + { + gdb_byte buf[8]; + int regnum = SPARC_F0_REGNUM + element * 2 + bitpos / 32; + + valbuf += bitpos / 8; + if (len < 8) + { + memset (buf, 0, 8 - len); + memcpy (buf + 8 - len, valbuf, len); + valbuf = buf; + len = 8; + } + for (int n = 0; n < (len + 3) / 4; n++) + regcache_cooked_write (regcache, regnum + n, valbuf + n * 4); + } + else if (sparc64_floating_p (type) || (sparc64_complex_floating_p (type) && len <= 16)) { int regnum; @@ -776,7 +799,23 @@ sparc64_extract_floating_fields (struct regcache *regcache, struct type *type, { struct gdbarch *gdbarch = get_regcache_arch (regcache); - if (sparc64_floating_p (type)) + if (TYPE_CODE (type) == TYPE_CODE_ARRAY) + { + int len = TYPE_LENGTH (type); + int regnum = SPARC_F0_REGNUM + bitpos / 32; + + valbuf += bitpos / 8; + if (len < 4) + { + gdb_byte buf[4]; + regcache_cooked_read (regcache, regnum, buf); + memcpy (valbuf, buf + 4 - len, len); + } + else + for (int i = 0; i < (len + 3) / 4; i++) + regcache_cooked_read (regcache, regnum + i, valbuf + i * 4); + } + else if (sparc64_floating_p (type)) { int len = TYPE_LENGTH (type); int regnum;