public inbox for newlib@sourceware.org
 help / color / mirror / Atom feed
* Why int32_t is long int on 32 Bit Intel?
@ 2023-07-27 11:55 panda.trooper
  2023-07-27 23:13 ` Brian Inglis
  0 siblings, 1 reply; 17+ messages in thread
From: panda.trooper @ 2023-07-27 11:55 UTC (permalink / raw)
  To: newlib

[-- Attachment #1: Type: text/plain, Size: 178 bytes --]

Hi, can somebody explain what is the reason behind the architectural decision that on x86 the type of int32_t is long int by default and not int when using newlib?
Thanks,
Zoltan

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

* Re: Why int32_t is long int on 32 Bit Intel?
  2023-07-27 11:55 Why int32_t is long int on 32 Bit Intel? panda.trooper
@ 2023-07-27 23:13 ` Brian Inglis
  2023-07-28  8:06   ` panda.trooper
  0 siblings, 1 reply; 17+ messages in thread
From: Brian Inglis @ 2023-07-27 23:13 UTC (permalink / raw)
  To: newlib; +Cc: panda.trooper

On 2023-07-27 05:55, panda.trooper wrote:
> Hi, can somebody explain what is the reason behind the architectural decision that on x86 the type of int32_t is long int by default and not int when using newlib?

Lots of embedded processors have 16 bit int and 32 bit long, and 80186 
compatibles are still being produced and sold, although gcc -m16 now has 
limitations.

[The ancient PDP-11 is still supported by gcc 13:

https://gcc.gnu.org/onlinedocs/gcc/gcc-command-options/machine-dependent-options/pdp-11-options.html

probably because it may still be exemplary CISC ISA in comp arch courses using 
simulators like SimH et al.]

-- 
Take care. Thanks, Brian Inglis              Calgary, Alberta, Canada

La perfection est atteinte                   Perfection is achieved
non pas lorsqu'il n'y a plus rien à ajouter  not when there is no more to add
mais lorsqu'il n'y a plus rien à retirer     but when there is no more to cut
                                 -- Antoine de Saint-Exupéry

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

* Re: Why int32_t is long int on 32 Bit Intel?
  2023-07-27 23:13 ` Brian Inglis
@ 2023-07-28  8:06   ` panda.trooper
  2023-07-28 13:23     ` Anders Montonen
  0 siblings, 1 reply; 17+ messages in thread
From: panda.trooper @ 2023-07-28  8:06 UTC (permalink / raw)
  To: newlib

> On 2023-07-27 05:55, panda.trooper wrote:
> 
> > Hi, can somebody explain what is the reason behind the architectural decision that on x86 the type of int32_t is long int by default and not int when using newlib?
> 
> 
> Lots of embedded processors have 16 bit int and 32 bit long, and 80186
> compatibles are still being produced and sold, although gcc -m16 now has
> limitations.
> 
> [The ancient PDP-11 is still supported by gcc 13:
> 
> https://gcc.gnu.org/onlinedocs/gcc/gcc-command-options/machine-dependent-options/pdp-11-options.html
> 
> probably because it may still be exemplary CISC ISA in comp arch courses using
> simulators like SimH et al.]
> 
> --
> Take care. Thanks, Brian Inglis Calgary, Alberta, Canada
> 
> La perfection est atteinte Perfection is achieved
> non pas lorsqu'il n'y a plus rien à ajouter not when there is no more to add
> mais lorsqu'il n'y a plus rien à retirer but when there is no more to cut
> -- Antoine de Saint-Exupéry

Ok, I understand, some embedded systems have 16 bit int. But why not looking first if int is 32 bit and if yes, selecting that type as int32_t, and if the size doesn't fit, look for other types?

I am on x86 (32 bit) and have C++ code like this:

void foo(long) {}
void foo(int) {}

Now this compiles with bot, my native Linux GCC and with my newlib based i686-elf cross compiler. If I change this to this:

void foo(long) {}
void foo(int32_t) {}

then it will still compile with native Linux GCC (int32_t is int) but will fail with newlib i686-elf cross GCC, because both types are the same. The newlib behavior is kind of unintuitive to me. It is correct, because the standard only defines the size of the type, not the exact type. But I would not expect to get different types on the same CPU architecture with the same compiler just because I am using a different standard C library.

Is this expectation wrong? I am unsure.

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

