Using the code in PR 12850 at -O0, I get a seg fault on the mainline. I think this is a recent regression but I don't know for sure.
Reduced down to: __extension__ typedef unsigned long long int uint64_t; template<class _CharT> struct char_traits; template<typename _CharT, typename _Traits = char_traits<_CharT> > class basic_ostream; typedef basic_ostream<char> ostream; template<typename _CharT, typename _Traits> struct basic_ostream { typedef basic_ostream<_CharT, _Traits> __ostream_type; __ostream_type& operator<<(long long __n); __ostream_type& operator<<(unsigned long long __n); }; extern ostream cout; template<class IntType> struct linear_congruential { template<class CharT, class Traits> friend basic_ostream<CharT,Traits>& operator<<(basic_ostream<CharT,Traits>& os, const linear_congruential& lcg) { return os << lcg._x; } private: uint64_t _x; }; void instantiate_all() { linear_congruential<uint64_t> lcf; uint64_t _x; cout << lcf; }
Reduced a little further, note removing the templates make it go away: template<typename _CharT> struct basic_ostream { basic_ostream& operator<<(int __n); }; extern basic_ostream<char> cout; template<int> struct linear_congruential { template<class CharT> friend basic_ostream<CharT>& operator<<(basic_ostream<CharT>& os, const linear_congruential& lcg) { return os << 1; } }; void instantiate_all() { linear_congruential<0> lcf; cout << lcf; } ------ Here is the back trace: #0 0x002723cc in block_alloc (b=0) at /Users/pinskia/src/local3/gcc/gcc/local-alloc.c:1629 #1 0x002720b8 in block_alloc (b=0) at /Users/pinskia/src/local3/gcc/gcc/local-alloc.c:1598 #2 0x002731a4 in local_alloc () at /Users/pinskia/src/local3/gcc/gcc/local-alloc.c:420 #3 0x0030bdb0 in rest_of_compilation () at /Users/pinskia/src/local3/gcc/gcc/passes.c:492 #4 0x000d3a54 in execute_pass_list (pass=0x40574eb8) at /Users/pinskia/src/local3/gcc/gcc/tree- optimize.c:512 #5 0x000d3d48 in tree_rest_of_compilation (fndecl=0x4160146c) at /Users/pinskia/src/local3/gcc/ gcc/tree-optimize.c:648 #6 0x0007e984 in expand_body (fn=0x4160146c) at /Users/pinskia/src/local3/gcc/gcc/cp/ semantics.c:2895 #7 0x00331244 in cgraph_expand_function (node=0x424bdc80) at /Users/pinskia/src/local3/gcc/ gcc/cgraphunit.c:822 #8 0x00331e34 in cgraph_optimize () at /Users/pinskia/src/local3/gcc/gcc/cgraphunit.c:1689 #9 0x00047d50 in cp_finish_file () at /Users/pinskia/src/local3/gcc/gcc/cp/decl2.c:3070 #10 0x000bb42c in c_common_parse_file (set_yydebug=3) at /Users/pinskia/src/local3/gcc/gcc/c- opts.c:1093 #11 0x002ec6ec in toplev_main (argc=1112267904, argv=0x0) at /Users/pinskia/src/local3/gcc/gcc/ toplev.c:992 #12 0x000028e4 in _start (argc=1, argv=0x41600d00, envp=0x424bd880) at /SourceCache/Csu/Csu -47/crt.c:267 #13 0x8fe1a558 in __dyld__dyld_start ()
Hmm, adding either -da, -fdump-tree-all, or -fdump-rtl-all, works.
We are seg faulting at: 1629 reg_renumber[i] = qty[q].phys_reg + reg_offset[i]; reg_renumber is null at this point.
Note without this fixed, I cannot help fix 12850 as I have to compile at -O1.
This is perhaps the most bizarre interaction I've yet come across in GCC. Under normal operation, reg_renumber is zero prior to register allocation, then in rest_of_handle_old_regalloc, allocate_reg_info is called to allocate per-pseudo information, which is used two or three function calls later by local_alloc (and should remain valid for the remainder of the function's compilation). Unfortunately, between allocate_reg_info and local_alloc we call "regclass" which in this test case, unintentionally resets reg_renumber to zero! The incomplete and abridged call stack is reg_class -> scan_one_insn -> extract_insn -> recog_23 -> current_file_function_operand -> make_decl_rtl -> decl_assembler_name -> mangle_decl -> write_mangled_name -> write_encoding -> get_mostly_instantiated_function_type -> pop_access_scope -> pop_from_top_level -> pop_context_function_from. In the middle of pop_context_function_from is the line "reg_renumber = 0"! This problem is either a (i) middle-end issue, (ii) an rs6000 backend issue, or (iii) a C++ front-end issue. (i) I don't think that pop_context_function_from should (or needs to) reset reg_renumber to zero. I would hope that with cgraph, there is only ever a single function being expanded to RTL at a time, so reg_renumber can be left as is. Certainly, if we're not saving the value of reg_renumber (and the arrays contents) in push_function_context_to, then we shouldn't attempt to restore it afterwards. I'm currently testing this fix. (ii) This interaction can also be avoided if the rs6000's function current_file_function_operand used DECL_RTL_SET_P to test whether an identifier is local to a function prior to checking the result of DECL_RTL. This avoids the invocation of make_decl_rtl. Presumably, if we don't know the assembler name for this function, we can't be calling it :) [I'll test this fix next]. (iii) The problem might well be in the C++ front-end and its interaction with cgraph. It's unclear whether DECL_RTL should already have been set on current_function_decl prior to this point in rest_of_compilation. Clearly, this only appears to happen for C++ templates, so the rs6000 backend is perhaps reasonable in assuming DECL_RTL has been set by this point. The above analysis also explains why enabling various tree dumps resolves the segmentation fault, as we end up calling/caching decl_assembler_name for the current function before reaching local register allocation (avoiding this particular interaction). This is probably fall-out from the recent cgraph/varasm reorganizations that attempt to avoid calling decl_assembler_name until as late as physically possible. Calling it for the first time before or after local alloc probably works fine, calling it during (as is done on rs6000 targets) has unanticipated side-effects.
Subject: Bug 18683 CVSROOT: /cvs/gcc Module name: gcc Changes by: sayle@gcc.gnu.org 2004-12-21 01:37:35 Modified files: gcc : ChangeLog function.c gcc/testsuite : ChangeLog Added files: gcc/testsuite/g++.dg/opt: pr18683-1.C Log message: PR middle-end/18683 * function.c (pop_function_context_from): Don't reset reg_renumber. * g++.dg/opt/pr18683-1.C: New test case. Patches: http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/ChangeLog.diff?cvsroot=gcc&r1=2.6904&r2=2.6905 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/function.c.diff?cvsroot=gcc&r1=1.593&r2=1.594 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/ChangeLog.diff?cvsroot=gcc&r1=1.4787&r2=1.4788 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/g++.dg/opt/pr18683-1.C.diff?cvsroot=gcc&r1=NONE&r2=1.1
Subject: Bug 18683 CVSROOT: /cvs/gcc Module name: gcc Changes by: sayle@gcc.gnu.org 2004-12-21 03:18:51 Modified files: gcc : ChangeLog gcc/config/rs6000: rs6000.c Log message: PR middle-end/18683 * config/rs6000/rs6000.c (current_file_function_operand): Only check current_function_decl's DECL_RTL if it has already been set. Patches: http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/ChangeLog.diff?cvsroot=gcc&r1=2.6905&r2=2.6906 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/config/rs6000/rs6000.c.diff?cvsroot=gcc&r1=1.765&r2=1.766
Fixed, thanks Roger.