comp.lang.ada
 help / color / mirror / Atom feed
* Gem 39 - compiler specific?
@ 2009-09-02 20:38 Maciej Sobczak
  2009-09-02 23:20 ` Randy Brukardt
  2009-09-03  0:12 ` Adam Beneschan
  0 siblings, 2 replies; 20+ messages in thread
From: Maciej Sobczak @ 2009-09-02 20:38 UTC (permalink / raw)


Consider:

http://www.adacore.com/2008/06/09/gem-39/

The example code performs Unchecked_Conversion between addresses of
two different array types.
As far as I understand, there is no standard provision for arrays to
occupy contiguous memory space (and not even for the alignment of
their components) and such a conversion relies heavily on the
assumption that arrays can be "overlaid" by plain address
reinterpretation.

Still, this technique is quite attractive. What is the chance (in
practice) to hit the compiler that does not get it "right"?

--
Maciej Sobczak * www.msobczak.com * www.inspirel.com

Database Access Library for Ada: www.inspirel.com/soci-ada



^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Gem 39 - compiler specific?
  2009-09-02 20:38 Gem 39 - compiler specific? Maciej Sobczak
@ 2009-09-02 23:20 ` Randy Brukardt
  2009-09-03  7:26   ` Dmitry A. Kazakov
  2009-09-03  0:12 ` Adam Beneschan
  1 sibling, 1 reply; 20+ messages in thread
From: Randy Brukardt @ 2009-09-02 23:20 UTC (permalink / raw)


"Maciej Sobczak" <see.my.homepage@gmail.com> wrote in message 
news:9e0bbbcd-260f-48ed-8043-d6280c633e85@h3g2000yqa.googlegroups.com...
> Consider:
>
> http://www.adacore.com/2008/06/09/gem-39/
>
> The example code performs Unchecked_Conversion between addresses of
> two different array types.
> As far as I understand, there is no standard provision for arrays to
> occupy contiguous memory space (and not even for the alignment of
> their components) and such a conversion relies heavily on the
> assumption that arrays can be "overlaid" by plain address
> reinterpretation.
>
> Still, this technique is quite attractive. What is the chance (in
> practice) to hit the compiler that does not get it "right"?

This is horrible code; it should never be written in Ada 95 or newer! The 
problem is that System.Address is not necessarily the same as a general 
access type, so this Unchecked_Conversion may not work (or may not even 
compile) on another implementation. (It won't on at least some versions of 
Janus/Ada, for instance.)

Ada 95 provides System.Address_to_Access_Conversions for this purpose, so at 
the very least the writer of the Rock (it surely isn't a "Gem"!!!) should 
have used it:

procedure Write_Buffer
      (Stream : not null access Ada.Streams.Root_Stream_Type'Class;
       Item   : in Buffer)  is
      Item_Size : constant Stream_Element_Offset :=
                     Buffer'Object_Size / Stream_Element'Size;

     subtype SEA is Stream_Element_Array (1..Item_Size);

     package A2A is new System.Address_to_Access_Conversions (SEA);

begin
      Ada.Streams.Write (Stream.all, A2A.To_Pointer (Item'Address).all);
end Write_Buffer;

(As an aside, this technique could not work in Janus/Ada if Buffer was an 
unconstrained array: 'Address of an unconstrained array points at the array 
descriptor, not the data. (That's in fact true for all objects in Janus/Ada: 
there is a static part and an optional dynamic part, and all operations like 
'Address and 'Size point at the static part. That was decided long before 
Ada 95 came around and tried to change these definitions; it's not practical 
to change in Janus/Ada as address clauses could not be made to work - among 
other things - if the static part is ignored.)

IMHO, using System.Address is for anything other than address clauses is 
*always* wrong in Ada 95: there are always ways to use general access types 
in order to deal with any "pointer" type issue. But we don't even need to do 
*that* here - you can directly used Unchecked_Conversion to directly convert 
between the array types:

procedure Write_Buffer
      (Stream : not null access Ada.Streams.Root_Stream_Type'Class;
       Item   : in Buffer)  is
      Item_Size : constant Stream_Element_Offset :=
                     Buffer'Object_Size / Stream_Element'Size;

     subtype SEA is Stream_Element_Array (1..Item_Size);

     function To_SEA is new Ada.Unchecked_Conversion (Source => Buffer, 
Target => SEA);

begin
      Ada.Streams.Write (Stream.all, To_SEA (Item));
end Write_Buffer;

And now there is no use of Address or access types at all (other than for 
the stream, of course). Any decent compiler will compile this conversion 
into nothing: No code is needed or should be generated for it. (Janus/Ada 
can do this, and it is pretty dumb. Indeed, it can does this precisely 
because this example needs to work cheaply, as it is the way the majority of 
user-defined stream attributes ought to be written.)

                                                 Randy.







^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Gem 39 - compiler specific?
  2009-09-02 20:38 Gem 39 - compiler specific? Maciej Sobczak
  2009-09-02 23:20 ` Randy Brukardt
