svn commit: r303342 - in head: include lib/libc/stdlib

Bruce Evans brde at optusnet.com.au
Wed Jul 27 01:26:58 UTC 2016


On Tue, 26 Jul 2016, Ed Schouten wrote:

> Log:
>  Fix typing of srandom() and initstate().
>
>  POSIX requires that these functions have an unsigned int for their first
>  argument; not an unsigned long.
>
>  My reasoning is that we can safely change these functions without
>  breaking the ABI. As far as I know, our supported architectures either
>  use registers for passing function arguments that are at least as big as
>  long (e.g., amd64), or int and long are of the same size (e.g., i386).

This might work here since the type is unsigned, but it wouldn't work to
change from int to long.

Doing the correct extension in callers seems to be accidental on amd64,
and doesn't happen for the signed case with gcc-4.2.  For passing at
least the first arg in the standard place (%rdi), gcc-4.2 loads both
int and u_int args using movl.  This always zero-extends.  This is
accidentally correct for u_ints, but for ints it does bad things like
turning -1 into 0xFFFFFFFF.

Callees don't depend on callers not passing garbage in the top bits.
They generate extra instructions which waste time to do the correct
extension if necessary.  That is, if you don't pun the types.  If
you pass (int)-1 to a function expecting long, then with gcc-4.2 on
amd64, -1 becomes 0xFFFFFFFF and the caller must trust this as a long
value and not "fix" it to get -1 again.  But clang sign-extends in
callers, so this works, perhaps not accidentally.  With unsigned types,
zero-extension works for both compilers.  Either gcc-4.2 is broken or
clang is doing more than the ABI requires.

I think the ABI shouldn't require much here.  I expected the extra
instructions to go away when sloppy unprotyped code and type pun
became less common, but compilers still generate them.  A stricter
ABI would require callers to do more and callees would keep doing
more.

Bruce


More information about the svn-src-all mailing list