* Re: Why int32_t is long int on 32 Bit Intel?
  2023-07-28  8:06   ` panda.trooper
@ 2023-07-28 13:23     ` Anders Montonen
  2023-07-28 14:15       ` Joel Sherrill
  0 siblings, 1 reply; 17+ messages in thread
From: Anders Montonen @ 2023-07-28 13:23 UTC (permalink / raw)
  To: panda.trooper; +Cc: newlib

Hi,

> On 28 Jul 2023, at 11:06, panda.trooper <panda.trooper@protonmail.com> wrote:
> 
>> On 2023-07-27 05:55, panda.trooper wrote:
>> 
>>> Hi, can somebody explain what is the reason behind the architectural decision that on x86 the type of int32_t is long int by default and not int when using newlib?
>> 
>> 
>> Lots of embedded processors have 16 bit int and 32 bit long, and 80186
>> compatibles are still being produced and sold, although gcc -m16 now has
>> limitations.
>> 
>> [The ancient PDP-11 is still supported by gcc 13:
>> 
>> https://gcc.gnu.org/onlinedocs/gcc/gcc-command-options/machine-dependent-options/pdp-11-options.html
>> 
>> probably because it may still be exemplary CISC ISA in comp arch courses using
>> simulators like SimH et al.]
>> 
>> --
>> Take care. Thanks, Brian Inglis Calgary, Alberta, Canada
>> 
>> La perfection est atteinte Perfection is achieved
>> non pas lorsqu'il n'y a plus rien à ajouter not when there is no more to add
>> mais lorsqu'il n'y a plus rien à retirer but when there is no more to cut
>> -- Antoine de Saint-Exupéry
> 
> Ok, I understand, some embedded systems have 16 bit int. But why not looking first if int is 32 bit and if yes, selecting that type as int32_t, and if the size doesn't fit, look for other types?
> 
> I am on x86 (32 bit) and have C++ code like this:
> 
> void foo(long) {}
> void foo(int) {}
> 
> Now this compiles with bot, my native Linux GCC and with my newlib based i686-elf cross compiler. If I change this to this:
> 
> void foo(long) {}
> void foo(int32_t) {}
> 
> then it will still compile with native Linux GCC (int32_t is int) but will fail with newlib i686-elf cross GCC, because both types are the same. The newlib behavior is kind of unintuitive to me. It is correct, because the standard only defines the size of the type, not the exact type. But I would not expect to get different types on the same CPU architecture with the same compiler just because I am using a different standard C library.
> 
> Is this expectation wrong? I am unsure.

The representation of data types is determined by the ABI. Most, if not all, x86-32 ABIs use 4-byte longs. These things would probably have been decided in the 80s, when the i386 was introduced.

http://agner.org/optimize/calling_conventions.pdf
http://www.sco.com/developers/devspecs/abi386-4.pdf

-a

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

* Re: Why int32_t is long int on 32 Bit Intel?
  2023-07-28 13:23     ` Anders Montonen
@ 2023-07-28 14:15       ` Joel Sherrill
  2023-07-28 15:49         ` [EXTERNAL]: " Mike Burgess
  0 siblings, 1 reply; 17+ messages in thread
From: Joel Sherrill @ 2023-07-28 14:15 UTC (permalink / raw)
  To: Anders Montonen; +Cc: panda.trooper, newlib

