64-bit NULL: a followup

Marcel Moolenaar marcel at xcllnt.net
Fri Nov 28 16:58:26 PST 2003


Previously on -standards:

On Mon, Oct 27, 2003 at 02:49:51PM +0100, Harti Brandt wrote:
> 
> a question came up wether the NULL should be defined as (0L) on sparc.
> (Solaris does this). Currently we define NULL as 0.

On Mon, 27 Oct 2003, Erik Trulsson wrote:
>
> Both are perfectly good definitions of NULL.

On Mon, 27 Oct 2003, Tony Finch wrote:
>
> No, NULL is an implementation-defined null pointer constant, not a null
> pointer. The difference is that a null pointer constant is an integer
> constant expression that evaluates to zero (optionally cast to void*),
> and a null pointer is a null pointer constant converted to a pointer type
> (which might involve changes in representation). Therefore using a bare
> NULL to terminate the execl argument list is not in general legal.

On ia64 I run into a problem where a caller of a function with a variable
number of arguments leaves garbage in the high order 32 bits due to the
fact that NULL is defined as 0, and thus has type int by default.

Take the following simple example:

extern int va(int, ...);
int foo(void)
{
	return (va(1, 2, 3, 4, 5, 6, 7, 8, NULL));
}

The last argument has to be passed onto the stack, which gcc does
as follows:

		:
  1c:   01 61 00 84                         adds r14=16,r12;;
  20:   00 00 00 1c 90 11       [MII]       st4 [r14]=r0
  26:   40 0a 00 00 48 a0                   mov r36=1
  2c:   24 00 00 90                         mov r37=2
  30:   00 30 0d 00 00 24       [MII]       mov r38=3
  36:   70 22 00 00 48 00                   mov r39=4
  3c:   55 00 00 90                         mov r40=5
  40:   00 48 19 00 00 24       [MII]       mov r41=6
  46:   a0 3a 00 00 48 60                   mov r42=7
  4c:   85 00 00 90                         mov r43=8
  50:   1c 00 00 00 01 00       [MFB]       nop.m 0x0
  56:   00 00 00 02 00 00                   nop.f 0x0
  5c:   08 00 00 50                         br.call.sptk.many b0=50 <foo+0x50>
		: 

Notice the "st4".  If NULL was defined as 0L, this would look like:

		:
  1c:   01 61 00 84                         adds r14=16,r12;;
  20:   00 00 00 1c 98 11       [MII]       st8 [r14]=r0
  26:   40 0a 00 00 48 a0                   mov r36=1
		:

Notice the "st8".  Since NULL is a pointer constant, programmers do
(implicitly) expect it to have the same width as a pointer type and
thus do not cast it to a pointer type or an integer type that has a
width larger or equal to a pointer type.

So, the bottomline is that we currently do have third-party code that
fails to run on ia64 (and possibly other 64-bit platforms) due to the
fact that NULL is defined as 0.

Since Erik thinks 0 and 0L are both perfectly good definitions for
NULL and Tony emphasizes that NULL is an integer expression, I think
we should change the definition of NULL to 0L to improve portability
to FreeBSD/LP64. It will definitely fix known breakages on ia64.

Thoughts?

-- 
 Marcel Moolenaar	  USPA: A-39004		 marcel at xcllnt.net


More information about the freebsd-standards mailing list