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.
This commit is contained in:
parent
eb026f09eb
commit
1933fd8ee0
@ -1,3 +1,12 @@
|
||||
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.
|
||||
|
||||
2017-05-17 Yao Qi <yao.qi@linaro.org>
|
||||
|
||||
* cli/cli-decode.c (add_alias_cmd): New function.
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user