compiler-rt: Fix signedness mismatch in f128 mul impl

The `1 - shift` expression was computed using small unsigned types and
then casted to i32, producing either an underflow error or an incorrect
result.

Reported by `@notviri` in #8733
This commit is contained in:
LemonBoy
2021-05-14 12:17:58 +02:00
committed by Andrew Kelley
parent 00ebbe6df2
commit 5185b5619a
2 changed files with 20 additions and 6 deletions

View File

@@ -98,8 +98,8 @@ fn mulXf3(comptime T: type, a: T, b: T) T {
// one or both of a or b is denormal, the other (if applicable) is a
// normal number. Renormalize one or both of a and b, and set scale to
// include the necessary exponent adjustment.
if (aAbs < implicitBit) scale +%= normalize(T, &aSignificand);
if (bAbs < implicitBit) scale +%= normalize(T, &bSignificand);
if (aAbs < implicitBit) scale += normalize(T, &aSignificand);
if (bAbs < implicitBit) scale += normalize(T, &bSignificand);
}
// Or in the implicit significand bit. (If we fell through from the
@@ -277,7 +277,7 @@ fn normalize(comptime T: type, significand: *std.meta.Int(.unsigned, @typeInfo(T
const shift = @clz(Z, significand.*) - @clz(Z, implicitBit);
significand.* <<= @intCast(std.math.Log2Int(Z), shift);
return 1 - shift;
return @as(i32, 1) - shift;
}
fn wideRightShiftWithSticky(comptime Z: type, hi: *Z, lo: *Z, count: u32) void {
@@ -285,15 +285,15 @@ fn wideRightShiftWithSticky(comptime Z: type, hi: *Z, lo: *Z, count: u32) void {
const typeWidth = @typeInfo(Z).Int.bits;
const S = std.math.Log2Int(Z);
if (count < typeWidth) {
const sticky = @truncate(u8, lo.* << @intCast(S, typeWidth -% count));
const sticky = @boolToInt((lo.* << @intCast(S, typeWidth -% count)) != 0);
lo.* = (hi.* << @intCast(S, typeWidth -% count)) | (lo.* >> @intCast(S, count)) | sticky;
hi.* = hi.* >> @intCast(S, count);
} else if (count < 2 * typeWidth) {
const sticky = @truncate(u8, hi.* << @intCast(S, 2 * typeWidth -% count) | lo.*);
const sticky = @boolToInt((hi.* << @intCast(S, 2 * typeWidth -% count) | lo.*) != 0);
lo.* = hi.* >> @intCast(S, count -% typeWidth) | sticky;
hi.* = 0;
} else {
const sticky = @truncate(u8, hi.* | lo.*);
const sticky = @boolToInt((hi.* | lo.*) != 0);
lo.* = sticky;
hi.* = 0;
}

View File

@@ -88,4 +88,18 @@ test "multf3" {
);
try test__multf3(0x1.23456734245345p-10000, 0x1.edcba524498724p-6497, 0x0, 0x0);
// Denormal operands.
try test__multf3(
0x0.0000000000000000000000000001p-16382,
0x1.p16383,
0x3f90000000000000,
0x0,
);
try test__multf3(
0x1.p16383,
0x0.0000000000000000000000000001p-16382,
0x3f90000000000000,
0x0,
);
}