Skip to content

Commit 4e4775d

Browse files
jacobly0andrewrk
authored andcommitted
x86_64: implement conversions between scalar floats and ints
Closes #22797
1 parent 138d30b commit 4e4775d

39 files changed

+7281
-447
lines changed

lib/compiler_rt.zig

+25-5
Original file line numberDiff line numberDiff line change
@@ -61,33 +61,43 @@ comptime {
6161
_ = @import("compiler_rt/fixhfsi.zig");
6262
_ = @import("compiler_rt/fixhfdi.zig");
6363
_ = @import("compiler_rt/fixhfti.zig");
64+
_ = @import("compiler_rt/fixhfei.zig");
6465
_ = @import("compiler_rt/fixsfsi.zig");
6566
_ = @import("compiler_rt/fixsfdi.zig");
6667
_ = @import("compiler_rt/fixsfti.zig");
68+
_ = @import("compiler_rt/fixsfei.zig");
6769
_ = @import("compiler_rt/fixdfsi.zig");
6870
_ = @import("compiler_rt/fixdfdi.zig");
6971
_ = @import("compiler_rt/fixdfti.zig");
72+
_ = @import("compiler_rt/fixdfei.zig");
7073
_ = @import("compiler_rt/fixtfsi.zig");
7174
_ = @import("compiler_rt/fixtfdi.zig");
7275
_ = @import("compiler_rt/fixtfti.zig");
76+
_ = @import("compiler_rt/fixtfei.zig");
7377
_ = @import("compiler_rt/fixxfsi.zig");
7478
_ = @import("compiler_rt/fixxfdi.zig");
7579
_ = @import("compiler_rt/fixxfti.zig");
80+
_ = @import("compiler_rt/fixxfei.zig");
7681
_ = @import("compiler_rt/fixunshfsi.zig");
7782
_ = @import("compiler_rt/fixunshfdi.zig");
7883
_ = @import("compiler_rt/fixunshfti.zig");
84+
_ = @import("compiler_rt/fixunshfei.zig");
7985
_ = @import("compiler_rt/fixunssfsi.zig");
8086
_ = @import("compiler_rt/fixunssfdi.zig");
8187
_ = @import("compiler_rt/fixunssfti.zig");
88+
_ = @import("compiler_rt/fixunssfei.zig");
8289
_ = @import("compiler_rt/fixunsdfsi.zig");
8390
_ = @import("compiler_rt/fixunsdfdi.zig");
8491
_ = @import("compiler_rt/fixunsdfti.zig");
92+
_ = @import("compiler_rt/fixunsdfei.zig");
8593
_ = @import("compiler_rt/fixunstfsi.zig");
8694
_ = @import("compiler_rt/fixunstfdi.zig");
8795
_ = @import("compiler_rt/fixunstfti.zig");
96+
_ = @import("compiler_rt/fixunstfei.zig");
8897
_ = @import("compiler_rt/fixunsxfsi.zig");
8998
_ = @import("compiler_rt/fixunsxfdi.zig");
9099
_ = @import("compiler_rt/fixunsxfti.zig");
100+
_ = @import("compiler_rt/fixunsxfei.zig");
91101

92102
_ = @import("compiler_rt/float_from_int.zig");
93103
_ = @import("compiler_rt/floatsihf.zig");
@@ -105,21 +115,31 @@ comptime {
105115
_ = @import("compiler_rt/floattidf.zig");
106116
_ = @import("compiler_rt/floattitf.zig");
107117
_ = @import("compiler_rt/floattixf.zig");
108-
_ = @import("compiler_rt/floatundihf.zig");
109-
_ = @import("compiler_rt/floatundisf.zig");
110-
_ = @import("compiler_rt/floatundidf.zig");
111-
_ = @import("compiler_rt/floatunditf.zig");
112-
_ = @import("compiler_rt/floatundixf.zig");
118+
_ = @import("compiler_rt/floateihf.zig");
119+
_ = @import("compiler_rt/floateisf.zig");
120+
_ = @import("compiler_rt/floateidf.zig");
121+
_ = @import("compiler_rt/floateitf.zig");
122+
_ = @import("compiler_rt/floateixf.zig");
113123
_ = @import("compiler_rt/floatunsihf.zig");
114124
_ = @import("compiler_rt/floatunsisf.zig");
115125
_ = @import("compiler_rt/floatunsidf.zig");
116126
_ = @import("compiler_rt/floatunsitf.zig");
117127
_ = @import("compiler_rt/floatunsixf.zig");
128+
_ = @import("compiler_rt/floatundihf.zig");
129+
_ = @import("compiler_rt/floatundisf.zig");
130+
_ = @import("compiler_rt/floatundidf.zig");
131+
_ = @import("compiler_rt/floatunditf.zig");
132+
_ = @import("compiler_rt/floatundixf.zig");
118133
_ = @import("compiler_rt/floatuntihf.zig");
119134
_ = @import("compiler_rt/floatuntisf.zig");
120135
_ = @import("compiler_rt/floatuntidf.zig");
121136
_ = @import("compiler_rt/floatuntitf.zig");
122137
_ = @import("compiler_rt/floatuntixf.zig");
138+
_ = @import("compiler_rt/floatuneihf.zig");
139+
_ = @import("compiler_rt/floatuneisf.zig");
140+
_ = @import("compiler_rt/floatuneidf.zig");
141+
_ = @import("compiler_rt/floatuneitf.zig");
142+
_ = @import("compiler_rt/floatuneixf.zig");
123143

124144
// comparison
125145
_ = @import("compiler_rt/comparef.zig");

lib/compiler_rt/divc3_test.zig

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ const __divdc3 = @import("./divdc3.zig").__divdc3;
99
const __divxc3 = @import("./divxc3.zig").__divxc3;
1010
const __divtc3 = @import("./divtc3.zig").__divtc3;
1111

12-
test {
12+
test "divc3" {
1313
try testDiv(f16, __divhc3);
1414
try testDiv(f32, __divsc3);
1515
try testDiv(f64, __divdc3);

lib/compiler_rt/fixdfei.zig

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
const divCeil = @import("std").math.divCeil;
2+
const common = @import("./common.zig");
3+
const bigIntFromFloat = @import("./int_from_float.zig").bigIntFromFloat;
4+
5+
pub const panic = common.panic;
6+
7+
comptime {
8+
@export(&__fixdfei, .{ .name = "__fixdfei", .linkage = common.linkage, .visibility = common.visibility });
9+
}
10+
11+
pub fn __fixdfei(r: [*]u32, bits: usize, a: f64) callconv(.c) void {
12+
return bigIntFromFloat(.signed, r[0 .. divCeil(usize, bits, 32) catch unreachable], a);
13+
}

lib/compiler_rt/fixdfti.zig

+4-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,10 @@ comptime {
88
if (common.want_windows_v2u64_abi) {
99
@export(&__fixdfti_windows_x86_64, .{ .name = "__fixdfti", .linkage = common.linkage, .visibility = common.visibility });
1010
} else {
11-
@export(&__fixdfti, .{ .name = "__fixdfti", .linkage = common.linkage, .visibility = common.visibility });
11+
@export(&__fixdfti, .{ .name = switch (builtin.cpu.arch) {
12+
.hexagon => "__hexagon",
13+
else => "_",
14+
} ++ "_fixdfti", .linkage = common.linkage, .visibility = common.visibility });
1215
}
1316
}
1417

lib/compiler_rt/fixhfei.zig

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
const divCeil = @import("std").math.divCeil;
2+
const common = @import("./common.zig");
3+
const bigIntFromFloat = @import("./int_from_float.zig").bigIntFromFloat;
4+
5+
pub const panic = common.panic;
6+
7+
comptime {
8+
@export(&__fixhfei, .{ .name = "__fixhfei", .linkage = common.linkage, .visibility = common.visibility });
9+
}
10+
11+
pub fn __fixhfei(r: [*]u32, bits: usize, a: f16) callconv(.c) void {
12+
return bigIntFromFloat(.signed, r[0 .. divCeil(usize, bits, 32) catch unreachable], a);
13+
}

lib/compiler_rt/fixsfei.zig

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
const divCeil = @import("std").math.divCeil;
2+
const common = @import("./common.zig");
3+
const bigIntFromFloat = @import("./int_from_float.zig").bigIntFromFloat;
4+
5+
pub const panic = common.panic;
6+
7+
comptime {
8+
@export(&__fixsfei, .{ .name = "__fixsfei", .linkage = common.linkage, .visibility = common.visibility });
9+
}
10+
11+
pub fn __fixsfei(r: [*]u32, bits: usize, a: f32) callconv(.c) void {
12+
return bigIntFromFloat(.signed, r[0 .. divCeil(usize, bits, 32) catch unreachable], a);
13+
}

lib/compiler_rt/fixsfti.zig

+4-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,10 @@ comptime {
88
if (common.want_windows_v2u64_abi) {
99
@export(&__fixsfti_windows_x86_64, .{ .name = "__fixsfti", .linkage = common.linkage, .visibility = common.visibility });
1010
} else {
11-
@export(&__fixsfti, .{ .name = "__fixsfti", .linkage = common.linkage, .visibility = common.visibility });
11+
@export(&__fixsfti, .{ .name = switch (builtin.cpu.arch) {
12+
.hexagon => "__hexagon",
13+
else => "_",
14+
} ++ "_fixsfti", .linkage = common.linkage, .visibility = common.visibility });
1215
}
1316
}
1417

lib/compiler_rt/fixtfei.zig

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
const divCeil = @import("std").math.divCeil;
2+
const common = @import("./common.zig");
3+
const bigIntFromFloat = @import("./int_from_float.zig").bigIntFromFloat;
4+
5+
pub const panic = common.panic;
6+
7+
comptime {
8+
@export(&__fixtfei, .{ .name = "__fixtfei", .linkage = common.linkage, .visibility = common.visibility });
9+
}
10+
11+
pub fn __fixtfei(r: [*]u32, bits: usize, a: f128) callconv(.c) void {
12+
return bigIntFromFloat(.signed, r[0 .. divCeil(usize, bits, 32) catch unreachable], a);
13+
}

lib/compiler_rt/fixunsdfei.zig

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
const divCeil = @import("std").math.divCeil;
2+
const common = @import("./common.zig");
3+
const bigIntFromFloat = @import("./int_from_float.zig").bigIntFromFloat;
4+
5+
pub const panic = common.panic;
6+
7+
comptime {
8+
@export(&__fixunsdfei, .{ .name = "__fixunsdfei", .linkage = common.linkage, .visibility = common.visibility });
9+
}
10+
11+
pub fn __fixunsdfei(r: [*]u32, bits: usize, a: f64) callconv(.c) void {
12+
return bigIntFromFloat(.unsigned, r[0 .. divCeil(usize, bits, 32) catch unreachable], a);
13+
}

lib/compiler_rt/fixunsdfti.zig

+4-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,10 @@ comptime {
88
if (common.want_windows_v2u64_abi) {
99
@export(&__fixunsdfti_windows_x86_64, .{ .name = "__fixunsdfti", .linkage = common.linkage, .visibility = common.visibility });
1010
} else {
11-
@export(&__fixunsdfti, .{ .name = "__fixunsdfti", .linkage = common.linkage, .visibility = common.visibility });
11+
@export(&__fixunsdfti, .{ .name = switch (builtin.cpu.arch) {
12+
.hexagon => "__hexagon",
13+
else => "_",
14+
} ++ "_fixunsdfti", .linkage = common.linkage, .visibility = common.visibility });
1215
}
1316
}
1417

lib/compiler_rt/fixunshfei.zig

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
const divCeil = @import("std").math.divCeil;
2+
const common = @import("./common.zig");
3+
const bigIntFromFloat = @import("./int_from_float.zig").bigIntFromFloat;
4+
5+
pub const panic = common.panic;
6+
7+
comptime {
8+
@export(&__fixunshfei, .{ .name = "__fixunshfei", .linkage = common.linkage, .visibility = common.visibility });
9+
}
10+
11+
pub fn __fixunshfei(r: [*]u32, bits: usize, a: f16) callconv(.c) void {
12+
return bigIntFromFloat(.unsigned, r[0 .. divCeil(usize, bits, 32) catch unreachable], a);
13+
}

lib/compiler_rt/fixunssfei.zig

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
const divCeil = @import("std").math.divCeil;
2+
const common = @import("./common.zig");
3+
const bigIntFromFloat = @import("./int_from_float.zig").bigIntFromFloat;
4+
5+
pub const panic = common.panic;
6+
7+
comptime {
8+
@export(&__fixunssfei, .{ .name = "__fixunssfei", .linkage = common.linkage, .visibility = common.visibility });
9+
}
10+
11+
pub fn __fixunssfei(r: [*]u32, bits: usize, a: f32) callconv(.c) void {
12+
return bigIntFromFloat(.unsigned, r[0 .. divCeil(usize, bits, 32) catch unreachable], a);
13+
}

lib/compiler_rt/fixunssfti.zig

+4-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,10 @@ comptime {
88
if (common.want_windows_v2u64_abi) {
99
@export(&__fixunssfti_windows_x86_64, .{ .name = "__fixunssfti", .linkage = common.linkage, .visibility = common.visibility });
1010
} else {
11-
@export(&__fixunssfti, .{ .name = "__fixunssfti", .linkage = common.linkage, .visibility = common.visibility });
11+
@export(&__fixunssfti, .{ .name = switch (builtin.cpu.arch) {
12+
.hexagon => "__hexagon",
13+
else => "_",
14+
} ++ "_fixunssfti", .linkage = common.linkage, .visibility = common.visibility });
1215
}
1316
}
1417

lib/compiler_rt/fixunstfei.zig

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
const divCeil = @import("std").math.divCeil;
2+
const common = @import("./common.zig");
3+
const bigIntFromFloat = @import("./int_from_float.zig").bigIntFromFloat;
4+
5+
pub const panic = common.panic;
6+
7+
comptime {
8+
@export(&__fixunstfei, .{ .name = "__fixunstfei", .linkage = common.linkage, .visibility = common.visibility });
9+
}
10+
11+
pub fn __fixunstfei(r: [*]u32, bits: usize, a: f128) callconv(.c) void {
12+
return bigIntFromFloat(.unsigned, r[0 .. divCeil(usize, bits, 32) catch unreachable], a);
13+
}

lib/compiler_rt/fixunsxfei.zig

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
const divCeil = @import("std").math.divCeil;
2+
const common = @import("./common.zig");
3+
const bigIntFromFloat = @import("./int_from_float.zig").bigIntFromFloat;
4+
5+
pub const panic = common.panic;
6+
7+
comptime {
8+
@export(&__fixunsxfei, .{ .name = "__fixunsxfei", .linkage = common.linkage, .visibility = common.visibility });
9+
}
10+
11+
pub fn __fixunsxfei(r: [*]u32, bits: usize, a: f80) callconv(.c) void {
12+
return bigIntFromFloat(.unsigned, r[0 .. divCeil(usize, bits, 32) catch unreachable], a);
13+
}

lib/compiler_rt/fixxfei.zig

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
const divCeil = @import("std").math.divCeil;
2+
const common = @import("./common.zig");
3+
const bigIntFromFloat = @import("./int_from_float.zig").bigIntFromFloat;
4+
5+
pub const panic = common.panic;
6+
7+
comptime {
8+
@export(&__fixxfei, .{ .name = "__fixxfei", .linkage = common.linkage, .visibility = common.visibility });
9+
}
10+
11+
pub fn __fixxfei(r: [*]u32, bits: usize, a: f80) callconv(.c) void {
12+
return bigIntFromFloat(.signed, r[0 .. divCeil(usize, bits, 32) catch unreachable], a);
13+
}

lib/compiler_rt/float_from_int.zig

+52-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
const Int = @import("std").meta.Int;
2-
const math = @import("std").math;
1+
const std = @import("std");
2+
const Int = std.meta.Int;
3+
const math = std.math;
34

45
pub fn floatFromInt(comptime T: type, x: anytype) T {
56
if (x == 0) return 0;
@@ -18,7 +19,7 @@ pub fn floatFromInt(comptime T: type, x: anytype) T {
1819
const max_exp = exp_bias;
1920

2021
// Sign
21-
const abs_val = if (@TypeOf(x) == comptime_int or @typeInfo(@TypeOf(x)).int.signedness == .signed) @abs(x) else x;
22+
const abs_val = @abs(x);
2223
const sign_bit = if (x < 0) @as(uT, 1) << (float_bits - 1) else 0;
2324
var result: uT = sign_bit;
2425

@@ -53,6 +54,54 @@ pub fn floatFromInt(comptime T: type, x: anytype) T {
5354
return @bitCast(sign_bit | result);
5455
}
5556

57+
const endian = @import("builtin").cpu.arch.endian();
58+
inline fn limb(limbs: []const u32, index: usize) u32 {
59+
return switch (endian) {
60+
.little => limbs[index],
61+
.big => limbs[limbs.len - 1 - index],
62+
};
63+
}
64+
65+
pub inline fn floatFromBigInt(comptime T: type, comptime signedness: std.builtin.Signedness, x: []const u32) T {
66+
switch (x.len) {
67+
0 => return 0,
68+
inline 1...4 => |limbs_len| return @floatFromInt(@as(
69+
@Type(.{ .int = .{ .signedness = signedness, .bits = 32 * limbs_len } }),
70+
@bitCast(x[0..limbs_len].*),
71+
)),
72+
else => {},
73+
}
74+
75+
// sign implicit fraction round sticky
76+
const I = comptime @Type(.{ .int = .{
77+
.signedness = signedness,
78+
.bits = @as(u16, @intFromBool(signedness == .signed)) + 1 + math.floatFractionalBits(T) + 1 + 1,
79+
} });
80+
81+
const clrsb = clrsb: {
82+
var clsb: usize = 0;
83+
const sign_bits: u32 = switch (signedness) {
84+
.signed => @bitCast(@as(i32, @bitCast(limb(x, x.len - 1))) >> 31),
85+
.unsigned => 0,
86+
};
87+
for (0..x.len) |limb_index| {
88+
const l = limb(x, x.len - 1 - limb_index) ^ sign_bits;
89+
clsb += @clz(l);
90+
if (l != 0) break;
91+
}
92+
break :clrsb clsb - @intFromBool(signedness == .signed);
93+
};
94+
const active_bits = 32 * x.len - clrsb;
95+
const exponent = active_bits -| @bitSizeOf(I);
96+
const exponent_limb = exponent / 32;
97+
const sticky = for (0..exponent_limb) |limb_index| {
98+
if (limb(x, limb_index) != 0) break true;
99+
} else limb(x, exponent_limb) & ((@as(u32, 1) << @truncate(exponent)) - 1) != 0;
100+
return math.ldexp(@as(T, @floatFromInt(
101+
std.mem.readPackedIntNative(I, std.mem.sliceAsBytes(x), exponent) | @intFromBool(sticky),
102+
)), @intCast(exponent));
103+
}
104+
56105
test {
57106
_ = @import("float_from_int_test.zig");
58107
}

0 commit comments

Comments
 (0)