This is the mail archive of the dwarf2@corp.sgi.com mailing list for the dwarf2 project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: Modifies vs. Replaces



On the assumption that we want to define a specific interpretation for a
location attribute on a non-defining declaration (rather than leaving a
range of implementer choices), let me offer some observations on the
pros, cons and implications of the available alternatives.

Actually, I only know of 3 alternates although there are some minor
variations. They were suggested by Michael Eager as follows:

 1) Ignore location information in the defining entry, and
    only use the location information provided in the non-defining
    entry [within the scope of the non-defining entity].
 2) Treat the location information provided in both entries as
    valid, describing a variable with multiple locations.
 3) Use only location information in the defining entry.

I think we can dismiss #3 quite quickly. What good is it to allow location
information to be specified on a non-defining declaration and then require
that it be ignored in favor of the location information on the corresponding
defining declaration? None that I can see...

Before considering the other two, let me try to summarize what are hopefully
universally agreed interpretations [if there is disagreement, then at least
we learn a bit more about about our range of views]:

 A) If there is a location attribute on the defining declaration, and no
    location attribute on a corresponding non-defining declaration, then
    the location for the non-defining declaration is taken from the
    defining one.

    A1) If the location attribute is a simple location expression, there
        is a single allocation that is invariant over time and space.

    A2) If the variable (in particular) is global (has a DW_AT_external
        attribute) then that allocation extends beyond just the (file)
	scope in which it is declared and includes the entire address
	space of the program.

    A3) If a location list were used to describe the allocation equivalent
        to A1 and A2 combined, it would have the form

	    0..MAXADDR, GlobalLocation

	that is, a single range extending from address zero to whatever
	address is the maximum that can possibly occur anywhere in that
        program.

	A key point here is that for a global variable, a location list
	must describe the entire address range of the program, not just
	the address range of the (file) scope in which the variable is
	declared.

    A4) If the variable in question does have "local allocations" within
        some scope within the defining scope, then the form of the location
	list will look like

	    0..LocalScopeLowAddr, GlobalLocation
	    ...<one or more location entries interior to LocalScope>...
	    LocalScopeHighAddr, GlobalLocation

	NOTE: I am deliberately leaving aside the meaning of

	    0..MAXADDR, GlobalLocation
	    ...<one or more location entries interior to LocalScope>...

	because it is not germane to the following key point (regarding
	the allocation information outside of the scope of the defining
	declaration).

	A key point here is that the location list for the defining
	declaration can only describe the single GlobalLocation for
	any addresses outside of the defining scope for the simple
	reason the compiler has no knowledge of what allocations will
	be determined for other units during the compilation of separately
	compiled modules.

    A5) Observe that a location list such as first illustrated in A4 is
        capable of describing a global variable whose allocation is
	sometimes not current or defined in any static location, in
	which case the global static allocation lifetime may be said to
	have a "hole" in it (terminology suggested by Todd Allen, and
	incidentally also used in exactly this same sense in the GEM
	backend compiler group here at Compaq).

 B) If neither has a location attribute, then the entity
    exists in the source but is unallocated in the compiled code --
    probably very rare for a global variable, but at least conceivable
    if the whole program is compiled all together.

Now we get to the meaning of the proposed new ability to specify a location
attribute for a non-defining declaration.

 C) If the non-defining declaration has a simple location expression,
    then if must "agree" with the global static allocation of the
    defining declaration.

    We could consider this harmless redundancy or we might try to rule
    it out. At this point in the discussion I don't see that it matters
    very much.

    Note: There is an awkwardness here because the single allocation
    in the non-defining declaration needs to be related to that in the
    defining declaration. Most importantly, would/could such a location
    attribute override and fill-in a hole in defining location? Rather
    than try to answer that question just yet, just keep it in mind
    during the following.

 D) If the non-defining declaration has a location list (due to some
    local allocations in other than the global location), then it might
    have either of two forms:

    D1) Form 1:

	    0..LocalScopeLowAddr, GlobalLocation
	    ...<one or more location entries interior to LocalScope>...
	    LocalScopeHighAddr, GlobalLocation

    D2) Form 2:

	    ...<one or more location entries interior to LocalScope>...

    At first blush, the second appears to have the advantage of being
    preferable because it is more compact. But before we can settle
    firmly on that conclusion, we need to consider the relationship
    between the two lists.

Finally, lets get back to the remaining two alternative relationships
suggested at the beginning.

 E) The first is: Ignore location information in the defining entry, and
    only use the location information provided in the non-defining
    entry [within the scope of the non-defining entry].

    This works out fairly cleanly:

    E1) The awkwardness suggested in C) does not arise; outside the scope of
        the non-defining declaration, the allocation of that non-defining
	declaration is simply not relevant and does not apply.

    E2) It does appear that Form D1 is most likely the only correct
        form. Within the scope of the non-defining declaration, the given
	location is the only relevant allocation information. By the
	nature of the globalness of the variable, it will necessarily
	initially and finally exist in the "normal" global location until
	the code does something concrete to change that fact.

	[This is not absolutely necessary, given the ability of optimizers
	to rearrange code in marvelous ways, but it is the normal and more
	general case compared to D2.]

    E3) Code generation in a module containing the non-defining declaration
        can great holes in the static allocation, without being influenced
	or compromised by the location information in the defining
	declaration.

 F) The second is: Treat the location information provided by both
    entries as valid, describing a variable with multiple locations.

    This does not work out quite so clean:

    F1) Does a simple (non-list) allocation in the non-defining declaration
        specify a "live" allocation even in places where the defining
	declaration tried to specify a hole?

	This seems unacceptable. It can be avoided, however, by specifying
	that the location of the non-defining declaration is applicable
	only within the scope of that declaration. Let us assume that
	and continue.

    F2) Suppose we use Form D1, that is, attempt to make the non-defining
        description "complete". Now we have a new wrinkle on the question
        overlapping address ranges: what does it mean when two list entries
	specify the *same location* for overlapping ranges.

	We can be generous here and consider this a kind of harmless
	redundancy. Or we could require that the list avoid such redundancy.
	The latter will generally be more compact; but perhaps it might
	be harder to produce in some implementations?

    F3) There appears to be no way to preclude the location information
        of the defining declaration from making it impossible to describe
	a lifetime hole in the scope of the non-defining declaration.

	Just because a variable is defining in one unit and non-defining
	in another does not make any difference from a code generation
	point of view. A compiler that can create lifetime holes in
	one case can do so in the other. But it seems strange and wrong
	for this to be describable by DWARF in one case but not the other.
	Especially when there is a formulation available without such an
	asymmetry and non-uniform descriptive power.

I apologize that this has been so long. But I wanted to work through the
full details of the main alternatives to make sure I understood the
implications of each.

Having done that, it does appear that the ability to describe lifetime
holes is the critical functional difference in the descriptive power
of the two main alternatives.

Since lifetime holes in staticly allocated variables (whether global or
otherwise) are created by Compaq's compilers, I have to side in
favor off a representation that can correctly describe them, if available.

Of the original three alternatives, I strongly support #1 as the better
interpretation for a location attribute on a non-defining declaration:

    Ignore location information in the defining entry, and
    only use the location information provided in the non-defining
    entry [within the scope of the non-defining entry].

Ron



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]