From: Joel Brobecker Date: Thu, 13 Jan 2011 16:23:00 +0000 (+0000) Subject: [ia64] small integral parameters and return values X-Git-Tag: cgen-snapshot-20110201~150 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=825d6d8a6983bce3664db1058afb19335db795cc;p=external%2Fbinutils.git [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. --- diff --git a/gdb/ChangeLog b/gdb/ChangeLog index c548a19..e52214d 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,12 @@ 2011-01-13 Joel Brobecker + * 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 + * ia64-tdep.c (floatformat_ia64_ext_little): Renames floatformat_ia64_ext. (floatformat_ia64_ext_big): New static const. diff --git a/gdb/ia64-tdep.c b/gdb/ia64-tdep.c index 81d42b6..05ca3a1 100644 --- a/gdb/ia64-tdep.c +++ b/gdb/ia64-tdep.c @@ -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);