comp.lang.ada
 help / color / mirror / Atom feed
* Is this a GNAT bug???
@ 2002-04-26 16:36 Robert Quinn
  2002-04-26 17:48 ` Mark Johnson
  0 siblings, 1 reply; 21+ messages in thread
From: Robert Quinn @ 2002-04-26 16:36 UTC (permalink / raw)


I originally posted a question regarding pragma pack, but after
stripping away all the details I found what may be a bug, or just
something I don't understand about low level programming.  I will post
it, and it is brief code, but in a nutshell an array of 64 bits packs
fine, but an array of 65 bits does not!

I will post code here that is actually compilable, unlike my last
message :)

I am using gnat3.13p on Sparc Solaris

Here is the WORKING, NO ERRORS code:

package test is
   type ONE_BIT_TYPE is range 0..1;
   for ONE_BIT_TYPE'SIZE use 1;

   type ARRAY_OF_64_BITS_TYPE is array (1..64) of ONE_BIT_TYPE;
   pragma pack (ARRAY_OF_BITS_TYPE);

   type MY_TYPE is record
      ARRAY_OF_64_BITS : ARRAY_OF_64_BITS_TYPE;
   end record;

   pragma pack (MY_TYPE);

   for MY_TYPE use record
      ARRAY_OF_64_BITS at 0 range 0..63;
   end record;

end test;

** NOW just replace 64 with 65 (and 63 with 64 on range) and Voila',
you get the error:
  "size of ARRAY_OF_65_BITS too small, minimum allowed is 72"

Here is the OFFENDING code:

package test is
   type ONE_BIT_TYPE is range 0..1;
   for ONE_BIT_TYPE'SIZE use 1;

   type ARRAY_OF_65_BITS_TYPE is array (1..65) of ONE_BIT_TYPE;
   pragma pack (ARRAY_OF_BITS_TYPE);

   type MY_TYPE is record
      ARRAY_OF_65_BITS : ARRAY_OF_65_BITS_TYPE;
   end record;

   pragma pack (MY_TYPE);

   for MY_TYPE use record
      ARRAY_OF_65_BITS at 0 range 0..64;
   end record;

end test;


So why can't I pack a bit array of 65 bits or more bits? Anyone have
any comments?



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

* Re: Is this a GNAT bug???
  2002-04-26 16:36 Is this a GNAT bug??? Robert Quinn
@ 2002-04-26 17:48 ` Mark Johnson
  2002-04-26 22:20   ` Robert Dewar
  2002-04-29 15:45   ` Robert Quinn
  0 siblings, 2 replies; 21+ messages in thread
From: Mark Johnson @ 2002-04-26 17:48 UTC (permalink / raw)


Robert Quinn wrote:
> 
[snip - code for 64 bit packed array & record ]
> ** NOW just replace 64 with 65 (and 63 with 64 on range) and Voila',
> you get the error:
>   "size of ARRAY_OF_65_BITS too small, minimum allowed is 72"
> 
[snip - same code w/ 65 bits...]
> So why can't I pack a bit array of 65 bits or more bits? Anyone have
> any comments?

You can pack them, but you cannot expect them to take only 65 bits. I
can't seem to find the specific ARM clause that applies; the closest I
found is 13.3(43) which states...
 A Size clause should be supported for an object if the specified Size
is at least as large as its subtype 'Size, and corresponds to a size in
storage elements that is a multiple of the object's Alignment (if the
Alignment is nonzero).
I'm kind of surprised not to find similar text when the ARM defines
'Size for a subtype.

The Alignment of Array_Of_65_Bits_Type is most likely 1, a storage
element is most likely 8 bits, so rounding up the Size to 72 can be
required by the compiler. I don't know if this was implemented in 3.13p,
but try adding -gnatR to the command line. If implemented, the compiler
will print out the representation information for the arrays and
records. The output I get from 3.15a is that Array_of_65_Bits_Type'Size
is 72 and 'Alignment is 1. Check the GNAT user's guide for more
information.

You may also find that pragma Pack does not do as much in GNAT as you
might hope. I have a long running argument w/ Robert Dewar on a
relatively recent change in GNAT 3.15 that caused some of our packed
arrays to grow in size. He points to text in 13.2 which states "the
implementation may, but need not, reorder components or cross aligned
word boundaries to improve packing".
  --Mark



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

