Skip to content

Commit 382b60d

Browse files
committed
x86_64: increase passing test coverage on windows
Now that codegen has no references to linker state this is much easier. Closes #24153
1 parent 22c8161 commit 382b60d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+12361
-7954
lines changed

lib/compiler_rt/stack_probe.zig

Lines changed: 28 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -127,23 +127,23 @@ fn win_probe_stack_only() void {
127127
},
128128
.x86_64 => {
129129
asm volatile (
130-
\\ push %%rcx
131-
\\ push %%rax
132-
\\ cmp $0x1000,%%rax
133-
\\ lea 24(%%rsp),%%rcx
130+
\\ pushq %%rcx
131+
\\ pushq %%rax
132+
\\ cmpq $0x1000,%%rax
133+
\\ leaq 24(%%rsp),%%rcx
134134
\\ jb 1f
135135
\\ 2:
136-
\\ sub $0x1000,%%rcx
137-
\\ test %%rcx,(%%rcx)
138-
\\ sub $0x1000,%%rax
139-
\\ cmp $0x1000,%%rax
136+
\\ subq $0x1000,%%rcx
137+
\\ testq %%rcx,(%%rcx)
138+
\\ subq $0x1000,%%rax
139+
\\ cmpq $0x1000,%%rax
140140
\\ ja 2b
141141
\\ 1:
142-
\\ sub %%rax,%%rcx
143-
\\ test %%rcx,(%%rcx)
144-
\\ pop %%rax
145-
\\ pop %%rcx
146-
\\ ret
142+
\\ subq %%rax,%%rcx
143+
\\ testq %%rcx,(%%rcx)
144+
\\ popq %%rax
145+
\\ popq %%rcx
146+
\\ retq
147147
);
148148
},
149149
.x86 => {
@@ -179,26 +179,26 @@ fn win_probe_stack_adjust_sp() void {
179179
switch (arch) {
180180
.x86_64 => {
181181
asm volatile (
182-
\\ push %%rcx
183-
\\ cmp $0x1000,%%rax
184-
\\ lea 16(%%rsp),%%rcx
182+
\\ pushq %%rcx
183+
\\ cmpq $0x1000,%%rax
184+
\\ leaq 16(%%rsp),%%rcx
185185
\\ jb 1f
186186
\\ 2:
187-
\\ sub $0x1000,%%rcx
188-
\\ test %%rcx,(%%rcx)
189-
\\ sub $0x1000,%%rax
190-
\\ cmp $0x1000,%%rax
187+
\\ subq $0x1000,%%rcx
188+
\\ testq %%rcx,(%%rcx)
189+
\\ subq $0x1000,%%rax
190+
\\ cmpq $0x1000,%%rax
191191
\\ ja 2b
192192
\\ 1:
193-
\\ sub %%rax,%%rcx
194-
\\ test %%rcx,(%%rcx)
193+
\\ subq %%rax,%%rcx
194+
\\ testq %%rcx,(%%rcx)
195195
\\
196-
\\ lea 8(%%rsp),%%rax
197-
\\ mov %%rcx,%%rsp
198-
\\ mov -8(%%rax),%%rcx
199-
\\ push (%%rax)
200-
\\ sub %%rsp,%%rax
201-
\\ ret
196+
\\ leaq 8(%%rsp),%%rax
197+
\\ movq %%rcx,%%rsp
198+
\\ movq -8(%%rax),%%rcx
199+
\\ pushq (%%rax)
200+
\\ subq %%rsp,%%rax
201+
\\ retq
202202
);
203203
},
204204
.x86 => {

lib/std/math/float.zig

Lines changed: 41 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -107,42 +107,61 @@ pub inline fn floatEpsAt(comptime T: type, x: T) T {
107107
}
108108
}
109109

110-
/// Returns the value inf for floating point type T.
111-
pub inline fn inf(comptime T: type) T {
112-
return reconstructFloat(T, floatExponentMax(T) + 1, mantissaOne(T));
110+
/// Returns the inf value for a floating point `Type`.
111+
pub inline fn inf(comptime Type: type) Type {
112+
const RuntimeType = switch (Type) {
113+
else => Type,
114+
comptime_float => f128, // any float type will do
115+
};
116+
return reconstructFloat(RuntimeType, floatExponentMax(RuntimeType) + 1, mantissaOne(RuntimeType));
113117
}
114118

115-
/// Returns the canonical quiet NaN representation for floating point type T.
116-
pub inline fn nan(comptime T: type) T {
119+
/// Returns the canonical quiet NaN representation for a floating point `Type`.
120+
pub inline fn nan(comptime Type: type) Type {
121+
const RuntimeType = switch (Type) {
122+
else => Type,
123+
comptime_float => f128, // any float type will do
124+
};
117125
return reconstructFloat(
118-
T,
119-
floatExponentMax(T) + 1,
120-
mantissaOne(T) | 1 << (floatFractionalBits(T) - 1),
126+
RuntimeType,
127+
floatExponentMax(RuntimeType) + 1,
128+
mantissaOne(RuntimeType) | 1 << (floatFractionalBits(RuntimeType) - 1),
121129
);
122130
}
123131

124-
/// Returns a signalling NaN representation for floating point type T.
132+
/// Returns a signalling NaN representation for a floating point `Type`.
125133
///
126134
/// TODO: LLVM is known to miscompile on some architectures to quiet NaN -
127135
/// this is tracked by https://github.com/ziglang/zig/issues/14366
128-
pub inline fn snan(comptime T: type) T {
136+
pub inline fn snan(comptime Type: type) Type {
137+
const RuntimeType = switch (Type) {
138+
else => Type,
139+
comptime_float => f128, // any float type will do
140+
};
129141
return reconstructFloat(
130-
T,
131-
floatExponentMax(T) + 1,
132-
mantissaOne(T) | 1 << (floatFractionalBits(T) - 2),
142+
RuntimeType,
143+
floatExponentMax(RuntimeType) + 1,
144+
mantissaOne(RuntimeType) | 1 << (floatFractionalBits(RuntimeType) - 2),
133145
);
134146
}
135147

136-
test "float bits" {
137-
inline for ([_]type{ f16, f32, f64, f80, f128, c_longdouble }) |T| {
138-
// (1 +) for the sign bit, since it is separate from the other bits
139-
const size = 1 + floatExponentBits(T) + floatMantissaBits(T);
140-
try expect(@bitSizeOf(T) == size);
148+
fn floatBits(comptime Type: type) !void {
149+
// (1 +) for the sign bit, since it is separate from the other bits
150+
const size = 1 + floatExponentBits(Type) + floatMantissaBits(Type);
151+
try expect(@bitSizeOf(Type) == size);
152+
try expect(floatFractionalBits(Type) <= floatMantissaBits(Type));
141153

142-
// for machine epsilon, assert expmin <= -prec <= expmax
143-
try expect(floatExponentMin(T) <= -floatFractionalBits(T));
144-
try expect(-floatFractionalBits(T) <= floatExponentMax(T));
145-
}
154+
// for machine epsilon, assert expmin <= -prec <= expmax
155+
try expect(floatExponentMin(Type) <= -floatFractionalBits(Type));
156+
try expect(-floatFractionalBits(Type) <= floatExponentMax(Type));
157+
}
158+
test floatBits {
159+
try floatBits(f16);
160+
try floatBits(f32);
161+
try floatBits(f64);
162+
try floatBits(f80);
163+
try floatBits(f128);
164+
try floatBits(c_longdouble);
146165
}
147166

148167
test inf {

lib/std/math/signbit.zig

Lines changed: 40 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,47 @@ const expect = std.testing.expect;
44

55
/// Returns whether x is negative or negative 0.
66
pub fn signbit(x: anytype) bool {
7-
const T = @TypeOf(x);
8-
const TBits = std.meta.Int(.unsigned, @typeInfo(T).float.bits);
9-
return @as(TBits, @bitCast(x)) >> (@bitSizeOf(T) - 1) != 0;
7+
return switch (@typeInfo(@TypeOf(x))) {
8+
.int, .comptime_int => x,
9+
.float => |float| @as(@Type(.{ .int = .{
10+
.signedness = .signed,
11+
.bits = float.bits,
12+
} }), @bitCast(x)),
13+
.comptime_float => @as(i128, @bitCast(@as(f128, x))), // any float type will do
14+
else => @compileError("std.math.signbit does not support " ++ @typeName(@TypeOf(x))),
15+
} < 0;
1016
}
1117

1218
test signbit {
13-
inline for ([_]type{ f16, f32, f64, f80, f128 }) |T| {
14-
try expect(!signbit(@as(T, 0.0)));
15-
try expect(!signbit(@as(T, 1.0)));
16-
try expect(signbit(@as(T, -2.0)));
17-
try expect(signbit(@as(T, -0.0)));
18-
try expect(!signbit(math.inf(T)));
19-
try expect(signbit(-math.inf(T)));
20-
try expect(!signbit(math.nan(T)));
21-
try expect(signbit(-math.nan(T)));
22-
}
19+
try testInts(i0);
20+
try testInts(u0);
21+
try testInts(i1);
22+
try testInts(u1);
23+
try testInts(i2);
24+
try testInts(u2);
25+
26+
try testFloats(f16);
27+
try testFloats(f32);
28+
try testFloats(f64);
29+
try testFloats(f80);
30+
try testFloats(f128);
31+
try testFloats(c_longdouble);
32+
try testFloats(comptime_float);
33+
}
34+
35+
fn testInts(comptime Type: type) !void {
36+
try expect((std.math.minInt(Type) < 0) == signbit(@as(Type, std.math.minInt(Type))));
37+
try expect(!signbit(@as(Type, 0)));
38+
try expect(!signbit(@as(Type, std.math.maxInt(Type))));
39+
}
40+
41+
fn testFloats(comptime Type: type) !void {
42+
try expect(!signbit(@as(Type, 0.0)));
43+
try expect(!signbit(@as(Type, 1.0)));
44+
try expect(signbit(@as(Type, -2.0)));
45+
try expect(signbit(@as(Type, -0.0)));
46+
try expect(!signbit(math.inf(Type)));
47+
try expect(signbit(-math.inf(Type)));
48+
try expect(!signbit(math.nan(Type)));
49+
try expect(signbit(-math.nan(Type)));
2350
}

lib/std/posix.zig

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7571,7 +7571,10 @@ const lfs64_abi = native_os == .linux and builtin.link_libc and (builtin.abi.isG
75717571
/// If this happens the fix is to add the error code to the corresponding
75727572
/// switch expression, possibly introduce a new error in the error set, and
75737573
/// send a patch to Zig.
7574-
pub const unexpected_error_tracing = builtin.zig_backend == .stage2_llvm and builtin.mode == .Debug;
7574+
pub const unexpected_error_tracing = builtin.mode == .Debug and switch (builtin.zig_backend) {
7575+
.stage2_llvm, .stage2_x86_64 => true,
7576+
else => false,
7577+
};
75757578

75767579
pub const UnexpectedError = error{
75777580
/// The Operating System returned an undocumented error code.

lib/std/start.zig

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -485,6 +485,9 @@ fn _start() callconv(.naked) noreturn {
485485
}
486486

487487
fn WinStartup() callconv(.withStackAlign(.c, 1)) noreturn {
488+
// Switch from the x87 fpu state set by windows to the state expected by the gnu abi.
489+
if (builtin.abi == .gnu) asm volatile ("fninit");
490+
488491
if (!builtin.single_threaded and !builtin.link_libc) {
489492
_ = @import("os/windows/tls.zig");
490493
}
@@ -495,6 +498,9 @@ fn WinStartup() callconv(.withStackAlign(.c, 1)) noreturn {
495498
}
496499

497500
fn wWinMainCRTStartup() callconv(.withStackAlign(.c, 1)) noreturn {
501+
// Switch from the x87 fpu state set by windows to the state expected by the gnu abi.
502+
if (builtin.abi == .gnu) asm volatile ("fninit");
503+
498504
if (!builtin.single_threaded and !builtin.link_libc) {
499505
_ = @import("os/windows/tls.zig");
500506
}

src/Air/Legalize.zig

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,10 @@ pub const Feature = enum {
9191

9292
/// Legalize (shift lhs, (splat rhs)) -> (shift lhs, rhs)
9393
unsplat_shift_rhs,
94-
/// Legalize reduce of a one element vector to a bitcast
94+
/// Legalize reduce of a one element vector to a bitcast.
9595
reduce_one_elem_to_bitcast,
96+
/// Legalize splat to a one element vector to a bitcast.
97+
splat_one_elem_to_bitcast,
9698

9799
/// Replace `intcast_safe` with an explicit safety check which `call`s the panic function on failure.
98100
/// Not compatible with `scalarize_intcast_safe`.
@@ -576,7 +578,17 @@ fn legalizeBody(l: *Legalize, body_start: usize, body_len: usize) Error!void {
576578
else => {},
577579
}
578580
},
579-
.splat => {},
581+
.splat => if (l.features.contains(.splat_one_elem_to_bitcast)) {
582+
const ty_op = l.air_instructions.items(.data)[@intFromEnum(inst)].ty_op;
583+
switch (ty_op.ty.toType().vectorLen(zcu)) {
584+
0 => unreachable,
585+
1 => continue :inst l.replaceInst(inst, .bitcast, .{ .ty_op = .{
586+
.ty = ty_op.ty,
587+
.operand = ty_op.operand,
588+
} }),
589+
else => {},
590+
}
591+
},
580592
.shuffle_one => if (l.features.contains(.scalarize_shuffle_one)) continue :inst try l.scalarize(inst, .shuffle_one),
581593
.shuffle_two => if (l.features.contains(.scalarize_shuffle_two)) continue :inst try l.scalarize(inst, .shuffle_two),
582594
.select => if (l.features.contains(.scalarize_select)) continue :inst try l.scalarize(inst, .select),

src/arch/riscv64/CodeGen.zig

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5958,10 +5958,14 @@ fn airBr(func: *Func, inst: Air.Inst.Index) !void {
59585958
if (first_br) break :result src_mcv;
59595959

59605960
try func.getValue(block_tracking.short, br.block_inst);
5961-
// .long = .none to avoid merging operand and block result stack frames.
5962-
const current_tracking: InstTracking = .{ .long = .none, .short = src_mcv };
5963-
try current_tracking.materializeUnsafe(func, br.block_inst, block_tracking.*);
5964-
for (current_tracking.getRegs()) |src_reg| func.register_manager.freeReg(src_reg);
5961+
try InstTracking.materializeUnsafe(
5962+
// .long = .none to avoid merging operand and block result stack frames.
5963+
.{ .long = .none, .short = src_mcv },
5964+
func,
5965+
br.block_inst,
5966+
block_tracking.*,
5967+
);
5968+
try func.freeValue(src_mcv);
59655969
break :result block_tracking.short;
59665970
}
59675971

@@ -8188,8 +8192,11 @@ fn genTypedValue(func: *Func, val: Value) InnerError!MCValue {
81888192
const lf = func.bin_file;
81898193
const src_loc = func.src_loc;
81908194

8191-
const result = if (val.isUndef(pt.zcu))
8192-
try lf.lowerUav(pt, val.toIntern(), .none, src_loc)
8195+
const result: codegen.GenResult = if (val.isUndef(pt.zcu))
8196+
switch (try lf.lowerUav(pt, val.toIntern(), .none, src_loc)) {
8197+
.sym_index => |sym_index| .{ .mcv = .{ .load_symbol = sym_index } },
8198+
.fail => |em| .{ .fail = em },
8199+
}
81938200
else
81948201
try codegen.genTypedValue(lf, pt, src_loc, val, func.target);
81958202
const mcv: MCValue = switch (result) {

0 commit comments

Comments
 (0)