[-- Attachment #1: Type: text/plain, Size: 4261 bytes --]

In my experience which dates back to the 80s including 80186 development
and decades with RTEMS, an int matches the native register size.

As a general rule, 16-bit CPUs have 16 bit int, 32-bit CPUs have 32-bit
int, and 64-bit CPUs have 64-bit ints.

There may be compiler options to change the register model but this means
all source must be compiled with this option. The aarch64 has LP64 (native
64-bit) and ILP32 (like 32-bit ARM) and this is the option description from
GCC:

-mabi=name
<https://gcc.gnu.org/onlinedocs/gcc/AArch64-Options.html#index-mabi>

Generate code for the specified data model. Permissible values are ‘ilp32’
for SysV-like data model where int, long int and pointers are 32 bits, and ‘
lp64’ for SysV-like data model where int is 32 bits, but long int and
pointers are 64 bits.

The default depends on the specific target configuration. Note that the
LP64 and ILP32 ABIs are not link-compatible; you must compile your entire
program with the same ABI, and link with a compatible set of libraries.
 If you look at the C standard, you want to look at "5.2.4.2.1 Sizes of
integer types <limits.h>" in C99. This defines the minimum ranges of each
integer type.  Picking one of the values at random, this is a typical
description:

  — maximum value for an object of type int
INT_MAX +32767 // 2 15 − 1

If you want another esoteric area, char may be signed or unsigned and it
varies based on architecture even with GCC. I don't remember the exact
distribution but RTEMS supports 18 processor architectures and I think the
split is about 1/3 one way.

--joel sherrill
RTEMS

On Fri, Jul 28, 2023 at 8:23 AM Anders Montonen <Anders.Montonen@iki.fi>
wrote:

> Hi,
>
> > On 28 Jul 2023, at 11:06, panda.trooper <panda.trooper@protonmail.com>
> wrote:
> >
> >> On 2023-07-27 05:55, panda.trooper wrote:
> >>
> >>> Hi, can somebody explain what is the reason behind the architectural
> decision that on x86 the type of int32_t is long int by default and not int
> when using newlib?
> >>
> >>
> >> Lots of embedded processors have 16 bit int and 32 bit long, and 80186
> >> compatibles are still being produced and sold, although gcc -m16 now has
> >> limitations.
> >>
> >> [The ancient PDP-11 is still supported by gcc 13:
> >>
> >>
> https://gcc.gnu.org/onlinedocs/gcc/gcc-command-options/machine-dependent-options/pdp-11-options.html
> >>
> >> probably because it may still be exemplary CISC ISA in comp arch
> courses using
> >> simulators like SimH et al.]
> >>
> >> --
> >> Take care. Thanks, Brian Inglis Calgary, Alberta, Canada
> >>
> >> La perfection est atteinte Perfection is achieved
> >> non pas lorsqu'il n'y a plus rien à ajouter not when there is no more
> to add
> >> mais lorsqu'il n'y a plus rien à retirer but when there is no more to
> cut
> >> -- Antoine de Saint-Exupéry
> >
> > Ok, I understand, some embedded systems have 16 bit int. But why not
> looking first if int is 32 bit and if yes, selecting that type as int32_t,
> and if the size doesn't fit, look for other types?
> >
> > I am on x86 (32 bit) and have C++ code like this:
> >
> > void foo(long) {}
> > void foo(int) {}
> >
> > Now this compiles with bot, my native Linux GCC and with my newlib based
> i686-elf cross compiler. If I change this to this:
> >
> > void foo(long) {}
> > void foo(int32_t) {}
> >
> > then it will still compile with native Linux GCC (int32_t is int) but
> will fail with newlib i686-elf cross GCC, because both types are the same.
> The newlib behavior is kind of unintuitive to me. It is correct, because
> the standard only defines the size of the type, not the exact type. But I
> would not expect to get different types on the same CPU architecture with
> the same compiler just because I am using a different standard C library.
> >
> > Is this expectation wrong? I am unsure.
>
> The representation of data types is determined by the ABI. Most, if not
> all, x86-32 ABIs use 4-byte longs. These things would probably have been
> decided in the 80s, when the i386 was introduced.
>
> http://agner.org/optimize/calling_conventions.pdf
> http://www.sco.com/developers/devspecs/abi386-4.pdf
>
> -a

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

* Re: [EXTERNAL]: Re: Why int32_t is long int on 32 Bit Intel?
  2023-07-28 14:15       ` Joel Sherrill
@ 2023-07-28 15:49         ` Mike Burgess
  2023-07-28 16:11           ` Stefan Tauner
  2023-07-28 18:27           ` panda.trooper
  0 siblings, 2 replies; 17+ messages in thread
From: Mike Burgess @ 2023-07-28 15:49 UTC (permalink / raw)
  To: Joel Sherrill, Anders Montonen; +Cc: panda.trooper, newlib

[-- Attachment #1: Type: text/plain, Size: 6595 bytes --]

I think the original question was, “Why, on a 32-bit architecture, does int32_t (and by extension, size_t) become `long` instead of just `int`?” This becomes an immediate portability headache; I have several compilers—for the _same_ architecture—that make different choices, which means I need to to use conditional compilation, casts, or other ugly work-arounds or suffer misguided warnings (i.e., printf argument type mismatch). Printf has a pretty good solution for size_t nowadays, but not so much for int32_t.

Mike
________________________________
From: Newlib <newlib-bounces+mburgess=ii-vi.com@sourceware.org> on behalf of Joel Sherrill <joel@rtems.org>
Sent: Friday, July 28, 2023 10:15 AM
To: Anders Montonen <Anders.Montonen@iki.fi>
Cc: panda.trooper <panda.trooper@protonmail.com>; newlib@sourceware.org <newlib@sourceware.org>
Subject: [EXTERNAL]: Re: Why int32_t is long int on 32 Bit Intel?

In my experience which dates back to the 80s including 80186 development
and decades with RTEMS, an int matches the native register size.

As a general rule, 16-bit CPUs have 16 bit int, 32-bit CPUs have 32-bit
int, and 64-bit CPUs have 64-bit ints.

There may be compiler options to change the register model but this means
all source must be compiled with this option. The aarch64 has LP64 (native
64-bit) and ILP32 (like 32-bit ARM) and this is the option description from
GCC:

-mabi=name
<https://urldefense.com/v3/__https://gcc.gnu.org/onlinedocs/gcc/AArch64-Options.html*index-mabi__;Iw!!BEJPKrpf!7JFtIWFkyYyyceaUH2Y8aZISARdyWaefFCB4tKJMmxFfxyXb7rJrv4c919c-KibqHRBVWjN-W2E$ [gcc[.]gnu[.]org]>

Generate code for the specified data model. Permissible values are ‘ilp32’
for SysV-like data model where int, long int and pointers are 32 bits, and ‘
lp64’ for SysV-like data model where int is 32 bits, but long int and
pointers are 64 bits.

The default depends on the specific target configuration. Note that the
LP64 and ILP32 ABIs are not link-compatible; you must compile your entire
program with the same ABI, and link with a compatible set of libraries.
 If you look at the C standard, you want to look at "5.2.4.2.1 Sizes of
integer types <limits.h>" in C99. This defines the minimum ranges of each
integer type.  Picking one of the values at random, this is a typical
description:

  — maximum value for an object of type int
INT_MAX +32767 // 2 15 − 1

If you want another esoteric area, char may be signed or unsigned and it
varies based on architecture even with GCC. I don't remember the exact
distribution but RTEMS supports 18 processor architectures and I think the
split is about 1/3 one way.

--joel sherrill
RTEMS

On Fri, Jul 28, 2023 at 8:23 AM Anders Montonen <Anders.Montonen@iki.fi>
wrote:

> Hi,
>
> > On 28 Jul 2023, at 11:06, panda.trooper <panda.trooper@protonmail.com>
> wrote:
> >
> >> On 2023-07-27 05:55, panda.trooper wrote:
> >>
> >>> Hi, can somebody explain what is the reason behind the architectural
> decision that on x86 the type of int32_t is long int by default and not int
> when using newlib?
> >>
> >>
> >> Lots of embedded processors have 16 bit int and 32 bit long, and 80186
> >> compatibles are still being produced and sold, although gcc -m16 now has
> >> limitations.
> >>
> >> [The ancient PDP-11 is still supported by gcc 13:
> >>
> >>
> https://urldefense.com/v3/__https://gcc.gnu.org/onlinedocs/gcc/gcc-command-options/machine-dependent-options/pdp-11-options.html__;!!BEJPKrpf!7JFtIWFkyYyyceaUH2Y8aZISARdyWaefFCB4tKJMmxFfxyXb7rJrv4c919c-KibqHRBVYzVGYH4$ [gcc[.]gnu[.]org]
> >>
> >> probably because it may still be exemplary CISC ISA in comp arch
> courses using
> >> simulators like SimH et al.]
> >>
> >> --
> >> Take care. Thanks, Brian Inglis Calgary, Alberta, Canada
> >>
> >> La perfection est atteinte Perfection is achieved
> >> non pas lorsqu'il n'y a plus rien à ajouter not when there is no more
> to add
> >> mais lorsqu'il n'y a plus rien à retirer but when there is no more to
> cut
> >> -- Antoine de Saint-Exupéry
> >
> > Ok, I understand, some embedded systems have 16 bit int. But why not
> looking first if int is 32 bit and if yes, selecting that type as int32_t,
> and if the size doesn't fit, look for other types?
> >
> > I am on x86 (32 bit) and have C++ code like this:
> >
> > void foo(long) {}
> > void foo(int) {}
> >
> > Now this compiles with bot, my native Linux GCC and with my newlib based
> i686-elf cross compiler. If I change this to this:
> >
> > void foo(long) {}
> > void foo(int32_t) {}
> >
> > then it will still compile with native Linux GCC (int32_t is int) but
> will fail with newlib i686-elf cross GCC, because both types are the same.
> The newlib behavior is kind of unintuitive to me. It is correct, because
> the standard only defines the size of the type, not the exact type. But I
> would not expect to get different types on the same CPU architecture with
> the same compiler just because I am using a different standard C library.
> >
> > Is this expectation wrong? I am unsure.
>
> The representation of data types is determined by the ABI. Most, if not
> all, x86-32 ABIs use 4-byte longs. These things would probably have been
> decided in the 80s, when the i386 was introduced.
>
> https://urldefense.com/v3/__http://agner.org/optimize/calling_conventions.pdf__;!!BEJPKrpf!7JFtIWFkyYyyceaUH2Y8aZISARdyWaefFCB4tKJMmxFfxyXb7rJrv4c919c-KibqHRBVxNCABro$ [agner[.]org]
> https://urldefense.com/v3/__http://www.sco.com/developers/devspecs/abi386-4.pdf__;!!BEJPKrpf!7JFtIWFkyYyyceaUH2Y8aZISARdyWaefFCB4tKJMmxFfxyXb7rJrv4c919c-KibqHRBVAG9vnH0$ [sco[.]com]
>
> -a

----------------------------------------------------------------------
This email is from Coherent Corp. or a Coherent group company. The contents of this email, including any attachments, are intended solely for the intended recipient and may contain Coherent proprietary and/or confidential information and material. Any review, use, disclosure, re-transmission, dissemination, distribution, retention, or copying of this email and any of its contents by any person other than the intended recipient is strictly prohibited. If you received this email in error, please immediately notify the sender and destroy any and all copies of this email and any attachments. To contact us directly, please email postmaster@coherent.com.   

Privacy: For information about how Coherent processes personal information, please review our privacy policy at https://ii-vi.com/privacy/.

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

* Re: [EXTERNAL]: Re: Why int32_t is long int on 32 Bit Intel?
  2023-07-28 15:49         ` [EXTERNAL]: " Mike Burgess
@ 2023-07-28 16:11           ` Stefan Tauner
  2023-07-28 16:26             ` Mike Burgess
  2023-07-28 18:27           ` panda.trooper
  1 sibling, 1 reply; 17+ messages in thread
From: Stefan Tauner @ 2023-07-28 16:11 UTC (permalink / raw)
  To: newlib

On Fri, 28 Jul 2023 15:49:25 +0000
Mike Burgess <Mike.Burgess@coherent.com> wrote:

> Printf has a pretty good solution for size_t nowadays, but not so much for int32_t.

It does. inttypes.h

-- 
Kind regards/Mit freundlichen Grüßen, Stefan Tauner

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

* Re: [EXTERNAL]: Re: Why int32_t is long int on 32 Bit Intel?
  2023-07-28 16:11           ` Stefan Tauner
@ 2023-07-28 16:26             ` Mike Burgess
  2023-07-28 17:06               ` Richard Damon
  0 siblings, 1 reply; 17+ messages in thread
From: Mike Burgess @ 2023-07-28 16:26 UTC (permalink / raw)
  To: Stefan Tauner, newlib

[-- Attachment #1: Type: text/plain, Size: 1990 bytes --]

Stefan, I was referring to %zu. But, when the argument is int32_t, one needs to correctly pick %d or %ld to avoid a senseless warning. Or, always use %ld and—safely and without penalty—cast the argument to long. But I dislike cluttering my code with casts that might hide future defects. (Let's not have an argument about using printf at all, as this is far beyond the scope of the original question.)

<inttypes.h> I guess does have definitions that _might_ solve this, but they are awkward and by experience don’t always exist.

Mike


________________________________
From: Newlib <newlib-bounces+mburgess=ii-vi.com@sourceware.org> on behalf of Stefan Tauner <stefan.tauner@gmx.at>
Sent: Friday, July 28, 2023 12:11 PM
To: newlib@sourceware.org <newlib@sourceware.org>
Subject: Re: [EXTERNAL]: Re: Why int32_t is long int on 32 Bit Intel?

On Fri, 28 Jul 2023 15:49:25 +0000
Mike Burgess <Mike.Burgess@coherent.com> wrote:

> Printf has a pretty good solution for size_t nowadays, but not so much for int32_t.

It does. inttypes.h

--
Kind regards/Mit freundlichen Grüßen, Stefan Tauner

----------------------------------------------------------------------
This email is from Coherent Corp. or a Coherent group company. The contents of this email, including any attachments, are intended solely for the intended recipient and may contain Coherent proprietary and/or confidential information and material. Any review, use, disclosure, re-transmission, dissemination, distribution, retention, or copying of this email and any of its contents by any person other than the intended recipient is strictly prohibited. If you received this email in error, please immediately notify the sender and destroy any and all copies of this email and any attachments. To contact us directly, please email postmaster@coherent.com.   

Privacy: For information about how Coherent processes personal information, please review our privacy policy at https://ii-vi.com/privacy/.

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

* Re: [EXTERNAL]: Re: Why int32_t is long int on 32 Bit Intel?
  2023-07-28 16:26             ` Mike Burgess
@ 2023-07-28 17:06               ` Richard Damon
  2023-07-28 18:05                 ` Grant Edwards
  0 siblings, 1 reply; 17+ messages in thread
From: Richard Damon @ 2023-07-28 17:06 UTC (permalink / raw)
  To: newlib

Actually, it is showing you are using the “wrong” format. If you are printing an int32_t, you should be using the format out of inttypes.h to be correct, even if it is “ugly”.

> On Jul 28, 2023, at 12:27 PM, Mike Burgess <Mike.Burgess@coherent.com> wrote:
> 
> Stefan, I was referring to %zu. But, when the argument is int32_t, one needs to correctly pick %d or %ld to avoid a senseless warning. Or, always use %ld and—safely and without penalty—cast the argument to long. But I dislike cluttering my code with casts that might hide future defects. (Let's not have an argument about using printf at all, as this is far beyond the scope of the original question.)
> 
> <inttypes.h> I guess does have definitions that _might_ solve this, but they are awkward and by experience don’t always exist.
> 
> Mike
> 
> 
> ________________________________
> From: Newlib <newlib-bounces+mburgess=ii-vi.com@sourceware.org> on behalf of Stefan Tauner <stefan.tauner@gmx.at>
> Sent: Friday, July 28, 2023 12:11 PM
> To: newlib@sourceware.org <newlib@sourceware.org>
> Subject: Re: [EXTERNAL]: Re: Why int32_t is long int on 32 Bit Intel?
> 
>> On Fri, 28 Jul 2023 15:49:25 +0000
>> Mike Burgess <Mike.Burgess@coherent.com> wrote:
>> 
>> Printf has a pretty good solution for size_t nowadays, but not so much for int32_t.
> 
> It does. inttypes.h
> 
> --
> Kind regards/Mit freundlichen Grüßen, Stefan Tauner
> 
> ----------------------------------------------------------------------
> This email is from Coherent Corp. or a Coherent group company. The contents of this email, including any attachments, are intended solely for the intended recipient and may contain Coherent proprietary and/or confidential information and material. Any review, use, disclosure, re-transmission, dissemination, distribution, retention, or copying of this email and any of its contents by any person other than the intended recipient is strictly prohibited. If you received this email in error, please immediately notify the sender and destroy any and all copies of this email and any attachments. To contact us directly, please email postmaster@coherent.com.   
> 
> Privacy: For information about how Coherent processes personal information, please review our privacy policy at https://ii-vi.com/privacy/.


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

* Re: [EXTERNAL]: Re: Why int32_t is long int on 32 Bit Intel?
  2023-07-28 17:06               ` Richard Damon
@ 2023-07-28 18:05                 ` Grant Edwards
  0 siblings, 0 replies; 17+ messages in thread
From: Grant Edwards @ 2023-07-28 18:05 UTC (permalink / raw)
  To: newlib

On 2023-07-28, Richard Damon <Richard@damon-family.org> wrote:

> Actually, it is showing you are using the “wrong” format. If you are
> printing an int32_t, you should be using the format out of
> inttypes.h to be correct, even if it is “ugly”.

Huh. I never knew about inttype.h until now and always wondered about
the "official" way to deal with this problem. [IMO, it definitely is
ugly.]

I tended to use the %ld with a (long) cast solution -- which doesn't
generate any extra code and is easy to read, but it still didn't seem
"right".

--
Grant




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

* Re: [EXTERNAL]: Re: Why int32_t is long int on 32 Bit Intel?
  2023-07-28 15:49         ` [EXTERNAL]: " Mike Burgess
  2023-07-28 16:11           ` Stefan Tauner
@ 2023-07-28 18:27           ` panda.trooper
  2023-07-28 20:23             ` Jon Beniston
  1 sibling, 1 reply; 17+ messages in thread
From: panda.trooper @ 2023-07-28 18:27 UTC (permalink / raw)
  To: newlib

[-- Attachment #1: Type: text/plain, Size: 8781 bytes --]

Thanks Mike pointing on the original question. I would like to describe the problem with another example to get across what I do not understand.

I would also like to note, that regarding C/C++ standard, there is no issue. The standard only specifies sizes for fixed size types, it does not specify the actual types which they alias. This issue is just about (my) expectations and curiosity.

It is also important, that the issue only existusing C++. There is no issue when using C, because C does not support overloading.

Let's assume we have a library that implements following functions:

void foo(int n) {
// go left n steps
}

void foo(long n) {
// go right n steps
}

Who would write such silly code, you may ask. Beiive me, there is such code out there. Sometimes legacy code that you cannot change.

When using this library you may have such code somewhere:

#include <cstdint>

void bar(int32_t n) {
foo(n);
}

Where are we going now? Left or right? The answer is, as often in C++: it depends. It depends on the compiler you are using and what your target architecture is.

Does it also depend on the standard C library we are using? Lately I learned, yes. But I did not expect it.

When I compile the example code for x86-32 with GCC and glibc, I go left. The same with 32 Bit MinGW. Only with newlib I go right.

In my real life project I have a similar situation. I have the same codebase for an embedded system that I compile with an i686-elf compiler and newlib, and there is a simulation of that embedded system that I compile with a native x86_64-unknown-linux-gnu compiler (-m32).

I realized, that I may get different behavior in my embedded setup and in my simulation because of this. This issue has effects on my type system. I cannot use int32_t, because I am not in control of the underlying type even on the very same CPU architecture! I find this amazing.

So again, just out of curiosity: what is the reason using long as int32_t on an architecture where int is suitable, too?

------- Original Message -------
On Friday, July 28th, 2023 at 17:49, Mike Burgess <Mike.Burgess@coherent.com> wrote:

> I think the original question was, “Why, on a 32-bit architecture, does int32_t (and by extension, size_t) become `long` instead of just `int`?” This becomes an immediate portability headache; I have several compilers—for the _same_ architecture—that make different choices, which means I need to to use conditional compilation, casts, or other ugly work-arounds or suffer misguided warnings (i.e., printf argument type mismatch). Printf has a pretty good solution for size_t nowadays, but not so much for int32_t.
>
> Mike
> ---------------------------------------------------------------
>
> From: Newlib <newlib-bounces+mburgess=ii-vi.com@sourceware.org> on behalf of Joel Sherrill <joel@rtems.org>
> Sent: Friday, July 28, 2023 10:15 AM
> To: Anders Montonen <Anders.Montonen@iki.fi>
> Cc: panda.trooper <panda.trooper@protonmail.com>; newlib@sourceware.org <newlib@sourceware.org>
> Subject: [EXTERNAL]: Re: Why int32_t is long int on 32 Bit Intel?
>
> In my experience which dates back to the 80s including 80186 development
> and decades with RTEMS, an int matches the native register size.
>
> As a general rule, 16-bit CPUs have 16 bit int, 32-bit CPUs have 32-bit
> int, and 64-bit CPUs have 64-bit ints.
>
> There may be compiler options to change the register model but this means
> all source must be compiled with this option. The aarch64 has LP64 (native
> 64-bit) and ILP32 (like 32-bit ARM) and this is the option description from
> GCC:
>
> -mabi=name
> <https://urldefense.com/v3/__https://gcc.gnu.org/onlinedocs/gcc/AArch64-Options.html*index-mabi__;Iw!!BEJPKrpf!7JFtIWFkyYyyceaUH2Y8aZISARdyWaefFCB4tKJMmxFfxyXb7rJrv4c919c-KibqHRBVWjN-W2E$ [gcc[.]gnu[.]org]>
>
> Generate code for the specified data model. Permissible values are ‘ilp32’
> for SysV-like data model where int, long int and pointers are 32 bits, and ‘
> lp64’ for SysV-like data model where int is 32 bits, but long int and
> pointers are 64 bits.
>
> The default depends on the specific target configuration. Note that the
> LP64 and ILP32 ABIs are not link-compatible; you must compile your entire
> program with the same ABI, and link with a compatible set of libraries.
> If you look at the C standard, you want to look at "5.2.4.2.1 Sizes of
> integer types <limits.h>" in C99. This defines the minimum ranges of each
> integer type. Picking one of the values at random, this is a typical
> description:
>
> — maximum value for an object of type int
> INT_MAX +32767 // 2 15 − 1
>
> If you want another esoteric area, char may be signed or unsigned and it
> varies based on architecture even with GCC. I don't remember the exact
> distribution but RTEMS supports 18 processor architectures and I think the
> split is about 1/3 one way.
>
> --joel sherrill
> RTEMS
>
> On Fri, Jul 28, 2023 at 8:23 AM Anders Montonen <Anders.Montonen@iki.fi>
> wrote:
>
>> Hi,
>>
>> > On 28 Jul 2023, at 11:06, panda.trooper <panda.trooper@protonmail.com>
>> wrote:
>> >
>> >> On 2023-07-27 05:55, panda.trooper wrote:
>> >>
>> >>> Hi, can somebody explain what is the reason behind the architectural
>> decision that on x86 the type of int32_t is long int by default and not int
>> when using newlib?
>> >>
>> >>
>> >> Lots of embedded processors have 16 bit int and 32 bit long, and 80186
>> >> compatibles are still being produced and sold, although gcc -m16 now has
>> >> limitations.
>> >>
>> >> [The ancient PDP-11 is still supported by gcc 13:
>> >>
>> >>
>> https://urldefense.com/v3/__https://gcc.gnu.org/onlinedocs/gcc/gcc-command-options/machine-dependent-options/pdp-11-options.html__;!!BEJPKrpf!7JFtIWFkyYyyceaUH2Y8aZISARdyWaefFCB4tKJMmxFfxyXb7rJrv4c919c-KibqHRBVYzVGYH4$ [gcc[.]gnu[.]org]
>> >>
>> >> probably because it may still be exemplary CISC ISA in comp arch
>> courses using
>> >> simulators like SimH et al.]
>> >>
>> >> --
>> >> Take care. Thanks, Brian Inglis Calgary, Alberta, Canada
>> >>
>> >> La perfection est atteinte Perfection is achieved
>> >> non pas lorsqu'il n'y a plus rien à ajouter not when there is no more
>> to add
>> >> mais lorsqu'il n'y a plus rien à retirer but when there is no more to
>> cut
>> >> -- Antoine de Saint-Exupéry
>> >
>> > Ok, I understand, some embedded systems have 16 bit int. But why not
>> looking first if int is 32 bit and if yes, selecting that type as int32_t,
>> and if the size doesn't fit, look for other types?
>> >
>> > I am on x86 (32 bit) and have C++ code like this:
>> >
>> > void foo(long) {}
>> > void foo(int) {}
>> >
>> > Now this compiles with bot, my native Linux GCC and with my newlib based
>> i686-elf cross compiler. If I change this to this:
>> >
>> > void foo(long) {}
>> > void foo(int32_t) {}
>> >
>> > then it will still compile with native Linux GCC (int32_t is int) but
>> will fail with newlib i686-elf cross GCC, because both types are the same.
>> The newlib behavior is kind of unintuitive to me. It is correct, because
>> the standard only defines the size of the type, not the exact type. But I
>> would not expect to get different types on the same CPU architecture with
>> the same compiler just because I am using a different standard C library.
>> >
>> > Is this expectation wrong? I am unsure.
>>
>> The representation of data types is determined by the ABI. Most, if not
>> all, x86-32 ABIs use 4-byte longs. These things would probably have been
>> decided in the 80s, when the i386 was introduced.
>>
>> https://urldefense.com/v3/__http://agner.org/optimize/calling_conventions.pdf__;!!BEJPKrpf!7JFtIWFkyYyyceaUH2Y8aZISARdyWaefFCB4tKJMmxFfxyXb7rJrv4c919c-KibqHRBVxNCABro$ [agner[.]org]
>> https://urldefense.com/v3/__http://www.sco.com/developers/devspecs/abi386-4.pdf__;!!BEJPKrpf!7JFtIWFkyYyyceaUH2Y8aZISARdyWaefFCB4tKJMmxFfxyXb7rJrv4c919c-KibqHRBVAG9vnH0$ [sco[.]com]
>>
>> -a
> ---------------------------------------------------------------
> This email is from Coherent Corp. or a Coherent group company. The contents of this email, including any attachments, are intended solely for the intended recipient and may contain Coherent proprietary and/or confidential information and material. Any review, use, disclosure, re-transmission, dissemination, distribution, retention, or copying of this email and any of its contents by any person other than the intended recipient is strictly prohibited. If you received this email in error, please immediately notify the sender and destroy any and all copies of this email and any attachments. To contact us directly, please email postmaster@coherent.com.
>
> Privacy: For information about how Coherent processes personal information, please review our privacy policy at https://ii-vi.com/privacy/.

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

* RE: [EXTERNAL]: Re: Why int32_t is long int on 32 Bit Intel?
  2023-07-28 18:27           ` panda.trooper
@ 2023-07-28 20:23             ` Jon Beniston
  2023-07-28 21:42               ` panda.trooper
  0 siblings, 1 reply; 17+ messages in thread
From: Jon Beniston @ 2023-07-28 20:23 UTC (permalink / raw)
  To: 'panda.trooper', newlib

>So again, just out of curiosity: what is the reason using long as int32_t on an architecture where int is suitable, too?

Long ago, there were 32-bit x86 compilers where int was 16-bit (E.g. Turbo C).

Also, are you sure it isn't gcc that's determining the type of int32_t rather than Newlib? I've not used i686-elf-gcc, but for some targets newlib defines int32_t based on __INT32_TYPE__ which is defined by gcc:

In gcc/config/newlib-stdint.h 

#ifndef STDINT_LONG32
#define STDINT_LONG32 (LONG_TYPE_SIZE == 32)
#endif
...
#define INT32_TYPE (STDINT_LONG32 ? "long int" : INT_TYPE_SIZE == 32 ? "int" : SHORT_TYPE_SIZE == 32 ? "short int" : CHAR_TYPE_SIZE == 32 ? "signed char" : 0)

Cheers,
Jon



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

* RE: [EXTERNAL]: Re: Why int32_t is long int on 32 Bit Intel?
  2023-07-28 20:23             ` Jon Beniston
@ 2023-07-28 21:42               ` panda.trooper
  2023-07-28 21:53                 ` Jon Beniston
  0 siblings, 1 reply; 17+ messages in thread
From: panda.trooper @ 2023-07-28 21:42 UTC (permalink / raw)
  To: Jon Beniston; +Cc: newlib

Hi Jon,

you are right, in recent GCC/newlib combinations it is GCC who decides by means of setting __INT32_TYPE__, and newlib takes whatever is defined in __INT32_TYPE__. However, in older newlib versions this was not the case. In the good old days the decision was made like this (newlib/libc/include/stdint.h in newlib version 1.18):

/* Check if "long" is 64bit or 32bit wide */
#if __STDINT_EXP(LONG_MAX) > 0x7fffffff
#define __have_long64 1
#elif __STDINT_EXP(LONG_MAX) == 0x7fffffff && !defined(__SPU__)
#define __have_long32 1
#endif
[...]
#if __have_long32
typedef signed long int32_t;
typedef unsigned long uint32_t;
#define __int32_t_defined 1
#elif __STDINT_EXP(INT_MAX) == 0x7fffffffL
typedef signed int int32_t;
typedef unsigned int uint32_t;
#define __int32_t_defined 1
[...]

Please notice "&& !defined(__SPU__)", which is an very interesting exception from the default case. In gcc/config/newlib-stdint.h you find references to this in form of the comment (just from before your excerpt):

/* newlib uses 32-bit long in certain cases for all non-SPU
   targets.  */
#ifndef STDINT_LONG32
#define STDINT_LONG32 (LONG_TYPE_SIZE == 32)
#endif

So the roots of this decision are in the history of newlib. I also assumed that those people who created gcc/config/newlib-stdint.h have quite some stakes in newlib (or the other way around). That's why I asked in this community.

Your explanation with Turbo C is also plausible. Thanks for that interesting insight.

One final question: do you know what "SPU" means in this context and why it is an exceptional case?

Cheers,
Zoltan

------- Original Message -------
On Friday, July 28th, 2023 at 22:23, Jon Beniston <jon@beniston.com> wrote:


> > So again, just out of curiosity: what is the reason using long as int32_t on an architecture where int is suitable, too?
> 
> 
> Long ago, there were 32-bit x86 compilers where int was 16-bit (E.g. Turbo C).
> 
> Also, are you sure it isn't gcc that's determining the type of int32_t rather than Newlib? I've not used i686-elf-gcc, but for some targets newlib defines int32_t based on INT32_TYPE which is defined by gcc:
> 
> In gcc/config/newlib-stdint.h
> 
> #ifndef STDINT_LONG32
> #define STDINT_LONG32 (LONG_TYPE_SIZE == 32)
> #endif
> ...
> #define INT32_TYPE (STDINT_LONG32 ? "long int" : INT_TYPE_SIZE == 32 ? "int" : SHORT_TYPE_SIZE == 32 ? "short int" : CHAR_TYPE_SIZE == 32 ? "signed char" : 0)
> 
> Cheers,
> Jon

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

* RE: [EXTERNAL]: Re: Why int32_t is long int on 32 Bit Intel?
  2023-07-28 21:42               ` panda.trooper
@ 2023-07-28 21:53                 ` Jon Beniston
  2023-07-29 12:47                   ` Trampas Stern
  0 siblings, 1 reply; 17+ messages in thread
From: Jon Beniston @ 2023-07-28 21:53 UTC (permalink / raw)
  To: 'panda.trooper'; +Cc: newlib

> One final question: do you know what "SPU" means in this context and why it is an exceptional case?

Old PlayStation processor, I believe.

Cheers,
Jon



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

* Re: [EXTERNAL]: Re: Why int32_t is long int on 32 Bit Intel?
  2023-07-28 21:53                 ` Jon Beniston
@ 2023-07-29 12:47                   ` Trampas Stern
  2023-07-29 13:19                     ` Stefan Tauner
  2023-07-29 21:21                     ` Grant Edwards
  0 siblings, 2 replies; 17+ messages in thread
From: Trampas Stern @ 2023-07-29 12:47 UTC (permalink / raw)
  To: Jon Beniston; +Cc: panda.trooper, newlib

[-- Attachment #1: Type: text/plain, Size: 528 bytes --]

What is worse is when you get to use some TI DSPs where a char is 16bit.
Most code and libraries, like FAT libraries, all assume a char is 8bit.
 The whole is char signed or unsigned is another C-ism along with is a
right shift sign extended.

Enjoy,
Trampas


On Fri, Jul 28, 2023 at 5:53 PM Jon Beniston <jon@beniston.com> wrote:

> > One final question: do you know what "SPU" means in this context and why
> it is an exceptional case?
>
> Old PlayStation processor, I believe.
>
> Cheers,
> Jon
>
>
>

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

* Re: [EXTERNAL]: Re: Why int32_t is long int on 32 Bit Intel?
  2023-07-29 12:47                   ` Trampas Stern
@ 2023-07-29 13:19                     ` Stefan Tauner
  2023-07-29 21:21                     ` Grant Edwards
  1 sibling, 0 replies; 17+ messages in thread
From: Stefan Tauner @ 2023-07-29 13:19 UTC (permalink / raw)
  To: newlib

On Sat, 29 Jul 2023 08:47:22 -0400
Trampas Stern <trampas@gmail.com> wrote:

> Most code and libraries, like FAT libraries, all assume a char is 8bit.

Well, it's mandated by POSIX to be 8 bits and in general a quite
reasonable assumption (if targeting POSIX systems) but not necessarily
true elsewhere... and if you depend on the signedness of char you are
doing it wrong too. If you want 8 unsigned bits you should use uint8_t
instead of char. In that regard it's quite similar to the int
"problem". In either case there is a proper solution in C that is
working on all conforming systems.

> right shift sign extended.

Right shifts of negative integers is UB in C (and not necessarily
sign-extended) if that's what you mean. We are also quite off-topic
already IMHO...

-- 
Kind regards/Mit freundlichen Grüßen, Stefan Tauner

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

* Re: [EXTERNAL]: Re: Why int32_t is long int on 32 Bit Intel?
  2023-07-29 12:47                   ` Trampas Stern
  2023-07-29 13:19                     ` Stefan Tauner
@ 2023-07-29 21:21                     ` Grant Edwards
  1 sibling, 0 replies; 17+ messages in thread
From: Grant Edwards @ 2023-07-29 21:21 UTC (permalink / raw)
  To: newlib

On 2023-07-29, Trampas Stern <trampas@gmail.com> wrote:
> What is worse is when you get to use some TI DSPs where a char is 16bit.

I did quite a bit of development on a TI DSP where char, int, long,
long long, float, double, and long double were all 32 bits.

And yes, sizeof (char) was still 1. :)

Fun times.



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

end of thread, other threads:[~2023-07-29 21:21 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-07-27 11:55 Why int32_t is long int on 32 Bit Intel? panda.trooper
2023-07-27 23:13 ` Brian Inglis
2023-07-28  8:06   ` panda.trooper
2023-07-28 13:23     ` Anders Montonen
2023-07-28 14:15       ` Joel Sherrill
2023-07-28 15:49         ` [EXTERNAL]: " Mike Burgess
2023-07-28 16:11           ` Stefan Tauner
2023-07-28 16:26             ` Mike Burgess
2023-07-28 17:06               ` Richard Damon
2023-07-28 18:05                 ` Grant Edwards
2023-07-28 18:27           ` panda.trooper
2023-07-28 20:23             ` Jon Beniston
2023-07-28 21:42               ` panda.trooper
2023-07-28 21:53                 ` Jon Beniston
2023-07-29 12:47                   ` Trampas Stern
2023-07-29 13:19                     ` Stefan Tauner
2023-07-29 21:21                     ` Grant Edwards

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).