2003-04-23 Andrew Cagney <cagney@redhat.com>

* infcall.c (call_function_by_hand): Make declaration of "i",
	"sal", "bpt" and "old_sp" more local to their use.  Delete #if
	lint.
This commit is contained in:
Andrew Cagney 2003-04-23 20:31:57 +00:00
parent d727590f88
commit ebc7896c3c
2 changed files with 129 additions and 118 deletions

View File

@ -1,3 +1,9 @@
2003-04-23 Andrew Cagney <cagney@redhat.com>
* infcall.c (call_function_by_hand): Make declaration of "i",
"sal", "bpt" and "old_sp" more local to their use. Delete #if
lint.
2003-04-23 Andrew Cagney <cagney@redhat.com> 2003-04-23 Andrew Cagney <cagney@redhat.com>
* infcall.c (call_function_by_hand): Delete variable * infcall.c (call_function_by_hand): Delete variable

View File

@ -237,7 +237,6 @@ struct value *
call_function_by_hand (struct value *function, int nargs, struct value **args) call_function_by_hand (struct value *function, int nargs, struct value **args)
{ {
register CORE_ADDR sp; register CORE_ADDR sp;
register int i;
int rc; int rc;
CORE_ADDR start_sp; CORE_ADDR start_sp;
/* CALL_DUMMY is an array of words (REGISTER_SIZE), but each word /* CALL_DUMMY is an array of words (REGISTER_SIZE), but each word
@ -258,7 +257,6 @@ call_function_by_hand (struct value *function, int nargs, struct value **args)
int sizeof_dummy1; int sizeof_dummy1;
char *dummy1; char *dummy1;
CORE_ADDR dummy_addr; CORE_ADDR dummy_addr;
CORE_ADDR old_sp;
struct type *value_type; struct type *value_type;
unsigned char struct_return; unsigned char struct_return;
CORE_ADDR struct_addr = 0; CORE_ADDR struct_addr = 0;
@ -322,55 +320,56 @@ call_function_by_hand (struct value *function, int nargs, struct value **args)
generic_push_dummy_frame (); generic_push_dummy_frame ();
} }
old_sp = read_sp ();
/* Ensure that the initial SP is correctly aligned. */ /* Ensure that the initial SP is correctly aligned. */
if (gdbarch_frame_align_p (current_gdbarch)) {
{ CORE_ADDR old_sp = read_sp ();
/* NOTE: cagney/2002-09-18: if (gdbarch_frame_align_p (current_gdbarch))
{
/* NOTE: cagney/2002-09-18:
On a RISC architecture, a void parameterless generic dummy
frame (i.e., no parameters, no result) typically does not
need to push anything the stack and hence can leave SP and
FP. Similarly, a framelss (possibly leaf) function does
not push anything on the stack and, hence, that too can
leave FP and SP unchanged. As a consequence, a sequence of
void parameterless generic dummy frame calls to frameless
functions will create a sequence of effectively identical
frames (SP, FP and TOS and PC the same). This, not
suprisingly, results in what appears to be a stack in an
infinite loop --- when GDB tries to find a generic dummy
frame on the internal dummy frame stack, it will always
find the first one.
On a RISC architecture, a void parameterless generic dummy To avoid this problem, the code below always grows the
frame (i.e., no parameters, no result) typically does not stack. That way, two dummy frames can never be identical.
need to push anything the stack and hence can leave SP and It does burn a few bytes of stack but that is a small price
FP. Similarly, a framelss (possibly leaf) function does not to pay :-). */
push anything on the stack and, hence, that too can leave FP sp = gdbarch_frame_align (current_gdbarch, old_sp);
and SP unchanged. As a consequence, a sequence of void if (sp == old_sp)
parameterless generic dummy frame calls to frameless {
functions will create a sequence of effectively identical if (INNER_THAN (1, 2))
frames (SP, FP and TOS and PC the same). This, not /* Stack grows down. */
suprisingly, results in what appears to be a stack in an sp = gdbarch_frame_align (current_gdbarch, old_sp - 1);
infinite loop --- when GDB tries to find a generic dummy else
frame on the internal dummy frame stack, it will always find /* Stack grows up. */
the first one. sp = gdbarch_frame_align (current_gdbarch, old_sp + 1);
}
To avoid this problem, the code below always grows the stack. gdb_assert ((INNER_THAN (1, 2) && sp <= old_sp)
That way, two dummy frames can never be identical. It does || (INNER_THAN (2, 1) && sp >= old_sp));
burn a few bytes of stack but that is a small price to pay }
:-). */ else
sp = gdbarch_frame_align (current_gdbarch, old_sp); /* FIXME: cagney/2002-09-18: Hey, you loose! Who knows how
if (sp == old_sp) badly aligned the SP is! Further, per comment above, if the
{ generic dummy frame ends up empty (because nothing is pushed)
if (INNER_THAN (1, 2)) GDB won't be able to correctly perform back traces. If a
/* Stack grows down. */ target is having trouble with backtraces, first thing to do
sp = gdbarch_frame_align (current_gdbarch, old_sp - 1); is add FRAME_ALIGN() to its architecture vector. After that,
else try adding SAVE_DUMMY_FRAME_TOS() and modifying
/* Stack grows up. */ DEPRECATED_FRAME_CHAIN so that when the next outer frame is a
sp = gdbarch_frame_align (current_gdbarch, old_sp + 1); generic dummy, it returns the current frame's base. */
} sp = old_sp;
gdb_assert ((INNER_THAN (1, 2) && sp <= old_sp) }
|| (INNER_THAN (2, 1) && sp >= old_sp));
}
else
/* FIXME: cagney/2002-09-18: Hey, you loose! Who knows how badly
aligned the SP is! Further, per comment above, if the generic
dummy frame ends up empty (because nothing is pushed) GDB won't
be able to correctly perform back traces. If a target is
having trouble with backtraces, first thing to do is add
FRAME_ALIGN() to its architecture vector. After that, try
adding SAVE_DUMMY_FRAME_TOS() and modifying
DEPRECATED_FRAME_CHAIN so that when the next outer frame is a
generic dummy, it returns the current frame's base. */
sp = old_sp;
if (INNER_THAN (1, 2)) if (INNER_THAN (1, 2))
{ {
@ -407,10 +406,13 @@ call_function_by_hand (struct value *function, int nargs, struct value **args)
/* Create a call sequence customized for this function /* Create a call sequence customized for this function
and the number of arguments for it. */ and the number of arguments for it. */
for (i = 0; i < (int) (SIZEOF_CALL_DUMMY_WORDS / sizeof (dummy[0])); i++) {
store_unsigned_integer (&dummy1[i * REGISTER_SIZE], int i;
REGISTER_SIZE, for (i = 0; i < (int) (SIZEOF_CALL_DUMMY_WORDS / sizeof (dummy[0])); i++)
(ULONGEST) dummy[i]); store_unsigned_integer (&dummy1[i * REGISTER_SIZE],
REGISTER_SIZE,
(ULONGEST) dummy[i]);
}
switch (CALL_DUMMY_LOCATION) switch (CALL_DUMMY_LOCATION)
{ {
@ -459,72 +461,74 @@ call_function_by_hand (struct value *function, int nargs, struct value **args)
internal_error (__FILE__, __LINE__, "bad switch"); internal_error (__FILE__, __LINE__, "bad switch");
} }
#ifdef lint
sp = old_sp; /* It really is used, for some ifdef's... */
#endif
if (nargs < TYPE_NFIELDS (ftype)) if (nargs < TYPE_NFIELDS (ftype))
error ("too few arguments in function call"); error ("too few arguments in function call");
for (i = nargs - 1; i >= 0; i--) {
{ int i;
int prototyped; for (i = nargs - 1; i >= 0; i--)
struct type *param_type; {
int prototyped;
struct type *param_type;
/* FIXME drow/2002-05-31: Should just always mark methods as
prototyped. Can we respect TYPE_VARARGS? Probably not. */
if (TYPE_CODE (ftype) == TYPE_CODE_METHOD)
prototyped = 1;
else if (i < TYPE_NFIELDS (ftype))
prototyped = TYPE_PROTOTYPED (ftype);
else
prototyped = 0;
/* FIXME drow/2002-05-31: Should just always mark methods as if (i < TYPE_NFIELDS (ftype))
prototyped. Can we respect TYPE_VARARGS? Probably not. */ param_type = TYPE_FIELD_TYPE (ftype, i);
if (TYPE_CODE (ftype) == TYPE_CODE_METHOD) else
prototyped = 1; param_type = NULL;
else if (i < TYPE_NFIELDS (ftype))
prototyped = TYPE_PROTOTYPED (ftype); args[i] = value_arg_coerce (args[i], param_type, prototyped);
else
prototyped = 0;
if (i < TYPE_NFIELDS (ftype)) /* elz: this code is to handle the case in which the function
param_type = TYPE_FIELD_TYPE (ftype, i); to be called has a pointer to function as parameter and the
else corresponding actual argument is the address of a function
param_type = NULL; and not a pointer to function variable. In aCC compiled
code, the calls through pointers to functions (in the body
of the function called by hand) are made via
$$dyncall_external which requires some registers setting,
this is taken care of if we call via a function pointer
variable, but not via a function address. In cc this is
not a problem. */
args[i] = value_arg_coerce (args[i], param_type, prototyped); if (using_gcc == 0)
{
/* elz: this code is to handle the case in which the function to if (param_type != NULL && TYPE_CODE (ftype) != TYPE_CODE_METHOD)
be called has a pointer to function as parameter and the {
corresponding actual argument is the address of a function /* if this parameter is a pointer to function. */
and not a pointer to function variable. In aCC compiled if (TYPE_CODE (param_type) == TYPE_CODE_PTR)
code, the calls through pointers to functions (in the body of if (TYPE_CODE (TYPE_TARGET_TYPE (param_type)) == TYPE_CODE_FUNC)
the function called by hand) are made via $$dyncall_external /* elz: FIXME here should go the test about the
which requires some registers setting, this is taken care of compiler used to compile the target. We want to
if we call via a function pointer variable, but not via a issue the error message only if the compiler
function address. In cc this is not a problem. */ used was HP's aCC. If we used HP's cc, then
there is no problem and no need to return at
if (using_gcc == 0) this point. */
{ /* Go see if the actual parameter is a variable of
if (param_type != NULL && TYPE_CODE (ftype) != TYPE_CODE_METHOD) type pointer to function or just a function. */
{ if (args[i]->lval == not_lval)
/* if this parameter is a pointer to function. */ {
if (TYPE_CODE (param_type) == TYPE_CODE_PTR) char *arg_name;
if (TYPE_CODE (TYPE_TARGET_TYPE (param_type)) == TYPE_CODE_FUNC) if (find_pc_partial_function ((CORE_ADDR) args[i]->aligner.contents[0], &arg_name, NULL, NULL))
/* elz: FIXME here should go the test about the error ("\
compiler used to compile the target. We want to
issue the error message only if the compiler used
was HP's aCC. If we used HP's cc, then there is
no problem and no need to return at this point. */
/* Go see if the actual parameter is a variable of
type pointer to function or just a function. */
if (args[i]->lval == not_lval)
{
char *arg_name;
if (find_pc_partial_function ((CORE_ADDR) args[i]->aligner.contents[0], &arg_name, NULL, NULL))
error ("\
You cannot use function <%s> as argument. \n\ You cannot use function <%s> as argument. \n\
You must use a pointer to function type variable. Command ignored.", arg_name); You must use a pointer to function type variable. Command ignored.", arg_name);
} }
} }
} }
} }
}
if (REG_STRUCT_HAS_ADDR_P ()) if (REG_STRUCT_HAS_ADDR_P ())
{ {
int i;
/* This is a machine like the sparc, where we may need to pass a /* This is a machine like the sparc, where we may need to pass a
pointer to the structure, not the structure itself. */ pointer to the structure, not the structure itself. */
for (i = nargs - 1; i >= 0; i--) for (i = nargs - 1; i >= 0; i--)
@ -632,7 +636,7 @@ You must use a pointer to function type variable. Command ignored.", arg_name);
{ {
/* If stack grows down, we must leave a hole at the top. */ /* If stack grows down, we must leave a hole at the top. */
int len = 0; int len = 0;
int i;
for (i = nargs - 1; i >= 0; i--) for (i = nargs - 1; i >= 0; i--)
len += TYPE_LENGTH (VALUE_ENCLOSING_TYPE (args[i])); len += TYPE_LENGTH (VALUE_ENCLOSING_TYPE (args[i]));
if (DEPRECATED_CALL_DUMMY_STACK_ADJUST_P ()) if (DEPRECATED_CALL_DUMMY_STACK_ADJUST_P ())
@ -774,24 +778,25 @@ You must use a pointer to function type variable. Command ignored.", arg_name);
struct regcache *buffer = retbuf; struct regcache *buffer = retbuf;
struct cleanup *old_cleanups = make_cleanup (null_cleanup, 0); struct cleanup *old_cleanups = make_cleanup (null_cleanup, 0);
int saved_async = 0; int saved_async = 0;
struct breakpoint *bpt;
struct symtab_and_line sal;
/* Now proceed, having reached the desired place. */ /* Now proceed, having reached the desired place. */
clear_proceed_status (); clear_proceed_status ();
init_sal (&sal); /* initialize to zeroes */ /* Create a momentary breakpoint at the return address of the
sal.pc = bp_addr; inferior. That way it breaks when it returns. */
sal.section = find_pc_overlay (sal.pc);
{ {
struct breakpoint *bpt;
struct symtab_and_line sal;
struct frame_id frame;
init_sal (&sal); /* initialize to zeroes */
sal.pc = bp_addr;
sal.section = find_pc_overlay (sal.pc);
/* Set up a frame ID for the dummy frame so we can pass it to /* Set up a frame ID for the dummy frame so we can pass it to
set_momentary_breakpoint. We need to give the breakpoint a set_momentary_breakpoint. We need to give the breakpoint a
frame ID so that the breakpoint code can correctly frame ID so that the breakpoint code can correctly
re-identify the dummy breakpoint. */ re-identify the dummy breakpoint. */
struct frame_id frame = frame_id_build (read_fp (), sal.pc); frame = frame_id_build (read_fp (), sal.pc);
/* Create a momentary breakpoint at the return address of the
inferior. That way it breaks when it returns. */
bpt = set_momentary_breakpoint (sal, frame, bp_call_dummy); bpt = set_momentary_breakpoint (sal, frame, bp_call_dummy);
bpt->disposition = disp_del; bpt->disposition = disp_del;
} }