[Mono-list] Gcc summit...interesting stuff

Fergus Henderson fjh@cs.mu.oz.au
Thu, 27 Nov 2003 15:23:35 +1100

On 26-Nov-2003, Chris Lattner <sabre@nondot.org> wrote:
> Fergus Henderson <fjh@cs.mu.oz.au> wrote:
>> Chris Lattner <sabre@nondot.org> wrote:
> > > Ok.  There are _inherently_ difficult parts though.  For example, you
> > > can't really translate '#ifdef BIG_ENDIAN' style code into a portable
> > > representation, no matter what it is.
> >
> > That's true.  But code which uses #ifdef BIG_ENDIAN is not
> > standard-conforming C code.
> How is it not?

It makes an assumption which is not guaranteed by the standard:
that the endianness will be fixed at compile time.

> Though not the best designed, there is a ton of code that
> contains their own byte swapping routines, which do different things on
> hosts of different endianness.

I agree that there is a ton of crap^H^H^H^Hnon-portable C code out there.
But I don't think we need to bend over backwards to support such code.
It's easy to write byte swapping routines without using #ifdef BIG_ENDIAN.
For example, here's an implementation of the BSD/Posix htons() and ntohs()

	// convert host byte order to big-endian
	uint16_t htons(uint16_t host_int) {
		uint16_t big_endian_int;
		uint8_t *p = (uint8_t *)&big_endian_int;
		p[0] = (host_int & 0xff00) >> 8;
		p[1] = host_int & 0xff;
		return big_endian_int;

	// convert big-endian to host byte order
	uint16_t ntohs(uint16_t big_endian_int) {
		uint8_t *p = (uint8_t *)&big_endian_int;
		return (p[0] << 8) + p[1];

Mind you, IMHO it's better to just use byte arrays rather than integer
types once you have converted to non-host byte order.  Then you can use
uint_least8_t and uint_least16_t rather than relying on the existence of
uint8_t and uint16_t:

	typedef struct { uint_least8_t bytes[2]; } network_uint16;

	network_uint16 my_htons(uint_least16_t host_int) {
		network_uint16_t big_endian_int;
		big_endian_int.bytes[0] = (host_int & 0xff00) >> 8;
		big_endian_int.bytes[1] = host_int & 0x00ff;
		return big_endian_int;

	uint_least16_t my_ntohs(network_uint16_t big_endian_int) {
		return (big_endian_int.bytes[0] << 8) + big_endian_int.bytes[1];

> The problem is doing it in such a way that running the code
> managed gives you an advantage though: which means that it should
> interoperate fairly well with the existing runtime and stuff.  *shrug*

Well, there's already an advantage even if you can't easily interoperate
with other CLI code: the generated binaries can run on any architecture.
You don't need to recompile for each different OS or architecture.

> Also, if you want the resulting CLI code to be portable to other systems,
> then you will have to provide ALL of the header files.


Fergus Henderson <fjh@cs.mu.oz.au>  |  "I have always known that the pursuit
The University of Melbourne         |  of excellence is a lethal habit"
WWW: <http://www.cs.mu.oz.au/~fjh>  |     -- the last words of T. S. Garp.