From mboxrd@z Thu Jan 1 00:00:00 1970 From: Jim Wilson To: Mark Mitchell Cc: gcc@gcc.gnu.org Subject: Re: Bootstrap failure of gcc-ss-20010409 in ia64 Date: Mon, 16 Apr 2001 15:39:00 -0000 Message-id: <200104162239.PAA13601@wilson.cygnus.com> References: <200104140901.CAA05718@wilson.cygnus.com> X-SW-Source: 2001-04/msg00739.html >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