[ia64] small integral parameters and return values

This patch fixes a small problem on ia64-hpux when calling functions
whose parameter are small integral values (less than 8 bytes).  In
that case, the parameter value was stored on the wrong side of the
register.  Same problem for return values.

With this patch, the results for gdb.base/callfuncs.exp improve from

        # of expected passes            41
        # of unexpected failures        78

To:

        # of expected passes            95
        # of unexpected failures        24

gdb/ChangeLog:

        * ia64-tdep.c (ia64_struct_type_p): New function.
        (ia64_extract_return_value): Handle integral values that are
        less than 8 bytes long.
        (ia64_push_dummy_call): Likewise.
This commit is contained in:
Joel Brobecker 2011-01-13 16:23:00 +00:00
parent 7458e66756
commit 825d6d8a69
2 changed files with 55 additions and 2 deletions

View File

@ -1,3 +1,10 @@
2011-01-13 Joel Brobecker <brobecker@adacore.com>
* ia64-tdep.c (ia64_struct_type_p): New function.
(ia64_extract_return_value): Handle integral values that are
less than 8 bytes long.
(ia64_push_dummy_call): Likewise.
2011-01-13 Joel Brobecker <brobecker@adacore.com>
* ia64-tdep.c (floatformat_ia64_ext_little): Renames

View File

@ -3177,6 +3177,15 @@ ia64_use_struct_convention (struct type *type)
return TYPE_LENGTH (type) > 32;
}
/* Return non-zero if TYPE is a structure or union type. */
static int
ia64_struct_type_p (const struct type *type)
{
return (TYPE_CODE (type) == TYPE_CODE_STRUCT
|| TYPE_CODE (type) == TYPE_CODE_UNION);
}
static void
ia64_extract_return_value (struct type *type, struct regcache *regcache,
gdb_byte *valbuf)
@ -3201,6 +3210,21 @@ ia64_extract_return_value (struct type *type, struct regcache *regcache,
regnum++;
}
}
else if (!ia64_struct_type_p (type) && TYPE_LENGTH (type) < 8)
{
/* This is an integral value, and its size is less than 8 bytes.
These values are LSB-aligned, so extract the relevant bytes,
and copy them into VALBUF. */
/* brobecker/2005-12-30: Actually, all integral values are LSB aligned,
so I suppose we should also add handling here for integral values
whose size is greater than 8. But I wasn't able to create such
a type, neither in C nor in Ada, so not worrying about these yet. */
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
ULONGEST val;
regcache_cooked_read_unsigned (regcache, IA64_GR8_REGNUM, &val);
store_unsigned_integer (valbuf, TYPE_LENGTH (type), byte_order, val);
}
else
{
ULONGEST val;
@ -3705,8 +3729,30 @@ ia64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
char val_buf[8];
memset (val_buf, 0, 8);
memcpy (val_buf, value_contents (arg) + argoffset,
(len > 8) ? 8 : len);
if (!ia64_struct_type_p (type) && len < 8)
{
/* Integral types are LSB-aligned, so we have to be careful
to insert the argument on the correct side of the buffer.
This is why we use store_unsigned_integer. */
store_unsigned_integer
(val_buf, 8, byte_order,
extract_unsigned_integer (value_contents (arg), len,
byte_order));
}
else
{
/* This is either an 8bit integral type, or an aggregate.
For 8bit integral type, there is no problem, we just
copy the value over.
For aggregates, the only potentially tricky portion
is to write the last one if it is less than 8 bytes.
In this case, the data is Byte0-aligned. Happy news,
this means that we don't need to differentiate the
handling of 8byte blocks and less-than-8bytes blocks. */
memcpy (val_buf, value_contents (arg) + argoffset,
(len > 8) ? 8 : len);
}
if (slotnum < rseslots)
write_memory (rse_address_add (bsp, slotnum), val_buf, 8);