(location_or_const_value_attribute): Fixed to use DECL_INCOMING_RTL for PARM_DECLs only when DECL_RTL isn't usable...
(location_or_const_value_attribute): Fixed to use DECL_INCOMING_RTL for PARM_DECLs only when DECL_RTL isn't usable, and even then, only when it actually points to the right place. From-SVN: r4189
This commit is contained in:
parent
a76386d8e5
commit
0e02aa7e28
159
gcc/dwarfout.c
159
gcc/dwarfout.c
|
@ -2100,68 +2100,109 @@ location_or_const_value_attribute (decl)
|
|||
return;
|
||||
|
||||
if ((TREE_CODE (decl) != VAR_DECL) && (TREE_CODE (decl) != PARM_DECL))
|
||||
abort ();
|
||||
|
||||
/* Existing Dwarf debuggers need and expect the location descriptors for
|
||||
formal parameters to reflect either the place where the parameters get
|
||||
passed (if they are passed on the stack and in memory) or else the
|
||||
(preserved) registers which the parameters get copied to during the
|
||||
function prologue.
|
||||
|
||||
At least this is the way things are for most common CISC machines
|
||||
(e.g. x86 and m68k) where parameters are passed in the stack, and for
|
||||
most common RISC machines (e.g. i860 and m88k) where parameters are
|
||||
passed in registers.
|
||||
|
||||
The rules for Sparc are a little weird for some reason. The DWARF
|
||||
generated by the USL C compiler for the Sparc/svr4 reference port says
|
||||
that the parameters are passed in the stack. I haven't figured out
|
||||
how to duplicate that behavior here (for the Sparc) yet, or even if
|
||||
I really need to.
|
||||
|
||||
Note that none of this is clearly spelled out in the current Dwarf
|
||||
version 1 specification, but it's obvious if you look at the output of
|
||||
the CI5 compiler, or if you try to use the svr4 SDB debugger. Hopefully,
|
||||
a later version of the Dwarf specification will clarify this. For now,
|
||||
we just need to generate the right thing. Note that Dwarf version 2
|
||||
will provide us with a means to describe *all* of the locations in which
|
||||
a given variable or parameter resides (and the PC ranges over which it
|
||||
occupies each one), but for now we can only describe one "location"
|
||||
for each formal parameter passed, and so we just try to mimic existing
|
||||
practice as much as possible.
|
||||
*/
|
||||
|
||||
if (TREE_CODE (decl) != PARM_DECL)
|
||||
/* If this decl is not a formal parameter, just use DECL_RTL. */
|
||||
rtl = DECL_RTL (decl);
|
||||
else
|
||||
{
|
||||
if (GET_CODE (DECL_INCOMING_RTL (decl)) == MEM)
|
||||
/* Parameter was passed in memory, so say that's where it lives. */
|
||||
rtl = DECL_INCOMING_RTL (decl);
|
||||
else
|
||||
{
|
||||
/* Parameter was passed in a register, so say it lives in the
|
||||
register it will be copied to during the prologue. */
|
||||
rtl = DECL_RTL (decl);
|
||||
|
||||
/* Note that in cases where the formal parameter is never used
|
||||
and where this compilation is done with -O, the copying of
|
||||
of an incoming register parameter to another register (in
|
||||
the prologue) can be totally optimized away. (In such cases
|
||||
the DECL_RTL will indicate a pseudo-register.) We could just
|
||||
use the DECL_RTL (as we normally do for register parameters)
|
||||
in these cases, but if we did that, we would end up generating
|
||||
a null location descriptor. (See `location_attribute' above.)
|
||||
That would be acceptable (according to the DWARF spec) but it
|
||||
is probably more useful to say that the formal resides where
|
||||
it was passed instead of saying that it resides nowhere. */
|
||||
if (is_pseudo_reg (rtl))
|
||||
rtl = DECL_INCOMING_RTL (decl);
|
||||
}
|
||||
/* Should never happen. */
|
||||
abort ();
|
||||
return;
|
||||
}
|
||||
|
||||
if (rtl == NULL)
|
||||
/* Here we have to decide where we are going to say the parameter "lives"
|
||||
(as far as the debugger is concerned). We only have a couple of choices.
|
||||
GCC provides us with DECL_RTL and with DECL_INCOMING_RTL. DECL_RTL
|
||||
normally indicates where the parameter lives during most of the activa-
|
||||
tion of the function. If optimization is enabled however, this could
|
||||
be either NULL or else a pseudo-reg. Both of those cases indicate that
|
||||
the parameter doesn't really live anywhere (as far as the code generation
|
||||
parts of GCC are concerned) during most of the function's activation.
|
||||
That will happen (for example) if the parameter is never referenced
|
||||
within the function.
|
||||
|
||||
We could just generate a location descriptor here for all non-NULL
|
||||
non-pseudo values of DECL_RTL and ignore all of the rest, but we can
|
||||
be a little nicer than that if we also consider DECL_INCOMING_RTL in
|
||||
cases where DECL_RTL is NULL or is a pseudo-reg.
|
||||
|
||||
Note however that we can only get away with using DECL_INCOMING_RTL as
|
||||
a backup substitute for DECL_RTL in certain limited cases. In cases
|
||||
where DECL_ARG_TYPE(decl) indicates the same type as TREE_TYPE(decl)
|
||||
we can be sure that the parameter was passed using the same type as it
|
||||
is declared to have within the function, and that its DECL_INCOMING_RTL
|
||||
points us to a place where a value of that type is passed. In cases
|
||||
where DECL_ARG_TYPE(decl) and TREE_TYPE(decl) are different types
|
||||
however, we cannot (in general) use DECL_INCOMING_RTL as a backup
|
||||
substitute for DECL_RTL because in these cases, DECL_INCOMING_RTL
|
||||
points us to a value of some type which is *different* from the type
|
||||
of the parameter itself. Thus, if we tried to use DECL_INCOMING_RTL
|
||||
to generate a location attribute in such cases, the debugger would
|
||||
end up (for example) trying to fetch a `float' from a place which
|
||||
actually contains the first part of a `double'. That would lead to
|
||||
really incorrect and confusing output at debug-time, and we don't
|
||||
want that now do we?
|
||||
|
||||
So in general, we DO NOT use DECL_INCOMING_RTL as a backup for DECL_RTL
|
||||
in cases where DECL_ARG_TYPE(decl) != TREE_TYPE(decl). There are a
|
||||
couple of cute exceptions however. On little-endian machines we can
|
||||
get away with using DECL_INCOMING_RTL even when DECL_ARG_TYPE(decl) is
|
||||
not the same as TREE_TYPE(decl) but only when DECL_ARG_TYPE(decl) is
|
||||
an integral type which is smaller than TREE_TYPE(decl). These cases
|
||||
arise when (on a little-endian machine) a non-prototyped function has
|
||||
a parameter declared to be of type `short' or `char'. In such cases,
|
||||
TREE_TYPE(decl) will be `short' or `char', DECL_ARG_TYPE(decl) will be
|
||||
`int', and DECL_INCOMING_RTL will point to the lowest-order byte of the
|
||||
passed `int' value. If the debugger then uses that address to fetch a
|
||||
`short' or a `char' (on a little-endian machine) the result will be the
|
||||
correct data, so we allow for such exceptional cases below.
|
||||
|
||||
Note that our goal here is to describe the place where the given formal
|
||||
parameter lives during most of the function's activation (i.e. between
|
||||
the end of the prologue and the start of the epilogue). We'll do that
|
||||
as best as we can. Note however that if the given formal parameter is
|
||||
modified sometime during the execution of the function, then a stack
|
||||
backtrace (at debug-time) will show the function as having been called
|
||||
with the *new* value rather than the value which was originally passed
|
||||
in. This happens rarely enough that it is not a major problem, but it
|
||||
*is* a problem, and I'd like to fix it. A future version of dwarfout.c
|
||||
may generate two additional attributes for any given TAG_formal_parameter
|
||||
DIE which will describe the "passed type" and the "passed location" for
|
||||
the given formal parameter in addition to the attributes we now generate
|
||||
to indicate the "declared type" and the "active location" for each
|
||||
parameter. This additional set of attributes could be used by debuggers
|
||||
for stack backtraces.
|
||||
|
||||
Separately, note that sometimes DECL_RTL can be NULL and DECL_INCOMING_RTL
|
||||
can be NULL also. This happens (for example) for inlined-instances of
|
||||
inline function formal parameters which are never referenced. This really
|
||||
shouldn't be happening. All PARM_DECL nodes should get valid non-NULL
|
||||
DECL_INCOMING_RTL values, but integrate.c doesn't currently generate
|
||||
these values for inlined instances of inline function parameters, so
|
||||
when we see such cases, we are just SOL (shit-out-of-luck) for the time
|
||||
being (until integrate.c gets fixed).
|
||||
*/
|
||||
|
||||
/* Use DECL_RTL as the "location" unless we find something better. */
|
||||
rtl = DECL_RTL (decl);
|
||||
|
||||
if (TREE_CODE (decl) == PARM_DECL)
|
||||
if (rtl == NULL_RTX || is_pseudo_reg (rtl))
|
||||
{
|
||||
/* This decl represents a formal parameter which was optimized out. */
|
||||
register tree declared_type = TYPE_MAIN_VARIANT (TREE_TYPE (decl));
|
||||
register tree passed_type = TYPE_MAIN_VARIANT (DECL_ARG_TYPE (decl));
|
||||
|
||||
/* Note that DECL_INCOMING_RTL may be NULL in here, but we handle
|
||||
*all* cases where (rtl == NULL_RTX) just below. */
|
||||
|
||||
if (declared_type == passed_type)
|
||||
rtl = DECL_INCOMING_RTL (decl);
|
||||
#if (BYTES_BIG_ENDIAN == 0)
|
||||
else
|
||||
if (TREE_CODE (declared_type) == INTEGER_TYPE)
|
||||
if (TYPE_SIZE (declared_type) <= TYPE_SIZE (passed_type))
|
||||
rtl = DECL_INCOMING_RTL (decl);
|
||||
#endif /* (BYTES_BIG_ENDIAN == 0) */
|
||||
}
|
||||
|
||||
if (rtl == NULL_RTX)
|
||||
return;
|
||||
|
||||
switch (GET_CODE (rtl))
|
||||
|
|
Loading…
Reference in New Issue