2002-08-21 Michael Snyder * arch-utils.c (generic_push_struct_return, generic_pop_struct_return): New functions, helpers for store_struct_return and extract_struct_value_address. * arch-utils.h: External interface to the above. * cris-tdep.c (cris_store_struct_return): Use above. (cris_extract_struct_value_address): Ditto. * ia64-tdep.c (ia64_store_struct_return): Use above. (ia64_extract_struct_value_address): Ditto. * mips-tdep.c (mips_store_struct_return): Use above. (mips_extract_struct_value_address): Ditto. * ia64-tdep.c (ia64_store_struct_return): Use above. (ia64_extract_struct_value_address): Ditto. Index: arch-utils.h =================================================================== RCS file: /cvs/src/src/gdb/arch-utils.h,v retrieving revision 1.40 diff -c -3 -p -r1.40 arch-utils.h *** arch-utils.h 20 Aug 2002 23:01:28 -0000 1.40 --- arch-utils.h 22 Aug 2002 02:26:47 -0000 *************** extern int generic_register_size (int re *** 156,161 **** --- 156,165 ---- /* Assume that the world is sane, the registers are all adjacent. */ extern int generic_register_byte (int regnum); + /* A stack of struct_returns. */ + extern void generic_push_struct_return (CORE_ADDR addr, CORE_ADDR sp); + extern CORE_ADDR generic_pop_struct_return (CORE_ADDR sp); + /* Prop up old targets that use various IN_SIGTRAMP() macros. */ extern int legacy_pc_in_sigtramp (CORE_ADDR pc, char *name); Index: arch-utils.c =================================================================== RCS file: /cvs/src/src/gdb/arch-utils.c,v retrieving revision 1.66 diff -c -3 -p -r1.66 arch-utils.c *** arch-utils.c 20 Aug 2002 23:01:28 -0000 1.66 --- arch-utils.c 22 Aug 2002 02:26:47 -0000 *************** generic_register_byte (int regnum) *** 453,458 **** --- 453,504 ---- } + /* A simple stack of struct return addresses, stored by + store_struct_return and fetched by extract_struct_value_address. + Uses the stack pointer value as a key/identifier. */ + + struct struct_return_stack { + CORE_ADDR addr; + CORE_ADDR sp; + }; + + static struct struct_return_stack *struct_return_stack = NULL; + static int struct_return_stack_depth = 0; + static int struct_return_tos = 0; + + enum { STRUCT_RETURN_STACK_CHUNK = 128 }; + + void + generic_push_struct_return (CORE_ADDR addr, CORE_ADDR sp) + { + if (struct_return_tos >= struct_return_stack_depth) + { + struct_return_stack_depth += STRUCT_RETURN_STACK_CHUNK; + struct_return_stack = xrealloc (struct_return_stack, + struct_return_stack_depth * + sizeof (struct struct_return_stack)); + } + struct_return_stack[struct_return_tos].addr = addr; + struct_return_stack[struct_return_tos].sp = sp; + struct_return_tos++; + } + + CORE_ADDR + generic_pop_struct_return (CORE_ADDR sp) + { + /* Stack empty? */ + if (struct_return_tos == 0) + return 0; + + /* Does this SP match the one on the top of our stack? */ + if (sp != struct_return_stack[struct_return_tos - 1].sp) + return 0; + + /* Top-of-stack is a valid struct_return value. Return it. */ + return struct_return_stack[--struct_return_tos].addr; + } + + int legacy_pc_in_sigtramp (CORE_ADDR pc, char *name) { Index: rs6000-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/rs6000-tdep.c,v retrieving revision 1.76 diff -c -3 -p -r1.76 rs6000-tdep.c *** rs6000-tdep.c 21 Aug 2002 22:56:02 -0000 1.76 --- rs6000-tdep.c 22 Aug 2002 02:26:47 -0000 *************** rs6000_extract_return_value (struct type *** 1193,1200 **** living. This only allows a single nested call to a structure-returning function. Come on, guys! -- gnu@cygnus.com, Aug 92 */ - static CORE_ADDR rs6000_struct_return_address; - /* Return whether handle_inferior_event() should proceed through code starting at PC in function NAME when stepping. --- 1193,1198 ---- *************** rs6000_stab_reg_to_regnum (int num) *** 1789,1802 **** In RS/6000, struct return addresses are passed as an extra parameter in r3. In function return, callee is not responsible of returning this address ! back. Since gdb needs to find it, we will store in a designated variable ! `rs6000_struct_return_address'. */ static void rs6000_store_struct_return (CORE_ADDR addr, CORE_ADDR sp) { write_register (3, addr); - rs6000_struct_return_address = addr; } /* Write into appropriate registers a function return value --- 1787,1800 ---- In RS/6000, struct return addresses are passed as an extra parameter in r3. In function return, callee is not responsible of returning this address ! back. Since gdb needs to find it, we will store in a LIFO queue of ! struct-return addresses. */ static void rs6000_store_struct_return (CORE_ADDR addr, CORE_ADDR sp) { + generic_push_struct_return (addr, sp); write_register (3, addr); } /* Write into appropriate registers a function return value *************** rs6000_store_return_value (struct type * *** 1833,1841 **** as a CORE_ADDR (or an expression that can be used as one). */ static CORE_ADDR ! rs6000_extract_struct_value_address (char *regbuf) { ! return rs6000_struct_return_address; } /* Return whether PC is in a dummy function call. --- 1831,1848 ---- as a CORE_ADDR (or an expression that can be used as one). */ static CORE_ADDR ! rs6000_extract_struct_value_address (struct regcache *regcache) { ! ULONGEST ret, sp; ! ! /* First try to fetch a struct_return from the cache. */ ! regcache_cooked_read_unsigned (regcache, SP_REGNUM, &sp); ! ret = generic_pop_struct_return (sp); ! /* Failing that, get it from register 3. FIXME name? constant? */ ! if (ret == 0) ! regcache_cooked_read_unsigned (regcache, 3, &ret); ! ! return ret; } /* Return whether PC is in a dummy function call. *************** rs6000_gdbarch_init (struct gdbarch_info *** 2684,2690 **** set_gdbarch_store_struct_return (gdbarch, rs6000_store_struct_return); set_gdbarch_store_return_value (gdbarch, rs6000_store_return_value); ! set_gdbarch_deprecated_extract_struct_value_address (gdbarch, rs6000_extract_struct_value_address); set_gdbarch_pop_frame (gdbarch, rs6000_pop_frame); set_gdbarch_skip_prologue (gdbarch, rs6000_skip_prologue); --- 2691,2697 ---- set_gdbarch_store_struct_return (gdbarch, rs6000_store_struct_return); set_gdbarch_store_return_value (gdbarch, rs6000_store_return_value); ! set_gdbarch_extract_struct_value_address (gdbarch, rs6000_extract_struct_value_address); set_gdbarch_pop_frame (gdbarch, rs6000_pop_frame); set_gdbarch_skip_prologue (gdbarch, rs6000_skip_prologue); Index: mips-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/mips-tdep.c,v retrieving revision 1.118 diff -c -3 -p -r1.118 mips-tdep.c *** mips-tdep.c 21 Aug 2002 22:39:26 -0000 1.118 --- mips-tdep.c 22 Aug 2002 02:26:47 -0000 *************** mips_eabi_push_arguments (int nargs, *** 2622,2628 **** fprintf_unfiltered (gdb_stdlog, "mips_eabi_push_arguments: struct_return reg=%d 0x%s\n", argreg, paddr_nz (struct_addr)); ! write_register (argreg++, struct_addr); } /* Now load as many as possible of the first arguments into --- 2622,2628 ---- fprintf_unfiltered (gdb_stdlog, "mips_eabi_push_arguments: struct_return reg=%d 0x%s\n", argreg, paddr_nz (struct_addr)); ! argreg++; /* Reg reserved for passing struct_addr. */ } /* Now load as many as possible of the first arguments into *************** mips_n32n64_push_arguments (int nargs, *** 2873,2879 **** fprintf_unfiltered (gdb_stdlog, "mips_n32n64_push_arguments: struct_return reg=%d 0x%s\n", argreg, paddr_nz (struct_addr)); ! write_register (argreg++, struct_addr); } /* Now load as many as possible of the first arguments into --- 2873,2879 ---- fprintf_unfiltered (gdb_stdlog, "mips_n32n64_push_arguments: struct_return reg=%d 0x%s\n", argreg, paddr_nz (struct_addr)); ! argreg++; /* Reg reserved for passing struct_addr. */ } /* Now load as many as possible of the first arguments into *************** mips_o32_push_arguments (int nargs, *** 3099,3105 **** fprintf_unfiltered (gdb_stdlog, "mips_o32_push_arguments: struct_return reg=%d 0x%s\n", argreg, paddr_nz (struct_addr)); ! write_register (argreg++, struct_addr); stack_offset += MIPS_STACK_ARGSIZE; } --- 3099,3105 ---- fprintf_unfiltered (gdb_stdlog, "mips_o32_push_arguments: struct_return reg=%d 0x%s\n", argreg, paddr_nz (struct_addr)); ! argreg++; /* Reg reserved for passing struct_addr. */ stack_offset += MIPS_STACK_ARGSIZE; } *************** mips_o64_push_arguments (int nargs, *** 3398,3404 **** fprintf_unfiltered (gdb_stdlog, "mips_o64_push_arguments: struct_return reg=%d 0x%s\n", argreg, paddr_nz (struct_addr)); ! write_register (argreg++, struct_addr); stack_offset += MIPS_STACK_ARGSIZE; } --- 3398,3404 ---- fprintf_unfiltered (gdb_stdlog, "mips_o64_push_arguments: struct_return reg=%d 0x%s\n", argreg, paddr_nz (struct_addr)); ! argreg++; /* Reg reserved for passing struct_addr. */ stack_offset += MIPS_STACK_ARGSIZE; } *************** mips_n32n64_store_return_value (struct t *** 4902,4917 **** static void mips_store_struct_return (CORE_ADDR addr, CORE_ADDR sp) { ! /* Nothing to do -- push_arguments does all the work. */ } static CORE_ADDR ! mips_extract_struct_value_address (struct regcache *ignore) { ! /* FIXME: This will only work at random. The caller passes the ! struct_return address in V0, but it is not preserved. It may ! still be there, or this may be a random value. */ ! return read_register (V0_REGNUM); } /* Exported procedure: Is PC in the signal trampoline code */ --- 4902,4926 ---- static void mips_store_struct_return (CORE_ADDR addr, CORE_ADDR sp) { ! /* Save the struct_return address in a LIFO stack. */ ! addr = ROUND_DOWN (addr, 16); ! generic_push_struct_return (addr, sp); ! write_register (A0_REGNUM, addr); } static CORE_ADDR ! mips_extract_struct_value_address (struct regcache *regcache) { ! ULONGEST ret, sp; ! ! /* First try to fetch a struct_return from the cache. */ ! regcache_cooked_read_unsigned (regcache, SP_REGNUM, &sp); ! ret = generic_pop_struct_return (sp); ! /* Failing that, get it from V0. */ ! if (ret == 0) ! regcache_cooked_read_unsigned (regcache, V0_REGNUM, &ret); ! ! return ret; } /* Exported procedure: Is PC in the signal trampoline code */ Index: cris-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/cris-tdep.c,v retrieving revision 1.20 diff -c -3 -p -r1.20 cris-tdep.c *** cris-tdep.c 11 Jul 2002 19:25:13 -0000 1.20 --- cris-tdep.c 22 Aug 2002 02:26:47 -0000 *************** cris_abi (void) *** 173,181 **** return (gdbarch_tdep (current_gdbarch)->cris_abi); } - /* For saving call-clobbered contents in R9 when returning structs. */ - static CORE_ADDR struct_return_address; - struct frame_extra_info { CORE_ADDR return_pc; --- 173,178 ---- *************** void *** 1085,1091 **** cris_store_struct_return (CORE_ADDR addr, CORE_ADDR sp) { write_register (STR_REGNUM, addr); ! struct_return_address = addr; } /* Extract from regbuf the address where a function should return a --- 1082,1088 ---- cris_store_struct_return (CORE_ADDR addr, CORE_ADDR sp) { write_register (STR_REGNUM, addr); ! generic_push_return_address (addr, sp); } /* Extract from regbuf the address where a function should return a *************** cris_store_struct_return (CORE_ADDR addr *** 1093,1101 **** way. */ CORE_ADDR ! cris_extract_struct_value_address (char *regbuf) { ! return struct_return_address; } /* Returns 1 if a value of the given type being returned from a function --- 1090,1107 ---- way. */ CORE_ADDR ! cris_extract_struct_value_address (struct regcache *regcache) { ! ULONGEST ret, sp; ! ! /* First try to fetch a struct_return from the cache. */ ! regcache_cooked_read_unsigned (regcache, SP_REGNUM, &sp); ! ret = generic_pop_struct_return (sp); ! /* Failing that, get it from STR_REGNUM. */ ! if (ret == 0) ! regcache_cooked_read_unsigned (regcache, STR_REGNUM, &ret); ! ! return ret; } /* Returns 1 if a value of the given type being returned from a function *************** cris_gdbarch_init (struct gdbarch_info i *** 4297,4303 **** set_gdbarch_pop_frame (gdbarch, cris_pop_frame); set_gdbarch_store_struct_return (gdbarch, cris_store_struct_return); ! set_gdbarch_deprecated_extract_struct_value_address (gdbarch, cris_extract_struct_value_address); set_gdbarch_use_struct_convention (gdbarch, cris_use_struct_convention); --- 4303,4309 ---- set_gdbarch_pop_frame (gdbarch, cris_pop_frame); set_gdbarch_store_struct_return (gdbarch, cris_store_struct_return); ! set_gdbarch_extract_struct_value_address (gdbarch, cris_extract_struct_value_address); set_gdbarch_use_struct_convention (gdbarch, cris_use_struct_convention); Index: ia64-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/ia64-tdep.c,v retrieving revision 1.32 diff -c -3 -p -r1.32 ia64-tdep.c *** ia64-tdep.c 17 Jun 2002 23:32:31 -0000 1.32 --- ia64-tdep.c 22 Aug 2002 02:26:47 -0000 *************** ia64_extract_return_value (struct type * *** 1428,1451 **** TYPE_LENGTH (type)); } - /* FIXME: Turn this into a stack of some sort. Unfortunately, something - like this is necessary though since the IA-64 calling conventions specify - that r8 is not preserved. */ - static CORE_ADDR struct_return_address; - CORE_ADDR ! ia64_extract_struct_value_address (char *regbuf) { ! /* FIXME: See above. */ ! return struct_return_address; } void ia64_store_struct_return (CORE_ADDR addr, CORE_ADDR sp) { - /* FIXME: See above. */ /* Note that most of the work was done in ia64_push_arguments() */ ! struct_return_address = addr; } int --- 1428,1453 ---- TYPE_LENGTH (type)); } CORE_ADDR ! ia64_extract_struct_value_address (struct regcache *regcache) { ! ULONGEST ret, sp; ! ! /* First try to fetch a struct_return from the cache. */ ! regcache_cooked_read_unsigned (regcache, SP_REGNUM, &sp); ! ret = generic_pop_struct_return (sp); ! /* Failing that, get it from GR8. */ ! if (ret == 0) ! regcache_cooked_read_unsigned (regcache, IA64_GR8_REGNUM, &ret); ! ! return ret; } void ia64_store_struct_return (CORE_ADDR addr, CORE_ADDR sp) { /* Note that most of the work was done in ia64_push_arguments() */ ! generic_push_struct_return (addr, sp); } int *************** ia64_gdbarch_init (struct gdbarch_info i *** 2194,2200 **** set_gdbarch_store_struct_return (gdbarch, ia64_store_struct_return); set_gdbarch_store_return_value (gdbarch, ia64_store_return_value); ! set_gdbarch_deprecated_extract_struct_value_address (gdbarch, ia64_extract_struct_value_address); set_gdbarch_memory_insert_breakpoint (gdbarch, ia64_memory_insert_breakpoint); set_gdbarch_memory_remove_breakpoint (gdbarch, ia64_memory_remove_breakpoint); --- 2196,2203 ---- set_gdbarch_store_struct_return (gdbarch, ia64_store_struct_return); set_gdbarch_store_return_value (gdbarch, ia64_store_return_value); ! set_gdbarch_extract_struct_value_address (gdbarch, ! ia64_extract_struct_value_address); set_gdbarch_memory_insert_breakpoint (gdbarch, ia64_memory_insert_breakpoint); set_gdbarch_memory_remove_breakpoint (gdbarch, ia64_memory_remove_breakpoint);