comp.lang.ada
 help / color / mirror / Atom feed
* Question about package Interfaces.
@ 2010-09-13  1:10 Peter C. Chapin
  2010-09-13  3:54 ` Robert A Duff
  0 siblings, 1 reply; 9+ messages in thread
From: Peter C. Chapin @ 2010-09-13  1:10 UTC (permalink / raw)


Really two questions...

My first question is about the types in package Interfaces such as
Integer_8, Unsigned_8, etc (I understand that the precise numbers
available depend on the implementation). The reference manual says this:

"[They are] signed and modular types of n bits, if supported by the
target architecture, for each n that is at least the size of a storage
element and that is a factor of the word size."

This is fine. However, I don't see anything in the reference manual that
requires these types to be represented by a specific number of bits. The
phrase "signed and modular types of n bits" is suggestive, I admit, but
does that also mean they are represented by exactly n bits in the
generated code? Would it be legal for a compiler to to store something
of type Unsigned_8 in a 16 bit object?

I guess I'm asking if the implementation required to behave as if the
representation clause

for Unsigned_8'Size use 8;

was in effect?

My second question is about the intrinsic Shift and Rotate functions in
package Interfaces. For example:

function Shift_Left
   (Value : Unsigned_8; Amount : Natural) return Unsigned_8;

About these functions the reference manual says:

"They operate on a bit-by-bit basis, using the binary representation of
the value of the operands to yield a binary representation for the result."

I don't see any description of what happens when the shift amount is
larger than the size of the object being shifted. For example;

Value : Interfaces.Unsigned_8;
...
Value := Interfaces.Shift_Left(Value, 1_000);

The reference manual does say, "For shifting, zero bits are shifted
in..." However, it has recently come to my attention that some
processors, such as Intel architecture machines, have shift instructions
that mask the shift count. For example, shifting a 32 bit operand by 32
bits results in an actual shift of 0 bits. Does that mean
implementations for such a system can't compile Interfaces.Shift_Left
into a single instruction but instead have to force "unlimited" shift
semantics on top of a hardware facility that doesn't do it that way?

The C standards says that attempting to shift an object of n bits by an
amount greater than or equal to n results in "undefined behavior." Thus
C compilers can just do what the hardware does in this situation. I can
see the potential efficiency advantage there.

Peter



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

* Re: Question about package Interfaces.
  2010-09-13  1:10 Question about package Interfaces Peter C. Chapin
@ 2010-09-13  3:54 ` Robert A Duff
  2010-09-13 13:47   ` Peter C. Chapin
  0 siblings, 1 reply; 9+ messages in thread
From: Robert A Duff @ 2010-09-13  3:54 UTC (permalink / raw)


"Peter C. Chapin" <chapinp@acm.org> writes:

> Really two questions...
>
> My first question is about the types in package Interfaces such as
> Integer_8, Unsigned_8, etc (I understand that the precise numbers
> available depend on the implementation). The reference manual says this:
>
> "[They are] signed and modular types of n bits, if supported by the
> target architecture, for each n that is at least the size of a storage
> element and that is a factor of the word size."
>
> This is fine. However, I don't see anything in the reference manual that
> requires these types to be represented by a specific number of bits. The
> phrase "signed and modular types of n bits" is suggestive, I admit, but
> does that also mean they are represented by exactly n bits in the
> generated code? Would it be legal for a compiler to to store something
> of type Unsigned_8 in a 16 bit object?
>
> I guess I'm asking if the implementation required to behave as if the
> representation clause
>
> for Unsigned_8'Size use 8;
>
> was in effect?

Unsigned_8'Size = 8.  But that does not mean that all objects
of subtype Unsigned_8 are 8 bits, nor that X'Size = 8
(where "X: Unsigned_8;").  For example, an object could
be stored in a 64-bit register.

A packed array A of Unsigned_8 will have A'Component_Size = 8,
and A(I)'Size = 8 for all I.

> My second question is about the intrinsic Shift and Rotate functions in
> package Interfaces. For example:
>
> function Shift_Left
>    (Value : Unsigned_8; Amount : Natural) return Unsigned_8;
>
> About these functions the reference manual says:
>
> "They operate on a bit-by-bit basis, using the binary representation of
> the value of the operands to yield a binary representation for the result."
>
> I don't see any description of what happens when the shift amount is
> larger than the size of the object being shifted. For example;
>
> Value : Interfaces.Unsigned_8;
> ...
> Value := Interfaces.Shift_Left(Value, 1_000);
>
> The reference manual does say, "For shifting, zero bits are shifted
> in..." However, it has recently come to my attention that some
> processors, such as Intel architecture machines, have shift instructions
> that mask the shift count. For example, shifting a 32 bit operand by 32
> bits results in an actual shift of 0 bits. Does that mean
> implementations for such a system can't compile Interfaces.Shift_Left
> into a single instruction but instead have to force "unlimited" shift
> semantics on top of a hardware facility that doesn't do it that way?

Yes, in general.  However, if the compiler knows that
the shift count is in a certain range it could optimize
to a single machine instruction, even on when the hardware
does something silly (as x86 does).

> The C standards says that attempting to shift an object of n bits by an
> amount greater than or equal to n results in "undefined behavior." Thus
> C compilers can just do what the hardware does in this situation. I can
> see the potential efficiency advantage there.

Ada doesn't say "undefined behavior" for this.  It prefers
sensible answers over efficiency.  But like I said, efficiency
is not lost, if the compiler is smart, and you declare
appropriate subranges.

- Bob



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

* Re: Question about package Interfaces.
  2010-09-13  3:54 ` Robert A Duff
