Subject: Re: emuns on ARM: What should we do?
To: Todd Vierling <tv@wasabisystems.com>
From: Richard Earnshaw <rearnsha@arm.com>
List: tech-toolchain
Date: 01/21/2002 16:18:00
> 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.
> 

Sure, he's assuming that the compiler won't waste system resources on an 
enum which is unlikely at worst to contain more than 32k different values.

> : > 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.  

But a debugger can no-longer display them as enums (since they aren't), 
and any uses of them really should be accompanied by casts.  Further, the 
compiler can no-longer detect attempts to assign a different enum type to 
the field.

Eg:

	enum a {p, q};
	enum b {y, z};

	enum a  x;
	uint8_t w; /* Really enum a */

	x = y;	/* Diagnostic */
	w = y;  /* ??? */

> 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!

At the expense of readability and testability.

And you can't force there to be no gaps, since the C standard does not put 
sufficient constraints on the layout of structures for you to guarantee 
that (you can minimize the number of systems where it might leave holes, 
but you can't eliminate it -- I don't believe it would be an incorrect 
implementation of the C standards for an ABI to mandate that each element 
of a structure be placed on a word boundary; not useful perhaps, but not 
invalid -- anyway, this is straying from the issue).

> 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.

If the code was written correctly 30 years ago it will still work.  If you 
modify the code then it was no-longer written thirty years ago.

There are lots of examples of code that worked with compilers 30 years ago 
(or even 5) that won't work with modern compilers because it contains 
assumptions that were contrary to C standard (OK, so I know that c89 is 
only 13 years ago).

R.