2003-01-19 Andrew Cagney <ac131313@redhat.com>

* frame-unwind.h (frame_unwind_pop_ftype): Declare.
	(struct frame_unwind): Add field pop.
	* frame.h (frame_pop): Declare.
	* frame.c (frame_saved_regs_pop): New function.
	(trad_frame_unwinder): Add frame_saved_regs_pop.
	(frame_pop): New function.
	* dummy-frame.c (dummy_frame_pop): New function.
	(discard_innermost_dummy): New function.
	(generic_pop_dummy_frame): Use discard_innermost_dummy.
	(dummy_frame_unwind): Add dummy_frame_pop.
	* infrun.c (normal_stop): Call frame_pop instead of POP_FRAME.
	* valops.c (hand_function_call): Ditto.
	* stack.c (return_command): Ditto.
This commit is contained in:
Andrew Cagney 2003-01-19 17:39:16 +00:00
parent b4fc4eff63
commit dbe9fe588f
8 changed files with 118 additions and 14 deletions

View File

@ -1,3 +1,19 @@
2003-01-19 Andrew Cagney <ac131313@redhat.com>
* frame-unwind.h (frame_unwind_pop_ftype): Declare.
(struct frame_unwind): Add field pop.
* frame.h (frame_pop): Declare.
* frame.c (frame_saved_regs_pop): New function.
(trad_frame_unwinder): Add frame_saved_regs_pop.
(frame_pop): New function.
* dummy-frame.c (dummy_frame_pop): New function.
(discard_innermost_dummy): New function.
(generic_pop_dummy_frame): Use discard_innermost_dummy.
(dummy_frame_unwind): Add dummy_frame_pop.
* infrun.c (normal_stop): Call frame_pop instead of POP_FRAME.
* valops.c (hand_function_call): Ditto.
* stack.c (return_command): Ditto.
2003-01-18 Andrew Cagney <ac131313@redhat.com> 2003-01-18 Andrew Cagney <ac131313@redhat.com>
* cris-tdep.c: Fix function declaration indentation. * cris-tdep.c: Fix function declaration indentation.

View File

