Subject: Re: emuns on ARM: What should we do?
To: None <Richard.Earnshaw@arm.com>
From: Todd Vierling <tv@wasabisystems.com>
List: port-arm
Date: 01/21/2002 10:50:03
On Mon, 21 Jan 2002, Richard Earnshaw wrote:

: > struct foo {
: >     enum bar a;
: >     int b;
: >     enum baz b;
: > };

: For someone who does care about space savings, the above structure would
: be written as
:
: struct foo {
:     enum bar a;
:     enum baz c;
:     int b;
: };
:
: Which would then save upto 33% of memory.

However, the person is still assuming something about the physical sizes of
those enums, based on the values of the enum in a C source file at "this
particular compile time".  Read on.

: > This will adversely impact:
: >
: > * big-endian ARM (because ABI incompatibilities are masked on little-endian
: >   systems by virtue of the fact that the LSB is first in a 4-byte int)
:
: No, it just means that the bug is likely to show itself earlier (one could
: regard that as a good thing).
:
: > * any uninitialized memory for a struct that is initialized by element (the
: >   extra bytes may get random data in code that assumes a shorter enum size)
:
: so... anyone comparing structures with memcmp or equivalent should be shot!

I said nothing about comparing structures.  The problem lies in creating a
structure from, say, stack-space, initializing an enum, and then passing it
to code that thinks the enum is larger.  Whoops, there's random data in byte
MSB+1....

(This is the way that the same problem described for big-endian ARM
manifests on little-endian systems.)

: > If space is such an issue, then -fshort-enums is not your answer.  That's
: > simply asking the compiler to make assumptions about your code that don't
: > help *general code* on a system that requires type alignment.
: >
: > If code *really* needs a space gain, it should be using bit-sized types and
: > not relying on a compiler hack.  If code is designed to save space, it
: > should be designed to know *exactly* how large its data is.
:
: Bit-sized enums are not portable.

I didn't say bit-sized enums.  I said bit-sized types.  INTEGERS.  As in,
rearranging the above example:

struct foo {
    uint32_t b;
    uint8_t a;
    uint8_t c;
};

This contains no assumptions about the sizes of an enum type, and can store
enum types just as well as "enum" itself.  Here, you explicitly state how
large of a value is allowed to go into that struct; you have no masked ABI
incompatibilities; and you don't as the compiler to hack around your own
sloppiness.  In fact, you even gain the ability to make the struct
machine-independent by making sure there are no compiler-generated alignment
gaps!

*No* other design (including, but not limited to, -fshort-enums) can be
justified under the argument of "it saves data space"; that's simply bogus.
If you don't define the sizes of your types ahead of time, you should *not*
be relying on the compiler to work around your own laziness.

: Anyone who really wanted to ensure portability of an interface that might
: change over time would simply add a place-holder enum that forced the type.

Again, you're asking established, working code to add something that has not
been required for >30 years, just to make it work the same as it has for
that same time.

-- 
-- Todd Vierling <tv@wasabisystems.com>  *  Wasabi & NetBSD:  Run with it.
-- CDs, Integration, Embedding, Support -- http://www.wasabisystems.com/