@ 2010-09-13 13:47   ` Peter C. Chapin
  2010-09-13 14:15     ` Robert A Duff
  2010-09-14  6:33     ` J-P. Rosen
  0 siblings, 2 replies; 9+ messages in thread
From: Peter C. Chapin @ 2010-09-13 13:47 UTC (permalink / raw)


On 2010-09-12 23:54, Robert A Duff wrote:

> Unsigned_8'Size = 8.  But that does not mean that all objects
> of subtype Unsigned_8 are 8 bits, nor that X'Size = 8
> (where "X: Unsigned_8;").  For example, an object could
> be stored in a 64-bit register.
> 
> A packed array A of Unsigned_8 will have A'Component_Size = 8,
> and A(I)'Size = 8 for all I.

So I have to explicitly ask for a packed array in order to get this
guarantee? Is that true even if I declare a component type with an
explicit representation clause requesting an 8 bit size? I guess probably.

>> The reference manual does say, "For shifting, zero bits are shifted
>> in..." However, it has recently come to my attention that some
>> processors, such as Intel architecture machines, have shift instructions
>> that mask the shift count. For example, shifting a 32 bit operand by 32
>> bits results in an actual shift of 0 bits. Does that mean
>> implementations for such a system can't compile Interfaces.Shift_Left
>> into a single instruction but instead have to force "unlimited" shift
>> semantics on top of a hardware facility that doesn't do it that way?
> 
> Yes, in general.  However, if the compiler knows that
> the shift count is in a certain range it could optimize
> to a single machine instruction, even on when the hardware
> does something silly (as x86 does).

Okay, good to know. It's another argument in favor of sensible user
defined subtypes.

Thanks

Peter



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

* Re: Question about package Interfaces.
  2010-09-13 13:47   ` Peter C. Chapin
@ 2010-09-13 14:15     ` Robert A Duff
  2010-09-13 18:31       ` Peter C. Chapin
  2010-09-14  6:33     ` J-P. Rosen
  1 sibling, 1 reply; 9+ messages in thread
From: Robert A Duff @ 2010-09-13 14:15 UTC (permalink / raw)


"Peter C. Chapin" <chapinp@acm.org> writes:

>> A packed array A of Unsigned_8 will have A'Component_Size = 8,
>> and A(I)'Size = 8 for all I.
>
> So I have to explicitly ask for a packed array in order to get this
> guarantee? Is that true even if I declare a component type with an
> explicit representation clause requesting an 8 bit size? I guess probably.

You can say "for A'Component_Size use 8;".  For records,
you can specify the size of each component.  For standalone
objects, you can specify 'Size.

But my point was just that the 'Size of an object
is not guaranteed to be the same as the 'Size of
its subtype.

You might want to look into the GNAT-specific
'Object_Size attribute.

- Bob



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

* Re: Question about package Interfaces.
  2010-09-13 14:15     ` Robert A Duff
@ 2010-09-13 18:31       ` Peter C. Chapin
  2010-09-13 22:47         ` Robert A Duff
  0 siblings, 1 reply; 9+ messages in thread
From: Peter C. Chapin @ 2010-09-13 18:31 UTC (permalink / raw)


On 2010-09-13 10:15, Robert A Duff wrote:

> You can say "for A'Component_Size use 8;".  For records,
> you can specify the size of each component.  For standalone
> objects, you can specify 'Size.
> 
> But my point was just that the 'Size of an object
> is not guaranteed to be the same as the 'Size of
> its subtype.

Okay I think I'm understanding. So for example:

declare
   type Byte is mod 2**8;
   for Byte'Size use 8; -- The subtype has this size.

   X : Byte;            -- Could be more than 8 bits.
   for X'Size use 8;    -- Except no.. must be 8 bits (is this legal).

   type Byte_Array is array(Natural range <>) of Byte;
   for Byte_Array'Component_Size use 8;
                        -- Each array component is 8 bits.
begin
   null;
end;

When you say "object" I understand you to mean the in-memory
representation of an entity.

> You might want to look into the GNAT-specific
> 'Object_Size attribute.

I looked it up, thanks. It was helpful. So I see that at least one issue
is related to alignment. So in the Byte_Array declaration above, without
the Component_Size declaration the compiler could use, say, 16 bits for
each component to force word (2 byte) alignment on the components if it
thought there was some advantage in doing so. However, with the
Component_Size declaration the compiler must pack the components (since
all 8 bits are needed for the representation).

