This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

[PATCH] ICE with builtin __complex__ types



hi -

The following input gives an ICE from cc1plus (from both the head cvs
version from a couple days ago and the 2.95 branch) on an i686-pc-linux-gnu
platform:


--------------------------------------------------------------
struct Complex8
{
  __complex__ double x;
};

void bar (const Complex8&);

void fpp (  ) 
{
  bar (Complex8 ());
}
--------------------------------------------------------------

$ cc1plus x.cc
 void fpp ()
x.cc:10: Internal compiler error.
x.cc:10: Please submit a full bug report.
x.cc:10: See <URL:http://www.gnu.org/software/gcc/faq.html#bugreport> for instructions.

Here's where the crash is occuring:

Program received signal SIGSEGV, Segmentation fault.
0x8064cf9 in put_reg_into_stack (function=0x0, reg=0x40118ff0, type=0x0, 
    promoted_mode=DFmode, decl_mode=DFmode, volatile_p=0, original_regno=0, 
    used_p=1, ht=0x0) at ../../src/gcc/function.c:1391
1391	  MEM_SET_IN_STRUCT_P (reg,
(gdb) list
1386	  /* If this is a memory ref that contains aggregate components,
1387	     mark it as such for cse and loop optimize.  If we are reusing a
1388	     previously generated stack slot, then we need to copy the bit in
1389	     case it was set for other reasons.  For instance, it is set for
1390	     __builtin_va_alist.  */
1391	  MEM_SET_IN_STRUCT_P (reg,
1392			       AGGREGATE_TYPE_P (type) || MEM_IN_STRUCT_P (new));
1393	  MEM_ALIAS_SET (reg) = get_alias_set (type);
1394	
1395	  /* Now make sure that all refs to the variable, previously made
(gdb) where
#0  0x8064cf9 in put_reg_into_stack (function=0x0, reg=0x40118ff0, type=0x0, 
    promoted_mode=DFmode, decl_mode=DFmode, volatile_p=0, original_regno=0, 
    used_p=1, ht=0x0) at ../../src/gcc/function.c:1391
#1  0x8064b87 in put_var_into_stack (decl=0x4011c800)
    at ../../src/gcc/function.c:1306
#2  0x8236fe2 in mark_addressable (exp=0x4011c800)
    at ../../../src/gcc/cp/typeck.c:5012
#3  0x8080e3b in expand_expr (exp=0x4011d2c0, target=0x4011e000, 
    tmode=VOIDmode, modifier=EXPAND_CONST_ADDRESS) at ../../src/gcc/expr.c:7869
#4  0x80811f8 in expand_expr (exp=0x4011d460, target=0x0, tmode=VOIDmode, 
    modifier=EXPAND_NORMAL) at ../../src/gcc/expr.c:8054
#5  0x807f1b2 in expand_expr (exp=0x4011d4c0, target=0x0, tmode=VOIDmode, 
    modifier=EXPAND_NORMAL) at ../../src/gcc/expr.c:6917
#6  0x807f1b2 in expand_expr (exp=0x4011d4e0, target=0x0, tmode=VOIDmode, 
    modifier=EXPAND_NORMAL) at ../../src/gcc/expr.c:6917
#7  0x8086d08 in store_one_arg (arg=0xbfffefa0, argblock=0x0, may_be_alloca=0, 
    variable_size=0, reg_parm_stack_space=0) at ../../src/gcc/calls.c:3830
#8  0x80859f8 in expand_call (exp=0x4011d520, target=0x0, ignore=1)
    at ../../src/gcc/calls.c:2232
#9  0x807f098 in expand_expr (exp=0x4011d520, target=0x0, tmode=VOIDmode, 
    modifier=EXPAND_NORMAL) at ../../src/gcc/expr.c:6879
#10 0x806d59b in expand_expr_stmt (exp=0x4011d520) at ../../src/gcc/stmt.c:1856
#11 0x81fe29b in cplus_expand_expr_stmt (exp=0x4011d520)
    at ../../../src/gcc/cp/decl.c:14166
#12 0x824b7dd in finish_expr_stmt (expr=0x4011d520)
    at ../../../src/gcc/cp/semantics.c:144
#13 0x824e7ac in expand_stmt (t=0x40118ec0)
    at ../../../src/gcc/cp/semantics.c:2302
#14 0x824ea0e in expand_stmt (t=0x4011d0a0)
    at ../../../src/gcc/cp/semantics.c:2396
#15 0x824ed4c in expand_body (fn=0x4011c580)
    at ../../../src/gcc/cp/semantics.c:2553
#16 0x82280e0 in yyparse () at parse.y:662
#17 0x804b366 in compile_file (name=0xbffffd4b "x.cc")
    at ../../src/gcc/toplev.c:3200
#18 0x804e8c9 in main (argc=2, argv=0xbffffc04) at ../../src/gcc/toplev.c:5555


It's dying at the statement

  MEM_SET_IN_STRUCT_P (reg,
		       AGGREGATE_TYPE_P (type) || MEM_IN_STRUCT_P (new));

because `type' is a null pointer.

Where does `type' come from?  The next level up (put_var_into_stack)
gets it from

  else if (GET_CODE (reg) == CONCAT)
    {
      /* A CONCAT contains two pseudos; put them both in the stack.
	 We do it so they end up consecutive.  */
      enum machine_mode part_mode = GET_MODE (XEXP (reg, 0));
      tree part_type = TREE_TYPE (TREE_TYPE (decl));
#ifdef FRAME_GROWS_DOWNWARD
      /* Since part 0 should have a lower address, do it second.  */
      put_reg_into_stack (function, XEXP (reg, 1), part_type, part_mode,
			  part_mode, TREE_SIDE_EFFECTS (decl), 0,
			  TREE_USED (decl) || DECL_INITIAL (decl) != 0,
			  0);

Here, `part_type' is passed to put_reg_into_stack as type. It is 0;
`decl' is

 <var_decl 0x4011c800
    type <record_type 0x40114880 Complex8
        permanent type_1 type_5 DC
        size <integer_cst 0x40115c80 constant permanent 128>
        align 32 symtab 0 alias set -1
        fields <field_decl 0x40114a80 x type <complex_type 0x4010b000 complex double>
           
            permanent nonlocal decl_3 DC file x.cc line 3
            size <integer_cst 0x401097a0 constant permanent 128>
            align 32
            bitpos <integer_cst 0x40115be0 constant permanent 0> context <record_type 0x40114880 Complex8> arguments <integer_cst 0x40115be0 0> chain <type_decl 0x40114a00 Complex8>>
        X() X(constX&) this=(X&) n_parents 0 use_template=0 interface-unknown vtable-needs-writing
        member-functions <tree_vec 0x4011b3c0
            permanent
            elt 0 <overload 0x40118e90>
            elt 2 <function_decl 0x4011c280 __as>>
        pointer_to_this <pointer_type 0x40114900> reference_to_this <reference_type 0x4011c080> chain <type_decl 0x40114980 Complex8>>
   
    addressable used DC file x.cc line 10 size <integer_cst 0x40115c80 128>
    align 32
    (concat:DC (reg:DF 24)
    (reg:DF 25))>


`reg' is shown at the tail end of this dump; it is a concat expression
with DC mode.

What seems to be happening here is this.
The code here in put_var_into_stack expects types with a CONCAT rtx,
such as the complex types, to have in their TREE_TYPE field the type
of each half of the concat.  This is indeed the case for complex types.
But it is not the case for record types, such as we're dealing with
here.  But the record type is being treated as a complex number when
the rtx for it is generated, because it has DC mode.  This is due
to an optimization in stor-layout.c (layout_type), which promotes the
mode of a record containing a single field from BLK to the mode of the
field.  So i tried to fix this by changing that code so that if it
did that for a complex field, it would also copy the TREE_TYPE field
from the field's type to the record type's TREE_TYPE:


Tue Oct 26 19:02:44 1999  scott snyder  <snyder@fnal.gov>

	* stor-layout.c (layout_type): For complex number types, the type
	field of the type is expected to be the numeric type of the
	complex.

--- stor-layout.c-orig	Thu Oct 28 18:38:33 1999
+++ stor-layout.c	Thu Oct 28 18:38:53 1999
@@ -966,6 +966,12 @@
 		 register instead of forcing it to live in the stack.  */
 	      if (simple_cst_equal (TYPE_SIZE (type), DECL_SIZE (field)))
 		mode = DECL_MODE (field);
+              /* For complex number types, the type field of the type
+                 is expected to be the numeric type of the complex. */
+              if (COMPLEX_MODE_P (mode))
+                {
+                  TREE_TYPE (type) = TREE_TYPE (TREE_TYPE (field));
+                }
 	    }
 
 	  if (mode != VOIDmode)


With this change, the compiler gets further on the example, but it then
crashes with another null pointer reference in a different place:


#0  protect_from_queue (x=0x0, modify=0) at ../../src/gcc/expr.c:361
#1  0x8078c4b in emit_move_insn (x=0x4011e000, y=0x0)
    at ../../src/gcc/expr.c:2541
#2  0x8078c0b in clear_storage (object=0x4011e000, size=0x40018498, align=4)
    at ../../src/gcc/expr.c:2522
#3  0x807b280 in store_constructor (exp=0x4011d2a0, target=0x4011e000, 
    align=32, cleared=0) at ../../src/gcc/expr.c:4106
#4  0x807e026 in expand_expr (exp=0x4011d2a0, target=0x4011e000, tmode=DCmode, 
    modifier=EXPAND_NORMAL) at ../../src/gcc/expr.c:6266
#5  0x807a99e in store_expr (exp=0x4011d2a0, target=0x4011e000, want_value=0)
    at ../../src/gcc/expr.c:3727
#6  0x8080f22 in expand_expr (exp=0x4011d2c0, target=0x4011e000, 
    tmode=VOIDmode, modifier=EXPAND_CONST_ADDRESS) at ../../src/gcc/expr.c:7919
#7  0x8081248 in expand_expr (exp=0x4011d460, target=0x0, tmode=VOIDmode, 
    modifier=EXPAND_NORMAL) at ../../src/gcc/expr.c:8054
#8  0x807f202 in expand_expr (exp=0x4011d4c0, target=0x0, tmode=VOIDmode, 
    modifier=EXPAND_NORMAL) at ../../src/gcc/expr.c:6917
#9  0x807f202 in expand_expr (exp=0x4011d4e0, target=0x0, tmode=VOIDmode, 
    modifier=EXPAND_NORMAL) at ../../src/gcc/expr.c:6917
#10 0x8086d58 in store_one_arg (arg=0xbfffefa0, argblock=0x0, may_be_alloca=0, 
    variable_size=0, reg_parm_stack_space=0) at ../../src/gcc/calls.c:3830
#11 0x8085a48 in expand_call (exp=0x4011d520, target=0x0, ignore=1)
    at ../../src/gcc/calls.c:2232
#12 0x807f0e8 in expand_expr (exp=0x4011d520, target=0x0, tmode=VOIDmode, 
    modifier=EXPAND_NORMAL) at ../../src/gcc/expr.c:6879
#13 0x806d5eb in expand_expr_stmt (exp=0x4011d520) at ../../src/gcc/stmt.c:1856
#14 0x81fe2eb in cplus_expand_expr_stmt (exp=0x4011d520)
    at ../../../src/gcc/cp/decl.c:14166
#15 0x824b82d in finish_expr_stmt (expr=0x4011d520)
    at ../../../src/gcc/cp/semantics.c:144
#16 0x824e7fc in expand_stmt (t=0x40118ec0)
    at ../../../src/gcc/cp/semantics.c:2302
#17 0x824ea5e in expand_stmt (t=0x4011d0a0)
    at ../../../src/gcc/cp/semantics.c:2396
#18 0x824ed9c in expand_body (fn=0x4011c580)
    at ../../../src/gcc/cp/semantics.c:2553
#19 0x8228130 in yyparse () at parse.y:662
#20 0x804b366 in compile_file (name=0xbffffd4b "x.cc")
    at ../../src/gcc/toplev.c:3200
#21 0x804e8c9 in main (argc=2, argv=0xbffffc04) at ../../src/gcc/toplev.c:5555


The problem arises in clear_storage:

#2  0x8078c0b in clear_storage (object=0x4011e000, size=0x40018498, align=4)
    at ../../src/gcc/expr.c:2522
2522	    emit_move_insn (object, CONST0_RTX (GET_MODE (object)));

(gdb) call debug_rtx(object)
(mem:DC (plus:SI (reg:SI 20 virtual-stack-vars)
        (const_int -16 [0xfffffff0])) 0)

Here, the mode of object is DC, but there is no CONST0_RTX available
for DCmode --- it's a null pointer.

So, i tried to fix this by providing CONST0_RTX's for the complex
modes:

Tue Oct 26 19:02:44 1999  scott snyder  <snyder@fnal.gov>

	* emit-rtl.c (init_emit_once): Fill in a 0 rtx for complex types.

--- emit-rtl.c-orig	Thu Oct 28 18:45:51 1999
+++ emit-rtl.c	Thu Oct 28 18:46:09 1999
@@ -3800,6 +3800,42 @@
     if (GET_MODE_CLASS (mode) == MODE_CC)
       const_tiny_rtx[0][(int) mode] = const0_rtx;
 
+  /* fill in a 0 rtx for complex types */
+  for (mode = GET_CLASS_NARROWEST_MODE (MODE_COMPLEX_INT); mode != VOIDmode;
+       mode = GET_MODE_WIDER_MODE (mode))
+    {
+      enum machine_mode realmode;
+      for (realmode = GET_CLASS_NARROWEST_MODE (MODE_INT);
+           realmode != VOIDmode;
+           realmode = GET_MODE_WIDER_MODE (realmode))
+        {
+          if (GET_MODE_SIZE (realmode) == GET_MODE_UNIT_SIZE (mode))
+            break;
+        }
+      if (realmode != VOIDmode)
+        const_tiny_rtx[0][(int) mode]
+          = gen_rtx_CONCAT (mode,
+                            const_tiny_rtx[0][(int)realmode],
+                            const_tiny_rtx[0][(int)realmode]);
+    }
+
+  for (mode = GET_CLASS_NARROWEST_MODE (MODE_COMPLEX_FLOAT); mode != VOIDmode;
+       mode = GET_MODE_WIDER_MODE (mode))
+    {
+      enum machine_mode realmode;
+      for (realmode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT);
+           realmode != VOIDmode;
+           realmode = GET_MODE_WIDER_MODE (realmode))
+        {
+          if (GET_MODE_SIZE (realmode) == GET_MODE_UNIT_SIZE (mode))
+            break;
+        }
+      if (realmode != VOIDmode)
+        const_tiny_rtx[0][(int) mode]
+          = gen_rtx_CONCAT (mode,
+                            const_tiny_rtx[0][(int)realmode],
+                            const_tiny_rtx[0][(int)realmode]);
+    }
 
   ggc_add_rtx_root (&const_tiny_rtx[0][0], sizeof(const_tiny_rtx)/sizeof(rtx));
   ggc_add_rtx_root (&const_true_rtx, 1);

With this change, the example compiles without error, and the generated
code appears reasonable.  I've further checked that it does not
change the results of the testsuite.


I ran into these problems in the first place while trying to test out
a recent snapshot of the new libstdc++, which uses these built-in complex
types to implement the std::complex classes.

sss


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]