* Re: Is this a GNAT bug???
  2002-04-26 17:48 ` Mark Johnson
@ 2002-04-26 22:20   ` Robert Dewar
  2002-04-29 15:45   ` Robert Quinn
  1 sibling, 0 replies; 21+ messages in thread
From: Robert Dewar @ 2002-04-26 22:20 UTC (permalink / raw)


Mark Johnson <mark_h_johnson@raytheon.com> wrote in message news:<3CC992D6.A87A3443@raytheon.com>...

> You may also find that pragma Pack does not do as much in GNAT as you
> might hope. I have a long running argument w/ Robert Dewar on a
> relatively recent change in GNAT 3.15 that caused some of our packed
> arrays to grow in size. He points to text in 13.2 which states "the
> implementation may, but need not, reorder components or cross aligned
> word boundaries to improve packing".

Actually you should not in general use Pack to specify a specific
layout.
In some very restricted cases (arrays with component sizes 1,2,4) the
effect of pragma Pack is defined, but in all other cases (records, and
arrays with
other component sizes), the effect of Pack is very much implementation
dependent. Basically what Pack says is "favor space in doing your
tradeoffs
between space and speed", but it is not any more definite than that.

If the exact layout is critical, you should use component size for
arrays
or a record representation clause for records. You should also be
careful
to specify sizes *AND* alignments for types where layout is critical
(Mark's
packed arrays got larger in GNAT 3.15 because there were some
instances of
records with no alignment clause, and GNAT 3.15 tends to favor speed
over
space when choosing default alignments (that's because modern
architectures
are *SO* dependent on alignment, we have programs that run ten times
faster
on 3.15 than on 3.14, just because of alignment. GNAT also likes to
maintain
alignment wherever possible, and does NOT let pragma Pack override an 
alignment in cases where this would degrade the code.

The moral of this story is that if you want to control things
yourself, rather
than rely on the default compiler choices, then take advantage of a
feature
that Ada has (and C sorely lacks). Specify your own sizes and
alignments and
don't depend on default choices of the compiler. The trouble with the
default
choices is that they will never satisfy everyone, and of course the
defaults
may change. We don't casually change defaults, but in this case, the
gain was
so huge that it seemed worthwhile, and we found only two or three
customers
whose code was depending on default alignment choices, with the fix
being to
specify the missing alignment clause.

Mark is right in his analysis of this particular case. This is by the
way another case where people should read the manual. Don't use rep
clauses in
GNAT without reading the section on rep clauses is a reasonable rule.

Oh, and this is also a good lesson in not approximating when you post
code to
CLA. You don't know what is important and what is not. In this case
the difference between 5 and 65 bits was a huge one. Read the manual
to understand
why!

Robert Dewar
Ada Core Technologies



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

* Re: Is this a GNAT bug???
  2002-04-26 17:48 ` Mark Johnson
  2002-04-26 22:20   ` Robert Dewar
@ 2002-04-29 15:45   ` Robert Quinn
  2002-04-30  2:44     ` Robert Dewar
  1 sibling, 1 reply; 21+ messages in thread
From: Robert Quinn @ 2002-04-29 15:45 UTC (permalink / raw)


Mark Johnson <mark_h_johnson@raytheon.com> wrote in message news:<3CC992D6.A87A3443@raytheon.com>...

> [snip] the closest I
> found is 13.3(43) which states...
>  A Size clause should be supported for an object if the specified Size
> is at least as large as its subtype 'Size, and corresponds to a size in
> storage elements that is a multiple of the object's Alignment (if the
> Alignment is nonzero).
> I'm kind of surprised not to find similar text when the ARM defines
> 'Size for a subtype.
> 
> The Alignment of Array_Of_65_Bits_Type is most likely 1, a storage
> element is most likely 8 bits, so rounding up the Size to 72 can be
> required by the compiler. 

Yes, the alignment is 1.  This doesn't make sense to me.  Why can I
specify any size I want, up to size 64, but arrays over 64 bits have
to have a size as a multiple of 8?  What is so special about 64 bits
or less?

I notice the following pattern with alignment/size:

# of bits in array               Alignment
    1 - 8                            1
    9 - 16                           2
    17 - 32                          4
    33 - 64                          8
       > 64                          1

I've tried setting the Alignment for a 65 bit array to 16, but that
doesn't help.

What I appear to be discovering is that, with Gnat on my unix
platform, you cannot specify the exact size greater than 64 of a type.
(Unless the size just happens to be a multiple of 8)

I tried the same thing on a VADS compiler without any problem, so it
must be just Gnat.

Anyone have any comments?

Thanks
Robert Quinn



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

* Re: Is this a GNAT bug???
  2002-04-29 15:45   ` Robert Quinn
@ 2002-04-30  2:44     ` Robert Dewar
  2002-04-30 14:15       ` Larry Kilgallen
  2002-04-30 16:41       ` Robert Quinn
  0 siblings, 2 replies; 21+ messages in thread
From: Robert Dewar @ 2002-04-30  2:44 UTC (permalink / raw)


robert_s_quinn@yahoo.com (Robert Quinn) wrote in message news:<db500a4f.0204290745.3cf7d2d@posting.google.com>...
> Mark Johnson <mark_h_johnson@raytheon.com> wrote in message news:<3CC992D6.A87A3443@raytheon.com>...

> Yes, the alignment is 1.  This doesn't make sense to me.  Why can I
> specify any size I want, up to size 64, but arrays over 64 bits have
> to have a size as a multiple of 8?  What is so special about 64 bits
> or less?

The language of rep clauses allows you to specify all sorts of things
that might not actually be allowed by a given compiler, e.g.

   type r is range 0 .. 1;
   for r'size use 999999999999999999999;

   for q'alignment use 43;

   for l'component'size use 83;

So the question is what set of rep clauses is implemented by a given compiler.
If you have an annex C compliant compiler, then there is a certainly well
defined subset which must be implemented. By staying within this subset you
achieve greater portability. Once you stray outside this subset, you are 
writing non-portable code that is implementation dependent. It does not
mean that your code is nonsense, just that it may not be implemented.

No two compilers have exactly the same set of allowed rep clauses. For instance
in comparing VADS and GNAT, there are clauses that VADS accepts that GNAT does
not (you identify one such in your message), and there are many clauses that
GNAT accepts that VADS does not (including all the new Ada 95 stuff :-)

Now if you are asking specifically in this case why GNAT does not implement
the non-portable rep clause you wish to use, the answer is that we can't
implement everything, so we implement what is most useful to our customers,
considered against the implementation cost.

If you were a customer of ACT, and willing to pay for this feature to be
added, no doubt ACT could be persuaded to accomodate you :-)

If your legacy code depends on particular rep clauses being supported, then
you had better pick a compiler that supports them. In fact GNAT supports almost
all the rep clauses supported by VADS precisely because we have many customers
who have converted legacy VADS code to GNAT. It just turns out that this 
particular case has not arisen in a significant manner.

Robert Dewar
Ada Core Technologies



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

* Re: Is this a GNAT bug???
  2002-04-30  2:44     ` Robert Dewar