@ 2009-09-03  0:12 ` Adam Beneschan
  1 sibling, 0 replies; 20+ messages in thread
From: Adam Beneschan @ 2009-09-03  0:12 UTC (permalink / raw)


On Sep 2, 1:38 pm, Maciej Sobczak <see.my.homep...@gmail.com> wrote:
> Consider:
>
> http://www.adacore.com/2008/06/09/gem-39/
>
> The example code performs Unchecked_Conversion between addresses of
> two different array types.
> As far as I understand, there is no standard provision for arrays to
> occupy contiguous memory space (and not even for the alignment of
> their components) and such a conversion relies heavily on the
> assumption that arrays can be "overlaid" by plain address
> reinterpretation.
>
> Still, this technique is quite attractive. What is the chance (in
> practice) to hit the compiler that does not get it "right"?

There are a number of portability problems with this gem ("uncut
gem"?).  All are mentioned or hinted at in the comments section of the
page you reference.

(1) It uses 'Object_Size which is not defined by the Ada language.

(2) It uses Unchecked_Conversion to convert between System.Address and
an access type.  As mentioned both in the comments and in Randy's
post, this is sloppy and really ought to use
System.Access_To_Address_Conversions (or, better, use
Unchecked_Conversion on the entire array as Randy also suggested).

(3) In the definition of Buffer:

    type Buffer is array (1..32) of Interfaces.Unsigned_16;

there is no guarantee that there won't be gaps between elements of the
array, which would screw the whole thing up.  (This is unlikely for a
byte-addressable machine, perhaps, but not all machines are like that;
Irvine Compiler's Ada compiler supports a target whose
System.Storage_Unit is 32, and on that machine, the compiler would put
each array element in a separate 32-bit word unless other
representation clauses tell it not to.)

I think it's necessary to add:

    for Buffer'Component_Size use 16;
    pragma Pack (Buffer);

to ensure that each array element takes up exactly 16 bits and there
are no extra gaps.  (If the Implementation Advice is followed (13.3
(71-73)), the compiler should reject the program if it cannot support
this, as might be the case on a machine with a 36-bit word; but that's
a darn sight better than accepting the program and letting it not work
right.)  I'm not 100% clear on whether the Pack is necessary.

With all those issues, I'd say this gem needs a bit of grinding.

                                      -- Adam



^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Gem 39 - compiler specific?
  2009-09-02 23:20 ` Randy Brukardt
@ 2009-09-03  7:26   ` Dmitry A. Kazakov
  2009-09-03 15:26     ` Adam Beneschan
  2009-09-03 21:53     ` Randy Brukardt
  0 siblings, 2 replies; 20+ messages in thread
From: Dmitry A. Kazakov @ 2009-09-03  7:26 UTC (permalink / raw)


On Wed, 2 Sep 2009 18:20:36 -0500, Randy Brukardt wrote:

> "Maciej Sobczak" <see.my.homepage@gmail.com> wrote in message 
> news:9e0bbbcd-260f-48ed-8043-d6280c633e85@h3g2000yqa.googlegroups.com...
>> Consider:
>>
>> http://www.adacore.com/2008/06/09/gem-39/
>>
>> The example code performs Unchecked_Conversion between addresses of
>> two different array types.
>> As far as I understand, there is no standard provision for arrays to
>> occupy contiguous memory space (and not even for the alignment of
>> their components) and such a conversion relies heavily on the
>> assumption that arrays can be "overlaid" by plain address
>> reinterpretation.
>>
>> Still, this technique is quite attractive. What is the chance (in
>> practice) to hit the compiler that does not get it "right"?
> 
> This is horrible code; it should never be written in Ada 95 or newer! The 
> problem is that System.Address is not necessarily the same as a general 
> access type, so this Unchecked_Conversion may not work (or may not even 
> compile) on another implementation. (It won't on at least some versions of 
> Janus/Ada, for instance.)
> 
> Ada 95 provides System.Address_to_Access_Conversions for this purpose, so at 
> the very least the writer of the Rock (it surely isn't a "Gem"!!!) should 
> have used it:
> 
> procedure Write_Buffer
>       (Stream : not null access Ada.Streams.Root_Stream_Type'Class;
>        Item   : in Buffer)  is
>       Item_Size : constant Stream_Element_Offset :=
>                      Buffer'Object_Size / Stream_Element'Size;
> 
>      subtype SEA is Stream_Element_Array (1..Item_Size);
> 
>      package A2A is new System.Address_to_Access_Conversions (SEA);
> 
> begin
>       Ada.Streams.Write (Stream.all, A2A.To_Pointer (Item'Address).all);
> end Write_Buffer;
> 
> (As an aside, this technique could not work in Janus/Ada if Buffer was an 
> unconstrained array: 'Address of an unconstrained array points at the array 
> descriptor, not the data.

It must point to the first array element 13.3(14). BTW, it is interesting
where it should point when the array is empty.

> (That's in fact true for all objects in Janus/Ada: 
> there is a static part and an optional dynamic part, and all operations like 
> 'Address and 'Size point at the static part. That was decided long before 
> Ada 95 came around and tried to change these definitions; it's not practical 
> to change in Janus/Ada as address clauses could not be made to work - among 
> other things - if the static part is ignored.)

Skewed address is not a problem here. The problem is that
System.Address_To_Access_Conversions should take an access type as a
parameter rather than declare it new. This makes its use quite limited.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Gem 39 - compiler specific?
  2009-09-03  7:26   ` Dmitry A. Kazakov
