Bootstrap failure of gcc-ss-20010409 in ia64

Jim Wilson wilson@cygnus.com
Mon Apr 16 15:39:00 GMT 2001


>a) We generate a M_refcopy function that contains a __exception_info variable.
>   We inline this into another function, generating an exception_info var
>   with an abstract origin pointing back to us.  We then optimize and emit
>   M_refcopy, and in the process of doing so, the block tree is modified such
>   that the exception_info variable no longer exists.  We then later try to
>   emit debug info for the inlinee, and we find a decl whose abstract origin
>   no longer exists.  This problem does not exist with the RTL inliner, because
>   we make a copy of the inline function before optimizing and emitting it,
>   and hence all abstract origin pointers back to us remain valid.

I have now verified that this is true.

When we get to M_refcopy, the C++ front end generates an AST which is saved
in DECL_SAVED_TREE.  This contains an __exception_info variable.  We then
generate BLOCK trees and RTL from the AST, putting the block trees in
DECL_INITIAL.  At this point, the block trees contain an __exception_info
variable.  We then optimize and emit the M_refcopy function.  The optimizer
function reorder_basic_blocks massages the RTL and block tree.  At this
point, there is no longer any __exception_info variable.  We then emit
assembly language and debug info for M_refcopy.

Later, we inline the M_refcopy function into the M_grab function.  The
tree inliner in the C++ front end uses the DECL_SAVED_TREE for this.
The DECL_SAVED_TREE still contains references to an __exception_info
variable, so we end up with one inlined into M_grab, whose abstract origin
points back to M_refcopy.  When we later emit debug info for M_grab (actually
in my case, another function that M_grab was inlined into), we follow the
abstract origin pointer back to M_refcopy, but there is no __exception_info
variable in M_refcopy, and we abort.

So the problem here is that a function only has one block tree, but we
really need two, one for the abstract instance, and one for the concrete
out-of-line instance (to use dwarf2 terminology).

This wasn't a problem with the older RTL inliner for a couple of reasons
that I can see.  Firstly, we only had one representation for a function,
the block trees and the RTL.  If we optimized a function, and then later
used the optimized block tree/RTL for inlining, then everything remains
consistent.  Now however we have two representations for a function, the
AST in DECL_SAVED_TREE, and the block tree/RTL.  After optimization, these
are no longer consistent with each other.  Secondly, the RTL inliner would
make copies of the block tree before optimizing a function in some instance,
and this ensured that the original abstract instance block trees survived
for use by the debug output routines.

I see of couple of different ways to fix this.  We could try to make the
dwarf2out.c file use the DECL_SAVED_TREE instead of the block tree when
emitting debug info for an abstract instance.  This info is not in the
form that we want it, and hence this will require writing a bit of code.
Another possible solution is to modify the FUNCTION_DECL tree to have
two block trees, the original one created by the front ends, and an optimized
one.  When emitting debug info for an abstract instance, we use the original
block tree.  When emitting debug info for a concrete out-of-line instance,
we use the optimized block tree.  Both of these solutions will require
writing some non-trivial code and then debugging and testing it.

Possible simpler solutions, which may not be desirable, are turning the
RTL inliner back on, and disabling optimization passes that can delete blocks
from the block tree (e.g. -freorder-blocks).

Jim



More information about the Gcc mailing list