Subject: Re: Exactly what is wrong with our compiler?
To: None <port-sparc64@netbsd.org>
From: David Laight <David.Laight@btinternet.com>
List: port-sparc64
Date: 01/04/2002 13:04:30
> > As far as I know the NTP problem is not a sparc64 specific problem but
> > a general gcc foulup that happens to hit sparc64 because it's a 64-bit
> > platform and doesn't to alignment fixups.

Neither do many of the 32bit systems.
Most of the code that assumed that a byte aligned address could be cast
to a structure ptr got fixed when the sparc ports were done.  Similarly
all the dereferencing 0 (expecting 0) bugs (a hack from the VAX days)
got fixed at much the same time.  (Dunno when they got sorted in netbsd,
but we fixed them as part of the SVR4 merge...)
> 
> I have looked into this more deeply in the hope of providing someone
> somewhere with a fix. I don't know if this is a compiler foul up or not.
> I have lost my copy of K&R2, so I can't check some of the issues
> surrounding pointers. 
> 
> The problem with the memory copy optimiser is that it assumes that the
> pointer it is being passed is correctly aligned based on its type. For
> instance, no assumptions are made about pointers to void or chars, but
> pointers to larger objects that must be aligned are assumed to be
> aligned. The problem with NTP is that it uses such a pointer to point to
> an unaligned object. Without more information on the ANSI C standard, I
> don't know whether or not this falls into the category of making a
> broken program worse.

The NTP code is broken!
K&R2 page 199: "A pointer to one type may be converted to a pointer to
another type.  The resulting pointer may cause addressing exceptions if the
subject pointer does not refer to an object suitably aligned in storage."

Most effects of casts are actually implementation defined though :-)

> 
> Here is a summary of what NTP does, followed by an example of a more
> normal way to do the same thing.
> 
> char *buf;
> int offset;
> struct big data, *ptr;
> 
> /* The NTP way. */
> ptr = (struct big *)(buf + offset);
> data = *ptr; /* ptr does not point to aligned storage */
> 
> /* The normal way */
> memcpy (&data, buf + offset, sizeof (data));
> 
> Note that gcc treats the use of memcpy and structure copies the same
> way.

I would have thought that memcpy( &data, ptr, sizeof data ) would be safe.
Since there is an (implied) cast to void * in the function call.  If gcc's
inlining of memcpy assumes otherwise it might be deemed broken.

    David