Date: Sat, 20 Feb 2016 15:13:45 +1100 (EST) From: Bruce Evans <brde@optusnet.com.au> To: Justin Hibbits <jhibbits@freebsd.org> Cc: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: Re: svn commit: r295833 - head/sys/sys Message-ID: <20160220142119.U1712@besplex.bde.org> In-Reply-To: <201602200134.u1K1YDOD016555@repo.freebsd.org> References: <201602200134.u1K1YDOD016555@repo.freebsd.org>
next in thread | previous in thread | raw e-mail | index | archive | help
On Sat, 20 Feb 2016, Justin Hibbits wrote: > Log: > Fix the definition of RM_MAX_END. > > Even though casting from signed to unsigned is well-defined in C, it's better to > first cast to the larger unsigned type, then negate. Casting ~0 is well-defined, but ~0 isn't. The operation is complementation, not negation. > Modified: head/sys/sys/rman.h > ============================================================================== > --- head/sys/sys/rman.h Sat Feb 20 01:32:58 2016 (r295832) > +++ head/sys/sys/rman.h Sat Feb 20 01:34:13 2016 (r295833) > @@ -61,7 +61,7 @@ enum rman_type { RMAN_UNINIT = 0, RMAN_G > */ > #define RM_TEXTLEN 32 > > -#define RM_MAX_END ((rman_res_t)~0) > +#define RM_MAX_END (~(rman_res_t)0) If the operation were negation, then its result -0 would actually be well- defined. It would be 0 again, even in the 1's complement and signed magnitude cases where -0 can be represented. -0 cast to unsigned must give 0 again, and not be all-bits-1 even if it started as all-bits 1 representing -0 in 2's complement. ~0 was under-specified in C90 as being the bitwise complement. The value of that is not specified unless the promotion of the orginal type is unsigned (~(unsigned char)0 is also not specified except on exotic machines (no longer permitted by POSIX) with unsigned char the same size as unsigned int). ~0 is even more under-specified in C99 because C99 is more careful with representations and has trap representations. (This is not fixed in C11.) Complementing a non- trap-representation might give a trap representation if done bitwise, even starting from a nondescript value like 0. But if there are no trap or padding bits, the only reasonable interpretation of the spec is that ~0 gives all-bits-1 with whatever value that has. In the 2's complement case, the value is -1 and casting this to unsigned works right. In the 1's complement case, the value is -0 and casting this to unsigned gives unsigned plain 0. In the signed-magnitude case, I think it gives -0x7fffffff with 32-bit ints and casting this to unsigned gives 0x80000001. C90 allows other representations, so the result can be anything. The clearest way to write the expression is probably ((rman_res_t)-1) like the buggy ~0 version did in the 2's complement case. Everyone knows what -1 is. Conversion of -1 to unsigned is better known than what ~0 is. It takes an explicit specification for both. Conversion of -1 involves "[in extra precision] repeatedly adding or subtracting one more than the maximim value that can be represented in the new type until [the result is representable]". Thus ((rman_res_t)-1) is maxof(rman_res_t) + 1 - 1 == maxof(rman_res_t). (~(rman_res_t)0) involves the specification of the '~' operator saying that complementing the bits actually works for the unsigned case. The precise wording is "If the promoted type [of E] is an unsigned type, then the expression ~E is equivalent to the maximum value representable in that type minus E". Thus (~(rman_res_t)0) is maxof(rman_res_t) - 0 = maxof(rman_res_t). I think the precise wording is redundant, but this is not clear. Something is needed to ensure that complementing bits doesn't give a trap representation for the unsigned case. Complementing only value bits wouldn't give a trap representation, but complementing padding bits could (should) give a trap representation. The spec is too fuzzy to say which bits are complemented, except in the unsigned case padding bits must not be complemented if this would give a trap representation. Bruce
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20160220142119.U1712>