authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-07-10 23:53:14-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-07-10 23:53:14-04:00
log76c89a3de9661264395d111fa3db8d4cfa633f83
tree62d4c9456e5caae29dc59c792371f3e1d4e04a3f
parentf3333a56e8452c16ad30da99f8e4a62a16e58a03
parent2b5215436c47e7546cbe5000345cd81fc45019b8
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #12071 from topolarity/windows-abi-change

compiler_rt: Update Windows ABI for float<->int conversion routines

30 files changed, 334 insertions(+), 207 deletions(-)

lib/compiler_rt/common.zig+4
...@@ -17,6 +17,10 @@ pub const want_aeabi = switch (builtin.abi) {...@@ -17,6 +17,10 @@ pub const want_aeabi = switch (builtin.abi) {
17};17};
18pub const want_ppc_abi = builtin.cpu.arch.isPPC() or builtin.cpu.arch.isPPC64();18pub const want_ppc_abi = builtin.cpu.arch.isPPC() or builtin.cpu.arch.isPPC64();
1919
20// Libcalls that involve u128 on Windows x86-64 are expected by LLVM to use the
21// calling convention of @Vector(2, u64), rather than what's standard.
22pub const want_windows_v2u64_abi = builtin.os.tag == .windows and builtin.cpu.arch == .x86_64;
23
20/// This governs whether to use these symbol names for f16/f32 conversions24/// This governs whether to use these symbol names for f16/f32 conversions
21/// rather than the standard names:25/// rather than the standard names:
22/// * __gnu_f2h_ieee26/// * __gnu_f2h_ieee
lib/compiler_rt/fixdfti.zig+12-1
...@@ -1,12 +1,23 @@...@@ -1,12 +1,23 @@
1const builtin = @import("builtin");
1const common = @import("./common.zig");2const common = @import("./common.zig");
2const floatToInt = @import("./float_to_int.zig").floatToInt;3const floatToInt = @import("./float_to_int.zig").floatToInt;
34
4pub const panic = common.panic;5pub const panic = common.panic;
56
6comptime {7comptime {
7 @export(__fixdfti, .{ .name = "__fixdfti", .linkage = common.linkage });8 if (common.want_windows_v2u64_abi) {
9 @export(__fixdfti_windows_x86_64, .{ .name = "__fixdfti", .linkage = common.linkage });
10 } else {
11 @export(__fixdfti, .{ .name = "__fixdfti", .linkage = common.linkage });
12 }
8}13}
914
10pub fn __fixdfti(a: f64) callconv(.C) i128 {15pub fn __fixdfti(a: f64) callconv(.C) i128 {
11 return floatToInt(i128, a);16 return floatToInt(i128, a);
12}17}
18
19const v2u64 = @Vector(2, u64);
20
21fn __fixdfti_windows_x86_64(a: f64) callconv(.C) v2u64 {
22 return @bitCast(v2u64, floatToInt(i128, a));
23}
lib/compiler_rt/fixhfti.zig+13-2
...@@ -1,12 +1,23 @@...@@ -1,12 +1,23 @@
1const builtin = @import("builtin");
1const common = @import("./common.zig");2const common = @import("./common.zig");
2const floatToInt = @import("./float_to_int.zig").floatToInt;3const floatToInt = @import("./float_to_int.zig").floatToInt;
34
4pub const panic = common.panic;5pub const panic = common.panic;
56
6comptime {7comptime {
7 @export(__fixhfti, .{ .name = "__fixhfti", .linkage = common.linkage });8 if (common.want_windows_v2u64_abi) {
9 @export(__fixhfti_windows_x86_64, .{ .name = "__fixhfti", .linkage = common.linkage });
10 } else {
11 @export(__fixhfti, .{ .name = "__fixhfti", .linkage = common.linkage });
12 }
8}13}
914
10fn __fixhfti(a: f16) callconv(.C) i128 {15pub fn __fixhfti(a: f16) callconv(.C) i128 {
11 return floatToInt(i128, a);16 return floatToInt(i128, a);
12}17}
18
19const v2u64 = @Vector(2, u64);
20
21fn __fixhfti_windows_x86_64(a: f16) callconv(.C) v2u64 {
22 return @bitCast(v2u64, floatToInt(i128, a));
23}
lib/compiler_rt/fixsfti.zig+12-1
...@@ -1,12 +1,23 @@...@@ -1,12 +1,23 @@
1const builtin = @import("builtin");
1const common = @import("./common.zig");2const common = @import("./common.zig");
2const floatToInt = @import("./float_to_int.zig").floatToInt;3const floatToInt = @import("./float_to_int.zig").floatToInt;
34
4pub const panic = common.panic;5pub const panic = common.panic;
56
6comptime {7comptime {
7 @export(__fixsfti, .{ .name = "__fixsfti", .linkage = common.linkage });8 if (common.want_windows_v2u64_abi) {
9 @export(__fixsfti_windows_x86_64, .{ .name = "__fixsfti", .linkage = common.linkage });
10 } else {
11 @export(__fixsfti, .{ .name = "__fixsfti", .linkage = common.linkage });
12 }
8}13}
914
10pub fn __fixsfti(a: f32) callconv(.C) i128 {15pub fn __fixsfti(a: f32) callconv(.C) i128 {
11 return floatToInt(i128, a);16 return floatToInt(i128, a);
12}17}
18
19const v2u64 = @Vector(2, u64);
20
21fn __fixsfti_windows_x86_64(a: f32) callconv(.C) v2u64 {
22 return @bitCast(v2u64, floatToInt(i128, a));
23}
lib/compiler_rt/fixtfti.zig+12-1
...@@ -1,12 +1,23 @@...@@ -1,12 +1,23 @@
1const builtin = @import("builtin");
1const common = @import("./common.zig");2const common = @import("./common.zig");
2const floatToInt = @import("./float_to_int.zig").floatToInt;3const floatToInt = @import("./float_to_int.zig").floatToInt;
34
4pub const panic = common.panic;5pub const panic = common.panic;
56
6comptime {7comptime {
7 @export(__fixtfti, .{ .name = "__fixtfti", .linkage = common.linkage });8 if (common.want_windows_v2u64_abi) {
9 @export(__fixtfti_windows_x86_64, .{ .name = "__fixtfti", .linkage = common.linkage });
10 } else {
11 @export(__fixtfti, .{ .name = "__fixtfti", .linkage = common.linkage });
12 }
8}13}
914
10pub fn __fixtfti(a: f128) callconv(.C) i128 {15pub fn __fixtfti(a: f128) callconv(.C) i128 {
11 return floatToInt(i128, a);16 return floatToInt(i128, a);
12}17}
18
19const v2u64 = @Vector(2, u64);
20
21fn __fixtfti_windows_x86_64(a: f128) callconv(.C) v2u64 {
22 return @bitCast(v2u64, floatToInt(i128, a));
23}
lib/compiler_rt/fixunsdfti.zig+12-1
...@@ -1,12 +1,23 @@...@@ -1,12 +1,23 @@
1const builtin = @import("builtin");
1const common = @import("./common.zig");2const common = @import("./common.zig");
2const floatToInt = @import("./float_to_int.zig").floatToInt;3const floatToInt = @import("./float_to_int.zig").floatToInt;
34
4pub const panic = common.panic;5pub const panic = common.panic;
56
6comptime {7comptime {
7 @export(__fixunsdfti, .{ .name = "__fixunsdfti", .linkage = common.linkage });8 if (common.want_windows_v2u64_abi) {
9 @export(__fixunsdfti_windows_x86_64, .{ .name = "__fixunsdfti", .linkage = common.linkage });
10 } else {
11 @export(__fixunsdfti, .{ .name = "__fixunsdfti", .linkage = common.linkage });
12 }
8}13}
914
10pub fn __fixunsdfti(a: f64) callconv(.C) u128 {15pub fn __fixunsdfti(a: f64) callconv(.C) u128 {
11 return floatToInt(u128, a);16 return floatToInt(u128, a);
12}17}
18
19const v2u64 = @Vector(2, u64);
20
21fn __fixunsdfti_windows_x86_64(a: f64) callconv(.C) v2u64 {
22 return @bitCast(v2u64, floatToInt(u128, a));
23}
lib/compiler_rt/fixunshfti.zig+12-1
...@@ -1,12 +1,23 @@...@@ -1,12 +1,23 @@
1const builtin = @import("builtin");
1const common = @import("./common.zig");2const common = @import("./common.zig");
2const floatToInt = @import("./float_to_int.zig").floatToInt;3const floatToInt = @import("./float_to_int.zig").floatToInt;
34
4pub const panic = common.panic;5pub const panic = common.panic;
56
6comptime {7comptime {
7 @export(__fixunshfti, .{ .name = "__fixunshfti", .linkage = common.linkage });8 if (common.want_windows_v2u64_abi) {
9 @export(__fixunshfti_windows_x86_64, .{ .name = "__fixunshfti", .linkage = common.linkage });
10 } else {
11 @export(__fixunshfti, .{ .name = "__fixunshfti", .linkage = common.linkage });
12 }
8}13}
914
10pub fn __fixunshfti(a: f16) callconv(.C) u128 {15pub fn __fixunshfti(a: f16) callconv(.C) u128 {
11 return floatToInt(u128, a);16 return floatToInt(u128, a);
12}17}
18
19const v2u64 = @import("std").meta.Vector(2, u64);
20
21fn __fixunshfti_windows_x86_64(a: f16) callconv(.C) v2u64 {
22 return @bitCast(v2u64, floatToInt(u128, a));
23}
lib/compiler_rt/fixunssfti.zig+12-1
...@@ -1,12 +1,23 @@...@@ -1,12 +1,23 @@
1const builtin = @import("builtin");
1const common = @import("./common.zig");2const common = @import("./common.zig");
2const floatToInt = @import("./float_to_int.zig").floatToInt;3const floatToInt = @import("./float_to_int.zig").floatToInt;
34
4pub const panic = common.panic;5pub const panic = common.panic;
56
6comptime {7comptime {
7 @export(__fixunssfti, .{ .name = "__fixunssfti", .linkage = common.linkage });8 if (common.want_windows_v2u64_abi) {
9 @export(__fixunssfti_windows_x86_64, .{ .name = "__fixunssfti", .linkage = common.linkage });
10 } else {
11 @export(__fixunssfti, .{ .name = "__fixunssfti", .linkage = common.linkage });
12 }
8}13}
914
10pub fn __fixunssfti(a: f32) callconv(.C) u128 {15pub fn __fixunssfti(a: f32) callconv(.C) u128 {
11 return floatToInt(u128, a);16 return floatToInt(u128, a);
12}17}
18
19const v2u64 = @Vector(2, u64);
20
21fn __fixunssfti_windows_x86_64(a: f32) callconv(.C) v2u64 {
22 return @bitCast(v2u64, floatToInt(u128, a));
23}
lib/compiler_rt/fixunstfti.zig+12-1
...@@ -1,12 +1,23 @@...@@ -1,12 +1,23 @@
1const builtin = @import("builtin");
1const common = @import("./common.zig");2const common = @import("./common.zig");
2const floatToInt = @import("./float_to_int.zig").floatToInt;3const floatToInt = @import("./float_to_int.zig").floatToInt;
34
4pub const panic = common.panic;5pub const panic = common.panic;
56
6comptime {7comptime {
7 @export(__fixunstfti, .{ .name = "__fixunstfti", .linkage = common.linkage });8 if (common.want_windows_v2u64_abi) {
9 @export(__fixunstfti_windows_x86_64, .{ .name = "__fixunstfti", .linkage = common.linkage });
10 } else {
11 @export(__fixunstfti, .{ .name = "__fixunstfti", .linkage = common.linkage });
12 }
8}13}
914
10pub fn __fixunstfti(a: f128) callconv(.C) u128 {15pub fn __fixunstfti(a: f128) callconv(.C) u128 {
11 return floatToInt(u128, a);16 return floatToInt(u128, a);
12}17}
18
19const v2u64 = @Vector(2, u64);
20
21fn __fixunstfti_windows_x86_64(a: f128) callconv(.C) v2u64 {
22 return @bitCast(v2u64, floatToInt(u128, a));
23}
lib/compiler_rt/fixunsxfti.zig+12-1
...@@ -1,12 +1,23 @@...@@ -1,12 +1,23 @@
1const builtin = @import("builtin");
1const common = @import("./common.zig");2const common = @import("./common.zig");
2const floatToInt = @import("./float_to_int.zig").floatToInt;3const floatToInt = @import("./float_to_int.zig").floatToInt;
34
4pub const panic = common.panic;5pub const panic = common.panic;
56
6comptime {7comptime {
7 @export(__fixunsxfti, .{ .name = "__fixunsxfti", .linkage = common.linkage });8 if (common.want_windows_v2u64_abi) {
9 @export(__fixunsxfti_windows_x86_64, .{ .name = "__fixunsxfti", .linkage = common.linkage });
10 } else {
11 @export(__fixunsxfti, .{ .name = "__fixunsxfti", .linkage = common.linkage });
12 }
8}13}
914
10pub fn __fixunsxfti(a: f80) callconv(.C) u128 {15pub fn __fixunsxfti(a: f80) callconv(.C) u128 {
11 return floatToInt(u128, a);16 return floatToInt(u128, a);
12}17}
18
19const v2u64 = @Vector(2, u64);
20
21fn __fixunsxfti_windows_x86_64(a: f80) callconv(.C) v2u64 {
22 return @bitCast(v2u64, floatToInt(u128, a));
23}
lib/compiler_rt/fixxfti.zig+13-2
...@@ -1,12 +1,23 @@...@@ -1,12 +1,23 @@
1const builtin = @import("builtin");
1const common = @import("./common.zig");2const common = @import("./common.zig");
2const floatToInt = @import("./float_to_int.zig").floatToInt;3const floatToInt = @import("./float_to_int.zig").floatToInt;
34
4pub const panic = common.panic;5pub const panic = common.panic;
56
6comptime {7comptime {
7 @export(__fixxfti, .{ .name = "__fixxfti", .linkage = common.linkage });8 if (common.want_windows_v2u64_abi) {
9 @export(__fixxfti_windows_x86_64, .{ .name = "__fixxfti", .linkage = common.linkage });
10 } else {
11 @export(__fixxfti, .{ .name = "__fixxfti", .linkage = common.linkage });
12 }
8}13}
914
10fn __fixxfti(a: f80) callconv(.C) i128 {15pub fn __fixxfti(a: f80) callconv(.C) i128 {
11 return floatToInt(i128, a);16 return floatToInt(i128, a);
12}17}
18
19const v2u64 = @Vector(2, u64);
20
21fn __fixxfti_windows_x86_64(a: f80) callconv(.C) v2u64 {
22 return @bitCast(v2u64, floatToInt(i128, a));
23}
lib/compiler_rt/floattidf.zig+10-1
...@@ -1,12 +1,21 @@...@@ -1,12 +1,21 @@
1const builtin = @import("builtin");
1const common = @import("./common.zig");2const common = @import("./common.zig");
2const intToFloat = @import("./int_to_float.zig").intToFloat;3const intToFloat = @import("./int_to_float.zig").intToFloat;
34
4pub const panic = common.panic;5pub const panic = common.panic;
56
6comptime {7comptime {
7 @export(__floattidf, .{ .name = "__floattidf", .linkage = common.linkage });8 if (common.want_windows_v2u64_abi) {
9 @export(__floattidf_windows_x86_64, .{ .name = "__floattidf", .linkage = common.linkage });
10 } else {
11 @export(__floattidf, .{ .name = "__floattidf", .linkage = common.linkage });
12 }
8}13}
914
10pub fn __floattidf(a: i128) callconv(.C) f64 {15pub fn __floattidf(a: i128) callconv(.C) f64 {
11 return intToFloat(f64, a);16 return intToFloat(f64, a);
12}17}
18
19fn __floattidf_windows_x86_64(a: @Vector(2, u64)) callconv(.C) f64 {
20 return intToFloat(f64, @bitCast(i128, a));
21}
lib/compiler_rt/floattihf.zig+11-2
...@@ -1,12 +1,21 @@...@@ -1,12 +1,21 @@
1const builtin = @import("builtin");
1const common = @import("./common.zig");2const common = @import("./common.zig");
2const intToFloat = @import("./int_to_float.zig").intToFloat;3const intToFloat = @import("./int_to_float.zig").intToFloat;
34
4pub const panic = common.panic;5pub const panic = common.panic;
56
6comptime {7comptime {
7 @export(__floattihf, .{ .name = "__floattihf", .linkage = common.linkage });8 if (common.want_windows_v2u64_abi) {
9 @export(__floattihf_windows_x86_64, .{ .name = "__floattihf", .linkage = common.linkage });
10 } else {
11 @export(__floattihf, .{ .name = "__floattihf", .linkage = common.linkage });
12 }
8}13}
914
10fn __floattihf(a: i128) callconv(.C) f16 {15pub fn __floattihf(a: i128) callconv(.C) f16 {
11 return intToFloat(f16, a);16 return intToFloat(f16, a);
12}17}
18
19fn __floattihf_windows_x86_64(a: @Vector(2, u64)) callconv(.C) f16 {
20 return intToFloat(f16, @bitCast(i128, a));
21}
lib/compiler_rt/floattisf.zig+10-1
...@@ -1,12 +1,21 @@...@@ -1,12 +1,21 @@
1const builtin = @import("builtin");
1const common = @import("./common.zig");2const common = @import("./common.zig");
2const intToFloat = @import("./int_to_float.zig").intToFloat;3const intToFloat = @import("./int_to_float.zig").intToFloat;
34
4pub const panic = common.panic;5pub const panic = common.panic;
56
6comptime {7comptime {
7 @export(__floattisf, .{ .name = "__floattisf", .linkage = common.linkage });8 if (common.want_windows_v2u64_abi) {
9 @export(__floattisf_windows_x86_64, .{ .name = "__floattisf", .linkage = common.linkage });
10 } else {
11 @export(__floattisf, .{ .name = "__floattisf", .linkage = common.linkage });
12 }
8}13}
914
10pub fn __floattisf(a: i128) callconv(.C) f32 {15pub fn __floattisf(a: i128) callconv(.C) f32 {
11 return intToFloat(f32, a);16 return intToFloat(f32, a);
12}17}
18
19fn __floattisf_windows_x86_64(a: @Vector(2, u64)) callconv(.C) f32 {
20 return intToFloat(f32, @bitCast(i128, a));
21}
lib/compiler_rt/floattitf.zig+10-1
...@@ -1,12 +1,21 @@...@@ -1,12 +1,21 @@
1const builtin = @import("builtin");
1const common = @import("./common.zig");2const common = @import("./common.zig");
2const intToFloat = @import("./int_to_float.zig").intToFloat;3const intToFloat = @import("./int_to_float.zig").intToFloat;
34
4pub const panic = common.panic;5pub const panic = common.panic;
56
6comptime {7comptime {
7 @export(__floattitf, .{ .name = "__floattitf", .linkage = common.linkage });8 if (common.want_windows_v2u64_abi) {
9 @export(__floattitf_windows_x86_64, .{ .name = "__floattitf", .linkage = common.linkage });
10 } else {
11 @export(__floattitf, .{ .name = "__floattitf", .linkage = common.linkage });
12 }
8}13}
914
10pub fn __floattitf(a: i128) callconv(.C) f128 {15pub fn __floattitf(a: i128) callconv(.C) f128 {
11 return intToFloat(f128, a);16 return intToFloat(f128, a);
12}17}
18
19fn __floattitf_windows_x86_64(a: @Vector(2, u64)) callconv(.C) f128 {
20 return intToFloat(f128, @bitCast(i128, a));
21}
lib/compiler_rt/floattixf.zig+11-2
...@@ -1,12 +1,21 @@...@@ -1,12 +1,21 @@
1const builtin = @import("builtin");
1const common = @import("./common.zig");2const common = @import("./common.zig");
2const intToFloat = @import("./int_to_float.zig").intToFloat;3const intToFloat = @import("./int_to_float.zig").intToFloat;
34
4pub const panic = common.panic;5pub const panic = common.panic;
56
6comptime {7comptime {
7 @export(__floattixf, .{ .name = "__floattixf", .linkage = common.linkage });8 if (common.want_windows_v2u64_abi) {
9 @export(__floattixf_windows_x86_64, .{ .name = "__floattixf", .linkage = common.linkage });
10 } else {
11 @export(__floattixf, .{ .name = "__floattixf", .linkage = common.linkage });
12 }
8}13}
914
10fn __floattixf(a: i128) callconv(.C) f80 {15pub fn __floattixf(a: i128) callconv(.C) f80 {
11 return intToFloat(f80, a);16 return intToFloat(f80, a);
12}17}
18
19fn __floattixf_windows_x86_64(a: @Vector(2, u64)) callconv(.C) f80 {
20 return intToFloat(f80, @bitCast(i128, a));
21}
lib/compiler_rt/floatuntidf.zig+10-1
...@@ -1,12 +1,21 @@...@@ -1,12 +1,21 @@
1const builtin = @import("builtin");
1const common = @import("./common.zig");2const common = @import("./common.zig");
2const intToFloat = @import("./int_to_float.zig").intToFloat;3const intToFloat = @import("./int_to_float.zig").intToFloat;
34
4pub const panic = common.panic;5pub const panic = common.panic;
56
6comptime {7comptime {
7 @export(__floatuntidf, .{ .name = "__floatuntidf", .linkage = common.linkage });8 if (common.want_windows_v2u64_abi) {
9 @export(__floatuntidf_windows_x86_64, .{ .name = "__floatuntidf", .linkage = common.linkage });
10 } else {
11 @export(__floatuntidf, .{ .name = "__floatuntidf", .linkage = common.linkage });
12 }
8}13}
914
10pub fn __floatuntidf(a: u128) callconv(.C) f64 {15pub fn __floatuntidf(a: u128) callconv(.C) f64 {
11 return intToFloat(f64, a);16 return intToFloat(f64, a);
12}17}
18
19fn __floatuntidf_windows_x86_64(a: @Vector(2, u64)) callconv(.C) f64 {
20 return intToFloat(f64, @bitCast(u128, a));
21}
lib/compiler_rt/floatuntihf.zig+11-2
...@@ -1,12 +1,21 @@...@@ -1,12 +1,21 @@
1const builtin = @import("builtin");
1const common = @import("./common.zig");2const common = @import("./common.zig");
2const intToFloat = @import("./int_to_float.zig").intToFloat;3const intToFloat = @import("./int_to_float.zig").intToFloat;
34
4pub const panic = common.panic;5pub const panic = common.panic;
56
6comptime {7comptime {
7 @export(__floatuntihf, .{ .name = "__floatuntihf", .linkage = common.linkage });8 if (common.want_windows_v2u64_abi) {
9 @export(__floatuntihf_windows_x86_64, .{ .name = "__floatuntihf", .linkage = common.linkage });
10 } else {
11 @export(__floatuntihf, .{ .name = "__floatuntihf", .linkage = common.linkage });
12 }
8}13}
914
10fn __floatuntihf(a: u128) callconv(.C) f16 {15pub fn __floatuntihf(a: u128) callconv(.C) f16 {
11 return intToFloat(f16, a);16 return intToFloat(f16, a);
12}17}
18
19fn __floatuntihf_windows_x86_64(a: @Vector(2, u64)) callconv(.C) f16 {
20 return intToFloat(f16, @bitCast(u128, a));
21}
lib/compiler_rt/floatuntisf.zig+10-1
...@@ -1,12 +1,21 @@...@@ -1,12 +1,21 @@
1const builtin = @import("builtin");
1const common = @import("./common.zig");2const common = @import("./common.zig");
2const intToFloat = @import("./int_to_float.zig").intToFloat;3const intToFloat = @import("./int_to_float.zig").intToFloat;
34
4pub const panic = common.panic;5pub const panic = common.panic;
56
6comptime {7comptime {
7 @export(__floatuntisf, .{ .name = "__floatuntisf", .linkage = common.linkage });8 if (common.want_windows_v2u64_abi) {
9 @export(__floatuntisf_windows_x86_64, .{ .name = "__floatuntisf", .linkage = common.linkage });
10 } else {
11 @export(__floatuntisf, .{ .name = "__floatuntisf", .linkage = common.linkage });
12 }
8}13}
914
10pub fn __floatuntisf(a: u128) callconv(.C) f32 {15pub fn __floatuntisf(a: u128) callconv(.C) f32 {
11 return intToFloat(f32, a);16 return intToFloat(f32, a);
12}17}
18
19fn __floatuntisf_windows_x86_64(a: @Vector(2, u64)) callconv(.C) f32 {
20 return intToFloat(f32, @bitCast(u128, a));
21}
lib/compiler_rt/floatuntitf.zig+8-5
...@@ -1,13 +1,16 @@...@@ -1,13 +1,16 @@
1const builtin = @import("builtin");
1const common = @import("./common.zig");2const common = @import("./common.zig");
2const intToFloat = @import("./int_to_float.zig").intToFloat;3const intToFloat = @import("./int_to_float.zig").intToFloat;
34
4pub const panic = common.panic;5pub const panic = common.panic;
56
6comptime {7comptime {
7 if (common.want_ppc_abi) {8 const symbol_name = if (common.want_ppc_abi) "__floatuntikf" else "__floatuntitf";
8 @export(__floatuntikf, .{ .name = "__floatuntikf", .linkage = common.linkage });9
10 if (common.want_windows_v2u64_abi) {
11 @export(__floatuntitf_windows_x86_64, .{ .name = symbol_name, .linkage = common.linkage });
9 } else {12 } else {
10 @export(__floatuntitf, .{ .name = "__floatuntitf", .linkage = common.linkage });13 @export(__floatuntitf, .{ .name = symbol_name, .linkage = common.linkage });
11 }14 }
12}15}
1316
...@@ -15,6 +18,6 @@ pub fn __floatuntitf(a: u128) callconv(.C) f128 {...@@ -15,6 +18,6 @@ pub fn __floatuntitf(a: u128) callconv(.C) f128 {
15 return intToFloat(f128, a);18 return intToFloat(f128, a);
16}19}
1720
18fn __floatuntikf(a: u128) callconv(.C) f128 {21fn __floatuntitf_windows_x86_64(a: @Vector(2, u64)) callconv(.C) f128 {
19 return intToFloat(f128, a);22 return intToFloat(f128, @bitCast(u128, a));
20}23}
lib/compiler_rt/floatuntixf.zig+10-1
...@@ -1,12 +1,21 @@...@@ -1,12 +1,21 @@
1const builtin = @import("builtin");
1const common = @import("./common.zig");2const common = @import("./common.zig");
2const intToFloat = @import("./int_to_float.zig").intToFloat;3const intToFloat = @import("./int_to_float.zig").intToFloat;
34
4pub const panic = common.panic;5pub const panic = common.panic;
56
6comptime {7comptime {
7 @export(__floatuntixf, .{ .name = "__floatuntixf", .linkage = common.linkage });8 if (common.want_windows_v2u64_abi) {
9 @export(__floatuntixf_windows_x86_64, .{ .name = "__floatuntixf", .linkage = common.linkage });
10 } else {
11 @export(__floatuntixf, .{ .name = "__floatuntixf", .linkage = common.linkage });
12 }
8}13}
914
10pub fn __floatuntixf(a: u128) callconv(.C) f80 {15pub fn __floatuntixf(a: u128) callconv(.C) f80 {
11 return intToFloat(f80, a);16 return intToFloat(f80, a);
12}17}
18
19fn __floatuntixf_windows_x86_64(a: @Vector(2, u64)) callconv(.C) f80 {
20 return intToFloat(f80, @bitCast(u128, a));
21}
lib/compiler_rt/modti3.zig+5-19
...@@ -5,27 +5,13 @@...@@ -5,27 +5,13 @@
5const std = @import("std");5const std = @import("std");
6const builtin = @import("builtin");6const builtin = @import("builtin");
7const udivmod = @import("udivmod.zig").udivmod;7const udivmod = @import("udivmod.zig").udivmod;
8const arch = builtin.cpu.arch;
9const common = @import("common.zig");8const common = @import("common.zig");
109
11pub const panic = common.panic;10pub const panic = common.panic;
1211
13comptime {12comptime {
14 if (builtin.os.tag == .windows) {13 if (common.want_windows_v2u64_abi) {
15 switch (arch) {14 @export(__modti3_windows_x86_64, .{ .name = "__modti3", .linkage = common.linkage });
16 .i386 => {
17 @export(__modti3, .{ .name = "__modti3", .linkage = common.linkage });
18 },
19 .x86_64 => {
20 // The "ti" functions must use Vector(2, u64) parameter types to adhere to the ABI
21 // that LLVM expects compiler-rt to have.
22 @export(__modti3_windows_x86_64, .{ .name = "__modti3", .linkage = common.linkage });
23 },
24 else => {},
25 }
26 if (arch.isAARCH64()) {
27 @export(__modti3, .{ .name = "__modti3", .linkage = common.linkage });
28 }
29 } else {15 } else {
30 @export(__modti3, .{ .name = "__modti3", .linkage = common.linkage });16 @export(__modti3, .{ .name = "__modti3", .linkage = common.linkage });
31 }17 }
...@@ -35,10 +21,10 @@ pub fn __modti3(a: i128, b: i128) callconv(.C) i128 {...@@ -35,10 +21,10 @@ pub fn __modti3(a: i128, b: i128) callconv(.C) i128 {
35 return mod(a, b);21 return mod(a, b);
36}22}
3723
38const v128 = @import("std").meta.Vector(2, u64);24const v2u64 = @Vector(2, u64);
3925
40fn __modti3_windows_x86_64(a: v128, b: v128) callconv(.C) v128 {26fn __modti3_windows_x86_64(a: v2u64, b: v2u64) callconv(.C) v2u64 {
41 return @bitCast(v128, mod(@bitCast(i128, a), @bitCast(i128, b)));27 return @bitCast(v2u64, mod(@bitCast(i128, a), @bitCast(i128, b)));
42}28}
4329
44inline fn mod(a: i128, b: i128) i128 {30inline fn mod(a: i128, b: i128) i128 {
lib/compiler_rt/multi3.zig+5-16
...@@ -4,25 +4,14 @@...@@ -4,25 +4,14 @@
44
5const std = @import("std");5const std = @import("std");
6const builtin = @import("builtin");6const builtin = @import("builtin");
7const arch = builtin.cpu.arch;
8const native_endian = builtin.cpu.arch.endian();7const native_endian = builtin.cpu.arch.endian();
9const common = @import("common.zig");8const common = @import("common.zig");
109
11pub const panic = common.panic;10pub const panic = common.panic;
1211
13comptime {12comptime {
14 if (builtin.os.tag == .windows) {13 if (common.want_windows_v2u64_abi) {
15 switch (arch) {14 @export(__multi3_windows_x86_64, .{ .name = "__multi3", .linkage = common.linkage });
16 .i386 => {
17 @export(__multi3, .{ .name = "__multi3", .linkage = common.linkage });
18 },
19 .x86_64 => {
20 // The "ti" functions must use Vector(2, u64) parameter types to adhere to the ABI
21 // that LLVM expects compiler-rt to have.
22 @export(__multi3_windows_x86_64, .{ .name = "__multi3", .linkage = common.linkage });
23 },
24 else => {},
25 }
26 } else {15 } else {
27 @export(__multi3, .{ .name = "__multi3", .linkage = common.linkage });16 @export(__multi3, .{ .name = "__multi3", .linkage = common.linkage });
28 }17 }
...@@ -32,10 +21,10 @@ pub fn __multi3(a: i128, b: i128) callconv(.C) i128 {...@@ -32,10 +21,10 @@ pub fn __multi3(a: i128, b: i128) callconv(.C) i128 {
32 return mul(a, b);21 return mul(a, b);
33}22}
3423
35const v128 = @Vector(2, u64);24const v2u64 = @Vector(2, u64);
3625
37fn __multi3_windows_x86_64(a: v128, b: v128) callconv(.C) v128 {26fn __multi3_windows_x86_64(a: v2u64, b: v2u64) callconv(.C) v2u64 {
38 return @bitCast(v128, mul(@bitCast(i128, a), @bitCast(i128, b)));27 return @bitCast(v2u64, mul(@bitCast(i128, a), @bitCast(i128, b)));
39}28}
4029
41inline fn mul(a: i128, b: i128) i128 {30inline fn mul(a: i128, b: i128) i128 {
lib/compiler_rt/udivmodti4.zig+5-16
...@@ -1,24 +1,13 @@...@@ -1,24 +1,13 @@
1const std = @import("std");1const std = @import("std");
2const builtin = @import("builtin");2const builtin = @import("builtin");
3const udivmod = @import("udivmod.zig").udivmod;3const udivmod = @import("udivmod.zig").udivmod;
4const arch = builtin.cpu.arch;
5const common = @import("common.zig");4const common = @import("common.zig");
65
7pub const panic = common.panic;6pub const panic = common.panic;
87
9comptime {8comptime {
10 if (builtin.os.tag == .windows) {9 if (common.want_windows_v2u64_abi) {
11 switch (arch) {10 @export(__udivmodti4_windows_x86_64, .{ .name = "__udivmodti4", .linkage = common.linkage });
12 .i386 => {
13 @export(__udivmodti4, .{ .name = "__udivmodti4", .linkage = common.linkage });
14 },
15 .x86_64 => {
16 // The "ti" functions must use Vector(2, u64) parameter types to adhere to the ABI
17 // that LLVM expects compiler-rt to have.
18 @export(__udivmodti4_windows_x86_64, .{ .name = "__udivmodti4", .linkage = common.linkage });
19 },
20 else => {},
21 }
22 } else {11 } else {
23 @export(__udivmodti4, .{ .name = "__udivmodti4", .linkage = common.linkage });12 @export(__udivmodti4, .{ .name = "__udivmodti4", .linkage = common.linkage });
24 }13 }
...@@ -28,10 +17,10 @@ pub fn __udivmodti4(a: u128, b: u128, maybe_rem: ?*u128) callconv(.C) u128 {...@@ -28,10 +17,10 @@ pub fn __udivmodti4(a: u128, b: u128, maybe_rem: ?*u128) callconv(.C) u128 {
28 return udivmod(u128, a, b, maybe_rem);17 return udivmod(u128, a, b, maybe_rem);
29}18}
3019
31const v128 = std.meta.Vector(2, u64);20const v2u64 = @Vector(2, u64);
3221
33fn __udivmodti4_windows_x86_64(a: v128, b: v128, maybe_rem: ?*u128) callconv(.C) v128 {22fn __udivmodti4_windows_x86_64(a: v2u64, b: v2u64, maybe_rem: ?*u128) callconv(.C) v2u64 {
34 return @bitCast(v128, udivmod(u128, @bitCast(u128, a), @bitCast(u128, b), maybe_rem));23 return @bitCast(v2u64, udivmod(u128, @bitCast(u128, a), @bitCast(u128, b), maybe_rem));
35}24}
3625
37test {26test {
lib/compiler_rt/udivti3.zig+5-19
...@@ -1,27 +1,13 @@...@@ -1,27 +1,13 @@
1const std = @import("std");1const std = @import("std");
2const builtin = @import("builtin");2const builtin = @import("builtin");
3const udivmod = @import("udivmod.zig").udivmod;3const udivmod = @import("udivmod.zig").udivmod;
4const arch = builtin.cpu.arch;
5const common = @import("common.zig");4const common = @import("common.zig");
65
7pub const panic = common.panic;6pub const panic = common.panic;
87
9comptime {8comptime {
10 if (builtin.os.tag == .windows) {9 if (common.want_windows_v2u64_abi) {
11 switch (arch) {10 @export(__udivti3_windows_x86_64, .{ .name = "__udivti3", .linkage = common.linkage });
12 .i386 => {
13 @export(__udivti3, .{ .name = "__udivti3", .linkage = common.linkage });
14 },
15 .x86_64 => {
16 // The "ti" functions must use Vector(2, u64) parameter types to adhere to the ABI
17 // that LLVM expects compiler-rt to have.
18 @export(__udivti3_windows_x86_64, .{ .name = "__udivti3", .linkage = common.linkage });
19 },
20 else => {},
21 }
22 if (arch.isAARCH64()) {
23 @export(__udivti3, .{ .name = "__udivti3", .linkage = common.linkage });
24 }
25 } else {11 } else {
26 @export(__udivti3, .{ .name = "__udivti3", .linkage = common.linkage });12 @export(__udivti3, .{ .name = "__udivti3", .linkage = common.linkage });
27 }13 }
...@@ -31,8 +17,8 @@ pub fn __udivti3(a: u128, b: u128) callconv(.C) u128 {...@@ -31,8 +17,8 @@ pub fn __udivti3(a: u128, b: u128) callconv(.C) u128 {
31 return udivmod(u128, a, b, null);17 return udivmod(u128, a, b, null);
32}18}
3319
34const v128 = std.meta.Vector(2, u64);20const v2u64 = @Vector(2, u64);
3521
36fn __udivti3_windows_x86_64(a: v128, b: v128) callconv(.C) v128 {22fn __udivti3_windows_x86_64(a: v2u64, b: v2u64) callconv(.C) v2u64 {
37 return @bitCast(v128, udivmod(u128, @bitCast(u128, a), @bitCast(u128, b), null));23 return @bitCast(v2u64, udivmod(u128, @bitCast(u128, a), @bitCast(u128, b), null));
38}24}
lib/compiler_rt/umodti3.zig+5-19
...@@ -1,27 +1,13 @@...@@ -1,27 +1,13 @@
1const std = @import("std");1const std = @import("std");
2const builtin = @import("builtin");2const builtin = @import("builtin");
3const udivmod = @import("udivmod.zig").udivmod;3const udivmod = @import("udivmod.zig").udivmod;
4const arch = builtin.cpu.arch;
5const common = @import("common.zig");4const common = @import("common.zig");
65
7pub const panic = common.panic;6pub const panic = common.panic;
87
9comptime {8comptime {
10 if (builtin.os.tag == .windows) {9 if (common.want_windows_v2u64_abi) {
11 switch (arch) {10 @export(__umodti3_windows_x86_64, .{ .name = "__umodti3", .linkage = common.linkage });
12 .i386 => {
13 @export(__umodti3, .{ .name = "__umodti3", .linkage = common.linkage });
14 },
15 .x86_64 => {
16 // The "ti" functions must use Vector(2, u64) parameter types to adhere to the ABI
17 // that LLVM expects compiler-rt to have.
18 @export(__umodti3_windows_x86_64, .{ .name = "__umodti3", .linkage = common.linkage });
19 },
20 else => {},
21 }
22 if (arch.isAARCH64()) {
23 @export(__umodti3, .{ .name = "__umodti3", .linkage = common.linkage });
24 }
25 } else {11 } else {
26 @export(__umodti3, .{ .name = "__umodti3", .linkage = common.linkage });12 @export(__umodti3, .{ .name = "__umodti3", .linkage = common.linkage });
27 }13 }
...@@ -33,10 +19,10 @@ pub fn __umodti3(a: u128, b: u128) callconv(.C) u128 {...@@ -33,10 +19,10 @@ pub fn __umodti3(a: u128, b: u128) callconv(.C) u128 {
33 return r;19 return r;
34}20}
3521
36const v128 = std.meta.Vector(2, u64);22const v2u64 = @Vector(2, u64);
3723
38fn __umodti3_windows_x86_64(a: v128, b: v128) callconv(.C) v128 {24fn __umodti3_windows_x86_64(a: v2u64, b: v2u64) callconv(.C) v2u64 {
39 var r: u128 = undefined;25 var r: u128 = undefined;
40 _ = udivmod(u128, @bitCast(u128, a), @bitCast(u128, b), &r);26 _ = udivmod(u128, @bitCast(u128, a), @bitCast(u128, b), &r);
41 return @bitCast(v128, r);27 return @bitCast(v2u64, r);
42}28}
lib/std/fmt.zig-8
...@@ -2284,10 +2284,6 @@ test "float.hexadecimal.precision" {...@@ -2284,10 +2284,6 @@ test "float.hexadecimal.precision" {
2284}2284}
22852285
2286test "float.decimal" {2286test "float.decimal" {
2287 if (builtin.zig_backend == .stage1 and builtin.os.tag == .windows) {
2288 // https://github.com/ziglang/zig/issues/12063
2289 return error.SkipZigTest;
2290 }
2291 try expectFmt("f64: 152314000000000000000000000000", "f64: {d}", .{@as(f64, 1.52314e+29)});2287 try expectFmt("f64: 152314000000000000000000000000", "f64: {d}", .{@as(f64, 1.52314e+29)});
2292 try expectFmt("f32: 0", "f32: {d}", .{@as(f32, 0.0)});2288 try expectFmt("f32: 0", "f32: {d}", .{@as(f32, 0.0)});
2293 try expectFmt("f32: 0", "f32: {d:.0}", .{@as(f32, 0.0)});2289 try expectFmt("f32: 0", "f32: {d:.0}", .{@as(f32, 0.0)});
...@@ -2311,10 +2307,6 @@ test "float.decimal" {...@@ -2311,10 +2307,6 @@ test "float.decimal" {
2311}2307}
23122308
2313test "float.libc.sanity" {2309test "float.libc.sanity" {
2314 if (builtin.zig_backend == .stage1 and builtin.os.tag == .windows) {
2315 // https://github.com/ziglang/zig/issues/12063
2316 return error.SkipZigTest;
2317 }
2318 try expectFmt("f64: 0.00001", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 916964781)))});2310 try expectFmt("f64: 0.00001", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 916964781)))});
2319 try expectFmt("f64: 0.00001", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 925353389)))});2311 try expectFmt("f64: 0.00001", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 925353389)))});
2320 try expectFmt("f64: 0.10000", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1036831278)))});2312 try expectFmt("f64: 0.10000", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1036831278)))});
src/codegen/llvm.zig+30-11
...@@ -4802,7 +4802,7 @@ pub const FuncGen = struct {...@@ -4802,7 +4802,7 @@ pub const FuncGen = struct {
4802 const operand_bits = @intCast(u16, operand_scalar_ty.bitSize(target));4802 const operand_bits = @intCast(u16, operand_scalar_ty.bitSize(target));
4803 const rt_int_bits = compilerRtIntBits(operand_bits);4803 const rt_int_bits = compilerRtIntBits(operand_bits);
4804 const rt_int_ty = self.context.intType(rt_int_bits);4804 const rt_int_ty = self.context.intType(rt_int_bits);
4805 const extended = e: {4805 var extended = e: {
4806 if (operand_scalar_ty.isSignedInt()) {4806 if (operand_scalar_ty.isSignedInt()) {
4807 break :e self.builder.buildSExtOrBitCast(operand, rt_int_ty, "");4807 break :e self.builder.buildSExtOrBitCast(operand, rt_int_ty, "");
4808 } else {4808 } else {
...@@ -4819,7 +4819,16 @@ pub const FuncGen = struct {...@@ -4819,7 +4819,16 @@ pub const FuncGen = struct {
4819 compiler_rt_operand_abbrev,4819 compiler_rt_operand_abbrev,
4820 compiler_rt_dest_abbrev,4820 compiler_rt_dest_abbrev,
4821 }) catch unreachable;4821 }) catch unreachable;
4822 const param_types = [1]*const llvm.Type{rt_int_ty};4822
4823 var param_types = [1]*const llvm.Type{rt_int_ty};
4824 if (rt_int_bits == 128 and (target.os.tag == .windows and target.cpu.arch == .x86_64)) {
4825 // On Windows x86-64, "ti" functions must use Vector(2, u64) instead of the standard
4826 // i128 calling convention to adhere to the ABI that LLVM expects compiler-rt to have.
4827 const v2i64 = self.context.intType(64).vectorType(2);
4828 extended = self.builder.buildBitCast(extended, v2i64, "");
4829 param_types = [1]*const llvm.Type{v2i64};
4830 }
4831
4823 const libc_fn = self.getLibcFunction(fn_name, &param_types, dest_llvm_ty);4832 const libc_fn = self.getLibcFunction(fn_name, &param_types, dest_llvm_ty);
4824 const params = [1]*const llvm.Value{extended};4833 const params = [1]*const llvm.Value{extended};
48254834
...@@ -4851,7 +4860,12 @@ pub const FuncGen = struct {...@@ -4851,7 +4860,12 @@ pub const FuncGen = struct {
4851 }4860 }
48524861
4853 const rt_int_bits = compilerRtIntBits(@intCast(u16, dest_scalar_ty.bitSize(target)));4862 const rt_int_bits = compilerRtIntBits(@intCast(u16, dest_scalar_ty.bitSize(target)));
4854 const libc_ret_ty = self.context.intType(rt_int_bits);4863 const ret_ty = self.context.intType(rt_int_bits);
4864 const libc_ret_ty = if (rt_int_bits == 128 and (target.os.tag == .windows and target.cpu.arch == .x86_64)) b: {
4865 // On Windows x86-64, "ti" functions must use Vector(2, u64) instead of the standard
4866 // i128 calling convention to adhere to the ABI that LLVM expects compiler-rt to have.
4867 break :b self.context.intType(64).vectorType(2);
4868 } else ret_ty;
48554869
4856 const operand_bits = operand_scalar_ty.floatBits(target);4870 const operand_bits = operand_scalar_ty.floatBits(target);
4857 const compiler_rt_operand_abbrev = compilerRtFloatAbbrev(operand_bits);4871 const compiler_rt_operand_abbrev = compilerRtFloatAbbrev(operand_bits);
...@@ -4871,13 +4885,11 @@ pub const FuncGen = struct {...@@ -4871,13 +4885,11 @@ pub const FuncGen = struct {
4871 const libc_fn = self.getLibcFunction(fn_name, &param_types, libc_ret_ty);4885 const libc_fn = self.getLibcFunction(fn_name, &param_types, libc_ret_ty);
4872 const params = [1]*const llvm.Value{operand};4886 const params = [1]*const llvm.Value{operand};
48734887
4874 const result = self.builder.buildCall(libc_fn, &params, params.len, .C, .Auto, "");4888 var result = self.builder.buildCall(libc_fn, &params, params.len, .C, .Auto, "");
4875
4876 if (libc_ret_ty == dest_llvm_ty) {
4877 return result;
4878 }
48794889
4880 return self.builder.buildTrunc(result, dest_llvm_ty, "");4890 if (libc_ret_ty != ret_ty) result = self.builder.buildBitCast(result, ret_ty, "");
4891 if (ret_ty != dest_llvm_ty) result = self.builder.buildTrunc(result, dest_llvm_ty, "");
4892 return result;
4881 }4893 }
48824894
4883 fn airSliceField(self: *FuncGen, inst: Air.Inst.Index, index: c_uint) !?*const llvm.Value {4895 fn airSliceField(self: *FuncGen, inst: Air.Inst.Index, index: c_uint) !?*const llvm.Value {
...@@ -6490,8 +6502,15 @@ pub const FuncGen = struct {...@@ -6490,8 +6502,15 @@ pub const FuncGen = struct {
6490 const one = int_llvm_ty.constInt(1, .False);6502 const one = int_llvm_ty.constInt(1, .False);
6491 const shift_amt = int_llvm_ty.constInt(float_bits - 1, .False);6503 const shift_amt = int_llvm_ty.constInt(float_bits - 1, .False);
6492 const sign_mask = one.constShl(shift_amt);6504 const sign_mask = one.constShl(shift_amt);
6493 const bitcasted_operand = self.builder.buildBitCast(params[0], int_llvm_ty, "");6505 const result = if (ty.zigTypeTag() == .Vector) blk: {
6494 const result = self.builder.buildXor(bitcasted_operand, sign_mask, "");6506 const splat_sign_mask = self.builder.buildVectorSplat(ty.vectorLen(), sign_mask, "");
6507 const cast_ty = int_llvm_ty.vectorType(ty.vectorLen());
6508 const bitcasted_operand = self.builder.buildBitCast(params[0], cast_ty, "");
6509 break :blk self.builder.buildXor(bitcasted_operand, splat_sign_mask, "");
6510 } else blk: {
6511 const bitcasted_operand = self.builder.buildBitCast(params[0], int_llvm_ty, "");
6512 break :blk self.builder.buildXor(bitcasted_operand, sign_mask, "");
6513 };
6495 return self.builder.buildBitCast(result, llvm_ty, "");6514 return self.builder.buildBitCast(result, llvm_ty, "");
6496 },6515 },
6497 .add, .sub, .div, .mul => FloatOpStrat{6516 .add, .sub, .div, .mul => FloatOpStrat{
src/stage1/codegen.cpp+38-58
...@@ -3371,14 +3371,12 @@ static LLVMValueRef add_icmp(CodeGen *g, LLVMValueRef val, Icmp kind) {...@@ -3371,14 +3371,12 @@ static LLVMValueRef add_icmp(CodeGen *g, LLVMValueRef val, Icmp kind) {
3371}3371}
33723372
3373static LLVMValueRef gen_soft_int_to_float_op(CodeGen *g, LLVMValueRef value_ref, ZigType *operand_type, ZigType *result_type) {3373static LLVMValueRef gen_soft_int_to_float_op(CodeGen *g, LLVMValueRef value_ref, ZigType *operand_type, ZigType *result_type) {
3374 uint32_t vector_len = operand_type->id == ZigTypeIdVector ? operand_type->data.vector.len : 0;
3375
3376 // Handle integers of non-pot bitsize by widening them.3374 // Handle integers of non-pot bitsize by widening them.
3377 const size_t bitsize = operand_type->data.integral.bit_count;3375 const size_t bitsize = operand_type->data.integral.bit_count;
3378 const bool is_signed = operand_type->data.integral.is_signed;3376 const bool is_signed = operand_type->data.integral.is_signed;
3379 if (bitsize < 32 || !is_power_of_2(bitsize)) {3377 if (bitsize < 32 || !is_power_of_2(bitsize)) {
3380 const size_t wider_bitsize = bitsize < 32 ? 32 : round_to_next_power_of_2(bitsize);3378 const size_t wider_bitsize = bitsize < 32 ? 32 : round_to_next_power_of_2(bitsize);
3381 ZigType *const wider_type = get_int_type(g, is_signed, wider_bitsize);3379 ZigType *wider_type = get_int_type(g, is_signed, wider_bitsize);
3382 value_ref = gen_widen_or_shorten(g, false, operand_type, wider_type, value_ref);3380 value_ref = gen_widen_or_shorten(g, false, operand_type, wider_type, value_ref);
3383 operand_type = wider_type;3381 operand_type = wider_type;
3384 }3382 }
...@@ -3395,35 +3393,22 @@ static LLVMValueRef gen_soft_int_to_float_op(CodeGen *g, LLVMValueRef value_ref,...@@ -3395,35 +3393,22 @@ static LLVMValueRef gen_soft_int_to_float_op(CodeGen *g, LLVMValueRef value_ref,
3395 }3393 }
33963394
3397 int param_count = 1;3395 int param_count = 1;
3398 LLVMValueRef func_ref = get_soft_float_fn(g, fn_name, param_count, operand_type->llvm_type, result_type->llvm_type);3396 LLVMValueRef func_ref;
33993397 if ((operand_type->data.integral.bit_count == 128) && (g->zig_target->os == OsWindows) && (g->zig_target->arch == ZigLLVM_x86_64)) {
3400 LLVMValueRef result;3398 // On Windows x86-64, "ti" functions must use Vector(2, u64) instead of the standard i128 calling
3401 if (vector_len == 0) {3399 // convention to adhere to the ABI that LLVM expects compiler-rt to have.
3402 LLVMValueRef params[1] = {value_ref};3400 LLVMTypeRef v2i64 = LLVMVectorType(LLVMInt64Type(), 2);
3403 result = LLVMBuildCall(g->builder, func_ref, params, param_count, "");3401 value_ref = LLVMBuildBitCast(g->builder, value_ref, v2i64, "");
3402 func_ref = get_soft_float_fn(g, fn_name, param_count, v2i64, result_type->llvm_type);
3404 } else {3403 } else {
3405 ZigType *alloca_ty = operand_type;3404 func_ref = get_soft_float_fn(g, fn_name, param_count, operand_type->llvm_type, result_type->llvm_type);
3406 result = build_alloca(g, alloca_ty, "", 0);
3407
3408 LLVMTypeRef usize_ref = g->builtin_types.entry_usize->llvm_type;
3409 for (uint32_t i = 0; i < vector_len; i++) {
3410 LLVMValueRef index_value = LLVMConstInt(usize_ref, i, false);
3411 LLVMValueRef params[1] = {
3412 LLVMBuildExtractElement(g->builder, value_ref, index_value, ""),
3413 };
3414 LLVMValueRef call_result = LLVMBuildCall(g->builder, func_ref, params, param_count, "");
3415 LLVMBuildInsertElement(g->builder, LLVMBuildLoad(g->builder, result, ""),
3416 call_result, index_value, "");
3417 }
3418
3419 result = LLVMBuildLoad(g->builder, result, "");
3420 }3405 }
3421 return result;3406
3407 LLVMValueRef params[1] = {value_ref};
3408 return LLVMBuildCall(g->builder, func_ref, params, param_count, "");
3422}3409}
34233410
3424static LLVMValueRef gen_soft_float_to_int_op(CodeGen *g, LLVMValueRef value_ref, ZigType *operand_type, ZigType *result_type) {3411static LLVMValueRef gen_soft_float_to_int_op(CodeGen *g, LLVMValueRef value_ref, ZigType *operand_type, ZigType *result_type) {
3425 uint32_t vector_len = operand_type->id == ZigTypeIdVector ? operand_type->data.vector.len : 0;
3426
3427 // Handle integers of non-pot bitsize by truncating a sufficiently wide pot integer3412 // Handle integers of non-pot bitsize by truncating a sufficiently wide pot integer
3428 const size_t bitsize = result_type->data.integral.bit_count;3413 const size_t bitsize = result_type->data.integral.bit_count;
3429 const bool is_signed = result_type->data.integral.is_signed;3414 const bool is_signed = result_type->data.integral.is_signed;
...@@ -3445,46 +3430,41 @@ static LLVMValueRef gen_soft_float_to_int_op(CodeGen *g, LLVMValueRef value_ref,...@@ -3445,46 +3430,41 @@ static LLVMValueRef gen_soft_float_to_int_op(CodeGen *g, LLVMValueRef value_ref,
3445 }3430 }
34463431
3447 int param_count = 1;3432 int param_count = 1;
3448 LLVMValueRef func_ref = get_soft_float_fn(g, fn_name, param_count, operand_type->llvm_type, wider_type->llvm_type);3433 LLVMValueRef func_ref;
34493434 if ((wider_type->data.integral.bit_count == 128) && (g->zig_target->os == OsWindows) && (g->zig_target->arch == ZigLLVM_x86_64)) {
3450 LLVMValueRef result;3435 // On Windows x86-64, "ti" functions must use Vector(2, u64) instead of the standard i128 calling
3451 if (vector_len == 0) {3436 // convention to adhere to the ABI that LLVM expects compiler-rt to have.
3452 LLVMValueRef params[1] = {value_ref};3437 LLVMTypeRef v2i64 = LLVMVectorType(LLVMInt64Type(), 2);
3453 result = LLVMBuildCall(g->builder, func_ref, params, param_count, "");3438 func_ref = get_soft_float_fn(g, fn_name, param_count, operand_type->llvm_type, v2i64);
3454 } else {3439 } else {
3455 ZigType *alloca_ty = operand_type;3440 func_ref = get_soft_float_fn(g, fn_name, param_count, operand_type->llvm_type, wider_type->llvm_type);
3456 result = build_alloca(g, alloca_ty, "", 0);3441 }
34573442
3458 LLVMTypeRef usize_ref = g->builtin_types.entry_usize->llvm_type;3443 LLVMValueRef params[1] = {value_ref};
3459 for (uint32_t i = 0; i < vector_len; i++) {3444 LLVMValueRef result = LLVMBuildCall(g->builder, func_ref, params, param_count, "");
3460 LLVMValueRef index_value = LLVMConstInt(usize_ref, i, false);
3461 LLVMValueRef params[1] = {
3462 LLVMBuildExtractElement(g->builder, value_ref, index_value, ""),
3463 };
3464 LLVMValueRef call_result = LLVMBuildCall(g->builder, func_ref, params, param_count, "");
3465 LLVMBuildInsertElement(g->builder, LLVMBuildLoad(g->builder, result, ""),
3466 call_result, index_value, "");
3467 }
34683445
3469 result = LLVMBuildLoad(g->builder, result, "");3446 if ((wider_type->data.integral.bit_count == 128) && (g->zig_target->os == OsWindows) && (g->zig_target->arch == ZigLLVM_x86_64)) {
3447 result = LLVMBuildBitCast(g->builder, result, wider_type->llvm_type, "");
3470 }3448 }
34713449
3472 // Handle integers of non-pot bitsize by shortening them on the output3450 // Handle integers of non-pot bitsize by shortening them on the output
3473 if (result_type != wider_type) {3451 if (result_type != wider_type) {
3474 return gen_widen_or_shorten(g, false, wider_type, result_type, result);3452 result = gen_widen_or_shorten(g, false, wider_type, result_type, result);
3475 }3453 }
3454
3476 return result;3455 return result;
3477}3456}
34783457
3479static LLVMValueRef gen_soft_float_bin_op(CodeGen *g, LLVMValueRef op1_value, LLVMValueRef op2_value, ZigType *operand_type, IrBinOp op_id) {3458static LLVMValueRef gen_soft_float_bin_op(CodeGen *g, LLVMValueRef op1_value, LLVMValueRef op2_value, ZigType *operand_type, IrBinOp op_id) {
3480 uint32_t vector_len = operand_type->id == ZigTypeIdVector ? operand_type->data.vector.len : 0;3459 uint32_t vector_len = operand_type->id == ZigTypeIdVector ? operand_type->data.vector.len : 0;
34813460
3482 LLVMTypeRef return_type = operand_type->llvm_type;
3483 int param_count = 2;3461 int param_count = 2;
34843462
3485 const char *compiler_rt_type_abbrev = get_compiler_rt_type_abbrev(operand_type);3463 ZigType *operand_scalar_type = (operand_type->id == ZigTypeIdVector) ? operand_type->data.vector.elem_type : operand_type;
3486 const char *math_float_prefix = libc_float_prefix(g, operand_type);3464 LLVMTypeRef return_scalar_type = operand_scalar_type->llvm_type;
3487 const char *math_float_suffix = libc_float_suffix(g, operand_type);3465 const char *compiler_rt_type_abbrev = get_compiler_rt_type_abbrev(operand_scalar_type);
3466 const char *math_float_prefix = libc_float_prefix(g, operand_scalar_type);
3467 const char *math_float_suffix = libc_float_suffix(g, operand_scalar_type);
34883468
3489 char fn_name[64];3469 char fn_name[64];
3490 Icmp res_icmp = NONE;3470 Icmp res_icmp = NONE;
...@@ -3511,32 +3491,32 @@ static LLVMValueRef gen_soft_float_bin_op(CodeGen *g, LLVMValueRef op1_value, LL...@@ -3511,32 +3491,32 @@ static LLVMValueRef gen_soft_float_bin_op(CodeGen *g, LLVMValueRef op1_value, LL
3511 case IrBinOpShlSat:3491 case IrBinOpShlSat:
3512 zig_unreachable();3492 zig_unreachable();
3513 case IrBinOpCmpEq:3493 case IrBinOpCmpEq:
3514 return_type = g->builtin_types.entry_i32->llvm_type;3494 return_scalar_type = g->builtin_types.entry_i32->llvm_type;
3515 snprintf(fn_name, sizeof(fn_name), "__eq%sf2", compiler_rt_type_abbrev);3495 snprintf(fn_name, sizeof(fn_name), "__eq%sf2", compiler_rt_type_abbrev);
3516 res_icmp = EQ_ZERO;3496 res_icmp = EQ_ZERO;
3517 break;3497 break;
3518 case IrBinOpCmpNotEq:3498 case IrBinOpCmpNotEq:
3519 return_type = g->builtin_types.entry_i32->llvm_type;3499 return_scalar_type = g->builtin_types.entry_i32->llvm_type;
3520 snprintf(fn_name, sizeof(fn_name), "__ne%sf2", compiler_rt_type_abbrev);3500 snprintf(fn_name, sizeof(fn_name), "__ne%sf2", compiler_rt_type_abbrev);
3521 res_icmp = NE_ZERO;3501 res_icmp = NE_ZERO;
3522 break;3502 break;
3523 case IrBinOpCmpLessOrEq:3503 case IrBinOpCmpLessOrEq:
3524 return_type = g->builtin_types.entry_i32->llvm_type;3504 return_scalar_type = g->builtin_types.entry_i32->llvm_type;
3525 snprintf(fn_name, sizeof(fn_name), "__le%sf2", compiler_rt_type_abbrev);3505 snprintf(fn_name, sizeof(fn_name), "__le%sf2", compiler_rt_type_abbrev);
3526 res_icmp = LE_ZERO;3506 res_icmp = LE_ZERO;
3527 break;3507 break;
3528 case IrBinOpCmpLessThan:3508 case IrBinOpCmpLessThan:
3529 return_type = g->builtin_types.entry_i32->llvm_type;3509 return_scalar_type = g->builtin_types.entry_i32->llvm_type;
3530 snprintf(fn_name, sizeof(fn_name), "__le%sf2", compiler_rt_type_abbrev);3510 snprintf(fn_name, sizeof(fn_name), "__le%sf2", compiler_rt_type_abbrev);
3531 res_icmp = EQ_NEG;3511 res_icmp = EQ_NEG;
3532 break;3512 break;
3533 case IrBinOpCmpGreaterOrEq:3513 case IrBinOpCmpGreaterOrEq:
3534 return_type = g->builtin_types.entry_i32->llvm_type;3514 return_scalar_type = g->builtin_types.entry_i32->llvm_type;
3535 snprintf(fn_name, sizeof(fn_name), "__ge%sf2", compiler_rt_type_abbrev);3515 snprintf(fn_name, sizeof(fn_name), "__ge%sf2", compiler_rt_type_abbrev);
3536 res_icmp = GE_ZERO;3516 res_icmp = GE_ZERO;
3537 break;3517 break;
3538 case IrBinOpCmpGreaterThan:3518 case IrBinOpCmpGreaterThan:
3539 return_type = g->builtin_types.entry_i32->llvm_type;3519 return_scalar_type = g->builtin_types.entry_i32->llvm_type;
3540 snprintf(fn_name, sizeof(fn_name), "__ge%sf2", compiler_rt_type_abbrev);3520 snprintf(fn_name, sizeof(fn_name), "__ge%sf2", compiler_rt_type_abbrev);
3541 res_icmp = EQ_ONE;3521 res_icmp = EQ_ONE;
3542 break;3522 break;
...@@ -3569,7 +3549,7 @@ static LLVMValueRef gen_soft_float_bin_op(CodeGen *g, LLVMValueRef op1_value, LL...@@ -3569,7 +3549,7 @@ static LLVMValueRef gen_soft_float_bin_op(CodeGen *g, LLVMValueRef op1_value, LL
3569 zig_unreachable();3549 zig_unreachable();
3570 }3550 }
35713551
3572 LLVMValueRef func_ref = get_soft_float_fn(g, fn_name, param_count, operand_type->llvm_type, return_type);3552 LLVMValueRef func_ref = get_soft_float_fn(g, fn_name, param_count, operand_scalar_type->llvm_type, return_scalar_type);
35733553
3574 LLVMValueRef result;3554 LLVMValueRef result;
3575 if (vector_len == 0) {3555 if (vector_len == 0) {
test/behavior/vector.zig+14-12
...@@ -101,18 +101,20 @@ test "vector float operators" {...@@ -101,18 +101,20 @@ test "vector float operators" {
101 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO101 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
102 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO102 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
103103
104 const S = struct {104 inline for ([_]type{ f16, f32, f64, f80, f128 }) |T| {
105 fn doTheTest() !void {105 const S = struct {
106 var v: @Vector(4, f32) = [4]f32{ 10, 20, 30, 40 };106 fn doTheTest() !void {
107 var x: @Vector(4, f32) = [4]f32{ 1, 2, 3, 4 };107 var v: @Vector(4, T) = [4]T{ 10, 20, 30, 40 };
108 try expect(mem.eql(f32, &@as([4]f32, v + x), &[4]f32{ 11, 22, 33, 44 }));108 var x: @Vector(4, T) = [4]T{ 1, 2, 3, 4 };
109 try expect(mem.eql(f32, &@as([4]f32, v - x), &[4]f32{ 9, 18, 27, 36 }));109 try expect(mem.eql(T, &@as([4]T, v + x), &[4]T{ 11, 22, 33, 44 }));
110 try expect(mem.eql(f32, &@as([4]f32, v * x), &[4]f32{ 10, 40, 90, 160 }));110 try expect(mem.eql(T, &@as([4]T, v - x), &[4]T{ 9, 18, 27, 36 }));
111 try expect(mem.eql(f32, &@as([4]f32, -x), &[4]f32{ -1, -2, -3, -4 }));111 try expect(mem.eql(T, &@as([4]T, v * x), &[4]T{ 10, 40, 90, 160 }));
112 }112 try expect(mem.eql(T, &@as([4]T, -x), &[4]T{ -1, -2, -3, -4 }));
113 };113 }
114 try S.doTheTest();114 };
115 comptime try S.doTheTest();115 try S.doTheTest();
116 comptime try S.doTheTest();
117 }
116}118}
117119
118test "vector bit operators" {120test "vector bit operators" {