@ 2002-04-30 14:15       ` Larry Kilgallen
  2002-04-30 16:41       ` Robert Quinn
  1 sibling, 0 replies; 21+ messages in thread
From: Larry Kilgallen @ 2002-04-30 14:15 UTC (permalink / raw)


In article <5ee5b646.0204291844.21d7f5f0@posting.google.com>, dewar@gnat.com (Robert Dewar) writes:

> If you were a customer of ACT, and willing to pay for this feature to be
> added, no doubt ACT could be persuaded to accomodate you :-)

In fact, when you agreed to pay for the feature, you would become
a customer of ACT :-)



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

* Re: Is this a GNAT bug???
  2002-04-30  2:44     ` Robert Dewar
  2002-04-30 14:15       ` Larry Kilgallen
@ 2002-04-30 16:41       ` Robert Quinn
  2002-04-30 18:20         ` tmoran
  2002-04-30 21:55         ` Mark Johnson
  1 sibling, 2 replies; 21+ messages in thread
From: Robert Quinn @ 2002-04-30 16:41 UTC (permalink / raw)


dewar@gnat.com (Robert Dewar) wrote in message 

> So the question is what set of rep clauses is implemented by a given compiler.
> [snip] By staying within this subset you
> achieve greater portability. Once you stray outside this subset, you are 
> writing non-portable code that is implementation dependent. It does not
> mean that your code is nonsense, just that it may not be implemented.

Well that makes sense and I appreciate your reply.  I suppose if I
needed this feature I could work something out with ACT.

I guess the scenario I'm thinking of must not occur too frequently. 
I'll use specific numbers to make the example simple.  Suppose you
have a sequence of 12 bytes 94 bits).  Suppose the first and last byte
are header/tail info, leaving 10 bytes for data.  Suppose 65 bits of
the 10 bytes represent one kind of data, the remaining 13 bits another
kind of data.  It would be nice if you could convert this series of
bytes into a record, for example of the form:

type Message_Type is record
   Header_Data    : Header_Data_Type;
   Data_Element_1 : Data_Element_1_Type;
   Date_Element_2 : Data_Element_2_Type;
   Tail_Data      : Tail_Data_Type;
end record;
for Message_Type use record
   Header_Data at 0 range 0 .. 7;
   Data_Element_1 at 0 range 8 .. 72;
   Data_Element_2 at 0 range 73 .. 85;
   Tail_Data at 0 range 86 .. 93;
end record;

I could convert the sequence of bytes to an access type to this
record.  For example:

type Message_Type_Access is access Message_Type;
function Get_Message_Data is new Unchecked_Conversion
   (SOURCE => System.ADDRESS,
    TARGET => Message_Type_Access);

So the way to handle this same situation with Gnat would be to NOT use
the Unchecked_Conversion, but to make Data_Element_1 larger and just
try to read the bits right out of memory into Data_Element_1.

So reading a sequence of bits >= 65 bits out of memory is just always
going to be more work since you cannot convert it directly into a
type, right?

Ok, I can accept this.  Thanks for your insight, and for the etiquette
pointers on posting.  Please let me know if you have anything to add
to my remarks.

Robert Quinn



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

* Re: Is this a GNAT bug???
  2002-04-30 16:41       ` Robert Quinn