@ 2009-09-03 15:26     ` Adam Beneschan
  2009-09-03 16:38       ` Dmitry A. Kazakov
  2009-09-03 21:53     ` Randy Brukardt
  1 sibling, 1 reply; 20+ messages in thread
From: Adam Beneschan @ 2009-09-03 15:26 UTC (permalink / raw)


On Sep 3, 12:26 am, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
wrote:
> On Wed, 2 Sep 2009 18:20:36 -0500, Randy Brukardt wrote:
> > "Maciej Sobczak" <see.my.homep...@gmail.com> wrote in message
> >news:9e0bbbcd-260f-48ed-8043-d6280c633e85@h3g2000yqa.googlegroups.com...
> >> Consider:
>
> >>http://www.adacore.com/2008/06/09/gem-39/
>
> >> The example code performs Unchecked_Conversion between addresses of
> >> two different array types.
> >> As far as I understand, there is no standard provision for arrays to
> >> occupy contiguous memory space (and not even for the alignment of
> >> their components) and such a conversion relies heavily on the
> >> assumption that arrays can be "overlaid" by plain address
> >> reinterpretation.
>
> >> Still, this technique is quite attractive. What is the chance (in
> >> practice) to hit the compiler that does not get it "right"?
>
> > This is horrible code; it should never be written in Ada 95 or newer! The
> > problem is that System.Address is not necessarily the same as a general
> > access type, so this Unchecked_Conversion may not work (or may not even
> > compile) on another implementation. (It won't on at least some versions of
> > Janus/Ada, for instance.)
>
> > Ada 95 provides System.Address_to_Access_Conversions for this purpose, so at
> > the very least the writer of the Rock (it surely isn't a "Gem"!!!) should
> > have used it:
>
> > procedure Write_Buffer
> >       (Stream : not null access Ada.Streams.Root_Stream_Type'Class;
> >        Item   : in Buffer)  is
> >       Item_Size : constant Stream_Element_Offset :=
> >                      Buffer'Object_Size / Stream_Element'Size;
>
> >      subtype SEA is Stream_Element_Array (1..Item_Size);
>
> >      package A2A is new System.Address_to_Access_Conversions (SEA);
>
> > begin
> >       Ada.Streams.Write (Stream.all, A2A.To_Pointer (Item'Address).all);
> > end Write_Buffer;
>
> > (As an aside, this technique could not work in Janus/Ada if Buffer was an
> > unconstrained array: 'Address of an unconstrained array points at the array
> > descriptor, not the data.
>
> It must point to the first array element 13.3(14). BTW, it is interesting
> where it should point when the array is empty.
>
> > (That's in fact true for all objects in Janus/Ada:
> > there is a static part and an optional dynamic part, and all operations like
> > 'Address and 'Size point at the static part. That was decided long before
> > Ada 95 came around and tried to change these definitions; it's not practical
> > to change in Janus/Ada as address clauses could not be made to work - among
> > other things - if the static part is ignored.)
>
> Skewed address is not a problem here. The problem is that
> System.Address_To_Access_Conversions should take an access type as a
> parameter rather than declare it new. This makes its use quite limited.

I don't see any limitation, at least where To_Pointer is concerned
(which is what the above code needed to use).  If you declare an
instance of this package for any object type T:

  type Convert_T_Access is new System.Address_To_Access_Conversions
(T);

then an object of type Convert_T_Access.Object_Pointer can be
converted to any access type whose designated type is T.  I checked
through the legality rules in 4.6, and I couldn't find a way to
declare an access-to-T type that you couldn't convert an
Object_Pointer to.  Thus, if you have any access type

  type Acc_T is access T;  [or access all T, or access constant T]

you can convert an address Addr to an Acc_T by saying:

  Acc_T (Convert_T_Access.To_Pointer (Addr))

There do seem to be some limitations on using To_Address, though; you
can't convert an "access constant T" to an Object_Pointer, and you
can't convert an access-to-T type that is nested inside a subprogram.
So you couldn't use To_Address on those types.  Offhand, though, I'd
guess that there is much less need for this than for To_Pointer, so
this may not be a severe enough limitation to require fixing.

                              -- Adam




^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Gem 39 - compiler specific?
  2009-09-03 15:26     ` Adam Beneschan
