[PATCH v2] [compiler-rt] Avoid undefined behaviour in __floatsisf and __floatsidf
Stephen Canon via llvm-commits
llvm-commits at lists.llvm.org
Tue Nov 3 05:25:40 PST 2015
Looks good. Thanks for following up on this.
– Steve
> On Nov 2, 2015, at 9:59 PM, Matthew Fernandez <matthew.fernandez at gmail.com> wrote:
>
> These two functions for soft floating point support negate their signed int argument if it is negative. In the case where the argument is INT_MIN, this negation is undefined behaviour with respect to the C standard. This change performs the negation on an unsigned value, avoiding the just-described situation. This change does not alter the intended semantics of these functions.
>
> Signed-off-by: Matthew Fernandez <matthew.fernandez at gmail.com>
>
> Index: lib/builtins/floatsidf.c
> ===================================================================
> --- lib/builtins/floatsidf.c (revision 251670)
> +++ lib/builtins/floatsidf.c (working copy)
> @@ -31,13 +31,14 @@
>
> // All other cases begin by extracting the sign and absolute value of a
> rep_t sign = 0;
> + unsigned int aAbs = a;
> if (a < 0) {
> sign = signBit;
> - a = -a;
> + aAbs = -aAbs;
> }
>
> // Exponent of (fp_t)a is the width of abs(a).
> - const int exponent = (aWidth - 1) - __builtin_clz(a);
> + const int exponent = (aWidth - 1) - __builtin_clz(aAbs);
> rep_t result;
>
> // Shift a into the significand field and clear the implicit bit. Extra
> @@ -44,7 +45,7 @@
> // cast to unsigned int is necessary to get the correct behavior for
> // the input INT_MIN.
> const int shift = significandBits - exponent;
> - result = (rep_t)(unsigned int)a << shift ^ implicitBit;
> + result = (rep_t)aAbs << shift ^ implicitBit;
>
> // Insert the exponent
> result += (rep_t)(exponent + exponentBias) << significandBits;
> Index: lib/builtins/floatsisf.c
> ===================================================================
> --- lib/builtins/floatsisf.c (revision 251670)
> +++ lib/builtins/floatsisf.c (working copy)
> @@ -31,23 +31,24 @@
>
> // All other cases begin by extracting the sign and absolute value of a
> rep_t sign = 0;
> + unsigned int aAbs = a;
> if (a < 0) {
> sign = signBit;
> - a = -a;
> + aAbs = -aAbs;
> }
>
> // Exponent of (fp_t)a is the width of abs(a).
> - const int exponent = (aWidth - 1) - __builtin_clz(a);
> + const int exponent = (aWidth - 1) - __builtin_clz(aAbs);
> rep_t result;
>
> // Shift a into the significand field, rounding if it is a right-shift
> if (exponent <= significandBits) {
> const int shift = significandBits - exponent;
> - result = (rep_t)a << shift ^ implicitBit;
> + result = (rep_t)aAbs << shift ^ implicitBit;
> } else {
> const int shift = exponent - significandBits;
> - result = (rep_t)a >> shift ^ implicitBit;
> - rep_t round = (rep_t)a << (typeWidth - shift);
> + result = (rep_t)aAbs >> shift ^ implicitBit;
> + rep_t round = (rep_t)aAbs << (typeWidth - shift);
> if (round > signBit) result++;
> if (round == signBit) result += result & 1;
> }
More information about the llvm-commits
mailing list