@ 2002-04-30 18:20         ` tmoran
  2002-05-01  1:31           ` Robert Quinn
  2002-04-30 21:55         ` Mark Johnson
  1 sibling, 1 reply; 21+ messages in thread
From: tmoran @ 2002-04-30 18:20 UTC (permalink / raw)


> type Message_Type_Access is access Message_Type;
> function Get_Message_Data is new Unchecked_Conversion
>    (SOURCE => System.ADDRESS,
>     TARGET => Message_Type_Access);
  This is not good Ada.  You almost certainly want to convert an
access type for one way of looking at the data to an access type
for a different way.  No "system.address" involved.  If, most
unusually, you actually do need to convert a System.Address to
an access type, use the standard System.Address_To_Access_Conversions,
which is defined exactly for that purpose, and which the compiler
will implement so it actually works.  There is no reason to
assume an unchecked conversion from System.Address to an access
type will work as you hope.



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

* Re: Is this a GNAT bug???
  2002-04-30 16:41       ` Robert Quinn
  2002-04-30 18:20         ` tmoran
@ 2002-04-30 21:55         ` Mark Johnson
  2002-05-01 22:59           ` Nick Roberts
  1 sibling, 1 reply; 21+ messages in thread
From: Mark Johnson @ 2002-04-30 21:55 UTC (permalink / raw)


Robert Quinn wrote:
> [snip]
> I guess the scenario I'm thinking of must not occur too frequently.
> I'll use specific numbers to make the example simple.  Suppose you
> have a sequence of 12 bytes 94 bits).  Suppose the first and last byte
> are header/tail info, leaving 10 bytes for data.  Suppose 65 bits of
> the 10 bytes represent one kind of data, the remaining 13 bits another
> kind of data.
This is going to be hard on several platforms - especially if
portability is to be considered. We are in the process of rehosting a
large SGI application (VADS) to PC's (GNAT) and we have several places
in our code where we had to address bit and byte order differences.
Annex C compliance means that all the Section 13 recommendations are
supported. What you describe does not appear to fit those
recommendations.

You may be better off with declarations that define the "data" in
smaller chunks (e.g., a sequence of bytes) and use functions to extract
and fill in the values needed. For example, based on the default bit
order, the array you defined can be represented in the following ways on
a big & little endian machine.

Big endian (Bit_Order == System.High_Order_First)
Byte 00000000 11111111 22222222 33333333 ...
Bit  01234567 01234567 01234567 01234567 ...
Ind  00000000 00111111 11112222 22222233
-ex  01234567 89012345 67890123 45678901

Little endian (Bit_Order == System.Low_Order_First)
Byte 00000000 11111111 22222222 33333333 ...
Bit  76543210 76543210 76543210 76543210 ...
Ind  00000000 11111100 22221111 33222222
-ex  76543210 54321098 32109876 10987654

Where the byte & bit offset are the first two rows & the last two rows
represent the index into the bit array (0..31 shown). Basically the rule
is to normalize to "Storage_Unit" (in this case 8) and then use the
specified (usually default) bit order for the order of bits. The
annotated ARM (13.5.1 and 13.5.2) has more explanation of this if
needed.

We had a few cases of these & had to swap the bits and the bytes [sigh]
to otherwise preserve the coding style. In other cases, we were able to
override the default bit order and get what we wanted. For type T, you
can set T'Bit_Order to High or Low_Order_First, but that doesn't solve
all the problems - I can list a few if needed.

Putting a level of abstraction around the data is probably best to hide
this kind of manipulation.

[snip]
> I could convert the sequence of bytes to an access type to this
> record.  For example:
> 
> type Message_Type_Access is access Message_Type;
> function Get_Message_Data is new Unchecked_Conversion
>    (SOURCE => System.ADDRESS,
>     TARGET => Message_Type_Access);
> 
How about System.Address_To_Access_Conversions [13.7.2] instead? Read
the definition carefully, we screwed up one one such conversion when
making the change.

[snip]

> So reading a sequence of bits >= 65 bits out of memory is just always
> going to be more work since you cannot convert it directly into a
> type, right?
> 
Actually, depending on the platform, 65 may be 33 - or in the future
129. Another reason to try to encapsulate the awful code and hide it
from the rest of your application.
  --Mark



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

* Re: Is this a GNAT bug???
  2002-04-30 18:20         ` tmoran
@ 2002-05-01  1:31           ` Robert Quinn
  2002-05-01 17:08             ` Ted Dennison
  0 siblings, 1 reply; 21+ messages in thread
From: Robert Quinn @ 2002-05-01  1:31 UTC (permalink / raw)


tmoran@acm.org wrote in message news:<9gBz8.4053$451.2378814669@newssvr21.news.prodigy.com>...

> > type Message_Type_Access is access Message_Type;
> > function Get_Message_Data is new Unchecked_Conversion
> >    (SOURCE => System.ADDRESS,
> >     TARGET => Message_Type_Access);

>   This is not good Ada.  [snip] There is no reason to
> assume an unchecked conversion from System.Address to an access
> type will work as you hope.

Ahh, thanks for the note.  I used the Unchecked_Conversion out of
ignorance and habit, since the system I actually work on uses it a
lot.  Addresses are passed between tasks and then converted to an
appropriate access type.  Or sometimes data is read off a socket, an
address passed to a task, then converted to an appropriate access
type.  So I've seen this method used for both intertask communications
and for client-server communications.

Anyway I seledom delve into this realm, which is why I'm asking
questions - thanks!

Robert Quinn



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

* Re: Is this a GNAT bug???
  2002-05-01  1:31           ` Robert Quinn
@ 2002-05-01 17:08             ` Ted Dennison
  2002-05-02  1:55               ` Larry Kilgallen
  0 siblings, 1 reply; 21+ messages in thread
From: Ted Dennison @ 2002-05-01 17:08 UTC (permalink / raw)


robert_s_quinn@yahoo.com (Robert Quinn) wrote in message news:<db500a4f.0204301731.391cd20a@posting.google.com>...
> tmoran@acm.org wrote in message news:<9gBz8.4053$451.2378814669@newssvr21.news.prodigy.com>...
> >   This is not good Ada.  [snip] There is no reason to
> > assume an unchecked conversion from System.Address to an access
> > type will work as you hope.

...unless your vendor docs say it will. It will render your code
non-portable, but sometimes you might not care. Personally, I'd go for
the portable way though.

> Ahh, thanks for the note.  I used the Unchecked_Conversion out of
> ignorance and habit, since the system I actually work on uses it a
> lot.  Addresses are passed between tasks and then converted to an
> appropriate access type.  Or sometimes data is read off a socket, an
> address passed to a task, then converted to an appropriate access
> type.  So I've seen this method used for both intertask communications
> and for client-server communications.

That was probably old Ada83 code. Folks did that stuff a lot in Ada83,
as there was no other good way to get a pointer to a stack object.

Today, we would use 'Access (or 'Unchecked_Access), and keep
everything nice and type-safe.

Passing addresess or accesses between tasks seems kinda dangerous. I
don't know what their code did, so perhaps they carefully analyzed
things, discovered that for some arcane reason this was the only way
to pass their data, and made sure to access the contents safely.
However, if I were a betting man, I'd be willing to wadger quite a bit
that they did this because they stupidly thought Ada didn't pass
parameters by reference (like older C doesn't), and that they have a
race-condition in there. You certianly shouldn't clone such code
yourself unless you really know what you are doing.


-- 
T.E.D. 
Home     -  mailto:dennison@telepath.com (Yahoo: Ted_Dennison)
Homepage -  http://www.telepath.com/dennison/Ted/TED.html



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

* Re: Is this a GNAT bug???
  2002-04-30 21:55         ` Mark Johnson
