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]
Other format: [Raw text]

Re: [patch] for PR 18040


Florian Weimer <fw@deneb.enyo.de> writes:

> Unfortunately, var doesn't have to be addressable.  Consider the
> following example:
>
> with Ada.Unchecked_Conversion;
>
> procedure Bar is
>
>    type T is mod 2**4;
>    type Foo is record
>       A, B : T;
>    end record;
>    pragma Pack (Foo);
>    for Foo'Size use 8;
>
>    type U is mod 2**2;
>    type Baz is record
>       A, B : U;
>    end record;
>    pragma Pack (Baz);
>    for Baz'Size use 4;
>
>    Var1 : Foo;
>    pragma Import (Ada, Var1);
>
>    Var2 : U;
>    pragma Import (Ada, Var2);
>
>    function Convert is new Ada.Unchecked_Conversion (T, Baz);
>
> begin
>    Var2 := Convert (Var1.B).B;
> end Bar;

This is the case that I suggested could be handled by pushing the type
conversion to the top level of the nest, as-if the programmer had
written

with Ada.Unchecked_Conversion;

procedure Bar is

   type T is mod 2**4;
   type U is mod 2**2;

   type Foo is record
      A, B : T;
   end record;
   pragma Pack (Foo);
   for Foo'Size use 8;  -- N.B. I am assuming this number is in bits.

   type Quux is record
     AA, AB, BA, BB : U;
   end record;
   pragma Pack (Quux);
   for Quux'Size use 8;

   Var1 : Foo;
   pragma Import (Ada, Var1);
   
   Var2 : U;
   pragma Import (Ada, Var2);

   function Convert is new Ada.Unchecked_Conversion (Foo, Quux);

begin
   Var2 := Convert(Var1).BB;
end;

or, in C,

struct Foo __attribute__ ((packed)) {
  unsigned char A : 4;
  unsigned char B : 4;
};

struct Quux __attribute__ ((packed)) {
  unsigned char AA : 2;
  unsigned char AB : 2;
  unsigned char BA : 2;
  unsigned char BB : 2;
};

extern struct Foo var1;
extern char var2;  /* original type not representable in C */

void bar(void)
{
  struct Quux *q = (struct Quux *) &var1;

  var2.value = q->BB;
}

This transformation, however, has the problem that Kenner pointed out,
of possibly requiring a quadratic number of type-synthesis operations
at compile time.

> For the example above, all versions of GNAT I've tested (GNAT 3.15p,
> GCC 3.4, mainline) generate somewhat questionable code which involves
> bit operations on registers that are only partly defined (the
> undefined bits are subsequently masked away, though).

I'll add that I get much better code out of GNAT after the
transformation I demonstrated.  With GCC 3.3.5, before:

        movzbl  var1, %edx
        andb    $-16, %al
        shrb    $4, %dl
        orb     %dl, %al
        shrb    $2, %al
        andb    $3, %al
        movb    %al, var2
        ret

and after:

        movzbl  var1, %eax
        shrb    $6, %al
        movb    %al, var2
        ret

The C version also produces this improved code.

>> The only catch is that alias analysis must understand that rp aliases
>> var.  This may require some adjustment to GNAT's alias set logic.
>
> I'm not sure if this is actually required by the language, but
> real-world code probably needs this.

Agree.

zw


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