This is the mail archive of the gcc@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]
Other format: [Raw text]

SEGV in do_simple_structure_copy


Hello,

The Ada testcase below, compiled with -O2 on x86-linux, triggers a
SEGV in the current mainline compiler, there:

   do_simple_structure_copy 
   { ...
     for (; p && p->offset < last; p = p->next)
       { ...
         q = first_vi_for_offset (q, q->offset + fieldoffset);
  ==>    temprhs.var = q->id;

Below is a description of what is going on, plus suggestions on how to
address the problem. I'd welcome feedback before submitting a patch
with all the required testing process.

The test basically constructs a record type with two 6bits long
components, each of a record type also, and the two components (called
key1 and key2) are tighly packed with a representation clause (no
hole between the two components). Something like:

      6bits   6bits
    |.......|.......|
      key1    key2

Eventhough the field *decls* specify a 6bits length, the *type* of
each is actually QI integer (8bits long).

The SEGV above triggers on an assignment to a .key1 component from a
standalone variable of the corresponding type. This is

   Keys.One_Pair.Key1 := Keys.One_Key;

in k.adb.

Several factors come into play, AFAICS:

o the incoming 'size' argument is based on type and not decl information,
  and is used to bound the iteration (to compute 'last')

o the offset increments for each component within the loop are based on
  decl size information

o .key2 appears as a successor of .key1 in the lhs because they are part
  of the same outer object.

We remain in the for loop after processing the assignment to .key1
because the decl size is strictly smaller than the type size, so 'last' is
not reached, and there is a 'next' variable in sight. But then, we're out
of the source standalone variable contents, so first_vi_for_offset
returns null and we SEGV on the dereference.

A very simple way to deal with this is to just 'break' out of the loop
when 'q' happens to be null, with an appropriate comment briefly
explaining how this could happen.

Another way would be to compute the incoming 'size' argument from decl
information when appropriate. This seems more involved at first sight.

Thanks in advance for your help,

Olivier


-- $ gcc -c -O2 k.adb
-- raised STORAGE_ERROR : stack overflow (or erroneous memory access)
  
with Keys;
procedure K is
begin
   Keys.One_Pair.Key1 := Keys.One_Key;
end;

package Keys is

   Key_Size : constant := 6;

   type Key_Value_T is range 0 .. 2 ** Key_Size - 1;
   for Key_Value_T'Size use Key_Size;

   type Key_T is record
      Value : Key_Value_T;
   end record;
   for Key_T use record
      Value at 0 range 0 .. Key_Size - 1;
   end record;

   type Key_Pair_T is record
      Key1, Key2 : Key_T;
   end record;

   for Key_Pair_T use record
      Key1 at 0 range 0 .. Key_Size - 1;
      Key2 at 0 range Key_Size .. Key_Size + Key_Size - 1;
   end record;

   One_Key  : Key_T := (Value => 1);
   One_Pair : Key_Pair_T;

end;


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