@ 2002-05-01 22:59           ` Nick Roberts
  2002-05-02 13:56             ` Mark Johnson
  0 siblings, 1 reply; 21+ messages in thread
From: Nick Roberts @ 2002-05-01 22:59 UTC (permalink / raw)


On Tue, 30 Apr 2002 16:55:53 -0500, Mark Johnson
<mark_h_johnson@raytheon.com> wrote:

>Big endian (Bit_Order == System.High_Order_First)
>Byte 00000000 11111111 22222222 33333333 ...
>Bit  01234567 01234567 01234567 01234567 ...
>Ind  00000000 00111111 11112222 22222233
>-ex  01234567 89012345 67890123 45678901
>
>Little endian (Bit_Order == System.Low_Order_First)
>Byte 00000000 11111111 22222222 33333333 ...
>Bit  76543210 76543210 76543210 76543210 ...
>Ind  00000000 11111100 22221111 33222222
>-ex  76543210 54321098 32109876 10987654

My version of the above would be:

Big endian (Bit_Order == System.High_Order_First)
Byte   00000000 11111111 22222222 33333333 ...
Bit8V  76543210 76543210 76543210 76543210 ...
Bit8L  12345678 12345678 12345678 12345678 ...
Bit16H 00000000 01111111 00000000 01111111 ...
Bit16L 12345678 90123456 12345678 90123456 ...
Bit32H 00000000 01111111 11122222 22222233 ...
Bit32L 12345678 90123456 78901234 56789012 ...
Ind    00000000 00111111 11112222 22222233 ...
-ex    01234567 89012345 67890123 45678901 ...

Little endian (Bit_Order == System.Low_Order_First)
Byte   00000000 11111111 22222222 33333333 ...
Bit8V  76543210 76543210 76543210 76543210 ...
Bit8L  76543210 76543210 76543210 76543210 ...
Bit16H 00000000 11111100 00000000 11111100 ...
Bit16L 76543210 54321098 76543210 54321098 ...
Bit32H 00000000 11111100 22221111 33222222 ...
Bit32L 76543210 54321098 32109876 10987654 ...
Ind    00000000 11111100 22221111 33222222 ...
-ex    76543210 54321098 32109876 10987654 ...

where in both cases Bit8V n is defined as contributing 2^n to the
value of the byte as an unsigned integer (value 0 to 255).

I have added the rows Bit8L, Bit16H/L, and Bit32H/L to both cases,
which show what the conventional bit numbering would be on a machine
of the given endianness for a unsigned byte, 16-bit and 32-bit integer
in memory. (H is for the higher decimal digit, L for the lower.)

Am I actually correct?




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

* Re: Is this a GNAT bug???
  2002-05-01 17:08             ` Ted Dennison
@ 2002-05-02  1:55               ` Larry Kilgallen
  2002-05-02 14:04                 ` Mark Johnson
  0 siblings, 1 reply; 21+ messages in thread
From: Larry Kilgallen @ 2002-05-02  1:55 UTC (permalink / raw)


In article <4519e058.0205010908.7ebc64fd@posting.google.com>, dennison@telepath.com (Ted Dennison) writes:
> robert_s_quinn@yahoo.com (Robert Quinn) wrote in message news:<db500a4f.0204301731.391cd20a@posting.google.com>...
>> tmoran@acm.org wrote in message news:<9gBz8.4053$451.2378814669@newssvr21.news.prodigy.com>...
>> >   This is not good Ada.  [snip] There is no reason to
>> > assume an unchecked conversion from System.Address to an access
>> > type will work as you hope.
> 
> ...unless your vendor docs say it will. It will render your code
> non-portable, but sometimes you might not care. Personally, I'd go for
> the portable way though.

Portability in this regard is not so important if the rest of the
program is specific to a particular environment for other reasons.



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

* Re: Is this a GNAT bug???
  2002-05-01 22:59           ` Nick Roberts
@ 2002-05-02 13:56             ` Mark Johnson
  2002-05-02 20:19               ` Nick Roberts
  0 siblings, 1 reply; 21+ messages in thread
From: Mark Johnson @ 2002-05-02 13:56 UTC (permalink / raw)


Nick Roberts wrote:
> 
> On Tue, 30 Apr 2002 16:55:53 -0500, Mark Johnson
> <mark_h_johnson@raytheon.com> wrote:
> [both examples snipped]
> 
> Am I actually correct?

I believe so, but I am not sure what you are trying to show with your
examples - the values as loaded into a register? I was showing the in
memory representation of the data for the two byte orders. Note that it
takes different code to solve the "equivalence problem" for in memory
and in register representations.

If you were trying to show the in register data (as an 8, 16, and 32 bit
value) I suggest a different layout of the data to make it more clear to
the reader. Something like...