Does that sound right?

Peter



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

* Re: Question about package Interfaces.
  2010-09-13 18:31       ` Peter C. Chapin
@ 2010-09-13 22:47         ` Robert A Duff
  0 siblings, 0 replies; 9+ messages in thread
From: Robert A Duff @ 2010-09-13 22:47 UTC (permalink / raw)


"Peter C. Chapin" <chapinp@acm.org> writes:

> Does that sound right?

Yeah, pretty much.

- Bob



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

* Re: Question about package Interfaces.
  2010-09-13 13:47   ` Peter C. Chapin
  2010-09-13 14:15     ` Robert A Duff
@ 2010-09-14  6:33     ` J-P. Rosen
  2010-09-14 16:36       ` Jeffrey Carter
  1 sibling, 1 reply; 9+ messages in thread
From: J-P. Rosen @ 2010-09-14  6:33 UTC (permalink / raw)


Le 13/09/2010 15:47, Peter C. Chapin a �crit :
> On 2010-09-12 23:54, Robert A Duff wrote:
> 
>> Unsigned_8'Size = 8.  But that does not mean that all objects
>> of subtype Unsigned_8 are 8 bits, nor that X'Size = 8
>> (where "X: Unsigned_8;").  For example, an object could
>> be stored in a 64-bit register.
>>
>> A packed array A of Unsigned_8 will have A'Component_Size = 8,
>> and A(I)'Size = 8 for all I.
> 
> So I have to explicitly ask for a packed array in order to get this
> guarantee? 
I don't know exactly what you want to achieve, but bear in mind that
talking about the size of a single variable is meaningless.

Imagine that you declared:
X : Unsigned_8;
and you discover that the declaration advances the data counter by 4
bytes. You can interpret that as X occupying 32 bits, or as X occupying
only 8 bits with 3 unused padding bytes ahead of it.

There is positively no way to tell the difference.
-- 
---------------------------------------------------------
           J-P. Rosen (rosen@adalog.fr)
Visit Adalog's web site at http://www.adalog.fr



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

* Re: Question about package Interfaces.
  2010-09-14  6:33     ` J-P. Rosen
@ 2010-09-14 16:36       ` Jeffrey Carter
  2010-09-14 17:01         ` J-P. Rosen
  0 siblings, 1 reply; 9+ messages in thread
From: Jeffrey Carter @ 2010-09-14 16:36 UTC (permalink / raw)


On 09/13/2010 11:33 PM, J-P. Rosen wrote:
>
> Imagine that you declared:
> X : Unsigned_8;
> and you discover that the declaration advances the data counter by 4
> bytes. You can interpret that as X occupying 32 bits, or as X occupying
> only 8 bits with 3 unused padding bytes ahead of it.
>
> There is positively no way to tell the difference.

You could examine the machine code to see if it does 4-byte or 1-byte load and 
stores.

This might be important if X were, say, a memory-mapped control register for a 
H/W device. But then, I'd expect to see

for X'Size use 8;
for X'Address use ...;

-- 
Jeff Carter
"To Err is human, to really screw up, you need C++!"
St�phane Richard
63

--- news://freenews.netfront.net/ - complaints: news@netfront.net ---



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

* Re: Question about package Interfaces.
  2010-09-14 16:36       ` Jeffrey Carter
@ 2010-09-14 17:01         ` J-P. Rosen
  0 siblings, 0 replies; 9+ messages in thread
From: J-P. Rosen @ 2010-09-14 17:01 UTC (permalink / raw)


Le 14/09/2010 18:36, Jeffrey Carter a �crit :
> On 09/13/2010 11:33 PM, J-P. Rosen wrote:
>>
>> Imagine that you declared:
>> X : Unsigned_8;
>> and you discover that the declaration advances the data counter by 4
>> bytes. You can interpret that as X occupying 32 bits, or as X occupying
>> only 8 bits with 3 unused padding bytes ahead of it.
>>
>> There is positively no way to tell the difference.
> 
> You could examine the machine code to see if it does 4-byte or 1-byte
> load and stores.
> 
Not exactly.
A compiler is allowed to overwrite unused bytes if it makes code more
efficient


-- 
---------------------------------------------------------
           J-P. Rosen (rosen@adalog.fr)
Visit Adalog's web site at http://www.adalog.fr



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

end of thread, other threads:[~2010-09-14 17:01 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-09-13  1:10 Question about package Interfaces Peter C. Chapin
2010-09-13  3:54 ` Robert A Duff
2010-09-13 13:47   ` Peter C. Chapin
2010-09-13 14:15     ` Robert A Duff
2010-09-13 18:31       ` Peter C. Chapin
2010-09-13 22:47         ` Robert A Duff
2010-09-14  6:33     ` J-P. Rosen
2010-09-14 16:36       ` Jeffrey Carter
2010-09-14 17:01         ` J-P. Rosen

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