@ -270,8 +270,48 @@ generic_pop_current_frame (void (*popper) (struct frame_info * frame))
(*popper) (frame); (*popper) (frame);
} }
/* Function: pop_dummy_frame /* Discard the innermost dummy frame from the dummy frame stack
Restore the machine state from a saved dummy stack frame. */ (passed in as a parameter). */
static void
discard_innermost_dummy (struct dummy_frame **stack)
{
struct dummy_frame *tbd = (*stack);
(*stack) = (*stack)->next;
regcache_xfree (tbd->regcache);
xfree (tbd);
}
/* Function: dummy_frame_pop. Restore the machine state from a saved
dummy stack frame. */
static void
dummy_frame_pop (struct frame_info *fi, void **cache,
struct regcache *regcache)
{
struct dummy_frame *dummy = cached_find_dummy_frame (fi, cache);
/* If it isn't, what are we even doing here? */
gdb_assert (get_frame_type (fi) == DUMMY_FRAME);
if (dummy == NULL)
error ("Can't pop dummy frame!");
/* Discard all dummy frames up-to but not including this one. */
while (dummy_frame_stack != dummy)
discard_innermost_dummy (&dummy_frame_stack);
/* Restore this one. */
regcache_cpy (regcache, dummy->regcache);
flush_cached_frames ();
/* Now discard it. */
discard_innermost_dummy (&dummy_frame_stack);
/* Note: target changed would be better. Registers, memory and
frame are all invalid. */
flush_cached_frames ();
}
void void
generic_pop_dummy_frame (void) generic_pop_dummy_frame (void)
@ -283,12 +323,10 @@ generic_pop_dummy_frame (void)
if (!dummy_frame) if (!dummy_frame)
error ("Can't pop dummy frame!"); error ("Can't pop dummy frame!");
dummy_frame_stack = dummy_frame->next;
regcache_cpy (current_regcache, dummy_frame->regcache); regcache_cpy (current_regcache, dummy_frame->regcache);
flush_cached_frames (); flush_cached_frames ();
regcache_xfree (dummy_frame->regcache); discard_innermost_dummy (&dummy_frame_stack);
xfree (dummy_frame);
} }
/* Function: fix_call_dummy /* Function: fix_call_dummy
@ -369,6 +407,7 @@ dummy_frame_id_unwind (struct frame_info *frame,
static struct frame_unwind dummy_frame_unwind = static struct frame_unwind dummy_frame_unwind =
{ {
dummy_frame_pop,
dummy_frame_pc_unwind, dummy_frame_pc_unwind,
dummy_frame_id_unwind, dummy_frame_id_unwind,
dummy_frame_register_unwind dummy_frame_register_unwind

View File

@ -82,12 +82,27 @@ typedef void (frame_unwind_id_ftype) (struct frame_info * frame,
void **unwind_cache, void **unwind_cache,
struct frame_id * id); struct frame_id * id);
/* Discard the frame by restoring the registers (in regcache) back to
that of the caller. */
/* NOTE: cagney/2003-01-19: While at present the callers all pop each
frame in turn, the implementor should try to code things so that
any frame can be popped directly. */
/* FIXME: cagney/2003-01-19: Since both FRAME and REGCACHE refer to a
common register cache, care must be taken when restoring the
registers. The `correct fix' is to first first save the registers
in a scratch cache, and second write that scratch cache back to to
the real register cache. */
typedef void (frame_unwind_pop_ftype) (struct frame_info *frame,
void **unwind_cache,
struct regcache *regcache);
struct frame_unwind struct frame_unwind
{ {
/* Should the frame's type go here? */ /* Should the frame's type go here? */
/* Should an attribute indicating the frame's address-in-block go /* Should an attribute indicating the frame's address-in-block go
here? */ here? */
frame_unwind_pop_ftype *pop;
frame_unwind_pc_ftype *pc; frame_unwind_pc_ftype *pc;
frame_unwind_id_ftype *id; frame_unwind_id_ftype *id;
frame_unwind_reg_ftype *reg; frame_unwind_reg_ftype *reg;

View File

@ -145,6 +145,18 @@ frame_id_unwind (struct frame_info *frame)
return frame->id_unwind_cache; return frame->id_unwind_cache;
} }
void
frame_pop (struct frame_info *frame)
{
/* FIXME: cagney/2003-01-18: There is probably a chicken-egg problem
with passing in current_regcache. The pop function needs to be
written carefully so as to not overwrite registers whose [old]
values are needed to restore other registers. Instead, this code
should pass in a scratch cache and, as a second step, restore the
registers using that. */
frame->unwind->pop (frame, &frame->unwind_cache, current_regcache);
flush_cached_frames ();
}
void void
frame_register_unwind (struct frame_info *frame, int regnum, frame_register_unwind (struct frame_info *frame, int regnum,
@ -715,7 +727,15 @@ frame_saved_regs_id_unwind (struct frame_info *next_frame, void **cache,
id->base = base; id->base = base;
} }
static void
frame_saved_regs_pop (struct frame_info *fi, void **cache,
struct regcache *regcache)
{
POP_FRAME;
}
const struct frame_unwind trad_frame_unwinder = { const struct frame_unwind trad_frame_unwinder = {
frame_saved_regs_pop,
frame_saved_regs_pc_unwind, frame_saved_regs_pc_unwind,
frame_saved_regs_id_unwind, frame_saved_regs_id_unwind,
frame_saved_regs_register_unwind frame_saved_regs_register_unwind

View File

@ -306,6 +306,10 @@ extern CORE_ADDR frame_pc_unwind (struct frame_info *frame);
caller's frame. */ caller's frame. */
extern struct frame_id frame_id_unwind (struct frame_info *frame); extern struct frame_id frame_id_unwind (struct frame_info *frame);
/* Discard the specified frame. Restoring the registers to the state
of the caller. */
extern void frame_pop (struct frame_info *frame);
/* Describe the saved registers of a frame. */ /* Describe the saved registers of a frame. */
#if defined (EXTRA_FRAME_INFO) || defined (FRAME_FIND_SAVED_REGS) #if defined (EXTRA_FRAME_INFO) || defined (FRAME_FIND_SAVED_REGS)

View File

@ -3109,10 +3109,10 @@ normal_stop (void)
if (stop_stack_dummy) if (stop_stack_dummy)
{ {
/* Pop the empty frame that contains the stack dummy. /* Pop the empty frame that contains the stack dummy. POP_FRAME
POP_FRAME ends with a setting of the current frame, so we ends with a setting of the current frame, so we can use that
can use that next. */ next. */
POP_FRAME; frame_pop (get_current_frame ());
/* Set stop_pc to what it was before we called the function. /* Set stop_pc to what it was before we called the function.
Can't rely on restore_inferior_status because that only gets Can't rely on restore_inferior_status because that only gets
called if we don't stop in the called function. */ called if we don't stop in the called function. */

View File

@ -1625,6 +1625,10 @@ return_command (char *retval_exp, int from_tty)
error ("Not confirmed."); error ("Not confirmed.");
} }
/* FIXME: cagney/2003-01-18: Rather than pop each frame in turn,
this code should just go straight to the relevant frame and pop
that. */
/* Do the real work. Pop until the specified frame is current. We /* Do the real work. Pop until the specified frame is current. We
use this method because the deprecated_selected_frame is not valid after use this method because the deprecated_selected_frame is not valid after
a POP_FRAME. The pc comparison makes this work even if the a POP_FRAME. The pc comparison makes this work even if the
@ -1632,11 +1636,11 @@ return_command (char *retval_exp, int from_tty)
while (selected_frame_addr != get_frame_base (frame = get_current_frame ()) while (selected_frame_addr != get_frame_base (frame = get_current_frame ())
|| selected_frame_pc != get_frame_pc (frame)) || selected_frame_pc != get_frame_pc (frame))
POP_FRAME; frame_pop (get_current_frame ());
/* Then pop that frame. */ /* Then pop that frame. */
POP_FRAME; frame_pop (get_current_frame ());
/* Compute the return value (if any) and store in the place /* Compute the return value (if any) and store in the place
for return values. */ for return values. */
@ -1646,9 +1650,14 @@ return_command (char *retval_exp, int from_tty)
/* If we are at the end of a call dummy now, pop the dummy frame too. */ /* If we are at the end of a call dummy now, pop the dummy frame too. */
/* FIXME: cagney/2003-01-18: This is silly. Instead of popping all
the frames except the dummy, and then, as an afterthought,
popping the dummy frame, this code should just pop through to the
dummy frame. */
if (CALL_DUMMY_HAS_COMPLETED (read_pc(), read_sp (), if (CALL_DUMMY_HAS_COMPLETED (read_pc(), read_sp (),
get_frame_base (get_current_frame ()))) get_frame_base (get_current_frame ())))
POP_FRAME; frame_pop (get_current_frame ());
/* If interactive, print the frame that is now current. */ /* If interactive, print the frame that is now current. */

View File

@ -1711,8 +1711,9 @@ You must use a pointer to function type variable. Command ignored.", arg_name);
{ {
/* The user wants the context restored. */ /* The user wants the context restored. */
/* We must get back to the frame we were before the dummy call. */ /* We must get back to the frame we were before the dummy
POP_FRAME; call. */
frame_pop (get_current_frame ());
/* FIXME: Insert a bunch of wrap_here; name can be very long if it's /* FIXME: Insert a bunch of wrap_here; name can be very long if it's
a C++ name with arguments and stuff. */ a C++ name with arguments and stuff. */