Big endian (Bit_Order == System.High_Order_First)
16 bit value...
Byte 00000000 11111111
Bit  01234567 01234567
Ind  00000000 00111111
-ex  01234567 89012345

32 bit value...
Byte 00000000 11111111 22222222 33333333
Bit  01234567 01234567 01234567 01234567
Ind  00000000 00111111 11112222 22222233
-ex  01234567 89012345 67890123 45678901

Little endian (Bit_Order == System.Low_Order_First)
16 bit value...
Byte 11111111 00000000 
Bit  76543210 76543210
Ind  11111100 00000000
-ex  54321098 76543210

32 bit value...
Byte 33333333 22222222 11111111 00000000 ...
Bit  76543210 76543210 76543210 76543210 ...
Ind  33222222 22221111 11111100 00000000 
-ex  10987654 32109876 54321098 76543210 

Which more clearly shows that the bytes are swapped when the data from
memory is loaded into a register and shows the relative position (2^n as
you described) of each bit within the 16 or 32 bit value. For example,
on a big endian machine index 0 is the most significant bit and on a
little endian machine it is the least significant bit.

For problems where you interface with C programs - values are often
represented in header files as bits shifted so this way of looking at
the problem is often better. However, many Ada programs must be able to
read a stream of bytes and manipulate the data in those streams. In
those cases the in memory way of looking at the problem tends to be
better.
  --Mark



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

* Re: Is this a GNAT bug???
  2002-05-02  1:55               ` Larry Kilgallen
@ 2002-05-02 14:04                 ` Mark Johnson
  2002-05-02 15:25                   ` Larry Kilgallen
  0 siblings, 1 reply; 21+ messages in thread
From: Mark Johnson @ 2002-05-02 14:04 UTC (permalink / raw)


Larry Kilgallen wrote:
> 
> Portability in this regard is not so important if the rest of the
> program is specific to a particular environment for other reasons.

Don't discount the need for portability. I have worked on at least two
projects in the last 10 years where we moved code that was over 8-10
years old between platforms. The first one replaced a system with 2 on
site support engineers and < 100 hour MTBF with a system that had on
call support and > 1700 hour MTBF. The second system has >$300k/year
maintenance and the replacement hardware cost about $200k. Making it
easy to do the move can be done without a significant cost today - if
you use the right methods.
  --Mark



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

* Re: Is this a GNAT bug???
  2002-05-02 14:04                 ` Mark Johnson
@ 2002-05-02 15:25                   ` Larry Kilgallen
  0 siblings, 0 replies; 21+ messages in thread
From: Larry Kilgallen @ 2002-05-02 15:25 UTC (permalink / raw)


In article <3CD1475B.482F5E85@raytheon.com>, Mark Johnson <mark_h_johnson@raytheon.com> writes:
> Larry Kilgallen wrote:
>> 
>> Portability in this regard is not so important if the rest of the
>> program is specific to a particular environment for other reasons.
> 
> Don't discount the need for portability. I have worked on at least two
> projects in the last 10 years where we moved code that was over 8-10
> years old between platforms. The first one replaced a system with 2 on
> site support engineers and < 100 hour MTBF with a system that had on
> call support and > 1700 hour MTBF. The second system has >$300k/year
> maintenance and the replacement hardware cost about $200k. Making it
> easy to do the move can be done without a significant cost today - if
> you use the right methods.

Ok, I will be specific.

Software to interact with a particular operating system, the only
purpose being support of that operating system.



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

* Re: Is this a GNAT bug???
  2002-05-02 13:56             ` Mark Johnson
@ 2002-05-02 20:19               ` Nick Roberts
  2002-05-02 21:55                 ` Mark Johnson
  0 siblings, 1 reply; 21+ messages in thread
From: Nick Roberts @ 2002-05-02 20:19 UTC (permalink / raw)


On Thu, 02 May 2002 08:56:53 -0500, Mark Johnson
<mark_h_johnson@raytheon.com> wrote:

>> Am I actually correct?
>
>I believe so, but I am not sure what you are trying to show with your
>examples - the values as loaded into a register? I was showing the in
>memory representation of the data for the two byte orders. Note that it
>takes different code to solve the "equivalence problem" for in memory
>and in register representations.

I wasn't trying to show values as loaded into registers, Mark. I was
trying to show the difference in the ways in which big-endian and
little-endian machines store their integers in memory. The Bit?H/L
rows were intended to show the bit numberings of the data as it would
be numbered if loaded from memory into a register (8, 16, or 32-bit). 

As you infer, big and little-endianness is about both bit numbering
and byte ordering; I was trying to demonstrate the difference in byte
ordering as well as the difference in bit numbering.

The reason why I wanted to show the in-memory representation of 16 and
32-bit integers, as well as 8-bit ones (bytes), is because for some
machines (or Ada implementations) Streams.Stream_Element'Size could be
16 or 32 bits (rather than 8). Since the issue of endianness is most
likely to affect those doing stream-oriented I/O of a record type, the
way a 16 or 32-bit stream element is stored in memory is likely to be
of significance.

For those who may be wondering, Streams.Stream_Element'Size could of
course be something other than 8, 16, or 32. But then on such a
machine the issue of being big-endian or little-endian is irrelevant
(as the machine will be neither).

Note that the diagrams of both Mark and myself assume a storage
element size of 8 bits. If this is 16 or 32 bits, different diagrams
would be more appropriate.

