> This is what I have applied after bootstrapping and testing on
> x86_64-unknown-linux-gnu.

Thanks.  Last identified problem: the miscompilation with variant record.

  gnat.dg/pack17.adb

raised PROGRAM_ERROR : pack17.adb:36 explicit raise
FAIL: gnat.dg/pack17.adb execution test


Things start to go wrong at line 28:

24   procedure Fill (R : out Record_With_QImode_Variants) is
25   begin
26      R.C_Filler := (True, False, True, False, True, False, True);
27      R.C_Map := (True, False, True);
28      R.T_Int := 17;
29   end;

R is a packed record with variant part and -gnatR1 gives its layout:

for Record_With_Qimode_Variants'Object_Size use 24;
for Record_With_Qimode_Variants'Value_Size use 19;
for Record_With_Qimode_Variants'Alignment use 1;
for Record_With_Qimode_Variants use record
   D        at 0 range  0 ..  0;
   C_Filler at 0 range  1 ..  7;
   C_Map    at 1 range  0 ..  2;
   F_Bit    at 1 range  3 ..  3;
   F_Filler at 1 range  4 .. 10;
   T_Int    at 1 range  3 .. 10;

Now, since T_Int is within a variant, the assignment is translated into:

  r_1(D)->d___XVN.O.t_int = 17;

d___XVN is QUAL_UNION_TYPE and O a RECORD_TYPE (fields of QUAL_UNION_TYPE are 
always of RECORD_TYPE, that's why the overloading of qualifier is indeed OK).

The compiler now generates:

        movl    8(%ebp), %eax
        movb    $17, 1(%eax)

which is of course wrong given the layout above.

It seems to me that the new code implicitly assumes that the first field in a 
bitfield group starts on a byte boundary, which doesn't hold in Ada.

-- 
Eric Botcazou
-- { dg-do run }

procedure Pack17 is

   type Bitmap_T is array (Natural range <>) of Boolean;
   pragma Pack (Bitmap_T);

   type Uint8 is range 0 .. 2 ** 8 - 1;
   for Uint8'Size use 8;

   type Record_With_QImode_Variants (D : Boolean) is record
      C_Filler : Bitmap_T (1..7);
      C_Map : Bitmap_T (1..3);
      case D is
         when False =>
            F_Bit : Boolean;
            F_Filler : Bitmap_T (1..7);
         when True =>
            T_Int : Uint8;
      end case;
   end record;
   pragma Pack (Record_With_QImode_Variants);

   procedure Fill (R : out Record_With_QImode_Variants) is
   begin
      R.C_Filler := (True, False, True, False, True, False, True);
      R.C_Map := (True, False, True);
      R.T_Int := 17;
   end;

   RT : Record_With_QImode_Variants (D => True);

begin
   Fill (RT);
   if RT.T_Int /= 17 then
     raise Program_Error;
   end if;
end;

Reply via email to