[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

[Bug middle-end/14711] [3.3 regression] ICE in final.c:2117 when compiling a huge source file



------- Additional Comments From roger at eyesopen dot com  2004-04-04 20:54 -------
I believe that the 2^31 limit is a reasonable hard limit caused by the way
that GCC internally maintains line numbers, for example, in scan.h, we use
"extern int lineno".  It looks like these line numbers must be signed, as
negative values are used as "rogue" values in REG_NOTES, and also occassionally,
but perhaps not intentionally during normal compilation [a gdb watch on
"lineno" reveals it holds the value -70 temporarily during a typical compile].

The 2^19 limit is caused by GCC's representation/encoding of the tree node
EXPR_WITH_FILE_LOCATION.  The EXPR_WFL_LINECOL stores a line and column
number in a single 32-bit integer, "complexity", using the bottom 12 bits for
the column position, and the top 20 bits for the line number.

In the C++ testcase, the line number is temporarily saved/restored during C++
template parsing by push_tinset_level/pop_tinst_level which maintains a stack
of file locations, using a linked list of EXPR_WITH_FILE_LOCATION tree nodes,
current_tinst_level.

Because EXPR_WFL_LINENO uses a right shift of a signed field to extract the
top 20 bits back out of the EXPR_WFL_LINECOL, on many (but not all!) machines
we return a negative value if the msb is set, i.e. the value was greater than
2^19.  This negative value is what eventually causes the ICE in final.c.

The EXPR_WFL_LINECOL representation is unchanged on mainline and in 3.4, so
this problem still exists in current CVS, but is just latent due to other
changes, not to removing the 2^19 line restriction.

Possible solutions include:
[1] Using an unsigned right shift, i.e. (int)((unsigned int)x >> 12), to
extract the top twenty bits for EXPR_WFL_LINECOL.  This requires that we
never need to represent negative values in EXPR_WFL_LINECOL.  The negative
values of the global "lineno" make this fix non-obvious.  It would however
avoid the final.c ICE caused by negative line numbers, and simply truncate
the lineno field, wrapping around a 2^20 relatively harmlessly, except for
debugging information.

[2] Change the division of bits in EXPR_WFL_LINECOL, so that we use less
than 12 bits for column, and more than 20 bits for line number.  This is
a less than ideal work-around.

[3] Change the representation of current_tinst_level to avoid problematic
use of EXPR_WITH_FILE_LOCATION.  A linked list of location structs would
allow more accurate representation/recovery of these fields and probably
save space, avoiding all the unneeded common tree bits.  This wouldn't help
other uses of the EXPR_WITH_FILE_LOCATION though.

[4] Expand EXPR_WITH_FILE_LOCATION's tree node so that it can store a full
integer for line number, perhaps combining column with other fields or just
increasing the size of this node.  I'm a bit confused why its using the
"complexity" field at the moment, and just as confused why we have a complexity
field, why the C front end is using it for C_EXP_ORIGINAL_CODE, and why the
f77 front-end that doesn't even set/use C_EXP_ORIGINAL_CODE tests for it!!

[5] Defensively tweak the middle-end to avoid creating line number notes when
current "lineno < 0".  This would avoid unintentionally creating invalid NOTES,
but again would be papering over the problem, and may cause problems if we
later rely on finding these notes in the insn stream.

I'm currently investigating why lineno is ever negative...


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=14711

------- You are receiving this mail because: -------
You reported the bug, or are watching the reporter.



Reply to: