Skip to content
This repository was archived by the owner on May 21, 2019. It is now read-only.

Remove UB from int-to-float conversion for INT_MIN. #24

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 6 additions & 7 deletions lib/builtins/floatsidf.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,27 +24,26 @@ COMPILER_RT_ABI fp_t
__floatsidf(int a) {

const int aWidth = sizeof a * CHAR_BIT;

// Handle zero as a special case to protect clz
if (a == 0)
return fromRep(0);

// All other cases begin by extracting the sign and absolute value of a
rep_t sign = 0;
unsigned aAbs = (unsigned)a;
if (a < 0) {
sign = signBit;
a = -a;
aAbs = ~(unsigned)a + 1U;
}

// 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
// cast to unsigned int is necessary to get the correct behavior for
// the input INT_MIN.
// Shift a into the significand field and clear the implicit bit.
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;
Expand Down
13 changes: 7 additions & 6 deletions lib/builtins/floatsisf.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,30 +24,31 @@ COMPILER_RT_ABI fp_t
__floatsisf(int a) {

const int aWidth = sizeof a * CHAR_BIT;

// Handle zero as a special case to protect clz
if (a == 0)
return fromRep(0);

// All other cases begin by extracting the sign and absolute value of a
rep_t sign = 0;
unsigned aAbs = (unsigned)a;
if (a < 0) {
sign = signBit;
a = -a;
aAbs = ~(unsigned)a + 1U;
}

// 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;
}
Expand Down