010301.2 | A | T. Allen | Ada | Nested inlines |
PURPOSE:
Issue #1:
I believe that the wording of 3.3.8.2 does not allow for nested inlines
because of these restrictions:
1) An abstract instance tree consists of its root and all children of
that
root (transitively).
2) A concrete instance tree consists of its root and all children of
that
root (transitively).
3) Each concrete instance tree is uniquely associated with exactly one
abstract instance tree.
4) Each entry within a concrete instance tree is associated with one
particular entry in the associated abstract instance
tree.
Any inline subroutine nested within outer inline subroutine and called from
that outer inline subroutine would break this relationship because:
1) the declaration of the nested inline subroutine would be considered
part of its own abstract instance tree and also part
of the outer
inline subroutine's abstract instance tree.
2) the inline expansion(s) of the nested inline subroutine would be
considered part of their own concrete instance
tree(s) and also part of
the outer inline subroutine's concrete instance tree.
This problem cannot be solved by insisting that the abstract instance tree
for the outer inline subroutine contain appropriate abstract instance entries
for each nested inline expansion, either. This is because, from concrete
instance to concrete instance of the outer inline subroutine, the nested
inline subroutine might be expanded inline or called out-of-line, as the
compiler chose (or even as the user chosen, via optimization options).
I propose that the definition of an abstract instance tree be changed
slightly to exclude any abstract instance trees nested within it. Likewise,
the definition of a concrete instance tree should be changed to exclude any
concrete instance trees nested within it. I suspect this was the intent from
the start, so you may just want to think of this as a clarification.
(Also see Issue #5 below, which elaborates on this more.)
Issue #2:
The set of attributes listed in 3.3.8.1 to be excluded from an abstract
instance tree, and the same set in parentheses in 3.3.8.2 are too C-centric.
They don't take into account additional concrete-instance-dependent
attributes that might be added by new languages and/or vendors. I propose
making the text more vague and changing the sets into suggested lists for
C-like languages. Arguably, this is just a clarification, too.
Issue #3:
The rules that there be a one-to-one correspondence between entries in
concrete and abstract instance trees are unnecessarily restrictive, and the
exceptions presented _also_ are unnecessarily restrictive.
Basically, the exceptions presented are too C-centric. For example, in Ada,
it may be _necessary_ to describe an anonymous type in a concrete instance
tree because some aspect of its description depends on aspects of each
distinct concrete instance. Actually, come to think of it, I expect this
applies to C99's dynamically bounded arrays, too!
There are other cases, too. For instance, an anonymous type in a concrete
instance might contain no attributes (other than DW_AT_abstract_origin), but
still be necessary as a parent for some other debugging information entry
that does contain concrete-instance-dependent attributes.
In Ada, there will be other cases than those mentioned where a debugging
information entry in a concrete instance tree would contain no attributes
(other than DW_AT_abstract_origin). I see no point in describing such
entities.
So, I propose eliminating the exceptions as stated, and replacing them with
the permission (but not even the requirement) to omit any debugging
information entry from a concrete instance tree if it would contain no
attributes (other than DW_AT_abstract_origin) and no children. That should
be sufficiently vague as to be useful for any language, and should cover the
explicit exceptions from the DWARF 2.0.0 document, at least for C-like
languages. We could retain the explicit exceptions listed there as
suggestions for things to be omitted in C-like languages.
Issue #3b:
Furthermore, I would like to loosen the restriction on one-to-one
correspondence between concrete and abstract instance trees to allow a
concrete instance tree to omit a debugging information entry if that
debugging information entry becomes useless in the concrete instance.
For example, an anonymous variable object might be created in the abstract
instance tree to describe the upper bound of an array. In a particular
concrete instance, it might happen that the upper bound of the array is a
constant, and so it is described with a constant FORM on the array, instead
of the reference FORM that the abstract tree was expecting. There's really
no useful way to "finish" the description of that anonymous variable entry,
since it doesn't really exist in that inline expansion. Furthermore, no one
will really care about it, since it's anonymous and never referenced. So, I
propose that the concrete instance tree be allowed to omit that debugging
information entry, as well.
Issue #4:
It is useful for a concrete instance tree to create new debugging information
entries that were not contained in the abstract instance tree. This is true
in cases where there is no way to know, when generating the abstract instance
tree, that a given entity will be needed, say, as part of the description of
another entity that was in both the abstract and concrete instance trees.
This issue is a counterpart to Issue #3b. For instance, it allows an
abstract instance tree to omit an anonymous variable created to hold the
bound of an array if it expects the bound usually will be static. In any
inline expansion where that expectation wasn't met, the debugging information
entry for the anonymous variable could be created on-the-fly.
Issue #5:
I think the DWARF 2.0.0 document is unclear on how to describe inline
subroutines that contain nested subroutines. To clarify, I am not talking
about concrete instances nested within other concrete instances, but rather
about inline subroutines that contain other subroutines, such that from the
nested subroutines ones could up-level reference variables from the outer
inline subroutine.
In the case where the nested subroutine isn't inline, then arguably it's
straightforward how to describe them. Still, I propose to add text to
clarify the issue and also to act as contrast the following text.
In the case where the nested subroutine is inline, it isn't clear whether or
not the abstract instance tree for the nested subroutine should be reiterated
in the concrete instance tree for the outer subroutine. We believe it will
include no new useful information, so applying the conclusion from Issue #3,
we think there is no point in reiterating it there.
Likewise, it isn't clear whether or not the abstract instance tree must
contain abstract concrete instance trees for any inline expansions that occur
for nested subroutines. We think there is no useful information that would
be emitted there, either, so think they should be omitted. (In such a case,
all the useful information would be in the concrete instance tree for the
nested subroutine within the concrete instance tree for the outer subroutine.)
This is an application of the proposal for Issue #1.
If the nested subroutine's abstract instance was reiterated in the outer
subroutine's concrete instances, or the nested subroutine's concrete
instances were required to be present in the outer subroutine's abstract
instance, this could create nasty chains of DW_AT_abstract_origin attributes.
And if both existed, it would be unclear which of them should be referenced
by the DW_AT_abstract_origin attribute in the nested subroutine's concrete
instances in the outer subroutine's concrete instances. Thinking about that
makes my brain hurt. This is yet another reason for disallowing any
debugging information entry from being in more than one abstract or concrete
instance tree (see Issue #1).
WORDING CHANGES:
3.3.8.1
:
Any subroutine that contains a DW_AT_inline attribute will be known as
an
"abstract instance root". Any set of abstract instance
entries that are
all children (either directly or indirectly) of some abstract instance
root, together with the root itself, will be known as an "abstract
| instance tree". However, in the case where an abstract instance tree is
| nested within another abstract instance tree, the entries in the nested
| abstract instance tree are not considered to be entries in the outer
| abstract instance tree.
A debugging information entry that is a member of an abstract instance
| tree should not contain any attributes which describe aspects of the
| subroutine which would vary between distinct inline expansions or distinct
| out-of-line expansions. For example, the DW_AT_low_pc, DW_AT_high_pc,
| DW_AT_ranges, DW_AT_entry_pc, DW_AT_location, DW_AT_return_addr,
| DW_AT_start_scope, and DW_AT_segment attributes probably will need to be
| omitted, but that list is not exhaustive.
:
3.3.8.2
:
For the remainder of this discussion, any debugging information entry
that
is owned (either directly or indirectly) by a debugging information
entry
with the tag DW_TAG_inlined_subroutine will be referred to as a
concrete
| inlined instance entry. However, in the case where a concrete instance
| tree is nested within another concrete instance tree, the entries in the
| nested concrete instance tree are not considered to be entries in the
| outer concrete instance tree.
:
| Concrete inlined instance entries may omit most of the attributes (except
| for any that were omitted from the abstract instance entries because they
| would vary between concrete inlined instances), that such entries would
| otherwise normally have. In place of these omitted attributes, the
concrete inlined instance entry has a DW_AT_abstract_origin attribute
that
may be used to obtain the missing information (indirectly) from the
associated abstract instance entry. The value of the abstract origin
attribute is a reference to the associated abstract instance entry.
:
For each pair of entries that are associated via a
DW_AT_abstract_origin
attribute, both members of the pair will have the same tag. So, for
example, an entry with the tag DW_TAG_variable can only be associated
with
another entry that also has the tag DW_TAG_variable. The only exception
to this rule is that the root of a concrete instance tree (which must
always have the tag DW_TAG_inlined_subroutine) can only be associated
with
the root of its associated abstract instance tree (which must have the
tag
DW_TAG_subprogram).
| The structure and content of any given concrete instance tree will be
| generally analogous to the structure and content of its associated
| abstract instance tree. There are a few exceptions:
|
| 1. Entries in the concrete instance tree which would contain only
| DW_AT_abstract_origin attributes and which would
have no children
| may be omitted, because they would provide no
useful information.
| In C-like languages, such entries frequently
include those for
| anonymous types, and members of structure, union,
or class types.
| If any entry within a concrete inlined instance
tree needs to refer
| to an entity declared within the scope of the
relevant inline
| subroutine and for which no concrete instance entry
exists, the
| reference should simply refer to the abstract
instance entry.
|
| 2. Entries in the concrete instance tree which are associated with
| entries in the abstract instance tree such that
neither has a
| DW_AT_name attribute, and neither is referenced by
any other
| debugging information entry may be omitted. This
may happen for
| debugging information entries in the abstract
instance trees that
| became unnecessary in the concrete instance tree
because of
| additional information available there. For
example, an anonymous
| variable might have been created and described in
the abstract
| instance tree, but because of the actual parameters
for a particular
| inline expansion, it could be described as a
constant value without
| the need for that separate debugging information
entry.
|
| 3. A concrete instance tree may contain entries which do not
correspond
| to entries in the abstract instance tree to
describe new entities
| that are specific to a particular inline expansion.
In that case,
| they will not have associated entries in the
abstract instance tree,
| should not contain DW_AT_abstract_origin
attributes, and must
| contain all their own attributes directly. This
allows an abstract
| instance tree to omit debugging information entries
for anonymous
| entities if the implementation believes they are
unlikely to be
| needed in most inline expansions. In any expansion
which deviates
| from that expectation, the entries can be described
in its concrete
| instance tree.
If an entry within a concrete inlined instance tree contains attributes
describing the declaration coordinates of that entry, then those
attributes should refer to the file, line and column of the original
declaration of the subroutine, not to the point at which it was
inlined.
:
| 3.3.8.4 Nested Inline Subroutines
|
| Some languages and compilers may permit the logical nesting of a
| subroutine within another subroutine, and may permit either the outer or
| the nested subroutine, or both to be inline.
|
| For a non-inline subroutine nested within an inline subroutine, the nested
| subroutine is described normally in both the abstract and concrete inlined
| instance trees for the outer subroutine. All rules pertaining to the
| abstract and concrete instance trees for the outer subroutine apply also
| to the abstract and concrete instance entries for the nested subroutine.
|
| For an inline subroutine nested within another inlined subroutine, the
| following rules apply to their abstract and concrete instance trees:
|
| 1. The abstract instance tree for the nested subroutine is described
| within the abstract instance tree for the outer
subroutine according
| to the rules in section 3.3.8.1, and without regard
to the fact that
| it is within an outer abstract instance tree.
| 2. No abstract instance tree for a nested subroutine is described
| within the concrete instance tree for an outer
subroutine.
| 3. No concrete instance tree for a nested subroutine is described
| within the abstract instance tree for an outer
subroutine.
| 4. The concrete instance tree for any inline or out-of-line expansion
| of the nested subroutine is described within a
concrete instance
| tree for the outer subroutine according to the
rules in 3.3.8.2 or
| 3.3.8.3, and without regard to the fact that it is
within an
| outer concrete instance tree.
Adopted with editorial changes: clarify intent; clarify 3.3.8.2 items 1, 2, 3; add example.