@ 2009-09-03 16:38       ` Dmitry A. Kazakov
  2009-09-03 17:27         ` Adam Beneschan
  0 siblings, 1 reply; 20+ messages in thread
From: Dmitry A. Kazakov @ 2009-09-03 16:38 UTC (permalink / raw)


On Thu, 3 Sep 2009 08:26:50 -0700 (PDT), Adam Beneschan wrote:

> On Sep 3, 12:26�am, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
> wrote:

>> Skewed address is not a problem here. The problem is that
>> System.Address_To_Access_Conversions should take an access type as a
>> parameter rather than declare it new. This makes its use quite limited.
> 
> I don't see any limitation, at least where To_Pointer is concerned
> (which is what the above code needed to use).  If you declare an
> instance of this package for any object type T:
> 
>   type Convert_T_Access is new System.Address_To_Access_Conversions
> (T);
> 
> then an object of type Convert_T_Access.Object_Pointer can be
> converted to any access type whose designated type is T.  I checked
> through the legality rules in 4.6, and I couldn't find a way to
> declare an access-to-T type that you couldn't convert an
> Object_Pointer to.  Thus, if you have any access type
> 
>   type Acc_T is access T;  [or access all T, or access constant T]
> 
> you can convert an address Addr to an Acc_T by saying:
> 
>   Acc_T (Convert_T_Access.To_Pointer (Addr))

But Acc_T is a pool-specific access, while Address_To_Access_Conversions
creates a general access type. Here Unchecked_Conversion between access
types is required, which AFIAK is not guaranteed to work anyway. In some
cases I use:

declare
   X : T;
   for X'Address use Addr;
   pragma Import (X);
begin
   ...

> There do seem to be some limitations on using To_Address, though; you
> can't convert an "access constant T" to an Object_Pointer, and you
> can't convert an access-to-T type that is nested inside a subprogram.

Yes, accessibility rules is another major nuisance.

> So you couldn't use To_Address on those types. Offhand, though, I'd
> guess that there is much less need for this than for To_Pointer, so
> this may not be a severe enough limitation to require fixing.

That happens quite often in generic bodies. An access type comes from a
formal parameter, Address_To_Access_Conversions is instantiated within the
generics. In many (most?) cases I used considered it, I must resort to the
old and ugly Ada programmer's friend .all'Unchecked_Access...

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Gem 39 - compiler specific?
  2009-09-03 16:38       ` Dmitry A. Kazakov
@ 2009-09-03 17:27         ` Adam Beneschan
  2009-09-03 20:26           ` Dmitry A. Kazakov
                             ` (2 more replies)
  0 siblings, 3 replies; 20+ messages in thread
From: Adam Beneschan @ 2009-09-03 17:27 UTC (permalink / raw)


On Sep 3, 9:38 am, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
wrote:
> On Thu, 3 Sep 2009 08:26:50 -0700 (PDT), Adam Beneschan wrote:
> > On Sep 3, 12:26 am, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
> > wrote:
> >> Skewed address is not a problem here. The problem is that
> >> System.Address_To_Access_Conversions should take an access type as a
> >> parameter rather than declare it new. This makes its use quite limited.
>
> > I don't see any limitation, at least where To_Pointer is concerned
> > (which is what the above code needed to use).  If you declare an
> > instance of this package for any object type T:
>
> >   type Convert_T_Access is new System.Address_To_Access_Conversions
> > (T);
>
> > then an object of type Convert_T_Access.Object_Pointer can be
> > converted to any access type whose designated type is T.  I checked
> > through the legality rules in 4.6, and I couldn't find a way to
> > declare an access-to-T type that you couldn't convert an
> > Object_Pointer to.  Thus, if you have any access type
>
> >   type Acc_T is access T;  [or access all T, or access constant T]
>
> > you can convert an address Addr to an Acc_T by saying:
>
> >   Acc_T (Convert_T_Access.To_Pointer (Addr))
>
> But Acc_T is a pool-specific access, while Address_To_Access_Conversions
> creates a general access type.

Sigh... I missed that---you can't convert a general access type to a
pool-specific one.  4.6 can be hard to follow, the way it's organized,
but that's not a good excuse.  I've read it enough times that I should
know better.

However, one could make that case that if you declare a pool-specific
access type, then by definition it should point to something that's in
a pool; and that if you want an access that could point to an
arbitrary address (as Access_To_Address_Conversions would let you do),
you should use a general access type.

                                    -- Adam



