From 0e02aa7e28e766906045ae4660c20e9372c093f8 Mon Sep 17 00:00:00 2001 From: Richard Kenner Date: Wed, 21 Apr 1993 18:14:38 -0400 Subject: [PATCH] (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 --- gcc/dwarfout.c | 159 +++++++++++++++++++++++++++++++------------------ 1 file changed, 100 insertions(+), 59 deletions(-) diff --git a/gcc/dwarfout.c b/gcc/dwarfout.c index 1026f468148..39fe99b0ee6 100644 --- a/gcc/dwarfout.c +++ b/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))