Big endian (System.Storage_Size=16, Bit_Order=High_Order_First)
SE      0000000000000000 1111111111111111 ...
Bit16VH 1111110000000000 1111110000000000 ...
Bit16VL 5432109876543210 5432109876543210 ...
Bit16H  0000000001111111 0000000001111111 ...
Bit16L  1234567890123456 1234567890123456 ...
Bit32H  0000000001111111 1112222222222233 ...
Bit32L  1234567890123456 7890123456789012 ...
Ind     0000000000111111 1111222222222233 ...
-ex     0123456789012345 6789012345678901 ...

Little endian (System.Storage_Size=16, Bit_Order=Low_Order_First)
SE      0000000000000000 1111111111111111 ...
Bit16VH 1111110000000000 1111110000000000 ...
Bit16VL 5432109876543210 5432109876543210 ...
Bit16H  1111110000000000 1111110000000000 ...
Bit16L  5432109876543210 5432109876543210 ...
Bit32H  1111110000000000 3322222222221111 ...
Bit32L  5432109876543210 1098765432109876 ...
Ind     1111110000000000 3322222222221111 ...
-ex     5432109876543210 1098765432109876 ...

Big endian (System.Storage_Size=32, Bit_Order=High_Order_First)
Bit32VH 33222222222211111111110000000000 ...
Bit32VL 10987654321098765432109876543210 ...
Bit32H  00000000011111111112222222222233 ...
Bit32L  12345678901234567890123456789012 ...
Ind     00000000001111111111222222222233 ...
-ex     01234567890123456789012345678901 ...

Little endian (System.Storage_Size=32, Bit_Order=Low_Order_First)
Bit32VH 33222222222211111111110000000000 ...
Bit32VL 10987654321098765432109876543210 ...
Bit32H  33222222222211111111110000000000 ...
Bit32L  10987654321098765432109876543210 ...
Ind     33222222222211111111110000000000 ...
-ex     10987654321098765432109876543210 ...

Finally, I believe big-endian bit numbering conventionally starts from
1 (rather than 0), and I wanted to show this. (Of course, this is only
a convention. I think it is widespread, but certainly not universal.
The PowerPC is normally big-endian as regards byte ordering, but the
IBM documentation numbers the bits from 0 for the LSB to 31/63 for the
MSB; the situation is further confused by some PowerPCs being able to
operate in little-endian mode!)

But this can be a confusing subject, and (as I've proved several times
on comp.lang.ada) I'm not exactly immune to error. I hope the above
makes sense, but please say if it doesn't!




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

* Re: Is this a GNAT bug???
  2002-05-02 20:19               ` Nick Roberts
@ 2002-05-02 21:55                 ` Mark Johnson
  0 siblings, 0 replies; 21+ messages in thread
From: Mark Johnson @ 2002-05-02 21:55 UTC (permalink / raw)


Nick Roberts wrote:
> 
> I wasn't trying to show values as loaded into registers, Mark. I was
> trying to show the difference in the ways in which big-endian and
> little-endian machines store their integers in memory. The Bit?H/L
> rows were intended to show the bit numberings of the data as it would
> be numbered if loaded from memory into a register (8, 16, or 32-bit).
> 
I guess I look at the problem differently - I either...
 - care what order the bits and bytes are in memory OR
 - care what order the bits and bytes are in a register
I generally don't care what the register values look like in memory -
after all, I only manipulate them using registers. If I do a byte swap
at the interface to convert a 16 or 32 bit value from big to little
endian format, I get the appropriate value when loaded into a register.

I almost always care what format data is in memory when dealing with an
external interface - hence the emphasis on getting representation
clauses with bits and bytes correct in those cases. When the compiler
manipulates that data in registers, it hides the details from me.

> [snip]
> For those who may be wondering, Streams.Stream_Element'Size could of
> course be something other than 8, 16, or 32. But then on such a
> machine the issue of being big-endian or little-endian is irrelevant
> (as the machine will be neither).
> 
Not quite true. The PDP-10 was a big endian 36 bit machine (page 2-15,
PDP-10 System Reference Manual). The byte manipulation functions on that
system used bit zero as the most significant bit and allowed you to
extract "S" bits at an offset of "P" (actually 36-P). There were load
and deposit byte instructions w/ and w/o increment of the byte pointer.
You could easily manipulate a stream of 8 bit bytes (e.g., from mag
tape) but text was more often stored as five 7 bit bytes (one bit pad)
in each word.

I am not sure for other 36 bit machines what they used - I think Multics
(Honeywell DPS8/M) was also a big endian machine, but I couldn't find a
good reference at http://www.multicians.org/ to confirm that. Multics
stored text by the way as 9 bit bytes.

> [snip]
> Finally, I believe big-endian bit numbering conventionally starts from
> 1 (rather than 0), and I wanted to show this. (Of course, this is only
> a convention. I think it is widespread, but certainly not universal.
Sorry, the same example - the PDP-10 System Reference numbers bits in a
word from zero through 35. Actually, I think it depends more on the
original developer - were they a "C" or "Pascal" type of person :-).

  --Mark



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

* Is this a gnat bug?
@ 2003-09-20 22:50 Waldek Hebisch
  2003-09-20 23:09 ` Ludovic Brenta
  2003-09-21  2:37 ` Waldek Hebisch
  0 siblings, 2 replies; 21+ messages in thread