^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Gem 39 - compiler specific?
  2009-09-03 17:27         ` Adam Beneschan
@ 2009-09-03 20:26           ` Dmitry A. Kazakov
  2009-09-03 22:06             ` Randy Brukardt
  2009-09-03 21:58           ` Randy Brukardt
  2009-09-04 17:26           ` Robert A Duff
  2 siblings, 1 reply; 20+ messages in thread
From: Dmitry A. Kazakov @ 2009-09-03 20:26 UTC (permalink / raw)


On Thu, 3 Sep 2009 10:27:57 -0700 (PDT), Adam Beneschan wrote:

> On Sep 3, 9:38�am, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
> wrote:
>> On Thu, 3 Sep 2009 08:26:50 -0700 (PDT), Adam Beneschan wrote:
>>> On Sep 3, 12:26�am, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
>>> wrote:
>>>> Skewed address is not a problem here. The problem is that
>>>> System.Address_To_Access_Conversions should take an access type as a
>>>> parameter rather than declare it new. This makes its use quite limited.
>>
>>> I don't see any limitation, at least where To_Pointer is concerned
>>> (which is what the above code needed to use). �If you declare an
>>> instance of this package for any object type T:
>>
>>> � type Convert_T_Access is new System.Address_To_Access_Conversions
>>> (T);
>>
>>> then an object of type Convert_T_Access.Object_Pointer can be
>>> converted to any access type whose designated type is T. �I checked
>>> through the legality rules in 4.6, and I couldn't find a way to
>>> declare an access-to-T type that you couldn't convert an
>>> Object_Pointer to. �Thus, if you have any access type
>>
>>> � type Acc_T is access T; �[or access all T, or access constant T]
>>
>>> you can convert an address Addr to an Acc_T by saying:
>>
>>> � Acc_T (Convert_T_Access.To_Pointer (Addr))
>>
>> But Acc_T is a pool-specific access, while Address_To_Access_Conversions
>> creates a general access type.
> 
> Sigh... I missed that---you can't convert a general access type to a
> pool-specific one.  4.6 can be hard to follow, the way it's organized,
> but that's not a good excuse.  I've read it enough times that I should
> know better.
> 
> However, one could make that case that if you declare a pool-specific
> access type, then by definition it should point to something that's in
> a pool; and that if you want an access that could point to an
> arbitrary address (as Access_To_Address_Conversions would let you do),
> you should use a general access type.

Address may have some specific representation when points into a pool. The
idea of Access_To_Address_Conversions is to provide programmer a bit more
safety than Unchecked_Conversion would.

Why do we have Access_To_Address_Conversions? Why not to require
Unchecked_Conversion to do all the checks Access_To_Address_Conversions
does in the corresponding cases? I mean, there is no obvious reason why the
implementation of Access_To_Address_Conversions should be safer than one of
Unchecked_Conversion. The information the compiler has at the instantiation
point is just same.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Gem 39 - compiler specific?
  2009-09-03  7:26   ` Dmitry A. Kazakov
  2009-09-03 15:26     ` Adam Beneschan
@ 2009-09-03 21:53     ` Randy Brukardt
  1 sibling, 0 replies; 20+ messages in thread
