diff options
author | Vladimir Mezentsev <vladimir.mezentsev@oracle.com> | 2017-05-19 03:06:19 -0700 |
---|---|---|
committer | Jose E. Marchesi <jose.marchesi@oracle.com> | 2017-05-19 03:06:19 -0700 |
commit | 1933fd8ee01ad2e74a9c6341bc40f54962a8f889 (patch) | |
tree | 4fa1d4f8a0b9c540d3efcc87c6fe499534ecdde3 /gdb/sparc-tdep.c | |
parent | eb026f09eb6fcb96a5de1e655cdde041ba44affb (diff) | |
download | gdb-1933fd8ee01ad2e74a9c6341bc40f54962a8f889.zip gdb-1933fd8ee01ad2e74a9c6341bc40f54962a8f889.tar.gz gdb-1933fd8ee01ad2e74a9c6341bc40f54962a8f889.tar.bz2 |
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 <vladimir.mezentsev@oracle.com>
* 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.
Diffstat (limited to 'gdb/sparc-tdep.c')
-rw-r--r-- | gdb/sparc-tdep.c | 72 |
1 files changed, 55 insertions, 17 deletions
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; |