From: Waldek Hebisch @ 2003-09-20 22:50 UTC (permalink / raw)


I am trying to convert a sequence of eight bytes to a fixed point
number. For testing I put bytes in an array. I first collect bytes
in a modular type and then assign the result to an integer (I have
eight bytes in big endian order, but the actual number should be
small). When number formed from 4 lower order bytes is out of
range I get CONSTRAINT_ERROR but if only higher order bytes are
non-zero I get just zero result. I would expect CONSTRAINT_ERROR 
always when any of higher order bytes is non-zero. With both 
gnat-3.14p and gnat from gcc-3.3 the program below prints huge
number for 'pp' and 0.0 for 'price'. 

with Ada.Text_IO;

procedure tstnum is 
type fx15_2 is delta 0.01 range -9999999999999.99 .. 9999999999999.99 ;
type price_type is delta 0.01 digits 6;

procedure getnum(num : out price_type) is 
  type ll is mod 2**64;
  type ip is range 0 .. 1000000 ;
  type byteind is range 0 .. 7;
  bytes : array (byteind) of integer range 0 .. 255 := (0..3 => 247 , 4..7=>0);
  pp : ll := 0 ;
  pp1 : ip;
begin
        for i in bytes'range loop
	        pp := pp * 256;
		pp := pp + ll(bytes(i));
	end loop;
	Ada.Text_IO.Put_Line("pp = " & ll'image(pp));
	pp1 := ip(pp); -- Should range check ??
	num := price_type(fx15_2(pp1)/100);
end;

price : price_type;

begin
	getnum(price);
	Ada.Text_IO.Put_Line("price = " & price_type'image(price));
end tstnum;


--
                              Waldek Hebisch
hebisch@math.uni.wroc.pl    or hebisch@hera.math.uni.wroc.pl 



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

* Re: Is this a gnat bug?
  2003-09-20 22:50 Is this a gnat bug? Waldek Hebisch
@ 2003-09-20 23:09 ` Ludovic Brenta
  2003-09-21  2:37 ` Waldek Hebisch
  1 sibling, 0 replies; 21+ messages in thread
From: Ludovic Brenta @ 2003-09-20 23:09 UTC (permalink / raw)


hebisch@math.uni.wroc.pl (Waldek Hebisch) writes:

> I am trying to convert a sequence of eight bytes to a fixed point
> number. For testing I put bytes in an array. I first collect bytes
> in a modular type and then assign the result to an integer (I have
> eight bytes in big endian order, but the actual number should be
> small). When number formed from 4 lower order bytes is out of
> range I get CONSTRAINT_ERROR but if only higher order bytes are
> non-zero I get just zero result. I would expect CONSTRAINT_ERROR 
> always when any of higher order bytes is non-zero. With both 
> gnat-3.14p and gnat from gcc-3.3 the program below prints huge
> number for 'pp' and 0.0 for 'price'. 

Compile with -gnato.  With GNAT, range checks are disabled by default
for performance.  Here is what I get with 3.15p:

$ gnatmake -O3 tstnum
gnatgcc -c -O3 tstnum.adb
gnatbind -x tstnum.ali
gnatlink tstnum.ali

$ ./tstnum
pp =  17868022686844715008
price =  0.00

$ gnatmake -s -gnato -O3 tstnum
gnatgcc -c -gnato -O3 tstnum.adb
gnatbind -x tstnum.ali
gnatlink tstnum.ali

$ ./tstnum
pp =  17868022686844715008

raised CONSTRAINT_ERROR : tstnum.adb:20 overflow check failed


HTH

-- 
Ludovic Brenta.



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

* Re: Is this a gnat bug?
  2003-09-20 22:50 Is this a gnat bug? Waldek Hebisch
  2003-09-20 23:09 ` Ludovic Brenta
@ 2003-09-21  2:37 ` Waldek Hebisch
  1 sibling, 0 replies; 21+ messages in thread
From: Waldek Hebisch @ 2003-09-21  2:37 UTC (permalink / raw)


Thanks for answers -- with '-gnato' it works as expected.
--
                              Waldek Hebisch
hebisch@math.uni.wroc.pl    or hebisch@hera.math.uni.wroc.pl 



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

end of thread, other threads:[~2003-09-21  2:37 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2002-04-26 16:36 Is this a GNAT bug??? Robert Quinn
2002-04-26 17:48 ` Mark Johnson
2002-04-26 22:20   ` Robert Dewar
2002-04-29 15:45   ` Robert Quinn
2002-04-30  2:44     ` Robert Dewar
2002-04-30 14:15       ` Larry Kilgallen
2002-04-30 16:41       ` Robert Quinn
2002-04-30 18:20         ` tmoran
2002-05-01  1:31           ` Robert Quinn
2002-05-01 17:08             ` Ted Dennison
2002-05-02  1:55               ` Larry Kilgallen
2002-05-02 14:04                 ` Mark Johnson
2002-05-02 15:25                   ` Larry Kilgallen
2002-04-30 21:55         ` Mark Johnson
2002-05-01 22:59           ` Nick Roberts
2002-05-02 13:56             ` Mark Johnson
2002-05-02 20:19               ` Nick Roberts
2002-05-02 21:55                 ` Mark Johnson
  -- strict thread matches above, loose matches on Subject: below --
2003-09-20 22:50 Is this a gnat bug? Waldek Hebisch
2003-09-20 23:09 ` Ludovic Brenta
2003-09-21  2:37 ` Waldek Hebisch

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