From: Randy Brukardt @ 2009-09-03 21:53 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:19268dbw82hf4.aii8as09aapk.dlg@40tude.net...
> On Wed, 2 Sep 2009 18:20:36 -0500, Randy Brukardt wrote:
...
>> (As an aside, this technique could not work in Janus/Ada if Buffer was an
>> unconstrained array: 'Address of an unconstrained array points at the 
>> array
>> descriptor, not the data.
>
> It must point to the first array element 13.3(14). BTW, it is interesting
> where it should point when the array is empty.

The word in 13.3(14) is "should", not "must" (a word that is not allowed in 
Standards anyway). Specifically,
13.3(14) is Implementation Advice. There is no requirement in Ada to follow 
Implementation Advice, the only requirement is to document when you don't. 
That is, an Ada compiler's (formal) correctness cannot depend on 
Implementation Advice. What Janus/Ada does here is OK (but not recommended 
of course).

                      Randy.





^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Gem 39 - compiler specific?
  2009-09-03 17:27         ` Adam Beneschan
  2009-09-03 20:26           ` Dmitry A. Kazakov
@ 2009-09-03 21:58           ` Randy Brukardt
  2009-09-04 17:26           ` Robert A Duff
  2 siblings, 0 replies; 20+ messages in thread
From: Randy Brukardt @ 2009-09-03 21:58 UTC (permalink / raw)


"Adam Beneschan" <adam@irvine.com> wrote in message 
news:1bf4b63a-1e2d-41f1-97c6-8324d4b829ff@z3g2000prd.googlegroups.com...
...
> However, one could make that case that if you declare a pool-specific
> access type, then by definition it should point to something that's in
> a pool; and that if you want an access that could point to an
> arbitrary address (as Access_To_Address_Conversions would let you do),
> you should use a general access type.

I'd go further than that: it is a bug to have a pool-specific access type 
pointing at something outside of the pool. Indeed, Janus/Ada will raise 
Constraint_Error when dereferencing a value outside of the standard pool 
(for access types using the standard pool). [That was a feature of our Ada 
83 compiler that we carried over to Ada 95, since it caught a lot of bugs 
caused by Unchecked_Deallocation and from corrupted I/O.]

                                        Randy.





^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Gem 39 - compiler specific?
  2009-09-03 20:26           ` Dmitry A. Kazakov
@ 2009-09-03 22:06             ` Randy Brukardt
  2009-09-04  7:29               ` Dmitry A. Kazakov
  0 siblings, 1 reply; 20+ messages in thread
From: Randy Brukardt @ 2009-09-03 22:06 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:6o3frhrv0n0p$.8wj0gszs5h07$.dlg@40tude.net...
...
> Why do we have Access_To_Address_Conversions? Why not to require
> Unchecked_Conversion to do all the checks Access_To_Address_Conversions
> does in the corresponding cases? I mean, there is no obvious reason why 
> the
> implementation of Access_To_Address_Conversions should be safer than one 
> of
> Unchecked_Conversion. The information the compiler has at the 
> instantiation
> point is just same.

Because the intent is that Unchecked_Conversion never actually does anything 
other than change the type. In particular, it should not change the 
representation. But it is not uncommon for System.Address and an access type 
to have a different representation. For instance, the Janus/Ada 16-bit 
MS-DOS compilers uses a 32-bit segmented value for System.Address, but 
access types were just 16-bit pointers into the heap. (Our early 32-bit 386 
compilers used 48-bit addresses; that was quite useful on early DOS 
extenders, for instance.)

The intent leads to the rule that Unchecked_Conversion is only well-defined 
when the sizes of the two types are the same. As noted, that doesn't need to 
be the case for System.Address.

You seem to want to muddle up the semantics to include some real 
conversions. That would be a problem inside of generics (what if the actual 
parameter is System.Address?? Do you get the special semantics or not? 
Either answer is uncomfortable and requiring the special semantics would 
have bad consequences on code generation and legality rules), and in any 
case is not very consistent.

                                 Randy.





^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Gem 39 - compiler specific?
  2009-09-03 22:06             ` Randy Brukardt
@ 2009-09-04  7:29               ` Dmitry A. Kazakov
  2009-09-04 12:07                 ` Maciej Sobczak
  0 siblings, 1 reply; 20+ messages in thread
From: Dmitry A. Kazakov @ 2009-09-04  7:29 UTC (permalink / raw)


On Thu, 3 Sep 2009 17:06:48 -0500, Randy Brukardt wrote:

> The intent leads to the rule that Unchecked_Conversion is only well-defined 
> when the sizes of the two types are the same. As noted, that doesn't need to 
> be the case for System.Address.
> 
> You seem to want to muddle up the semantics to include some real 
> conversions.

Do we need that semantics (reinterpret bit pattern as another type)? It is
difficult to invent a case where an access value would be obtained from a
bit patterns. It is never needed, IMO.

> That would be a problem inside of generics (what if the actual 
> parameter is System.Address??

OK. (However there are already similar cases with generics)

> Do you get the special semantics or not? 
> Either answer is uncomfortable and requiring the special semantics would 
> have bad consequences on code generation and legality rules), and in any 
> case is not very consistent.

Yes.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Gem 39 - compiler specific?
  2009-09-04  7:29               ` Dmitry A. Kazakov
@ 2009-09-04 12:07                 ` Maciej Sobczak
  2009-09-04 13:06                   ` Dmitry A. Kazakov
  2009-09-04 22:41                   ` sjw
  0 siblings, 2 replies; 20+ messages in thread
From: Maciej Sobczak @ 2009-09-04 12:07 UTC (permalink / raw)


On 4 Wrz, 09:29, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
wrote:

> Do we need that semantics (reinterpret bit pattern as another type)? It is
> difficult to invent a case where an access value would be obtained from a
> bit patterns. It is never needed, IMO.

Hint: interfacing with other languages (notably C and C++) with
libraries that have some callback or object map functionality.

I have done it very recently and I used
System.Address_To_Access_Conversions. The access values to genuine Ada
objects (even of class-wide types) are converted to addresses and
handed to the C++ component, which at some later point in time calls
back into Ada providing the previously stored address that Ada
converts to the original access value.

A very important part of this business is that the C++ component
*never* uses the given address in any other way than to remember it.
It is just a "cookie".

This is an example of scenario where access values are obtained from
what is essentially a bit pattern. The conversions are from access to
address and then from address to access and both are performed by the
Ada code within a single compilation unit. As far as I understand it
is safe, AARM-wise.

--
Maciej Sobczak * www.msobczak.com * www.inspirel.com

Database Access Library for Ada: www.inspirel.com/soci-ada



^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Gem 39 - compiler specific?
  2009-09-04 12:07                 ` Maciej Sobczak
@ 2009-09-04 13:06                   ` Dmitry A. Kazakov
  2009-09-04 17:18                     ` Dmitry A. Kazakov
  2009-09-04 20:34                     ` Maciej Sobczak
  2009-09-04 22:41                   ` sjw
  1 sibling, 2 replies; 20+ messages in thread
From: Dmitry A. Kazakov @ 2009-09-04 13:06 UTC (permalink / raw)


On Fri, 4 Sep 2009 05:07:47 -0700 (PDT), Maciej Sobczak wrote:

> On 4 Wrz, 09:29, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
> wrote:
> 
>> Do we need that semantics (reinterpret bit pattern as another type)? It is
>> difficult to invent a case where an access value would be obtained from a
>> bit patterns. It is never needed, IMO.
> 
> Hint: interfacing with other languages (notably C and C++) with
> libraries that have some callback or object map functionality.

You mean void *? That is Address (or some access type), not a bit pattern.

In short, you never needed Unchecked_Conversion that would behave
differently from Address_To_Access_Conversions does.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Gem 39 - compiler specific?
  2009-09-04 13:06                   ` Dmitry A. Kazakov
@ 2009-09-04 17:18                     ` Dmitry A. Kazakov
  2009-09-04 20:34                     ` Maciej Sobczak
  1 sibling, 0 replies; 20+ messages in thread
From: Dmitry A. Kazakov @ 2009-09-04 17:18 UTC (permalink / raw)


On Fri, 4 Sep 2009 15:06:12 +0200, Dmitry A. Kazakov wrote:

> In short, you never needed Unchecked_Conversion that would behave
> differently from Address_To_Access_Conversions does.

No, I was wrong. In Ada 2005 there is such case. Let we have:

   type I is interface ...;
   type T is new .... and I with ...;
   type I_Ptr is access I'Class;
   type T_Ptr is access T'Class;

   X : aliased T;
   P1 : I_Ptr := X'Access;
   P2 : T_Ptr := X'Access;

then likely:

   U_C (P1) /= U_C (P2)

   To_Address (P1) = To_Address (P2)

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Gem 39 - compiler specific?
  2009-09-03 17:27         ` Adam Beneschan
  2009-09-03 20:26           ` Dmitry A. Kazakov
  2009-09-03 21:58           ` Randy Brukardt
@ 2009-09-04 17:26           ` Robert A Duff
  2 siblings, 0 replies; 20+ messages in thread
From: Robert A Duff @ 2009-09-04 17:26 UTC (permalink / raw)


Adam Beneschan <adam@irvine.com> writes:

> However, one could make that case that if you declare a pool-specific
> access type, then by definition it should point to something that's in
> a pool; and that if you want an access that could point to an
> arbitrary address (as Access_To_Address_Conversions would let you do),
> you should use a general access type.

The term "pool specific" is a misnomer.  It's got nothing to do with
"storage pools".  This is my fault -- I was trying to reduce the amount
of terminology in Ada 95, by using the new term, but I must have been
confused when I did that.

The correct term should be "collection-specific", using the Ada 83 term
"collection".

So instead of your "in a pool" above, I'd put it this way: A
pool-specific (sic) access value has to point to some object
created by "new" for that access type.  (Well, I'm ignoring
derived access types, which are vanishingly rare in practice.)
It can't (legitimately) point to a stack object, a component
of another object, or an object created by "new" for some other
type.

- Bob



^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Gem 39 - compiler specific?
  2009-09-04 13:06                   ` Dmitry A. Kazakov
  2009-09-04 17:18                     ` Dmitry A. Kazakov
@ 2009-09-04 20:34                     ` Maciej Sobczak
  1 sibling, 0 replies; 20+ messages in thread
From: Maciej Sobczak @ 2009-09-04 20:34 UTC (permalink / raw)


On 4 Wrz, 15:06, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
wrote:

> > Hint: interfacing with other languages (notably C and C++) with
> > libraries that have some callback or object map functionality.
>
> You mean void *? That is Address (or some access type), not a bit pattern.

But as long as the C (or C++) component cannot do anything with it,
the fact that it is an address of something that exists outside of
that component's domain is irrelevant. It is really just a bunch of
opaque bits.

> In short, you never needed Unchecked_Conversion that would behave
> differently from Address_To_Access_Conversions does.

In my case, no - because trivially I never needed U_C at all.

(and then I have found gem 39)

--
Maciej Sobczak * www.msobczak.com * www.inspirel.com

Database Access Library for Ada: www.inspirel.com/soci-ada



^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Gem 39 - compiler specific?
  2009-09-04 12:07                 ` Maciej Sobczak
  2009-09-04 13:06                   ` Dmitry A. Kazakov
@ 2009-09-04 22:41                   ` sjw
  2009-09-05 20:45                     ` Maciej Sobczak
  1 sibling, 1 reply; 20+ messages in thread
From: sjw @ 2009-09-04 22:41 UTC (permalink / raw)


On Sep 4, 1:07 pm, Maciej Sobczak <see.my.homep...@gmail.com> wrote:

> I have done it very recently and I used
> System.Address_To_Access_Conversions. The access values to genuine Ada
> objects (even of class-wide types) are converted to addresses and
> handed to the C++ component, which at some later point in time calls
> back into Ada providing the previously stored address that Ada
> converts to the original access value.
>
> A very important part of this business is that the C++ component
> *never* uses the given address in any other way than to remember it.
> It is just a "cookie".

Then I don't quite see why you needed to convert at all?

   procedure P (Q : Fancy_Access);
   pragma Import (C, Q);

Or is it that the size of a Fancy_Access makes it hard to represent on
the C side?



^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Gem 39 - compiler specific?
  2009-09-04 22:41                   ` sjw
@ 2009-09-05 20:45                     ` Maciej Sobczak
  2009-09-06  6:54                       ` sjw
  0 siblings, 1 reply; 20+ messages in thread
From: Maciej Sobczak @ 2009-09-05 20:45 UTC (permalink / raw)


On 5 Wrz, 00:41, sjw <simon.j.wri...@mac.com> wrote:

> Then I don't quite see why you needed to convert at all?
>
>    procedure P (Q : Fancy_Access);
>    pragma Import (C, Q);

You meant pragma Import (C, P);

Good question.
B.3/68:

"An Ada access T parameter, or an Ada out or in out parameter of an
elementary type T, is passed as a t* argument to a C function, where t
is the C type corresponding to the Ada type T."

This is the only guarantee concerning access types when interfacing
with C.
The paragraph is clearly constrained to those types that have some
corresponding type on the C side. For example access to
Interfaces.C.int will be passed as int*.
But I see nothing about access to types that have no C counterpart. In
particular, access values to class-wide types are not covered at all.

This is the reason why I think that passing address (seen as void* on
the C side) is the proper way.
All corrections to this reasoning are highly welcome.

--
Maciej Sobczak * www.msobczak.com * www.inspirel.com

Database Access Library for Ada: www.inspirel.com/soci-ada



^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Gem 39 - compiler specific?
  2009-09-05 20:45                     ` Maciej Sobczak
@ 2009-09-06  6:54                       ` sjw
  0 siblings, 0 replies; 20+ messages in thread
From: sjw @ 2009-09-06  6:54 UTC (permalink / raw)


On Sep 5, 9:45 pm, Maciej Sobczak <see.my.homep...@gmail.com> wrote:

> You meant pragma Import (C, P);

Yes

> B.3/68:
>
> "An Ada access T parameter, or an Ada out or in out parameter of an
> elementary type T, is passed as a t* argument to a C function, where t
> is the C type corresponding to the Ada type T."
>
> This is the only guarantee concerning access types when interfacing
> with C.
> The paragraph is clearly constrained to those types that have some
> corresponding type on the C side. For example access to
> Interfaces.C.int will be passed as int*.
> But I see nothing about access to types that have no C counterpart. In
> particular, access values to class-wide types are not covered at all.
>
> This is the reason why I think that passing address (seen as void* on
> the C side) is the proper way.
> All corrections to this reasoning are highly welcome.

The last time I had to do something like this, I said something like

with Ada.Streams;
package Accessing is

   type Stream_Access is access all
Ada.Streams.Root_Stream_Type'Class;
   for Stream_Access'Size use 32;

   procedure Pass (SA : Stream_Access);
   pragma Import (C, Pass);

end Accessing;

but that was a long time ago, and GNAT now says

accessing.ads:7:20: warning: "Pass.SA" involves a tagged type which
does not correspond to any C type

which is a pretty strong hint!



^ permalink raw reply	[flat|nested] 20+ messages in thread

end of thread, other threads:[~2009-09-06  6:54 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-09-02 20:38 Gem 39 - compiler specific? Maciej Sobczak
2009-09-02 23:20 ` Randy Brukardt
2009-09-03  7:26   ` Dmitry A. Kazakov
2009-09-03 15:26     ` Adam Beneschan
2009-09-03 16:38       ` Dmitry A. Kazakov
2009-09-03 17:27         ` Adam Beneschan
2009-09-03 20:26           ` Dmitry A. Kazakov
2009-09-03 22:06             ` Randy Brukardt
2009-09-04  7:29               ` Dmitry A. Kazakov
2009-09-04 12:07                 ` Maciej Sobczak
2009-09-04 13:06                   ` Dmitry A. Kazakov
2009-09-04 17:18                     ` Dmitry A. Kazakov
2009-09-04 20:34                     ` Maciej Sobczak
2009-09-04 22:41                   ` sjw
2009-09-05 20:45                     ` Maciej Sobczak
2009-09-06  6:54                       ` sjw
2009-09-03 21:58           ` Randy Brukardt
2009-09-04 17:26           ` Robert A Duff
2009-09-03 21:53     ` Randy Brukardt
2009-09-03  0:12 ` Adam Beneschan

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox