}
-/* A default function for COERCE_FLOAT_TO_DOUBLE: do the coercion only
- when we don't have any type for the argument at hand. This occurs
- when we have no debug info, or when passing varargs.
-
- This is an annoying default: the rule the compiler follows is to do
- the standard promotions whenever there is no prototype in scope,
- and almost all targets want this behavior. But there are some old
- architectures which want this odd behavior. If you want to go
- through them all and fix them, please do. Modern gdbarch-style
- targets may find it convenient to use standard_coerce_float_to_double. */
+/* Functions to use for the COERCE_FLOAT_TO_DOUBLE gdbarch method.
+
+ How you should pass arguments to a function depends on whether it
+ was defined in K&R style or prototype style. If you define a
+ function using the K&R syntax that takes a `float' argument, then
+ callers must pass that argument as a `double'. If you define the
+ function using the prototype syntax, then you must pass the
+ argument as a `float', with no promotion.
+
+ Unfortunately, on certain older platforms, the debug info doesn't
+ indicate reliably how each function was defined. A function type's
+ TYPE_FLAG_PROTOTYPED flag may be clear, even if the function was
+ defined in prototype style. When calling a function whose
+ TYPE_FLAG_PROTOTYPED flag is clear, GDB consults the
+ COERCE_FLOAT_TO_DOUBLE gdbarch method to decide what to do.
+
+ For modern targets, it is proper to assume that, if the prototype
+ flag is clear, that can be trusted: `float' arguments should be
+ promoted to `double'. You should register the function
+ `standard_coerce_float_to_double' to get this behavior.
+
+ For some older targets, if the prototype flag is clear, that
+ doesn't tell us anything. So we guess that, if we don't have a
+ type for the formal parameter (i.e., the first argument to
+ COERCE_FLOAT_TO_DOUBLE is null), then we should promote it;
+ otherwise, we should leave it alone. The function
+ `default_coerce_float_to_double' provides this behavior; it is the
+ default value, for compatibility with older configurations. */
int
default_coerce_float_to_double (struct type *formal, struct type *actual)
{
}
-/* Always coerce floats to doubles when there is no prototype in scope.
- If your architecture follows the standard type promotion rules for
- calling unprototyped functions, your gdbarch init function can pass
- this function to set_gdbarch_coerce_float_to_double to use its logic. */
int
standard_coerce_float_to_double (struct type *formal, struct type *actual)
{
CORE_ADDR real_pc;
struct type *param_type = NULL;
struct type *ftype = check_typedef (SYMBOL_TYPE (function));
+ int n_method_args = 0;
dummy = alloca (SIZEOF_CALL_DUMMY_WORDS);
sizeof_dummy1 = REGISTER_SIZE * SIZEOF_CALL_DUMMY_WORDS / sizeof (ULONGEST);
sp = old_sp; /* It really is used, for some ifdef's... */
#endif
- if (nargs < TYPE_NFIELDS (ftype))
+ if (TYPE_CODE (ftype) == TYPE_CODE_METHOD)
+ {
+ i = 0;
+ while (TYPE_CODE (TYPE_ARG_TYPES (ftype)[i]) != TYPE_CODE_VOID)
+ i++;
+ n_method_args = i;
+ if (nargs < i)
+ error ("too few arguments in method call");
+ }
+ else if (nargs < TYPE_NFIELDS (ftype))
error ("too few arguments in function call");
for (i = nargs - 1; i >= 0; i--)
{
+ /* Assume that methods are always prototyped, unless they are off the
+ end (which we should only be allowing if there is a ``...'').
+ FIXME. */
+ if (TYPE_CODE (ftype) == TYPE_CODE_METHOD)
+ {
+ if (i < n_method_args)
+ args[i] = value_arg_coerce (args[i], TYPE_ARG_TYPES (ftype)[i], 1);
+ else
+ args[i] = value_arg_coerce (args[i], NULL, 0);
+ }
+
/* If we're off the end of the known arguments, do the standard
promotions. FIXME: if we had a prototype, this should only
be allowed if ... were present. */
else
{
- int is_prototyped = TYPE_FLAGS (ftype) & TYPE_FLAG_PROTOTYPED;
param_type = TYPE_FIELD_TYPE (ftype, i);
-
- args[i] = value_arg_coerce (args[i], param_type, is_prototyped);
+ args[i] = value_arg_coerce (args[i], param_type, TYPE_PROTOTYPED (ftype));
}
/*elz: this code is to handle the case in which the function to be called
sp = PUSH_ARGUMENTS (nargs, args, sp, struct_return, struct_addr);
-#ifdef PUSH_RETURN_ADDRESS /* for targets that use no CALL_DUMMY */
- /* There are a number of targets now which actually don't write any
- CALL_DUMMY instructions into the target, but instead just save the
- machine state, push the arguments, and jump directly to the callee
- function. Since this doesn't actually involve executing a JSR/BSR
- instruction, the return address must be set up by hand, either by
- pushing onto the stack or copying into a return-address register
- as appropriate. Formerly this has been done in PUSH_ARGUMENTS,
- but that's overloading its functionality a bit, so I'm making it
- explicit to do it here. */
- sp = PUSH_RETURN_ADDRESS (real_pc, sp);
-#endif /* PUSH_RETURN_ADDRESS */
+ if (PUSH_RETURN_ADDRESS_P ())
+ /* for targets that use no CALL_DUMMY */
+ /* There are a number of targets now which actually don't write
+ any CALL_DUMMY instructions into the target, but instead just
+ save the machine state, push the arguments, and jump directly
+ to the callee function. Since this doesn't actually involve
+ executing a JSR/BSR instruction, the return address must be set
+ up by hand, either by pushing onto the stack or copying into a
+ return-address register as appropriate. Formerly this has been
+ done in PUSH_ARGUMENTS, but that's overloading its
+ functionality a bit, so I'm making it explicit to do it here. */
+ sp = PUSH_RETURN_ADDRESS (real_pc, sp);
if (STACK_ALIGN_P () && !INNER_THAN (1, 2))
{