authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-10-01 20:45:42-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2023-10-01 20:45:42-04:00
log0f1652dc603ad43be733cfdd721cedf38d9e45d9
tree48d5f6a90d1b2435eda1fa6eb66ba4b620536d36
parent62a0fbdaef575c857a7fa5f911447dd7275c9f22
parentda335f0ee4dfe5a736919acc5ab20777838b42c7
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #17262 from jacobly0/x86_64

x86_64: support operations that are implemented in compiler_rt

20 files changed, 1894 insertions(+), 1358 deletions(-)

lib/compiler_rt/common.zig+2-2
......@@ -82,7 +82,7 @@ pub fn panic(msg: []const u8, error_return_trace: ?*std.builtin.StackTrace, _: ?
8282/// need for extending them to wider fp types.
8383/// TODO remove this; do this type selection in the language rather than
8484/// here in compiler-rt.
85pub fn F16T(comptime other_type: type) type {
85pub fn F16T(comptime OtherType: type) type {
8686 return switch (builtin.cpu.arch) {
8787 .arm, .armeb, .thumb, .thumbeb => if (std.Target.arm.featureSetHas(builtin.cpu.features, .has_v8))
8888 switch (builtin.abi.floatAbi()) {
......@@ -93,7 +93,7 @@ pub fn F16T(comptime other_type: type) type {
9393 u16,
9494 .aarch64, .aarch64_be, .aarch64_32 => f16,
9595 .riscv64 => if (builtin.zig_backend == .stage1) u16 else f16,
96 .x86, .x86_64 => if (builtin.target.isDarwin()) switch (other_type) {
96 .x86, .x86_64 => if (builtin.target.isDarwin()) switch (OtherType) {
9797 // Starting with LLVM 16, Darwin uses different abi for f16
9898 // depending on the type of the other return/argument..???
9999 f32, f64 => u16,
src/Compilation.zig+1-2
......@@ -1871,8 +1871,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
18711871 comp.job_queued_compiler_rt_lib = true;
18721872 } else if (options.output_mode != .Obj) {
18731873 log.debug("queuing a job to build compiler_rt_obj", .{});
1874 // If build-obj with -fcompiler-rt is requested, that is handled specially
1875 // elsewhere. In this case we are making a static library, so we ask
1874 // In this case we are making a static library, so we ask
18761875 // for a compiler-rt object to put in it.
18771876 comp.job_queued_compiler_rt_obj = true;
18781877 }
src/InternPool.zig+10-15
......@@ -5407,19 +5407,19 @@ pub fn getAnonStructType(ip: *InternPool, gpa: Allocator, ini: AnonStructTypeIni
54075407
54085408/// This is equivalent to `Key.FuncType` but adjusted to have a slice for `param_types`.
54095409pub const GetFuncTypeKey = struct {
5410 param_types: []Index,
5410 param_types: []const Index,
54115411 return_type: Index,
5412 comptime_bits: u32,
5413 noalias_bits: u32,
5412 comptime_bits: u32 = 0,
5413 noalias_bits: u32 = 0,
54145414 /// `null` means generic.
5415 alignment: ?Alignment,
5415 alignment: ?Alignment = .none,
54165416 /// `null` means generic.
5417 cc: ?std.builtin.CallingConvention,
5418 is_var_args: bool,
5419 is_generic: bool,
5420 is_noinline: bool,
5421 section_is_generic: bool,
5422 addrspace_is_generic: bool,
5417 cc: ?std.builtin.CallingConvention = .Unspecified,
5418 is_var_args: bool = false,
5419 is_generic: bool = false,
5420 is_noinline: bool = false,
5421 section_is_generic: bool = false,
5422 addrspace_is_generic: bool = false,
54235423};
54245424
54255425pub fn getFuncType(ip: *InternPool, gpa: Allocator, key: GetFuncTypeKey) Allocator.Error!Index {
......@@ -5754,15 +5754,10 @@ pub fn getFuncInstance(ip: *InternPool, gpa: Allocator, arg: GetFuncInstanceKey)
57545754 const func_ty = try ip.getFuncType(gpa, .{
57555755 .param_types = arg.param_types,
57565756 .return_type = arg.bare_return_type,
5757 .comptime_bits = 0,
57585757 .noalias_bits = arg.noalias_bits,
57595758 .alignment = arg.alignment,
57605759 .cc = arg.cc,
5761 .is_var_args = false,
5762 .is_generic = false,
57635760 .is_noinline = arg.is_noinline,
5764 .section_is_generic = false,
5765 .addrspace_is_generic = false,
57665761 });
57675762
57685763 const generic_owner = unwrapCoercedFunc(ip, arg.generic_owner);
src/Sema.zig+3-8
......@@ -7373,10 +7373,10 @@ fn analyzeCall(
73737373 const memoized_arg_values = try sema.arena.alloc(InternPool.Index, func_ty_info.param_types.len);
73747374
73757375 const owner_info = mod.typeToFunc(fn_owner_decl.ty).?;
7376 const new_param_types = try sema.arena.alloc(InternPool.Index, owner_info.param_types.len);
73767377 var new_fn_info: InternPool.GetFuncTypeKey = .{
7377 .param_types = try sema.arena.alloc(InternPool.Index, owner_info.param_types.len),
7378 .param_types = new_param_types,
73787379 .return_type = owner_info.return_type,
7379 .comptime_bits = 0,
73807380 .noalias_bits = owner_info.noalias_bits,
73817381 .alignment = if (owner_info.align_is_generic) null else owner_info.alignment,
73827382 .cc = if (owner_info.cc_is_generic) null else owner_info.cc,
......@@ -7403,7 +7403,7 @@ fn analyzeCall(
74037403 block,
74047404 &child_block,
74057405 inst,
7406 new_fn_info.param_types,
7406 new_param_types,
74077407 &arg_i,
74087408 args_info,
74097409 is_comptime_call,
......@@ -21144,16 +21144,11 @@ fn zirReify(
2114421144
2114521145 const ty = try mod.funcType(.{
2114621146 .param_types = param_types,
21147 .comptime_bits = 0,
2114821147 .noalias_bits = noalias_bits,
2114921148 .return_type = return_type.toIntern(),
2115021149 .alignment = alignment,
2115121150 .cc = cc,
2115221151 .is_var_args = is_var_args,
21153 .is_generic = false,
21154 .is_noinline = false,
21155 .section_is_generic = false,
21156 .addrspace_is_generic = false,
2115721152 });
2115821153 return Air.internedToRef(ty.toIntern());
2115921154 },
src/arch/x86_64/CodeGen.zig+937-552
......@@ -215,6 +215,7 @@ pub const MCValue = union(enum) {
215215 /// but it has not been spilled there yet in the current control flow.
216216 /// Payload is a frame index.
217217 reserved_frame: FrameIndex,
218 air_ref: Air.Inst.Ref,
218219
219220 fn isMemory(mcv: MCValue) bool {
220221 return switch (mcv) {
......@@ -278,6 +279,7 @@ pub const MCValue = union(enum) {
278279 .lea_tlv,
279280 .lea_frame,
280281 .reserved_frame,
282 .air_ref,
281283 => unreachable, // not in memory
282284 .memory => |addr| .{ .immediate = addr },
283285 .indirect => |reg_off| switch (reg_off.off) {
......@@ -306,6 +308,7 @@ pub const MCValue = union(enum) {
306308 .load_tlv,
307309 .load_frame,
308310 .reserved_frame,
311 .air_ref,
309312 => unreachable, // not dereferenceable
310313 .immediate => |addr| .{ .memory = addr },
311314 .register => |reg| .{ .indirect = .{ .reg = reg } },
......@@ -335,6 +338,7 @@ pub const MCValue = union(enum) {
335338 .lea_tlv,
336339 .load_frame,
337340 .reserved_frame,
341 .air_ref,
338342 => unreachable, // not offsettable
339343 .immediate => |imm| .{ .immediate = @bitCast(@as(i64, @bitCast(imm)) +% off) },
340344 .register => |reg| .{ .register_offset = .{ .reg = reg, .off = off } },
......@@ -366,6 +370,7 @@ pub const MCValue = union(enum) {
366370 .lea_tlv,
367371 .lea_frame,
368372 .reserved_frame,
373 .air_ref,
369374 => unreachable,
370375 .memory => |addr| if (math.cast(i32, @as(i64, @bitCast(addr)))) |small_addr|
371376 Memory.sib(ptr_size, .{ .base = .{ .reg = .ds }, .disp = small_addr })
......@@ -405,6 +410,7 @@ pub const MCValue = union(enum) {
405410 .load_frame => |pl| try writer.print("[{} + 0x{x}]", .{ pl.index, pl.off }),
406411 .lea_frame => |pl| try writer.print("{} + 0x{x}", .{ pl.index, pl.off }),
407412 .reserved_frame => |pl| try writer.print("(dead:{})", .{pl}),
413 .air_ref => |pl| try writer.print("(air:0x{x})", .{@intFromEnum(pl)}),
408414 }
409415 }
410416};
......@@ -433,6 +439,7 @@ const InstTracking = struct {
433439 => result,
434440 .dead,
435441 .reserved_frame,
442 .air_ref,
436443 => unreachable,
437444 .eflags,
438445 .register,
......@@ -491,6 +498,7 @@ const InstTracking = struct {
491498 .register_overflow,
492499 .indirect,
493500 .reserved_frame,
501 .air_ref,
494502 => unreachable,
495503 };
496504 }
......@@ -531,6 +539,7 @@ const InstTracking = struct {
531539 .register_offset,
532540 .register_overflow,
533541 .indirect,
542 .air_ref,
534543 => unreachable,
535544 }
536545 }
......@@ -1807,11 +1816,11 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
18071816 .log2,
18081817 .log10,
18091818 .round,
1810 => try self.airUnaryMath(inst),
1819 => |tag| try self.airUnaryMath(inst, tag),
18111820
1812 .floor => try self.airRound(inst, 0b1_0_01),
1813 .ceil => try self.airRound(inst, 0b1_0_10),
1814 .trunc_float => try self.airRound(inst, 0b1_0_11),
1821 .floor => try self.airRound(inst, .{ .mode = .down, .precision = .inexact }),
1822 .ceil => try self.airRound(inst, .{ .mode = .up, .precision = .inexact }),
1823 .trunc_float => try self.airRound(inst, .{ .mode = .zero, .precision = .inexact }),
18151824 .sqrt => try self.airSqrt(inst),
18161825 .neg => try self.airFloatSign(inst),
18171826
......@@ -2439,7 +2448,7 @@ fn restoreState(self: *Self, state: State, deaths: []const Air.Inst.Index, compt
24392448}
24402449
24412450pub fn spillInstruction(self: *Self, reg: Register, inst: Air.Inst.Index) !void {
2442 const tracking = self.inst_tracking.getPtr(inst).?;
2451 const tracking = self.inst_tracking.getPtr(inst) orelse return;
24432452 assert(tracking.getReg().?.id() == reg.id());
24442453 try tracking.spill(self, inst);
24452454 tracking.trackSpill(self, inst);
......@@ -2515,63 +2524,96 @@ fn airFptrunc(self: *Self, inst: Air.Inst.Index) !void {
25152524 const src_ty = self.typeOf(ty_op.operand);
25162525 const src_bits = src_ty.floatBits(self.target.*);
25172526
2518 const src_mcv = try self.resolveInst(ty_op.operand);
2519 const dst_mcv = if (src_mcv.isRegister() and self.reuseOperand(inst, ty_op.operand, 0, src_mcv))
2520 src_mcv
2521 else
2522 try self.copyToRegisterWithInstTracking(inst, dst_ty, src_mcv);
2523 const dst_reg = dst_mcv.getReg().?.to128();
2524 const dst_lock = self.register_manager.lockReg(dst_reg);
2525 defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);
2527 const result = result: {
2528 if (switch (dst_bits) {
2529 16 => switch (src_bits) {
2530 32 => !self.hasFeature(.f16c),
2531 64, 80, 128 => true,
2532 else => unreachable,
2533 },
2534 32 => switch (src_bits) {
2535 64 => false,
2536 80, 128 => true,
2537 else => unreachable,
2538 },
2539 64 => switch (src_bits) {
2540 80, 128 => true,
2541 else => unreachable,
2542 },
2543 80 => switch (dst_bits) {
2544 128 => true,
2545 else => unreachable,
2546 },
2547 else => unreachable,
2548 }) {
2549 var callee: ["__trunc?f?f2".len]u8 = undefined;
2550 break :result try self.genCall(.{ .lib = .{
2551 .return_type = self.floatCompilerRtAbiType(dst_ty, src_ty).toIntern(),
2552 .param_types = &.{self.floatCompilerRtAbiType(src_ty, dst_ty).toIntern()},
2553 .callee = std.fmt.bufPrint(&callee, "__trunc{c}f{c}f2", .{
2554 floatCompilerRtAbiName(src_bits),
2555 floatCompilerRtAbiName(dst_bits),
2556 }) catch unreachable,
2557 } }, &.{src_ty}, &.{.{ .air_ref = ty_op.operand }});
2558 }
25262559
2527 if (dst_bits == 16 and self.hasFeature(.f16c)) {
2528 switch (src_bits) {
2529 32 => {
2530 const mat_src_reg = if (src_mcv.isRegister())
2560 const src_mcv = try self.resolveInst(ty_op.operand);
2561 const dst_mcv = if (src_mcv.isRegister() and self.reuseOperand(inst, ty_op.operand, 0, src_mcv))
2562 src_mcv
2563 else
2564 try self.copyToRegisterWithInstTracking(inst, dst_ty, src_mcv);
2565 const dst_reg = dst_mcv.getReg().?.to128();
2566 const dst_lock = self.register_manager.lockReg(dst_reg);
2567 defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);
2568
2569 if (dst_bits == 16) {
2570 assert(self.hasFeature(.f16c));
2571 switch (src_bits) {
2572 32 => {
2573 const mat_src_reg = if (src_mcv.isRegister())
2574 src_mcv.getReg().?
2575 else
2576 try self.copyToTmpRegister(src_ty, src_mcv);
2577 try self.asmRegisterRegisterImmediate(
2578 .{ .v_, .cvtps2ph },
2579 dst_reg,
2580 mat_src_reg.to128(),
2581 Immediate.u(0b1_00),
2582 );
2583 },
2584 else => unreachable,
2585 }
2586 } else {
2587 assert(src_bits == 64 and dst_bits == 32);
2588 if (self.hasFeature(.avx)) if (src_mcv.isMemory()) try self.asmRegisterRegisterMemory(
2589 .{ .v_ss, .cvtsd2 },
2590 dst_reg,
2591 dst_reg,
2592 src_mcv.mem(.qword),
2593 ) else try self.asmRegisterRegisterRegister(
2594 .{ .v_ss, .cvtsd2 },
2595 dst_reg,
2596 dst_reg,
2597 (if (src_mcv.isRegister())
25312598 src_mcv.getReg().?
25322599 else
2533 try self.copyToTmpRegister(src_ty, src_mcv);
2534 try self.asmRegisterRegisterImmediate(
2535 .{ .v_, .cvtps2ph },
2536 dst_reg,
2537 mat_src_reg.to128(),
2538 Immediate.u(0b1_00),
2539 );
2540 },
2541 else => return self.fail("TODO implement airFptrunc from {} to {}", .{
2542 src_ty.fmt(self.bin_file.options.module.?), dst_ty.fmt(self.bin_file.options.module.?),
2543 }),
2600 try self.copyToTmpRegister(src_ty, src_mcv)).to128(),
2601 ) else if (src_mcv.isMemory()) try self.asmRegisterMemory(
2602 .{ ._ss, .cvtsd2 },
2603 dst_reg,
2604 src_mcv.mem(.qword),
2605 ) else try self.asmRegisterRegister(
2606 .{ ._ss, .cvtsd2 },
2607 dst_reg,
2608 (if (src_mcv.isRegister())
2609 src_mcv.getReg().?
2610 else
2611 try self.copyToTmpRegister(src_ty, src_mcv)).to128(),
2612 );
25442613 }
2545 } else if (src_bits == 64 and dst_bits == 32) {
2546 if (self.hasFeature(.avx)) if (src_mcv.isMemory()) try self.asmRegisterRegisterMemory(
2547 .{ .v_ss, .cvtsd2 },
2548 dst_reg,
2549 dst_reg,
2550 src_mcv.mem(.qword),
2551 ) else try self.asmRegisterRegisterRegister(
2552 .{ .v_ss, .cvtsd2 },
2553 dst_reg,
2554 dst_reg,
2555 (if (src_mcv.isRegister())
2556 src_mcv.getReg().?
2557 else
2558 try self.copyToTmpRegister(src_ty, src_mcv)).to128(),
2559 ) else if (src_mcv.isMemory()) try self.asmRegisterMemory(
2560 .{ ._ss, .cvtsd2 },
2561 dst_reg,
2562 src_mcv.mem(.qword),
2563 ) else try self.asmRegisterRegister(
2564 .{ ._ss, .cvtsd2 },
2565 dst_reg,
2566 (if (src_mcv.isRegister())
2567 src_mcv.getReg().?
2568 else
2569 try self.copyToTmpRegister(src_ty, src_mcv)).to128(),
2570 );
2571 } else return self.fail("TODO implement airFptrunc from {} to {}", .{
2572 src_ty.fmt(self.bin_file.options.module.?), dst_ty.fmt(self.bin_file.options.module.?),
2573 });
2574 return self.finishAir(inst, dst_mcv, .{ ty_op.operand, .none, .none });
2614 break :result dst_mcv;
2615 };
2616 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
25752617}
25762618
25772619fn airFpext(self: *Self, inst: Air.Inst.Index) !void {
......@@ -2581,58 +2623,96 @@ fn airFpext(self: *Self, inst: Air.Inst.Index) !void {
25812623 const src_ty = self.typeOf(ty_op.operand);
25822624 const src_bits = src_ty.floatBits(self.target.*);
25832625
2584 const src_mcv = try self.resolveInst(ty_op.operand);
2585 const dst_mcv = if (src_mcv.isRegister() and self.reuseOperand(inst, ty_op.operand, 0, src_mcv))
2586 src_mcv
2587 else
2588 try self.copyToRegisterWithInstTracking(inst, dst_ty, src_mcv);
2589 const dst_reg = dst_mcv.getReg().?.to128();
2590 const dst_lock = self.register_manager.lockReg(dst_reg);
2591 defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);
2626 const result = result: {
2627 if (switch (src_bits) {
2628 16 => switch (dst_bits) {
2629 32, 64 => !self.hasFeature(.f16c),
2630 80, 128 => true,
2631 else => unreachable,
2632 },
2633 32 => switch (dst_bits) {
2634 64 => false,
2635 80, 128 => true,
2636 else => unreachable,
2637 },
2638 64 => switch (dst_bits) {
2639 80, 128 => true,
2640 else => unreachable,
2641 },
2642 80 => switch (dst_bits) {
2643 128 => true,
2644 else => unreachable,
2645 },
2646 else => unreachable,
2647 }) {
2648 var callee: ["__extend?f?f2".len]u8 = undefined;
2649 break :result try self.genCall(.{ .lib = .{
2650 .return_type = self.floatCompilerRtAbiType(dst_ty, src_ty).toIntern(),
2651 .param_types = &.{self.floatCompilerRtAbiType(src_ty, dst_ty).toIntern()},
2652 .callee = std.fmt.bufPrint(&callee, "__extend{c}f{c}f2", .{
2653 floatCompilerRtAbiName(src_bits),
2654 floatCompilerRtAbiName(dst_bits),
2655 }) catch unreachable,
2656 } }, &.{src_ty}, &.{.{ .air_ref = ty_op.operand }});
2657 }
25922658
2593 if (src_bits == 16 and self.hasFeature(.f16c)) {
2594 const mat_src_reg = if (src_mcv.isRegister())
2595 src_mcv.getReg().?
2659 const src_mcv = try self.resolveInst(ty_op.operand);
2660 const dst_mcv = if (src_mcv.isRegister() and self.reuseOperand(inst, ty_op.operand, 0, src_mcv))
2661 src_mcv
25962662 else
2597 try self.copyToTmpRegister(src_ty, src_mcv);
2598 try self.asmRegisterRegister(.{ .v_ps, .cvtph2 }, dst_reg, mat_src_reg.to128());
2599 switch (dst_bits) {
2600 32 => {},
2601 64 => try self.asmRegisterRegisterRegister(.{ .v_sd, .cvtss2 }, dst_reg, dst_reg, dst_reg),
2602 else => return self.fail("TODO implement airFpext from {} to {}", .{
2603 src_ty.fmt(self.bin_file.options.module.?), dst_ty.fmt(self.bin_file.options.module.?),
2604 }),
2605 }
2606 } else if (src_bits == 32 and dst_bits == 64) {
2607 if (self.hasFeature(.avx)) if (src_mcv.isMemory()) try self.asmRegisterRegisterMemory(
2608 .{ .v_sd, .cvtss2 },
2609 dst_reg,
2610 dst_reg,
2611 src_mcv.mem(.dword),
2612 ) else try self.asmRegisterRegisterRegister(
2613 .{ .v_sd, .cvtss2 },
2614 dst_reg,
2615 dst_reg,
2616 (if (src_mcv.isRegister())
2617 src_mcv.getReg().?
2618 else
2619 try self.copyToTmpRegister(src_ty, src_mcv)).to128(),
2620 ) else if (src_mcv.isMemory()) try self.asmRegisterMemory(
2621 .{ ._sd, .cvtss2 },
2622 dst_reg,
2623 src_mcv.mem(.dword),
2624 ) else try self.asmRegisterRegister(
2625 .{ ._sd, .cvtss2 },
2626 dst_reg,
2627 (if (src_mcv.isRegister())
2663 try self.copyToRegisterWithInstTracking(inst, dst_ty, src_mcv);
2664 const dst_reg = dst_mcv.getReg().?.to128();
2665 const dst_lock = self.register_manager.lockReg(dst_reg);
2666 defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);
2667
2668 if (src_bits == 16) {
2669 assert(self.hasFeature(.f16c));
2670 const mat_src_reg = if (src_mcv.isRegister())
26282671 src_mcv.getReg().?
26292672 else
2630 try self.copyToTmpRegister(src_ty, src_mcv)).to128(),
2631 );
2632 } else return self.fail("TODO implement airFpext from {} to {}", .{
2633 src_ty.fmt(self.bin_file.options.module.?), dst_ty.fmt(self.bin_file.options.module.?),
2634 });
2635 return self.finishAir(inst, dst_mcv, .{ ty_op.operand, .none, .none });
2673 try self.copyToTmpRegister(src_ty, src_mcv);
2674 try self.asmRegisterRegister(.{ .v_ps, .cvtph2 }, dst_reg, mat_src_reg.to128());
2675 switch (dst_bits) {
2676 32 => {},
2677 64 => try self.asmRegisterRegisterRegister(
2678 .{ .v_sd, .cvtss2 },
2679 dst_reg,
2680 dst_reg,
2681 dst_reg,
2682 ),
2683 else => unreachable,
2684 }
2685 } else {
2686 assert(src_bits == 32 and dst_bits == 64);
2687 if (self.hasFeature(.avx)) if (src_mcv.isMemory()) try self.asmRegisterRegisterMemory(
2688 .{ .v_sd, .cvtss2 },
2689 dst_reg,
2690 dst_reg,
2691 src_mcv.mem(.dword),
2692 ) else try self.asmRegisterRegisterRegister(
2693 .{ .v_sd, .cvtss2 },
2694 dst_reg,
2695 dst_reg,
2696 (if (src_mcv.isRegister())
2697 src_mcv.getReg().?
2698 else
2699 try self.copyToTmpRegister(src_ty, src_mcv)).to128(),
2700 ) else if (src_mcv.isMemory()) try self.asmRegisterMemory(
2701 .{ ._sd, .cvtss2 },
2702 dst_reg,
2703 src_mcv.mem(.dword),
2704 ) else try self.asmRegisterRegister(
2705 .{ ._sd, .cvtss2 },
2706 dst_reg,
2707 (if (src_mcv.isRegister())
2708 src_mcv.getReg().?
2709 else
2710 try self.copyToTmpRegister(src_ty, src_mcv)).to128(),
2711 );
2712 }
2713 break :result dst_mcv;
2714 };
2715 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
26362716}
26372717
26382718fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {
......@@ -5002,7 +5082,26 @@ fn airFloatSign(self: *Self, inst: Air.Inst.Index) !void {
50025082 return self.floatSign(inst, un_op, ty);
50035083}
50045084
5005fn airRound(self: *Self, inst: Air.Inst.Index, mode: u4) !void {
5085const RoundMode = packed struct(u5) {
5086 mode: enum(u4) {
5087 /// Round to nearest (even)
5088 nearest = 0b0_00,
5089 /// Round down (toward -∞)
5090 down = 0b0_01,
5091 /// Round up (toward +∞)
5092 up = 0b0_10,
5093 /// Round toward zero (truncate)
5094 zero = 0b0_11,
5095 /// Use current rounding mode of MXCSR.RC
5096 mxcsr = 0b1_00,
5097 },
5098 precision: enum(u1) {
5099 normal = 0b0,
5100 inexact = 0b1,
5101 },
5102};
5103
5104fn airRound(self: *Self, inst: Air.Inst.Index, mode: RoundMode) !void {
50065105 const un_op = self.air.instructions.items(.data)[inst].un_op;
50075106 const ty = self.typeOf(un_op);
50085107
......@@ -5018,12 +5117,9 @@ fn airRound(self: *Self, inst: Air.Inst.Index, mode: u4) !void {
50185117 return self.finishAir(inst, dst_mcv, .{ un_op, .none, .none });
50195118}
50205119
5021fn genRound(self: *Self, ty: Type, dst_reg: Register, src_mcv: MCValue, mode: u4) !void {
5120fn genRound(self: *Self, ty: Type, dst_reg: Register, src_mcv: MCValue, mode: RoundMode) !void {
50225121 const mod = self.bin_file.options.module.?;
5023 if (!self.hasFeature(.sse4_1))
5024 return self.fail("TODO implement genRound without sse4_1 feature", .{});
5025
5026 const mir_tag = @as(?Mir.Inst.FixedTag, switch (ty.zigTypeTag(mod)) {
5122 const mir_tag = @as(?Mir.Inst.FixedTag, if (self.hasFeature(.sse4_1)) switch (ty.zigTypeTag(mod)) {
50275123 .Float => switch (ty.floatBits(self.target.*)) {
50285124 32 => if (self.hasFeature(.avx)) .{ .v_ss, .round } else .{ ._ss, .round },
50295125 64 => if (self.hasFeature(.avx)) .{ .v_sd, .round } else .{ ._sd, .round },
......@@ -5050,9 +5146,28 @@ fn genRound(self: *Self, ty: Type, dst_reg: Register, src_mcv: MCValue, mode: u4
50505146 else => null,
50515147 },
50525148 else => unreachable,
5053 }) orelse return self.fail("TODO implement genRound for {}", .{
5054 ty.fmt(self.bin_file.options.module.?),
5055 });
5149 } else null) orelse {
5150 if (ty.zigTypeTag(mod) != .Float) return self.fail("TODO implement genRound for {}", .{
5151 ty.fmt(self.bin_file.options.module.?),
5152 });
5153
5154 var callee: ["__trunc?".len]u8 = undefined;
5155 const res = try self.genCall(.{ .lib = .{
5156 .return_type = ty.toIntern(),
5157 .param_types = &.{ty.toIntern()},
5158 .callee = std.fmt.bufPrint(&callee, "{s}{s}{s}", .{
5159 floatLibcAbiPrefix(ty),
5160 switch (mode.mode) {
5161 .down => "floor",
5162 .up => "ceil",
5163 .zero => "trunc",
5164 else => unreachable,
5165 },
5166 floatLibcAbiSuffix(ty),
5167 }) catch unreachable,
5168 } }, &.{ty}, &.{src_mcv});
5169 return self.genSetReg(dst_reg, ty, res);
5170 };
50565171 const abi_size: u32 = @intCast(ty.abiSize(mod));
50575172 const dst_alias = registerAlias(dst_reg, abi_size);
50585173 switch (mir_tag[0]) {
......@@ -5061,7 +5176,7 @@ fn genRound(self: *Self, ty: Type, dst_reg: Register, src_mcv: MCValue, mode: u4
50615176 dst_alias,
50625177 dst_alias,
50635178 src_mcv.mem(Memory.PtrSize.fromSize(abi_size)),
5064 Immediate.u(mode),
5179 Immediate.u(@as(u5, @bitCast(mode))),
50655180 ) else try self.asmRegisterRegisterRegisterImmediate(
50665181 mir_tag,
50675182 dst_alias,
......@@ -5070,13 +5185,13 @@ fn genRound(self: *Self, ty: Type, dst_reg: Register, src_mcv: MCValue, mode: u4
50705185 src_mcv.getReg().?
50715186 else
50725187 try self.copyToTmpRegister(ty, src_mcv), abi_size),
5073 Immediate.u(mode),
5188 Immediate.u(@as(u5, @bitCast(mode))),
50745189 ),
50755190 else => if (src_mcv.isMemory()) try self.asmRegisterMemoryImmediate(
50765191 mir_tag,
50775192 dst_alias,
50785193 src_mcv.mem(Memory.PtrSize.fromSize(abi_size)),
5079 Immediate.u(mode),
5194 Immediate.u(@as(u5, @bitCast(mode))),
50805195 ) else try self.asmRegisterRegisterImmediate(
50815196 mir_tag,
50825197 dst_alias,
......@@ -5084,7 +5199,7 @@ fn genRound(self: *Self, ty: Type, dst_reg: Register, src_mcv: MCValue, mode: u4
50845199 src_mcv.getReg().?
50855200 else
50865201 try self.copyToTmpRegister(ty, src_mcv), abi_size),
5087 Immediate.u(mode),
5202 Immediate.u(@as(u5, @bitCast(mode))),
50885203 ),
50895204 }
50905205}
......@@ -5244,9 +5359,21 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void {
52445359 else => unreachable,
52455360 },
52465361 else => unreachable,
5247 }) orelse return self.fail("TODO implement airSqrt for {}", .{
5248 ty.fmt(mod),
5249 });
5362 }) orelse {
5363 if (ty.zigTypeTag(mod) != .Float) return self.fail("TODO implement airSqrt for {}", .{
5364 ty.fmt(mod),
5365 });
5366
5367 var callee: ["__sqrt?".len]u8 = undefined;
5368 break :result try self.genCall(.{ .lib = .{
5369 .return_type = ty.toIntern(),
5370 .param_types = &.{ty.toIntern()},
5371 .callee = std.fmt.bufPrint(&callee, "{s}sqrt{s}", .{
5372 floatLibcAbiPrefix(ty),
5373 floatLibcAbiSuffix(ty),
5374 }) catch unreachable,
5375 } }, &.{ty}, &.{src_mcv});
5376 };
52505377 switch (mir_tag[0]) {
52515378 .v_ss, .v_sd => if (src_mcv.isMemory()) try self.asmRegisterRegisterMemory(
52525379 mir_tag,
......@@ -5280,13 +5407,32 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void {
52805407 return self.finishAir(inst, result, .{ un_op, .none, .none });
52815408}
52825409
5283fn airUnaryMath(self: *Self, inst: Air.Inst.Index) !void {
5410fn airUnaryMath(self: *Self, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void {
52845411 const un_op = self.air.instructions.items(.data)[inst].un_op;
5285 _ = un_op;
5286 return self.fail("TODO implement airUnaryMath for {}", .{
5287 self.air.instructions.items(.tag)[inst],
5288 });
5289 //return self.finishAir(inst, result, .{ un_op, .none, .none });
5412 const ty = self.typeOf(un_op);
5413 var callee: ["__round?".len]u8 = undefined;
5414 const result = try self.genCall(.{ .lib = .{
5415 .return_type = ty.toIntern(),
5416 .param_types = &.{ty.toIntern()},
5417 .callee = std.fmt.bufPrint(&callee, "{s}{s}{s}", .{
5418 floatLibcAbiPrefix(ty),
5419 switch (tag) {
5420 .sin,
5421 .cos,
5422 .tan,
5423 .exp,
5424 .exp2,
5425 .log,
5426 .log2,
5427 .log10,
5428 .round,
5429 => @tagName(tag),
5430 else => unreachable,
5431 },
5432 floatLibcAbiSuffix(ty),
5433 }) catch unreachable,
5434 } }, &.{ty}, &.{.{ .air_ref = un_op }});
5435 return self.finishAir(inst, result, .{ un_op, .none, .none });
52905436}
52915437
52925438fn reuseOperand(
......@@ -5439,6 +5585,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) InnerErro
54395585
54405586 try self.genCopy(dst_ty, dst_mcv, .{ .indirect = .{ .reg = addr_reg } });
54415587 },
5588 .air_ref => |ref| try self.load(dst_mcv, ptr_ty, try self.resolveInst(ref)),
54425589 }
54435590}
54445591
......@@ -5584,6 +5731,7 @@ fn store(self: *Self, ptr_ty: Type, ptr_mcv: MCValue, src_mcv: MCValue) InnerErr
55845731
55855732 try self.genCopy(src_ty, .{ .indirect = .{ .reg = addr_reg } }, src_mcv);
55865733 },
5734 .air_ref => |ref| try self.store(ptr_ty, ptr_mcv, try self.resolveInst(ref)),
55875735 }
55885736}
55895737
......@@ -5925,6 +6073,7 @@ fn genUnOpMir(self: *Self, mir_tag: Mir.Inst.FixedTag, dst_ty: Type, dst_mcv: MC
59256073 .lea_tlv,
59266074 .lea_frame,
59276075 .reserved_frame,
6076 .air_ref,
59286077 => unreachable, // unmodifiable destination
59296078 .register => |dst_reg| try self.asmRegister(mir_tag, registerAlias(dst_reg, abi_size)),
59306079 .memory, .load_got, .load_direct, .load_tlv => {
......@@ -6433,6 +6582,34 @@ fn genBinOp(
64336582 const lhs_ty = self.typeOf(lhs_air);
64346583 const rhs_ty = self.typeOf(rhs_air);
64356584 const abi_size: u32 = @intCast(lhs_ty.abiSize(mod));
6585
6586 if (lhs_ty.isRuntimeFloat() and switch (lhs_ty.floatBits(self.target.*)) {
6587 16 => !self.hasFeature(.f16c),
6588 32, 64 => false,
6589 80, 128 => true,
6590 else => unreachable,
6591 }) {
6592 var callee: ["__add?f3".len]u8 = undefined;
6593 return self.genCall(.{ .lib = .{
6594 .return_type = lhs_ty.toIntern(),
6595 .param_types = &.{ lhs_ty.toIntern(), rhs_ty.toIntern() },
6596 .callee = switch (air_tag) {
6597 .add, .sub, .mul, .div_float => std.fmt.bufPrint(&callee, "__{s}{c}f3", .{
6598 @tagName(air_tag)[0..3],
6599 floatCompilerRtAbiName(lhs_ty.floatBits(self.target.*)),
6600 }),
6601 .min, .max => std.fmt.bufPrint(&callee, "{s}f{s}{s}", .{
6602 floatLibcAbiPrefix(lhs_ty),
6603 @tagName(air_tag),
6604 floatLibcAbiSuffix(lhs_ty),
6605 }),
6606 else => return self.fail("TODO implement genBinOp for {s} {}", .{
6607 @tagName(air_tag), lhs_ty.fmt(self.bin_file.options.module.?),
6608 }),
6609 } catch unreachable,
6610 } }, &.{ lhs_ty, rhs_ty }, &.{ .{ .air_ref = lhs_air }, .{ .air_ref = rhs_air } });
6611 }
6612
64366613 if ((lhs_ty.scalarType(mod).isRuntimeFloat() and
64376614 lhs_ty.scalarType(mod).floatBits(self.target.*) == 80) or
64386615 lhs_ty.abiSize(mod) > @as(u6, if (self.hasFeature(.avx)) 32 else 16))
......@@ -6584,7 +6761,11 @@ fn genBinOp(
65846761 .min,
65856762 .max,
65866763 => {
6587 const mat_src_mcv: MCValue = if (switch (src_mcv) {
6764 const resolved_src_mcv = switch (src_mcv) {
6765 else => src_mcv,
6766 .air_ref => |ref| try self.resolveInst(ref),
6767 };
6768 const mat_src_mcv: MCValue = if (switch (resolved_src_mcv) {
65886769 .immediate,
65896770 .eflags,
65906771 .register_offset,
......@@ -6598,7 +6779,10 @@ fn genBinOp(
65986779 => true,
65996780 .memory => |addr| math.cast(i32, @as(i64, @bitCast(addr))) == null,
66006781 else => false,
6601 }) .{ .register = try self.copyToTmpRegister(rhs_ty, src_mcv) } else src_mcv;
6782 })
6783 .{ .register = try self.copyToTmpRegister(rhs_ty, resolved_src_mcv) }
6784 else
6785 resolved_src_mcv;
66026786 const mat_mcv_lock = switch (mat_src_mcv) {
66036787 .register => |reg| self.register_manager.lockReg(reg),
66046788 else => null,
......@@ -6645,6 +6829,7 @@ fn genBinOp(
66456829 .lea_tlv,
66466830 .lea_frame,
66476831 .reserved_frame,
6832 .air_ref,
66486833 => unreachable,
66496834 .register => |src_reg| try self.asmCmovccRegisterRegister(
66506835 registerAlias(tmp_reg, cmov_abi_size),
......@@ -6685,7 +6870,8 @@ fn genBinOp(
66856870 const mir_tag = @as(?Mir.Inst.FixedTag, switch (lhs_ty.zigTypeTag(mod)) {
66866871 else => unreachable,
66876872 .Float => switch (lhs_ty.floatBits(self.target.*)) {
6688 16 => if (self.hasFeature(.f16c)) {
6873 16 => {
6874 assert(self.hasFeature(.f16c));
66896875 const tmp_reg = (try self.register_manager.allocReg(null, sse)).to128();
66906876 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
66916877 defer self.register_manager.unlockReg(tmp_lock);
......@@ -6728,7 +6914,7 @@ fn genBinOp(
67286914 Immediate.u(0b1_00),
67296915 );
67306916 return dst_mcv;
6731 } else null,
6917 },
67326918 32 => switch (air_tag) {
67336919 .add => if (self.hasFeature(.avx)) .{ .v_ss, .add } else .{ ._ss, .add },
67346920 .sub => if (self.hasFeature(.avx)) .{ .v_ss, .sub } else .{ ._ss, .sub },
......@@ -6989,181 +7175,184 @@ fn genBinOp(
69897175 else => null,
69907176 },
69917177 .Float => switch (lhs_ty.childType(mod).floatBits(self.target.*)) {
6992 16 => if (self.hasFeature(.f16c)) switch (lhs_ty.vectorLen(mod)) {
6993 1 => {
6994 const tmp_reg = (try self.register_manager.allocReg(null, sse)).to128();
6995 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
6996 defer self.register_manager.unlockReg(tmp_lock);
7178 16 => tag: {
7179 assert(self.hasFeature(.f16c));
7180 switch (lhs_ty.vectorLen(mod)) {
7181 1 => {
7182 const tmp_reg = (try self.register_manager.allocReg(null, sse)).to128();
7183 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
7184 defer self.register_manager.unlockReg(tmp_lock);
69977185
6998 if (src_mcv.isMemory()) try self.asmRegisterRegisterMemoryImmediate(
6999 .{ .vp_w, .insr },
7000 dst_reg,
7001 dst_reg,
7002 src_mcv.mem(.word),
7003 Immediate.u(1),
7004 ) else try self.asmRegisterRegisterRegister(
7005 .{ .vp_, .unpcklwd },
7006 dst_reg,
7007 dst_reg,
7008 (if (src_mcv.isRegister())
7009 src_mcv.getReg().?
7010 else
7011 try self.copyToTmpRegister(rhs_ty, src_mcv)).to128(),
7012 );
7013 try self.asmRegisterRegister(.{ .v_ps, .cvtph2 }, dst_reg, dst_reg);
7014 try self.asmRegisterRegister(.{ .v_, .movshdup }, tmp_reg, dst_reg);
7015 try self.asmRegisterRegisterRegister(
7016 switch (air_tag) {
7017 .add => .{ .v_ss, .add },
7018 .sub => .{ .v_ss, .sub },
7019 .mul => .{ .v_ss, .mul },
7020 .div_float, .div_trunc, .div_floor, .div_exact => .{ .v_ss, .div },
7021 .max => .{ .v_ss, .max },
7022 .min => .{ .v_ss, .max },
7023 else => unreachable,
7024 },
7025 dst_reg,
7026 dst_reg,
7027 tmp_reg,
7028 );
7029 try self.asmRegisterRegisterImmediate(
7030 .{ .v_, .cvtps2ph },
7031 dst_reg,
7032 dst_reg,
7033 Immediate.u(0b1_00),
7034 );
7035 return dst_mcv;
7036 },
7037 2 => {
7038 const tmp_reg = (try self.register_manager.allocReg(null, sse)).to128();
7039 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
7040 defer self.register_manager.unlockReg(tmp_lock);
7186 if (src_mcv.isMemory()) try self.asmRegisterRegisterMemoryImmediate(
7187 .{ .vp_w, .insr },
7188 dst_reg,
7189 dst_reg,
7190 src_mcv.mem(.word),
7191 Immediate.u(1),
7192 ) else try self.asmRegisterRegisterRegister(
7193 .{ .vp_, .unpcklwd },
7194 dst_reg,
7195 dst_reg,
7196 (if (src_mcv.isRegister())
7197 src_mcv.getReg().?
7198 else
7199 try self.copyToTmpRegister(rhs_ty, src_mcv)).to128(),
7200 );
7201 try self.asmRegisterRegister(.{ .v_ps, .cvtph2 }, dst_reg, dst_reg);
7202 try self.asmRegisterRegister(.{ .v_, .movshdup }, tmp_reg, dst_reg);
7203 try self.asmRegisterRegisterRegister(
7204 switch (air_tag) {
7205 .add => .{ .v_ss, .add },
7206 .sub => .{ .v_ss, .sub },
7207 .mul => .{ .v_ss, .mul },
7208 .div_float, .div_trunc, .div_floor, .div_exact => .{ .v_ss, .div },
7209 .max => .{ .v_ss, .max },
7210 .min => .{ .v_ss, .max },
7211 else => unreachable,
7212 },
7213 dst_reg,
7214 dst_reg,
7215 tmp_reg,
7216 );
7217 try self.asmRegisterRegisterImmediate(
7218 .{ .v_, .cvtps2ph },
7219 dst_reg,
7220 dst_reg,
7221 Immediate.u(0b1_00),
7222 );
7223 return dst_mcv;
7224 },
7225 2 => {
7226 const tmp_reg = (try self.register_manager.allocReg(null, sse)).to128();
7227 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
7228 defer self.register_manager.unlockReg(tmp_lock);
70417229
7042 if (src_mcv.isMemory()) try self.asmRegisterMemoryImmediate(
7043 .{ .vp_d, .insr },
7044 dst_reg,
7045 src_mcv.mem(.dword),
7046 Immediate.u(1),
7047 ) else try self.asmRegisterRegisterRegister(
7048 .{ .v_ps, .unpckl },
7049 dst_reg,
7050 dst_reg,
7051 (if (src_mcv.isRegister())
7052 src_mcv.getReg().?
7053 else
7054 try self.copyToTmpRegister(rhs_ty, src_mcv)).to128(),
7055 );
7056 try self.asmRegisterRegister(.{ .v_ps, .cvtph2 }, dst_reg, dst_reg);
7057 try self.asmRegisterRegisterRegister(
7058 .{ .v_ps, .movhl },
7059 tmp_reg,
7060 dst_reg,
7061 dst_reg,
7062 );
7063 try self.asmRegisterRegisterRegister(
7064 switch (air_tag) {
7065 .add => .{ .v_ps, .add },
7066 .sub => .{ .v_ps, .sub },
7067 .mul => .{ .v_ps, .mul },
7068 .div_float, .div_trunc, .div_floor, .div_exact => .{ .v_ps, .div },
7069 .max => .{ .v_ps, .max },
7070 .min => .{ .v_ps, .max },
7071 else => unreachable,
7072 },
7073 dst_reg,
7074 dst_reg,
7075 tmp_reg,
7076 );
7077 try self.asmRegisterRegisterImmediate(
7078 .{ .v_, .cvtps2ph },
7079 dst_reg,
7080 dst_reg,
7081 Immediate.u(0b1_00),
7082 );
7083 return dst_mcv;
7084 },
7085 3...4 => {
7086 const tmp_reg = (try self.register_manager.allocReg(null, sse)).to128();
7087 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
7088 defer self.register_manager.unlockReg(tmp_lock);
7230 if (src_mcv.isMemory()) try self.asmRegisterMemoryImmediate(
7231 .{ .vp_d, .insr },
7232 dst_reg,
7233 src_mcv.mem(.dword),
7234 Immediate.u(1),
7235 ) else try self.asmRegisterRegisterRegister(
7236 .{ .v_ps, .unpckl },
7237 dst_reg,
7238 dst_reg,
7239 (if (src_mcv.isRegister())
7240 src_mcv.getReg().?
7241 else
7242 try self.copyToTmpRegister(rhs_ty, src_mcv)).to128(),
7243 );
7244 try self.asmRegisterRegister(.{ .v_ps, .cvtph2 }, dst_reg, dst_reg);
7245 try self.asmRegisterRegisterRegister(
7246 .{ .v_ps, .movhl },
7247 tmp_reg,
7248 dst_reg,
7249 dst_reg,
7250 );
7251 try self.asmRegisterRegisterRegister(
7252 switch (air_tag) {
7253 .add => .{ .v_ps, .add },
7254 .sub => .{ .v_ps, .sub },
7255 .mul => .{ .v_ps, .mul },
7256 .div_float, .div_trunc, .div_floor, .div_exact => .{ .v_ps, .div },
7257 .max => .{ .v_ps, .max },
7258 .min => .{ .v_ps, .max },
7259 else => unreachable,
7260 },
7261 dst_reg,
7262 dst_reg,
7263 tmp_reg,
7264 );
7265 try self.asmRegisterRegisterImmediate(
7266 .{ .v_, .cvtps2ph },
7267 dst_reg,
7268 dst_reg,
7269 Immediate.u(0b1_00),
7270 );
7271 return dst_mcv;
7272 },
7273 3...4 => {
7274 const tmp_reg = (try self.register_manager.allocReg(null, sse)).to128();
7275 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
7276 defer self.register_manager.unlockReg(tmp_lock);
70897277
7090 try self.asmRegisterRegister(.{ .v_ps, .cvtph2 }, dst_reg, dst_reg);
7091 if (src_mcv.isMemory()) try self.asmRegisterMemory(
7092 .{ .v_ps, .cvtph2 },
7093 tmp_reg,
7094 src_mcv.mem(.qword),
7095 ) else try self.asmRegisterRegister(
7096 .{ .v_ps, .cvtph2 },
7097 tmp_reg,
7098 (if (src_mcv.isRegister())
7099 src_mcv.getReg().?
7100 else
7101 try self.copyToTmpRegister(rhs_ty, src_mcv)).to128(),
7102 );
7103 try self.asmRegisterRegisterRegister(
7104 switch (air_tag) {
7105 .add => .{ .v_ps, .add },
7106 .sub => .{ .v_ps, .sub },
7107 .mul => .{ .v_ps, .mul },
7108 .div_float, .div_trunc, .div_floor, .div_exact => .{ .v_ps, .div },
7109 .max => .{ .v_ps, .max },
7110 .min => .{ .v_ps, .max },
7111 else => unreachable,
7112 },
7113 dst_reg,
7114 dst_reg,
7115 tmp_reg,
7116 );
7117 try self.asmRegisterRegisterImmediate(
7118 .{ .v_, .cvtps2ph },
7119 dst_reg,
7120 dst_reg,
7121 Immediate.u(0b1_00),
7122 );
7123 return dst_mcv;
7124 },
7125 5...8 => {
7126 const tmp_reg = (try self.register_manager.allocReg(null, sse)).to256();
7127 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
7128 defer self.register_manager.unlockReg(tmp_lock);
7278 try self.asmRegisterRegister(.{ .v_ps, .cvtph2 }, dst_reg, dst_reg);
7279 if (src_mcv.isMemory()) try self.asmRegisterMemory(
7280 .{ .v_ps, .cvtph2 },
7281 tmp_reg,
7282 src_mcv.mem(.qword),
7283 ) else try self.asmRegisterRegister(
7284 .{ .v_ps, .cvtph2 },
7285 tmp_reg,
7286 (if (src_mcv.isRegister())
7287 src_mcv.getReg().?
7288 else
7289 try self.copyToTmpRegister(rhs_ty, src_mcv)).to128(),
7290 );
7291 try self.asmRegisterRegisterRegister(
7292 switch (air_tag) {
7293 .add => .{ .v_ps, .add },
7294 .sub => .{ .v_ps, .sub },
7295 .mul => .{ .v_ps, .mul },
7296 .div_float, .div_trunc, .div_floor, .div_exact => .{ .v_ps, .div },
7297 .max => .{ .v_ps, .max },
7298 .min => .{ .v_ps, .max },
7299 else => unreachable,
7300 },
7301 dst_reg,
7302 dst_reg,
7303 tmp_reg,
7304 );
7305 try self.asmRegisterRegisterImmediate(
7306 .{ .v_, .cvtps2ph },
7307 dst_reg,
7308 dst_reg,
7309 Immediate.u(0b1_00),
7310 );
7311 return dst_mcv;
7312 },
7313 5...8 => {
7314 const tmp_reg = (try self.register_manager.allocReg(null, sse)).to256();
7315 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
7316 defer self.register_manager.unlockReg(tmp_lock);
71297317
7130 try self.asmRegisterRegister(.{ .v_ps, .cvtph2 }, dst_reg.to256(), dst_reg);
7131 if (src_mcv.isMemory()) try self.asmRegisterMemory(
7132 .{ .v_ps, .cvtph2 },
7133 tmp_reg,
7134 src_mcv.mem(.xword),
7135 ) else try self.asmRegisterRegister(
7136 .{ .v_ps, .cvtph2 },
7137 tmp_reg,
7138 (if (src_mcv.isRegister())
7139 src_mcv.getReg().?
7140 else
7141 try self.copyToTmpRegister(rhs_ty, src_mcv)).to128(),
7142 );
7143 try self.asmRegisterRegisterRegister(
7144 switch (air_tag) {
7145 .add => .{ .v_ps, .add },
7146 .sub => .{ .v_ps, .sub },
7147 .mul => .{ .v_ps, .mul },
7148 .div_float, .div_trunc, .div_floor, .div_exact => .{ .v_ps, .div },
7149 .max => .{ .v_ps, .max },
7150 .min => .{ .v_ps, .max },
7151 else => unreachable,
7152 },
7153 dst_reg.to256(),
7154 dst_reg.to256(),
7155 tmp_reg,
7156 );
7157 try self.asmRegisterRegisterImmediate(
7158 .{ .v_, .cvtps2ph },
7159 dst_reg,
7160 dst_reg.to256(),
7161 Immediate.u(0b1_00),
7162 );
7163 return dst_mcv;
7164 },
7165 else => null,
7166 } else null,
7318 try self.asmRegisterRegister(.{ .v_ps, .cvtph2 }, dst_reg.to256(), dst_reg);
7319 if (src_mcv.isMemory()) try self.asmRegisterMemory(
7320 .{ .v_ps, .cvtph2 },
7321 tmp_reg,
7322 src_mcv.mem(.xword),
7323 ) else try self.asmRegisterRegister(
7324 .{ .v_ps, .cvtph2 },
7325 tmp_reg,
7326 (if (src_mcv.isRegister())
7327 src_mcv.getReg().?
7328 else
7329 try self.copyToTmpRegister(rhs_ty, src_mcv)).to128(),
7330 );
7331 try self.asmRegisterRegisterRegister(
7332 switch (air_tag) {
7333 .add => .{ .v_ps, .add },
7334 .sub => .{ .v_ps, .sub },
7335 .mul => .{ .v_ps, .mul },
7336 .div_float, .div_trunc, .div_floor, .div_exact => .{ .v_ps, .div },
7337 .max => .{ .v_ps, .max },
7338 .min => .{ .v_ps, .max },
7339 else => unreachable,
7340 },
7341 dst_reg.to256(),
7342 dst_reg.to256(),
7343 tmp_reg,
7344 );
7345 try self.asmRegisterRegisterImmediate(
7346 .{ .v_, .cvtps2ph },
7347 dst_reg,
7348 dst_reg.to256(),
7349 Immediate.u(0b1_00),
7350 );
7351 return dst_mcv;
7352 },
7353 else => break :tag null,
7354 }
7355 },
71677356 32 => switch (lhs_ty.vectorLen(mod)) {
71687357 1 => switch (air_tag) {
71697358 .add => if (self.hasFeature(.avx)) .{ .v_ss, .add } else .{ ._ss, .add },
......@@ -7290,18 +7479,16 @@ fn genBinOp(
72907479
72917480 switch (air_tag) {
72927481 .add, .add_wrap, .sub, .sub_wrap, .mul, .mul_wrap, .div_float, .div_exact => {},
7293 .div_trunc, .div_floor => if (self.hasFeature(.sse4_1)) try self.genRound(
7482 .div_trunc, .div_floor => try self.genRound(
72947483 lhs_ty,
72957484 dst_reg,
72967485 .{ .register = dst_reg },
7297 switch (air_tag) {
7298 .div_trunc => 0b1_0_11,
7299 .div_floor => 0b1_0_01,
7486 .{ .mode = switch (air_tag) {
7487 .div_trunc => .zero,
7488 .div_floor => .down,
73007489 else => unreachable,
7301 },
7302 ) else return self.fail("TODO implement genBinOp for {s} {} without sse4_1 feature", .{
7303 @tagName(air_tag), lhs_ty.fmt(self.bin_file.options.module.?),
7304 }),
7490 }, .precision = .inexact },
7491 ),
73057492 .bit_and, .bit_or, .xor => {},
73067493 .max, .min => if (maybe_mask_reg) |mask_reg| if (self.hasFeature(.avx)) {
73077494 const rhs_copy_reg = registerAlias(src_mcv.getReg().?, abi_size);
......@@ -7558,6 +7745,7 @@ fn genBinOpMir(
75587745 .lea_tlv,
75597746 .lea_frame,
75607747 .reserved_frame,
7748 .air_ref,
75617749 => unreachable, // unmodifiable destination
75627750 .register, .register_offset => {
75637751 assert(dst_mcv.isRegister());
......@@ -7673,6 +7861,7 @@ fn genBinOpMir(
76737861 else => unreachable,
76747862 }
76757863 },
7864 .air_ref => |ref| try self.genBinOpMir(mir_tag, ty, dst_mcv, try self.resolveInst(ref)),
76767865 }
76777866 },
76787867 .memory, .indirect, .load_got, .load_direct, .load_tlv, .load_frame => {
......@@ -7696,13 +7885,18 @@ fn genBinOpMir(
76967885 };
76977886 defer if (dst_info) |info| self.register_manager.unlockReg(info.addr_lock);
76987887
7699 const src_info: OpInfo = switch (src_mcv) {
7888 const resolved_src_mcv = switch (src_mcv) {
7889 else => src_mcv,
7890 .air_ref => |ref| try self.resolveInst(ref),
7891 };
7892 const src_info: OpInfo = switch (resolved_src_mcv) {
77007893 .none,
77017894 .unreach,
77027895 .dead,
77037896 .undef,
77047897 .register_overflow,
77057898 .reserved_frame,
7899 .air_ref,
77067900 => unreachable,
77077901 .immediate,
77087902 .register,
......@@ -7716,7 +7910,7 @@ fn genBinOpMir(
77167910 .lea_frame,
77177911 => null,
77187912 .memory, .load_got, .load_direct, .load_tlv => src: {
7719 switch (src_mcv) {
7913 switch (resolved_src_mcv) {
77207914 .memory => |addr| if (math.cast(i32, @as(i64, @bitCast(addr))) != null and
77217915 math.cast(i32, @as(i64, @bitCast(addr)) + abi_size - limb_abi_size) != null)
77227916 break :src null,
......@@ -7728,7 +7922,7 @@ fn genBinOpMir(
77287922 const src_addr_lock = self.register_manager.lockRegAssumeUnused(src_addr_reg);
77297923 errdefer self.register_manager.unlockReg(src_addr_lock);
77307924
7731 try self.genSetReg(src_addr_reg, Type.usize, src_mcv.address());
7925 try self.genSetReg(src_addr_reg, Type.usize, resolved_src_mcv.address());
77327926 break :src .{
77337927 .addr_reg = src_addr_reg,
77347928 .addr_lock = src_addr_lock,
......@@ -7775,13 +7969,14 @@ fn genBinOpMir(
77757969 else => unreachable,
77767970 },
77777971 );
7778 switch (src_mcv) {
7972 switch (resolved_src_mcv) {
77797973 .none,
77807974 .unreach,
77817975 .dead,
77827976 .undef,
77837977 .register_overflow,
77847978 .reserved_frame,
7979 .air_ref,
77857980 => unreachable,
77867981 .register => |src_reg| switch (off) {
77877982 0 => try self.asmMemoryRegister(
......@@ -7857,7 +8052,7 @@ fn genBinOpMir(
78578052 => {
78588053 const src_limb_reg = try self.copyToTmpRegister(limb_ty, if (src_info) |info| .{
78598054 .indirect = .{ .reg = info.addr_reg, .off = off },
7860 } else switch (src_mcv) {
8055 } else switch (resolved_src_mcv) {
78618056 .eflags,
78628057 .register_offset,
78638058 .lea_direct,
......@@ -7865,7 +8060,7 @@ fn genBinOpMir(
78658060 .lea_tlv,
78668061 .lea_frame,
78678062 => switch (off) {
7868 0 => src_mcv,
8063 0 => resolved_src_mcv,
78698064 else => .{ .immediate = 0 },
78708065 },
78718066 .memory => |addr| .{ .memory = @bitCast(@as(i64, @bitCast(addr)) + off) },
......@@ -7910,19 +8105,25 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M
79108105 .lea_tlv,
79118106 .lea_frame,
79128107 .reserved_frame,
8108 .air_ref,
79138109 => unreachable, // unmodifiable destination
79148110 .register => |dst_reg| {
79158111 const dst_alias = registerAlias(dst_reg, abi_size);
79168112 const dst_lock = self.register_manager.lockReg(dst_reg);
79178113 defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);
79188114
7919 switch (src_mcv) {
8115 const resolved_src_mcv = switch (src_mcv) {
8116 else => src_mcv,
8117 .air_ref => |ref| try self.resolveInst(ref),
8118 };
8119 switch (resolved_src_mcv) {
79208120 .none,
79218121 .unreach,
79228122 .dead,
79238123 .undef,
79248124 .register_overflow,
79258125 .reserved_frame,
8126 .air_ref,
79268127 => unreachable,
79278128 .register => |src_reg| try self.asmRegisterRegister(
79288129 .{ .i_, .mul },
......@@ -7938,7 +8139,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M
79388139 Immediate.s(small),
79398140 );
79408141 } else {
7941 const src_reg = try self.copyToTmpRegister(dst_ty, src_mcv);
8142 const src_reg = try self.copyToTmpRegister(dst_ty, resolved_src_mcv);
79428143 return self.genIntMulComplexOpMir(dst_ty, dst_mcv, MCValue{ .register = src_reg });
79438144 }
79448145 },
......@@ -7954,19 +8155,22 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M
79548155 => try self.asmRegisterRegister(
79558156 .{ .i_, .mul },
79568157 dst_alias,
7957 registerAlias(try self.copyToTmpRegister(dst_ty, src_mcv), abi_size),
8158 registerAlias(try self.copyToTmpRegister(dst_ty, resolved_src_mcv), abi_size),
79588159 ),
79598160 .memory, .indirect, .load_frame => try self.asmRegisterMemory(
79608161 .{ .i_, .mul },
79618162 dst_alias,
7962 Memory.sib(Memory.PtrSize.fromSize(abi_size), switch (src_mcv) {
8163 Memory.sib(Memory.PtrSize.fromSize(abi_size), switch (resolved_src_mcv) {
79638164 .memory => |addr| .{
79648165 .base = .{ .reg = .ds },
79658166 .disp = math.cast(i32, @as(i64, @bitCast(addr))) orelse
79668167 return self.asmRegisterRegister(
79678168 .{ .i_, .mul },
79688169 dst_alias,
7969 registerAlias(try self.copyToTmpRegister(dst_ty, src_mcv), abi_size),
8170 registerAlias(
8171 try self.copyToTmpRegister(dst_ty, resolved_src_mcv),
8172 abi_size,
8173 ),
79708174 ),
79718175 },
79728176 .indirect => |reg_off| .{
......@@ -8124,31 +8328,85 @@ fn airFence(self: *Self, inst: Air.Inst.Index) !void {
81248328}
81258329
81268330fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier) !void {
8127 const mod = self.bin_file.options.module.?;
81288331 if (modifier == .always_tail) return self.fail("TODO implement tail calls for x86_64", .{});
8332
81298333 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
8130 const callee = pl_op.operand;
81318334 const extra = self.air.extraData(Air.Call, pl_op.payload);
8132 const args: []const Air.Inst.Ref = @ptrCast(self.air.extra[extra.end..][0..extra.data.args_len]);
8133 const ty = self.typeOf(callee);
8335 const arg_refs: []const Air.Inst.Ref =
8336 @ptrCast(self.air.extra[extra.end..][0..extra.data.args_len]);
81348337
8135 const fn_ty = switch (ty.zigTypeTag(mod)) {
8136 .Fn => ty,
8137 .Pointer => ty.childType(mod),
8138 else => unreachable,
8338 const ExpectedContents = extern struct {
8339 tys: [16][@sizeOf(Type)]u8 align(@alignOf(Type)),
8340 vals: [16][@sizeOf(MCValue)]u8 align(@alignOf(MCValue)),
81398341 };
8342 var stack align(@max(@alignOf(ExpectedContents), @alignOf(std.heap.StackFallbackAllocator(0)))) =
8343 std.heap.stackFallback(@sizeOf(ExpectedContents), self.gpa);
8344 const allocator = stack.get();
8345
8346 const arg_tys = try allocator.alloc(Type, arg_refs.len);
8347 defer allocator.free(arg_tys);
8348 for (arg_tys, arg_refs) |*arg_ty, arg_ref| arg_ty.* = self.typeOf(arg_ref);
8349
8350 const arg_vals = try allocator.alloc(MCValue, arg_refs.len);
8351 defer allocator.free(arg_vals);
8352 for (arg_vals, arg_refs) |*arg_val, arg_ref| arg_val.* = .{ .air_ref = arg_ref };
8353
8354 const ret = try self.genCall(.{ .air = pl_op.operand }, arg_tys, arg_vals);
8355
8356 var bt = self.liveness.iterateBigTomb(inst);
8357 self.feed(&bt, pl_op.operand);
8358 for (arg_refs) |arg_ref| self.feed(&bt, arg_ref);
81408359
8360 const result = if (self.liveness.isUnused(inst)) .unreach else ret;
8361 return self.finishAirResult(inst, result);
8362}
8363
8364fn genCall(self: *Self, info: union(enum) {
8365 air: Air.Inst.Ref,
8366 lib: struct {
8367 return_type: InternPool.Index,
8368 param_types: []const InternPool.Index,
8369 lib: ?[]const u8 = null,
8370 callee: []const u8,
8371 },
8372}, arg_types: []const Type, args: []const MCValue) !MCValue {
8373 const mod = self.bin_file.options.module.?;
8374
8375 const fn_ty = switch (info) {
8376 .air => |callee| fn_info: {
8377 const callee_ty = self.typeOf(callee);
8378 break :fn_info switch (callee_ty.zigTypeTag(mod)) {
8379 .Fn => callee_ty,
8380 .Pointer => callee_ty.childType(mod),
8381 else => unreachable,
8382 };
8383 },
8384 .lib => |lib| try mod.funcType(.{
8385 .param_types = lib.param_types,
8386 .return_type = lib.return_type,
8387 .cc = .C,
8388 }),
8389 };
81418390 const fn_info = mod.typeToFunc(fn_ty).?;
81428391
8143 var info = try self.resolveCallingConventionValues(fn_info, args[fn_info.param_types.len..], .call_frame);
8144 defer info.deinit(self);
8392 const ExpectedContents = [16]Type;
8393 var stack align(@max(@alignOf(ExpectedContents), @alignOf(std.heap.StackFallbackAllocator(0)))) =
8394 std.heap.stackFallback(@sizeOf(ExpectedContents), self.gpa);
8395 const allocator = stack.get();
8396
8397 const var_args = try allocator.alloc(Type, args.len - fn_info.param_types.len);
8398 defer allocator.free(var_args);
8399 for (var_args, arg_types[fn_info.param_types.len..]) |*var_arg, arg_ty| var_arg.* = arg_ty;
8400
8401 var call_info =
8402 try self.resolveCallingConventionValues(fn_info, var_args, .call_frame);
8403 defer call_info.deinit(self);
81458404
81468405 // We need a properly aligned and sized call frame to be able to call this function.
81478406 {
8148 const needed_call_frame =
8149 FrameAlloc.init(.{
8150 .size = info.stack_byte_count,
8151 .alignment = info.stack_align,
8407 const needed_call_frame = FrameAlloc.init(.{
8408 .size = call_info.stack_byte_count,
8409 .alignment = call_info.stack_align,
81528410 });
81538411 const frame_allocs_slice = self.frame_allocs.slice();
81548412 const stack_frame_size =
......@@ -8164,24 +8422,20 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
81648422
81658423 // set stack arguments first because this can clobber registers
81668424 // also clobber spill arguments as we go
8167 switch (info.return_value.long) {
8425 switch (call_info.return_value.long) {
81688426 .none, .unreach => {},
81698427 .indirect => |reg_off| try self.spillRegisters(&.{reg_off.reg}),
81708428 else => unreachable,
81718429 }
8172 for (args, info.args) |arg, mc_arg| {
8173 const arg_ty = self.typeOf(arg);
8174 const arg_mcv = try self.resolveInst(arg);
8175 switch (mc_arg) {
8176 .none => {},
8177 .register => |reg| try self.spillRegisters(&.{reg}),
8178 .load_frame => try self.genCopy(arg_ty, mc_arg, arg_mcv),
8179 else => unreachable,
8180 }
8181 }
8430 for (call_info.args, arg_types, args) |dst_arg, arg_ty, src_arg| switch (dst_arg) {
8431 .none => {},
8432 .register => |reg| try self.spillRegisters(&.{reg}),
8433 .load_frame => try self.genCopy(arg_ty, dst_arg, src_arg),
8434 else => unreachable,
8435 };
81828436
81838437 // now we are free to set register arguments
8184 const ret_lock = switch (info.return_value.long) {
8438 const ret_lock = switch (call_info.return_value.long) {
81858439 .none, .unreach => null,
81868440 .indirect => |reg_off| lock: {
81878441 const ret_ty = fn_info.return_type.toType();
......@@ -8189,125 +8443,80 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
81898443 try self.genSetReg(reg_off.reg, Type.usize, .{
81908444 .lea_frame = .{ .index = frame_index, .off = -reg_off.off },
81918445 });
8192 info.return_value.short = .{ .load_frame = .{ .index = frame_index } };
8446 call_info.return_value.short = .{ .load_frame = .{ .index = frame_index } };
81938447 break :lock self.register_manager.lockRegAssumeUnused(reg_off.reg);
81948448 },
81958449 else => unreachable,
81968450 };
81978451 defer if (ret_lock) |lock| self.register_manager.unlockReg(lock);
81988452
8199 for (args, info.args) |arg, mc_arg| {
8200 const arg_ty = self.typeOf(arg);
8201 const arg_mcv = try self.resolveInst(arg);
8202 switch (mc_arg) {
8453 for (call_info.args, arg_types, args) |dst_arg, arg_ty, src_arg| {
8454 switch (dst_arg) {
82038455 .none, .load_frame => {},
8204 .register => try self.genCopy(arg_ty, mc_arg, arg_mcv),
8456 .register => try self.genCopy(arg_ty, dst_arg, src_arg),
82058457 else => unreachable,
82068458 }
82078459 }
82088460
82098461 // Due to incremental compilation, how function calls are generated depends
82108462 // on linking.
8211 if (try self.air.value(callee, mod)) |func_value| {
8212 const func_key = mod.intern_pool.indexToKey(func_value.ip_index);
8213 if (switch (func_key) {
8214 .func => |func| func.owner_decl,
8215 .ptr => |ptr| switch (ptr.addr) {
8216 .decl => |decl| decl,
8463 switch (info) {
8464 .air => |callee| if (try self.air.value(callee, mod)) |func_value| {
8465 const func_key = mod.intern_pool.indexToKey(func_value.ip_index);
8466 if (switch (func_key) {
8467 .func => |func| func.owner_decl,
8468 .ptr => |ptr| switch (ptr.addr) {
8469 .decl => |decl| decl,
8470 else => null,
8471 },
82178472 else => null,
8218 },
8219 else => null,
8220 }) |owner_decl| {
8221 if (self.bin_file.cast(link.File.Elf)) |elf_file| {
8222 const sym_index = try elf_file.getOrCreateMetadataForDecl(owner_decl);
8223 const sym = elf_file.symbol(sym_index);
8224 sym.flags.needs_got = true;
8225 _ = try sym.getOrCreateGotEntry(sym_index, elf_file);
8226 _ = try self.addInst(.{
8227 .tag = .call,
8228 .ops = .direct_got_reloc,
8229 .data = .{ .reloc = .{
8230 .atom_index = try self.owner.getSymbolIndex(self),
8231 .sym_index = sym.esym_index,
8232 } },
8233 });
8234 } else if (self.bin_file.cast(link.File.Coff)) |coff_file| {
8235 const atom = try coff_file.getOrCreateAtomForDecl(owner_decl);
8236 const sym_index = coff_file.getAtom(atom).getSymbolIndex().?;
8237 try self.genSetReg(.rax, Type.usize, .{ .lea_got = sym_index });
8238 try self.asmRegister(.{ ._, .call }, .rax);
8239 } else if (self.bin_file.cast(link.File.MachO)) |macho_file| {
8240 const atom = try macho_file.getOrCreateAtomForDecl(owner_decl);
8241 const sym_index = macho_file.getAtom(atom).getSymbolIndex().?;
8242 try self.genSetReg(.rax, Type.usize, .{ .lea_got = sym_index });
8243 try self.asmRegister(.{ ._, .call }, .rax);
8244 } else if (self.bin_file.cast(link.File.Plan9)) |p9| {
8245 const atom_index = try p9.seeDecl(owner_decl);
8246 const atom = p9.getAtom(atom_index);
8247 try self.asmMemory(.{ ._, .call }, Memory.sib(.qword, .{
8248 .base = .{ .reg = .ds },
8249 .disp = @intCast(atom.getOffsetTableAddress(p9)),
8250 }));
8251 } else unreachable;
8252 } else if (func_value.getExternFunc(mod)) |extern_func| {
8253 const decl_name = mod.intern_pool.stringToSlice(mod.declPtr(extern_func.decl).name);
8254 const lib_name = mod.intern_pool.stringToSliceUnwrap(extern_func.lib_name);
8255 if (self.bin_file.cast(link.File.Elf)) |elf_file| {
8256 const atom_index = try self.owner.getSymbolIndex(self);
8257 const sym_index = try elf_file.getGlobalSymbol(decl_name, lib_name);
8258 _ = try self.addInst(.{
8259 .tag = .call,
8260 .ops = .extern_fn_reloc,
8261 .data = .{ .reloc = .{
8262 .atom_index = atom_index,
8263 .sym_index = sym_index,
8264 } },
8265 });
8266 } else if (self.bin_file.cast(link.File.Coff)) |coff_file| {
8267 const atom_index = try self.owner.getSymbolIndex(self);
8268 const sym_index = try coff_file.getGlobalSymbol(decl_name, lib_name);
8269 _ = try self.addInst(.{
8270 .tag = .mov,
8271 .ops = .import_reloc,
8272 .data = .{ .rx = .{
8273 .r1 = .rax,
8274 .payload = try self.addExtra(Mir.Reloc{
8275 .atom_index = atom_index,
8276 .sym_index = sym_index,
8277 }),
8278 } },
8279 });
8280 try self.asmRegister(.{ ._, .call }, .rax);
8281 } else if (self.bin_file.cast(link.File.MachO)) |macho_file| {
8282 const atom_index = try self.owner.getSymbolIndex(self);
8283 const sym_index = try macho_file.getGlobalSymbol(decl_name, lib_name);
8284 _ = try self.addInst(.{
8285 .tag = .call,
8286 .ops = .extern_fn_reloc,
8287 .data = .{ .reloc = .{
8288 .atom_index = atom_index,
8289 .sym_index = sym_index,
8290 } },
8291 });
8473 }) |owner_decl| {
8474 if (self.bin_file.cast(link.File.Elf)) |elf_file| {
8475 const sym_index = try elf_file.getOrCreateMetadataForDecl(owner_decl);
8476 const sym = elf_file.symbol(sym_index);
8477 sym.flags.needs_got = true;
8478 _ = try sym.getOrCreateGotEntry(sym_index, elf_file);
8479 _ = try self.addInst(.{
8480 .tag = .call,
8481 .ops = .direct_got_reloc,
8482 .data = .{ .reloc = .{
8483 .atom_index = try self.owner.getSymbolIndex(self),
8484 .sym_index = sym.esym_index,
8485 } },
8486 });
8487 } else if (self.bin_file.cast(link.File.Coff)) |coff_file| {
8488 const atom = try coff_file.getOrCreateAtomForDecl(owner_decl);
8489 const sym_index = coff_file.getAtom(atom).getSymbolIndex().?;
8490 try self.genSetReg(.rax, Type.usize, .{ .lea_got = sym_index });
8491 try self.asmRegister(.{ ._, .call }, .rax);
8492 } else if (self.bin_file.cast(link.File.MachO)) |macho_file| {
8493 const atom = try macho_file.getOrCreateAtomForDecl(owner_decl);
8494 const sym_index = macho_file.getAtom(atom).getSymbolIndex().?;
8495 try self.genSetReg(.rax, Type.usize, .{ .lea_got = sym_index });
8496 try self.asmRegister(.{ ._, .call }, .rax);
8497 } else if (self.bin_file.cast(link.File.Plan9)) |p9| {
8498 const atom_index = try p9.seeDecl(owner_decl);
8499 const atom = p9.getAtom(atom_index);
8500 try self.asmMemory(.{ ._, .call }, Memory.sib(.qword, .{
8501 .base = .{ .reg = .ds },
8502 .disp = @intCast(atom.getOffsetTableAddress(p9)),
8503 }));
8504 } else unreachable;
8505 } else if (func_value.getExternFunc(mod)) |extern_func| {
8506 const lib_name = mod.intern_pool.stringToSliceUnwrap(extern_func.lib_name);
8507 const decl_name = mod.intern_pool.stringToSlice(mod.declPtr(extern_func.decl).name);
8508 try self.genExternSymbolRef(.call, lib_name, decl_name);
82928509 } else {
8293 return self.fail("TODO implement calling extern functions", .{});
8510 return self.fail("TODO implement calling bitcasted functions", .{});
82948511 }
82958512 } else {
8296 return self.fail("TODO implement calling bitcasted functions", .{});
8297 }
8298 } else {
8299 assert(ty.zigTypeTag(mod) == .Pointer);
8300 const mcv = try self.resolveInst(callee);
8301 try self.genSetReg(.rax, Type.usize, mcv);
8302 try self.asmRegister(.{ ._, .call }, .rax);
8513 assert(self.typeOf(callee).zigTypeTag(mod) == .Pointer);
8514 try self.genSetReg(.rax, Type.usize, .{ .air_ref = callee });
8515 try self.asmRegister(.{ ._, .call }, .rax);
8516 },
8517 .lib => |lib| try self.genExternSymbolRef(.call, lib.lib, lib.callee),
83038518 }
8304
8305 var bt = self.liveness.iterateBigTomb(inst);
8306 self.feed(&bt, callee);
8307 for (args) |arg| self.feed(&bt, arg);
8308
8309 const result = if (self.liveness.isUnused(inst)) .unreach else info.return_value.short;
8310 return self.finishAirResult(inst, result);
8519 return call_info.return_value.short;
83118520}
83128521
83138522fn airRet(self: *Self, inst: Air.Inst.Index) !void {
......@@ -8357,26 +8566,64 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
83578566 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
83588567 const ty = self.typeOf(bin_op.lhs);
83598568
8360 try self.spillEflagsIfOccupied();
8361 self.eflags_inst = inst;
8569 const result: Condition = result: {
8570 switch (ty.zigTypeTag(mod)) {
8571 .Float => {
8572 const float_bits = ty.floatBits(self.target.*);
8573 if (switch (float_bits) {
8574 16 => !self.hasFeature(.f16c),
8575 32, 64 => false,
8576 80, 128 => true,
8577 else => unreachable,
8578 }) {
8579 var callee: ["__???f2".len]u8 = undefined;
8580 const ret = try self.genCall(.{ .lib = .{
8581 .return_type = .i32_type,
8582 .param_types = &.{ ty.toIntern(), ty.toIntern() },
8583 .callee = std.fmt.bufPrint(&callee, "__{s}{c}f2", .{
8584 switch (op) {
8585 .eq => "eq",
8586 .neq => "ne",
8587 .lt => "lt",
8588 .lte => "le",
8589 .gt => "gt",
8590 .gte => "ge",
8591 },
8592 floatCompilerRtAbiName(float_bits),
8593 }) catch unreachable,
8594 } }, &.{ ty, ty }, &.{ .{ .air_ref = bin_op.lhs }, .{ .air_ref = bin_op.rhs } });
8595 try self.genBinOpMir(.{ ._, .@"test" }, Type.i32, ret, ret);
8596 break :result switch (op) {
8597 .eq => .e,
8598 .neq => .ne,
8599 .lt => .l,
8600 .lte => .le,
8601 .gt => .g,
8602 .gte => .ge,
8603 };
8604 }
8605 },
8606 else => {},
8607 }
83628608
8363 const lhs_mcv = try self.resolveInst(bin_op.lhs);
8364 const lhs_lock = switch (lhs_mcv) {
8365 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
8366 else => null,
8367 };
8368 defer if (lhs_lock) |lock| self.register_manager.unlockReg(lock);
8609 try self.spillEflagsIfOccupied();
83698610
8370 const rhs_mcv = try self.resolveInst(bin_op.rhs);
8371 const rhs_lock = switch (rhs_mcv) {
8372 .register => |reg| self.register_manager.lockReg(reg),
8373 else => null,
8374 };
8375 defer if (rhs_lock) |lock| self.register_manager.unlockReg(lock);
8611 const lhs_mcv = try self.resolveInst(bin_op.lhs);
8612 const lhs_lock = switch (lhs_mcv) {
8613 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
8614 else => null,
8615 };
8616 defer if (lhs_lock) |lock| self.register_manager.unlockReg(lock);
8617
8618 const rhs_mcv = try self.resolveInst(bin_op.rhs);
8619 const rhs_lock = switch (rhs_mcv) {
8620 .register => |reg| self.register_manager.lockReg(reg),
8621 else => null,
8622 };
8623 defer if (rhs_lock) |lock| self.register_manager.unlockReg(lock);
83768624
8377 const result = MCValue{
8378 .eflags = switch (ty.zigTypeTag(mod)) {
8379 else => result: {
8625 switch (ty.zigTypeTag(mod)) {
8626 else => {
83808627 const abi_size: u16 = @intCast(ty.abiSize(mod));
83818628 const may_flip: enum {
83828629 may_flip,
......@@ -8478,7 +8725,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
84788725 },
84798726 );
84808727 },
8481 .Float => result: {
8728 .Float => {
84828729 const flipped = switch (op) {
84838730 .lt, .lte => true,
84848731 .eq, .gte, .gt, .neq => false,
......@@ -8494,7 +8741,8 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
84948741 const src_mcv = if (flipped) lhs_mcv else rhs_mcv;
84958742
84968743 switch (ty.floatBits(self.target.*)) {
8497 16 => if (self.hasFeature(.f16c)) {
8744 16 => {
8745 assert(self.hasFeature(.f16c));
84988746 const tmp1_reg = (try self.register_manager.allocReg(null, sse)).to128();
84998747 const tmp1_mcv = MCValue{ .register = tmp1_reg };
85008748 const tmp1_lock = self.register_manager.lockRegAssumeUnused(tmp1_reg);
......@@ -8523,9 +8771,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
85238771 try self.asmRegisterRegister(.{ .v_ps, .cvtph2 }, tmp1_reg, tmp1_reg);
85248772 try self.asmRegisterRegister(.{ .v_, .movshdup }, tmp2_reg, tmp1_reg);
85258773 try self.genBinOpMir(.{ ._ss, .ucomi }, ty, tmp1_mcv, tmp2_mcv);
8526 } else return self.fail("TODO implement airCmp for {}", .{
8527 ty.fmt(mod),
8528 }),
8774 },
85298775 32 => try self.genBinOpMir(
85308776 .{ ._ss, .ucomi },
85318777 ty,
......@@ -8538,9 +8784,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
85388784 .{ .register = dst_reg },
85398785 src_mcv,
85408786 ),
8541 else => return self.fail("TODO implement airCmp for {}", .{
8542 ty.fmt(mod),
8543 }),
8787 else => unreachable,
85448788 }
85458789
85468790 break :result switch (if (flipped) op.reverse() else op) {
......@@ -8551,9 +8795,11 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
85518795 .neq => .nz_or_p,
85528796 };
85538797 },
8554 },
8798 }
85558799 };
8556 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
8800
8801 self.eflags_inst = inst;
8802 return self.finishAir(inst, .{ .eflags = result }, .{ bin_op.lhs, bin_op.rhs, .none });
85578803}
85588804
85598805fn airCmpVector(self: *Self, inst: Air.Inst.Index) !void {
......@@ -8571,7 +8817,6 @@ fn airCmpLtErrorsLen(self: *Self, inst: Air.Inst.Index) !void {
85718817 try self.genLazySymbolRef(.lea, addr_reg, link.File.LazySymbol.initDecl(.const_data, null, mod));
85728818
85738819 try self.spillEflagsIfOccupied();
8574 self.eflags_inst = inst;
85758820
85768821 const op_ty = self.typeOf(un_op);
85778822 const op_abi_size: u32 = @intCast(op_ty.abiSize(mod));
......@@ -8585,8 +8830,9 @@ fn airCmpLtErrorsLen(self: *Self, inst: Air.Inst.Index) !void {
85858830 registerAlias(dst_reg, op_abi_size),
85868831 Memory.sib(Memory.PtrSize.fromSize(op_abi_size), .{ .base = .{ .reg = addr_reg } }),
85878832 );
8588 const result = MCValue{ .eflags = .b };
8589 return self.finishAir(inst, result, .{ un_op, .none, .none });
8833
8834 self.eflags_inst = inst;
8835 return self.finishAir(inst, .{ .eflags = .b }, .{ un_op, .none, .none });
85908836}
85918837
85928838fn airTry(self: *Self, inst: Air.Inst.Index) !void {
......@@ -8776,7 +9022,6 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC
87769022 }
87779023
87789024 try self.spillEflagsIfOccupied();
8779 self.eflags_inst = inst;
87809025
87819026 const pl_ty = opt_ty.optionalChild(mod);
87829027
......@@ -8785,6 +9030,7 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC
87859030 else
87869031 .{ .off = @intCast(pl_ty.abiSize(mod)), .ty = Type.bool };
87879032
9033 self.eflags_inst = inst;
87889034 switch (opt_mcv) {
87899035 .none,
87909036 .unreach,
......@@ -8799,6 +9045,7 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC
87999045 .lea_tlv,
88009046 .lea_frame,
88019047 .reserved_frame,
9048 .air_ref,
88029049 => unreachable,
88039050
88049051 .register => |opt_reg| {
......@@ -8866,7 +9113,6 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC
88669113fn isNullPtr(self: *Self, inst: Air.Inst.Index, ptr_ty: Type, ptr_mcv: MCValue) !MCValue {
88679114 const mod = self.bin_file.options.module.?;
88689115 try self.spillEflagsIfOccupied();
8869 self.eflags_inst = inst;
88709116
88719117 const opt_ty = ptr_ty.childType(mod);
88729118 const pl_ty = opt_ty.optionalChild(mod);
......@@ -8892,6 +9138,8 @@ fn isNullPtr(self: *Self, inst: Air.Inst.Index, ptr_ty: Type, ptr_mcv: MCValue)
88929138 }),
88939139 Immediate.u(0),
88949140 );
9141
9142 self.eflags_inst = inst;
88959143 return .{ .eflags = .e };
88969144}
88979145
......@@ -8904,9 +9152,6 @@ fn isErr(self: *Self, maybe_inst: ?Air.Inst.Index, ty: Type, operand: MCValue) !
89049152 }
89059153
89069154 try self.spillEflagsIfOccupied();
8907 if (maybe_inst) |inst| {
8908 self.eflags_inst = inst;
8909 }
89109155
89119156 const err_off = errUnionErrorOffset(ty.errorUnionPayload(mod), mod);
89129157 switch (operand) {
......@@ -8944,6 +9189,7 @@ fn isErr(self: *Self, maybe_inst: ?Air.Inst.Index, ty: Type, operand: MCValue) !
89449189 else => return self.fail("TODO implement isErr for {}", .{operand}),
89459190 }
89469191
9192 if (maybe_inst) |inst| self.eflags_inst = inst;
89479193 return MCValue{ .eflags = .a };
89489194}
89499195
......@@ -9825,6 +10071,7 @@ fn genCopy(self: *Self, ty: Type, dst_mcv: MCValue, src_mcv: MCValue) InnerError
982510071 .lea_tlv,
982610072 .lea_frame,
982710073 .reserved_frame,
10074 .air_ref,
982810075 => unreachable, // unmodifiable destination
982910076 .register => |reg| try self.genSetReg(reg, ty, src_mcv),
983010077 .register_offset => |dst_reg_off| try self.genSetReg(dst_reg_off.reg, ty, switch (src_mcv) {
......@@ -10150,6 +10397,7 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr
1015010397 @tagName(self.bin_file.tag),
1015110398 });
1015210399 },
10400 .air_ref => |ref| try self.genSetReg(dst_reg, ty, try self.resolveInst(ref)),
1015310401 }
1015410402}
1015510403
......@@ -10262,6 +10510,7 @@ fn genSetMem(self: *Self, base: Memory.Base, disp: i32, ty: Type, src_mcv: MCVal
1026210510 },
1026310511 else => try self.genInlineMemcpy(dst_ptr_mcv, src_mcv.address(), .{ .immediate = abi_size }),
1026410512 },
10513 .air_ref => |ref| try self.genSetMem(base, disp, ty, try self.resolveInst(ref)),
1026510514 }
1026610515}
1026710516
......@@ -10281,6 +10530,51 @@ fn genInlineMemset(self: *Self, dst_ptr: MCValue, value: MCValue, len: MCValue)
1028110530 try self.asmOpOnly(.{ .@"rep _sb", .sto });
1028210531}
1028310532
10533fn genExternSymbolRef(
10534 self: *Self,
10535 comptime tag: Mir.Inst.Tag,
10536 lib: ?[]const u8,
10537 callee: []const u8,
10538) InnerError!void {
10539 const atom_index = try self.owner.getSymbolIndex(self);
10540 if (self.bin_file.cast(link.File.Elf)) |elf_file| {
10541 _ = try self.addInst(.{
10542 .tag = tag,
10543 .ops = .extern_fn_reloc,
10544 .data = .{ .reloc = .{
10545 .atom_index = atom_index,
10546 .sym_index = try elf_file.getGlobalSymbol(callee, lib),
10547 } },
10548 });
10549 } else if (self.bin_file.cast(link.File.Coff)) |coff_file| {
10550 _ = try self.addInst(.{
10551 .tag = .mov,
10552 .ops = .import_reloc,
10553 .data = .{ .rx = .{
10554 .r1 = .rax,
10555 .payload = try self.addExtra(Mir.Reloc{
10556 .atom_index = atom_index,
10557 .sym_index = try coff_file.getGlobalSymbol(callee, lib),
10558 }),
10559 } },
10560 });
10561 switch (tag) {
10562 .mov => {},
10563 .call => try self.asmRegister(.{ ._, .call }, .rax),
10564 else => unreachable,
10565 }
10566 } else if (self.bin_file.cast(link.File.MachO)) |macho_file| {
10567 _ = try self.addInst(.{
10568 .tag = .call,
10569 .ops = .extern_fn_reloc,
10570 .data = .{ .reloc = .{
10571 .atom_index = atom_index,
10572 .sym_index = try macho_file.getGlobalSymbol(callee, lib),
10573 } },
10574 });
10575 } else return self.fail("TODO implement calling extern functions", .{});
10576}
10577
1028410578fn genLazySymbolRef(
1028510579 self: *Self,
1028610580 comptime tag: Mir.Inst.Tag,
......@@ -10480,106 +10774,150 @@ fn airFloatFromInt(self: *Self, inst: Air.Inst.Index) !void {
1048010774 const mod = self.bin_file.options.module.?;
1048110775 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
1048210776
10777 const dst_ty = self.typeOfIndex(inst);
10778 const dst_bits = dst_ty.floatBits(self.target.*);
10779
1048310780 const src_ty = self.typeOf(ty_op.operand);
1048410781 const src_bits: u32 = @intCast(src_ty.bitSize(mod));
1048510782 const src_signedness =
1048610783 if (src_ty.isAbiInt(mod)) src_ty.intInfo(mod).signedness else .unsigned;
10487 const dst_ty = self.typeOfIndex(inst);
10488
1048910784 const src_size = math.divCeil(u32, @max(switch (src_signedness) {
1049010785 .signed => src_bits,
1049110786 .unsigned => src_bits + 1,
1049210787 }, 32), 8) catch unreachable;
10493 if (src_size > 8) return self.fail("TODO implement airFloatFromInt from {} to {}", .{
10494 src_ty.fmt(mod), dst_ty.fmt(mod),
10495 });
1049610788
10497 const src_mcv = try self.resolveInst(ty_op.operand);
10498 const src_reg = if (src_mcv.isRegister())
10499 src_mcv.getReg().?
10500 else
10501 try self.copyToTmpRegister(src_ty, src_mcv);
10502 const src_lock = self.register_manager.lockRegAssumeUnused(src_reg);
10503 defer self.register_manager.unlockReg(src_lock);
10789 const result = result: {
10790 if (switch (dst_bits) {
10791 16, 80, 128 => true,
10792 32, 64 => src_size > 8 and src_size < 16,
10793 else => unreachable,
10794 }) {
10795 var callee: ["__floatun?i?f".len]u8 = undefined;
10796 break :result try self.genCall(.{ .lib = .{
10797 .return_type = dst_ty.toIntern(),
10798 .param_types = &.{src_ty.toIntern()},
10799 .callee = std.fmt.bufPrint(&callee, "__float{s}{c}i{c}f", .{
10800 switch (src_signedness) {
10801 .signed => "",
10802 .unsigned => "un",
10803 },
10804 intCompilerRtAbiName(src_bits),
10805 floatCompilerRtAbiName(dst_bits),
10806 }) catch unreachable,
10807 } }, &.{src_ty}, &.{.{ .air_ref = ty_op.operand }});
10808 }
1050410809
10505 if (src_bits < src_size * 8) try self.truncateRegister(src_ty, src_reg);
10810 if (src_size > 8) return self.fail("TODO implement airFloatFromInt from {} to {}", .{
10811 src_ty.fmt(mod), dst_ty.fmt(mod),
10812 });
1050610813
10507 const dst_reg = try self.register_manager.allocReg(inst, regClassForType(dst_ty, mod));
10508 const dst_mcv = MCValue{ .register = dst_reg };
10509 const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg);
10510 defer self.register_manager.unlockReg(dst_lock);
10814 const src_mcv = try self.resolveInst(ty_op.operand);
10815 const src_reg = if (src_mcv.isRegister())
10816 src_mcv.getReg().?
10817 else
10818 try self.copyToTmpRegister(src_ty, src_mcv);
10819 const src_lock = self.register_manager.lockRegAssumeUnused(src_reg);
10820 defer self.register_manager.unlockReg(src_lock);
1051110821
10512 const mir_tag = @as(?Mir.Inst.FixedTag, switch (dst_ty.zigTypeTag(mod)) {
10513 .Float => switch (dst_ty.floatBits(self.target.*)) {
10514 32 => if (self.hasFeature(.avx)) .{ .v_ss, .cvtsi2 } else .{ ._ss, .cvtsi2 },
10515 64 => if (self.hasFeature(.avx)) .{ .v_sd, .cvtsi2 } else .{ ._sd, .cvtsi2 },
10516 16, 80, 128 => null,
10517 else => unreachable,
10518 },
10519 else => null,
10520 }) orelse return self.fail("TODO implement airFloatFromInt from {} to {}", .{
10521 src_ty.fmt(mod), dst_ty.fmt(mod),
10522 });
10523 const dst_alias = dst_reg.to128();
10524 const src_alias = registerAlias(src_reg, src_size);
10525 switch (mir_tag[0]) {
10526 .v_ss, .v_sd => try self.asmRegisterRegisterRegister(mir_tag, dst_alias, dst_alias, src_alias),
10527 else => try self.asmRegisterRegister(mir_tag, dst_alias, src_alias),
10528 }
10822 if (src_bits < src_size * 8) try self.truncateRegister(src_ty, src_reg);
1052910823
10530 return self.finishAir(inst, dst_mcv, .{ ty_op.operand, .none, .none });
10824 const dst_reg = try self.register_manager.allocReg(inst, regClassForType(dst_ty, mod));
10825 const dst_mcv = MCValue{ .register = dst_reg };
10826 const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg);
10827 defer self.register_manager.unlockReg(dst_lock);
10828
10829 const mir_tag = @as(?Mir.Inst.FixedTag, switch (dst_ty.zigTypeTag(mod)) {
10830 .Float => switch (dst_ty.floatBits(self.target.*)) {
10831 32 => if (self.hasFeature(.avx)) .{ .v_ss, .cvtsi2 } else .{ ._ss, .cvtsi2 },
10832 64 => if (self.hasFeature(.avx)) .{ .v_sd, .cvtsi2 } else .{ ._sd, .cvtsi2 },
10833 16, 80, 128 => null,
10834 else => unreachable,
10835 },
10836 else => null,
10837 }) orelse return self.fail("TODO implement airFloatFromInt from {} to {}", .{
10838 src_ty.fmt(mod), dst_ty.fmt(mod),
10839 });
10840 const dst_alias = dst_reg.to128();
10841 const src_alias = registerAlias(src_reg, src_size);
10842 switch (mir_tag[0]) {
10843 .v_ss, .v_sd => try self.asmRegisterRegisterRegister(mir_tag, dst_alias, dst_alias, src_alias),
10844 else => try self.asmRegisterRegister(mir_tag, dst_alias, src_alias),
10845 }
10846
10847 break :result dst_mcv;
10848 };
10849 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
1053110850}
1053210851
1053310852fn airIntFromFloat(self: *Self, inst: Air.Inst.Index) !void {
1053410853 const mod = self.bin_file.options.module.?;
1053510854 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
1053610855
10537 const src_ty = self.typeOf(ty_op.operand);
1053810856 const dst_ty = self.typeOfIndex(inst);
1053910857 const dst_bits: u32 = @intCast(dst_ty.bitSize(mod));
1054010858 const dst_signedness =
1054110859 if (dst_ty.isAbiInt(mod)) dst_ty.intInfo(mod).signedness else .unsigned;
10542
1054310860 const dst_size = math.divCeil(u32, @max(switch (dst_signedness) {
1054410861 .signed => dst_bits,
1054510862 .unsigned => dst_bits + 1,
1054610863 }, 32), 8) catch unreachable;
10547 if (dst_size > 8) return self.fail("TODO implement airIntFromFloat from {} to {}", .{
10548 src_ty.fmt(self.bin_file.options.module.?), dst_ty.fmt(self.bin_file.options.module.?),
10549 });
1055010864
10551 const src_mcv = try self.resolveInst(ty_op.operand);
10552 const src_reg = if (src_mcv.isRegister())
10553 src_mcv.getReg().?
10554 else
10555 try self.copyToTmpRegister(src_ty, src_mcv);
10556 const src_lock = self.register_manager.lockRegAssumeUnused(src_reg);
10557 defer self.register_manager.unlockReg(src_lock);
10865 const src_ty = self.typeOf(ty_op.operand);
10866 const src_bits = src_ty.floatBits(self.target.*);
1055810867
10559 const dst_reg = try self.register_manager.allocReg(inst, regClassForType(dst_ty, mod));
10560 const dst_mcv = MCValue{ .register = dst_reg };
10561 const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg);
10562 defer self.register_manager.unlockReg(dst_lock);
10868 const result = result: {
10869 if (switch (src_bits) {
10870 16, 80, 128 => true,
10871 32, 64 => dst_size > 8 and dst_size < 16,
10872 else => unreachable,
10873 }) {
10874 var callee: ["__fixuns?f?i".len]u8 = undefined;
10875 break :result try self.genCall(.{ .lib = .{
10876 .return_type = dst_ty.toIntern(),
10877 .param_types = &.{src_ty.toIntern()},
10878 .callee = std.fmt.bufPrint(&callee, "__fix{s}{c}f{c}i", .{
10879 switch (dst_signedness) {
10880 .signed => "",
10881 .unsigned => "uns",
10882 },
10883 floatCompilerRtAbiName(src_bits),
10884 intCompilerRtAbiName(dst_bits),
10885 }) catch unreachable,
10886 } }, &.{src_ty}, &.{.{ .air_ref = ty_op.operand }});
10887 }
1056310888
10564 try self.asmRegisterRegister(
10565 @as(?Mir.Inst.FixedTag, switch (src_ty.zigTypeTag(mod)) {
10566 .Float => switch (src_ty.floatBits(self.target.*)) {
10889 if (dst_size > 8) return self.fail("TODO implement airIntFromFloat from {} to {}", .{
10890 src_ty.fmt(mod), dst_ty.fmt(mod),
10891 });
10892
10893 const src_mcv = try self.resolveInst(ty_op.operand);
10894 const src_reg = if (src_mcv.isRegister())
10895 src_mcv.getReg().?
10896 else
10897 try self.copyToTmpRegister(src_ty, src_mcv);
10898 const src_lock = self.register_manager.lockRegAssumeUnused(src_reg);
10899 defer self.register_manager.unlockReg(src_lock);
10900
10901 const dst_reg = try self.register_manager.allocReg(inst, regClassForType(dst_ty, mod));
10902 const dst_mcv = MCValue{ .register = dst_reg };
10903 const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg);
10904 defer self.register_manager.unlockReg(dst_lock);
10905
10906 try self.asmRegisterRegister(
10907 switch (src_bits) {
1056710908 32 => if (self.hasFeature(.avx)) .{ .v_, .cvttss2si } else .{ ._, .cvttss2si },
1056810909 64 => if (self.hasFeature(.avx)) .{ .v_, .cvttsd2si } else .{ ._, .cvttsd2si },
10569 16, 80, 128 => null,
1057010910 else => unreachable,
1057110911 },
10572 else => null,
10573 }) orelse return self.fail("TODO implement airIntFromFloat from {} to {}", .{
10574 src_ty.fmt(self.bin_file.options.module.?), dst_ty.fmt(self.bin_file.options.module.?),
10575 }),
10576 registerAlias(dst_reg, dst_size),
10577 src_reg.to128(),
10578 );
10912 registerAlias(dst_reg, dst_size),
10913 src_reg.to128(),
10914 );
1057910915
10580 if (dst_bits < dst_size * 8) try self.truncateRegister(dst_ty, dst_reg);
10916 if (dst_bits < dst_size * 8) try self.truncateRegister(dst_ty, dst_reg);
1058110917
10582 return self.finishAir(inst, dst_mcv, .{ ty_op.operand, .none, .none });
10918 break :result dst_mcv;
10919 };
10920 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
1058310921}
1058410922
1058510923fn airCmpxchg(self: *Self, inst: Air.Inst.Index) !void {
......@@ -11906,7 +12244,7 @@ const CallMCValues = struct {
1190612244fn resolveCallingConventionValues(
1190712245 self: *Self,
1190812246 fn_info: InternPool.Key.FuncType,
11909 var_args: []const Air.Inst.Ref,
12247 var_args: []const Type,
1191012248 stack_frame_base: FrameIndex,
1191112249) !CallMCValues {
1191212250 const mod = self.bin_file.options.module.?;
......@@ -11919,9 +12257,7 @@ fn resolveCallingConventionValues(
1191912257 dest.* = src.toType();
1192012258 }
1192112259 // TODO: promote var arg types
11922 for (param_types[fn_info.param_types.len..], var_args) |*param_ty, arg| {
11923 param_ty.* = self.typeOf(arg);
11924 }
12260 for (param_types[fn_info.param_types.len..], var_args) |*param_ty, arg_ty| param_ty.* = arg_ty;
1192512261
1192612262 var result: CallMCValues = .{
1192712263 .args = try self.gpa.alloc(MCValue, param_types.len),
......@@ -12230,3 +12566,52 @@ fn typeOfIndex(self: *Self, inst: Air.Inst.Index) Type {
1223012566 const mod = self.bin_file.options.module.?;
1223112567 return self.air.typeOfIndex(inst, &mod.intern_pool);
1223212568}
12569
12570fn intCompilerRtAbiName(int_bits: u32) u8 {
12571 return switch (int_bits) {
12572 1...32 => 's',
12573 33...64 => 'd',
12574 65...128 => 't',
12575 else => unreachable,
12576 };
12577}
12578
12579fn floatCompilerRtAbiName(float_bits: u32) u8 {
12580 return switch (float_bits) {
12581 16 => 'h',
12582 32 => 's',
12583 64 => 'd',
12584 80 => 'x',
12585 128 => 't',
12586 else => unreachable,
12587 };
12588}
12589
12590fn floatCompilerRtAbiType(self: *Self, ty: Type, other_ty: Type) Type {
12591 if (ty.toIntern() == .f16_type and
12592 (other_ty.toIntern() == .f32_type or other_ty.toIntern() == .f64_type) and
12593 self.target.isDarwin()) return Type.u16;
12594 return ty;
12595}
12596
12597fn floatLibcAbiPrefix(ty: Type) []const u8 {
12598 return switch (ty.toIntern()) {
12599 .f16_type,
12600 .f80_type,
12601 => "__",
12602 .f32_type, .f64_type, .f128_type, .c_longdouble_type => "",
12603 else => unreachable,
12604 };
12605}
12606
12607fn floatLibcAbiSuffix(ty: Type) []const u8 {
12608 return switch (ty.toIntern()) {
12609 .f16_type => "h",
12610 .f32_type => "f",
12611 .f64_type => "",
12612 .f80_type => "x",
12613 .f128_type => "q",
12614 .c_longdouble_type => "l",
12615 else => unreachable,
12616 };
12617}
src/arch/x86_64/abi.zig+2-2
......@@ -444,7 +444,7 @@ pub const SysV = struct {
444444 /// These registers need to be preserved (saved on the stack) and restored by the caller before
445445 /// the caller relinquishes control to a subroutine via call instruction (or similar).
446446 /// In other words, these registers are free to use by the callee.
447 pub const caller_preserved_regs = [_]Register{ .rax, .rcx, .rdx, .rsi, .rdi, .r8, .r9, .r10, .r11 };
447 pub const caller_preserved_regs = [_]Register{ .rax, .rcx, .rdx, .rsi, .rdi, .r8, .r9, .r10, .r11 } ++ sse_avx_regs;
448448
449449 pub const c_abi_int_param_regs = [_]Register{ .rdi, .rsi, .rdx, .rcx, .r8, .r9 };
450450 pub const c_abi_int_return_regs = [_]Register{ .rax, .rdx };
......@@ -457,7 +457,7 @@ pub const Win64 = struct {
457457 /// These registers need to be preserved (saved on the stack) and restored by the caller before
458458 /// the caller relinquishes control to a subroutine via call instruction (or similar).
459459 /// In other words, these registers are free to use by the callee.
460 pub const caller_preserved_regs = [_]Register{ .rax, .rcx, .rdx, .r8, .r9, .r10, .r11 };
460 pub const caller_preserved_regs = [_]Register{ .rax, .rcx, .rdx, .r8, .r9, .r10, .r11 } ++ sse_avx_regs;
461461
462462 pub const c_abi_int_param_regs = [_]Register{ .rcx, .rdx, .r8, .r9 };
463463 pub const c_abi_int_return_regs = [_]Register{.rax};
src/codegen/llvm.zig-9
......@@ -6394,15 +6394,6 @@ pub const FuncGen = struct {
63946394 const fn_ty = try mod.funcType(.{
63956395 .param_types = &.{},
63966396 .return_type = .void_type,
6397 .alignment = .none,
6398 .noalias_bits = 0,
6399 .comptime_bits = 0,
6400 .cc = .Unspecified,
6401 .is_var_args = false,
6402 .is_generic = false,
6403 .is_noinline = false,
6404 .section_is_generic = false,
6405 .addrspace_is_generic = false,
64066397 });
64076398 const fn_di_ty = try o.lowerDebugType(fn_ty, .full);
64086399 const subprogram = dib.createFunction(
test/behavior/abs.zig+2-1
......@@ -86,9 +86,10 @@ test "@abs floats" {
8686 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
8787 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
8888 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
89 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest;
8990
9091 try comptime testAbsFloats(f16);
91 if (builtin.zig_backend != .stage2_x86_64) try testAbsFloats(f16);
92 try testAbsFloats(f16);
9293 try comptime testAbsFloats(f32);
9394 try testAbsFloats(f32);
9495 try comptime testAbsFloats(f64);
test/behavior/asm.zig-2
......@@ -85,7 +85,6 @@ test "alternative constraints" {
8585
8686test "sized integer/float in asm input" {
8787 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
88 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
8988 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
9089 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
9190 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
......@@ -137,7 +136,6 @@ test "sized integer/float in asm input" {
137136
138137test "struct/array/union types as input values" {
139138 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
140 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
141139 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
142140 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
143141 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
test/behavior/bitcast.zig-2
......@@ -470,7 +470,6 @@ test "@bitCast of packed struct of bools all true" {
470470 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
471471 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
472472 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
473 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
474473 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
475474 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
476475
......@@ -492,7 +491,6 @@ test "@bitCast of packed struct of bools all false" {
492491 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
493492 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
494493 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
495 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
496494 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
497495 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
498496
test/behavior/bugs/12680.zig+2-1
......@@ -9,9 +9,10 @@ test "export a function twice" {
99 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1010 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
1111 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
12 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
1312 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1413 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
14 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest;
15
1516 if (builtin.os.tag == .macos and builtin.zig_backend == .stage2_c) {
1617 // TODO: test.c: error: aliases are not supported on darwin
1718 return error.SkipZigTest;
test/behavior/bugs/529.zig+1-1
......@@ -11,11 +11,11 @@ comptime {
1111const builtin = @import("builtin");
1212
1313test "issue 529 fixed" {
14 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1514 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1615 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1716 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1817 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
18 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest;
1919
2020 @import("529_other_file.zig").issue529(null);
2121 issue529(null);
test/behavior/cast.zig-23
......@@ -1611,7 +1611,6 @@ test "coercion from single-item pointer to @as to slice" {
16111611test "peer type resolution: const sentinel slice and mutable non-sentinel slice" {
16121612 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
16131613 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1614 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
16151614 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
16161615 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
16171616 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
......@@ -1664,7 +1663,6 @@ test "peer type resolution: float and comptime-known fixed-width integer" {
16641663test "peer type resolution: same array type with sentinel" {
16651664 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
16661665 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1667 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
16681666 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
16691667 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
16701668 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
......@@ -1687,7 +1685,6 @@ test "peer type resolution: same array type with sentinel" {
16871685test "peer type resolution: array with sentinel and array without sentinel" {
16881686 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
16891687 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1690 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
16911688 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
16921689 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
16931690 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
......@@ -1710,7 +1707,6 @@ test "peer type resolution: array with sentinel and array without sentinel" {
17101707test "peer type resolution: array and vector with same child type" {
17111708 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
17121709 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1713 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
17141710 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
17151711 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
17161712 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
......@@ -1756,7 +1752,6 @@ test "peer type resolution: array with smaller child type and vector with larger
17561752test "peer type resolution: error union and optional of same type" {
17571753 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
17581754 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1759 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
17601755 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
17611756 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
17621757 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
......@@ -1780,7 +1775,6 @@ test "peer type resolution: error union and optional of same type" {
17801775test "peer type resolution: C pointer and @TypeOf(null)" {
17811776 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
17821777 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1783 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
17841778 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
17851779 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
17861780 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
......@@ -1803,7 +1797,6 @@ test "peer type resolution: C pointer and @TypeOf(null)" {
18031797test "peer type resolution: three-way resolution combines error set and optional" {
18041798 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
18051799 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1806 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
18071800 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
18081801 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
18091802 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
......@@ -1846,7 +1839,6 @@ test "peer type resolution: three-way resolution combines error set and optional
18461839test "peer type resolution: vector and optional vector" {
18471840 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
18481841 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1849 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
18501842 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
18511843 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
18521844 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
......@@ -1869,7 +1861,6 @@ test "peer type resolution: vector and optional vector" {
18691861test "peer type resolution: optional fixed-width int and comptime_int" {
18701862 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
18711863 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1872 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
18731864 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
18741865 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
18751866 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
......@@ -1892,7 +1883,6 @@ test "peer type resolution: optional fixed-width int and comptime_int" {
18921883test "peer type resolution: array and tuple" {
18931884 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
18941885 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1895 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
18961886 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
18971887 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
18981888 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
......@@ -1916,7 +1906,6 @@ test "peer type resolution: array and tuple" {
19161906test "peer type resolution: vector and tuple" {
19171907 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
19181908 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1919 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
19201909 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
19211910 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
19221911 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
......@@ -1940,7 +1929,6 @@ test "peer type resolution: vector and tuple" {
19401929test "peer type resolution: vector and array and tuple" {
19411930 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
19421931 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1943 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
19441932 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
19451933 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
19461934 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
......@@ -1983,7 +1971,6 @@ test "peer type resolution: vector and array and tuple" {
19831971test "peer type resolution: empty tuple pointer and slice" {
19841972 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
19851973 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1986 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
19871974 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
19881975 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
19891976 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
......@@ -2005,7 +1992,6 @@ test "peer type resolution: empty tuple pointer and slice" {
20051992test "peer type resolution: tuple pointer and slice" {
20061993 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
20071994 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2008 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
20091995 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
20101996 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
20111997 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
......@@ -2027,7 +2013,6 @@ test "peer type resolution: tuple pointer and slice" {
20272013test "peer type resolution: tuple pointer and optional slice" {
20282014 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
20292015 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2030 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
20312016 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
20322017 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
20332018 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
......@@ -2049,7 +2034,6 @@ test "peer type resolution: tuple pointer and optional slice" {
20492034test "peer type resolution: many compatible pointers" {
20502035 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
20512036 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2052 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
20532037 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
20542038 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
20552039 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
......@@ -2116,7 +2100,6 @@ test "peer type resolution: many compatible pointers" {
21162100test "peer type resolution: tuples with comptime fields" {
21172101 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
21182102 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2119 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
21202103 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
21212104 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
21222105 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
......@@ -2149,7 +2132,6 @@ test "peer type resolution: tuples with comptime fields" {
21492132test "peer type resolution: C pointer and many pointer" {
21502133 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
21512134 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2152 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
21532135 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
21542136 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
21552137 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
......@@ -2173,7 +2155,6 @@ test "peer type resolution: C pointer and many pointer" {
21732155test "peer type resolution: pointer attributes are combined correctly" {
21742156 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
21752157 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2176 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
21772158 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
21782159 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
21792160 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
......@@ -2218,7 +2199,6 @@ test "peer type resolution: pointer attributes are combined correctly" {
22182199test "cast builtins can wrap result in optional" {
22192200 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
22202201 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2221 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
22222202 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
22232203 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
22242204 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
......@@ -2258,7 +2238,6 @@ test "cast builtins can wrap result in optional" {
22582238test "cast builtins can wrap result in error union" {
22592239 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
22602240 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2261 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
22622241 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
22632242 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
22642243
......@@ -2298,7 +2277,6 @@ test "cast builtins can wrap result in error union" {
22982277test "cast builtins can wrap result in error union and optional" {
22992278 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
23002279 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2301 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
23022280 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
23032281 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
23042282 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
......@@ -2496,7 +2474,6 @@ test "@as does not corrupt values with incompatible representations" {
24962474
24972475test "result information is preserved through many nested structures" {
24982476 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
2499 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
25002477 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
25012478 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
25022479 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
test/behavior/defer.zig-1
......@@ -133,7 +133,6 @@ test "errdefer with payload" {
133133}
134134
135135test "reference to errdefer payload" {
136 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
137136 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
138137 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
139138 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
test/behavior/floatop.zig+907-703
......@@ -2,16 +2,8 @@ const std = @import("std");
22const builtin = @import("builtin");
33const expect = std.testing.expect;
44const math = std.math;
5const pi = std.math.pi;
6const e = std.math.e;
7const has_f80_rt = switch (builtin.cpu.arch) {
8 .x86_64, .x86 => true,
9 else => false,
10};
11const no_x86_64_hardware_f16_support = builtin.zig_backend == .stage2_x86_64 and
12 !std.Target.x86.featureSetHas(builtin.cpu.features, .f16c);
13
14const epsilon_16 = 0.001;
5
6const epsilon_16 = 0.002;
157const epsilon = 0.000001;
168
179fn epsForType(comptime T: type) T {
......@@ -21,44 +13,195 @@ fn epsForType(comptime T: type) T {
2113 };
2214}
2315
24test "floating point comparisons" {
16test "add f16" {
17 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest;
18
19 try testAdd(f16);
20 try comptime testAdd(f16);
21}
22
23test "add f32/f64" {
24 try testAdd(f32);
25 try comptime testAdd(f32);
26 try testAdd(f64);
27 try comptime testAdd(f64);
28}
29
30test "add f80/f128/c_longdouble" {
31 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
32
33 try testAdd(f80);
34 try comptime testAdd(f80);
35 try testAdd(f128);
36 try comptime testAdd(f128);
37 try testAdd(c_longdouble);
38 try comptime testAdd(c_longdouble);
39}
40
41fn testAdd(comptime T: type) !void {
42 var one_point_two_five: T = 1.25;
43 var two_point_seven_five: T = 2.75;
44 try expect(one_point_two_five + two_point_seven_five == 4);
45}
46
47test "sub f16" {
48 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest;
49
50 try testSub(f16);
51 try comptime testSub(f16);
52}
53
54test "sub f32/f64" {
55 try testSub(f32);
56 try comptime testSub(f32);
57 try testSub(f64);
58 try comptime testSub(f64);
59}
60
61test "sub f80/f128/c_longdouble" {
62 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
63
64 try testSub(f80);
65 try comptime testSub(f80);
66 try testSub(f128);
67 try comptime testSub(f128);
68 try testSub(c_longdouble);
69 try comptime testSub(c_longdouble);
70}
71
72fn testSub(comptime T: type) !void {
73 var one_point_two_five: T = 1.25;
74 var two_point_seven_five: T = 2.75;
75 try expect(one_point_two_five - two_point_seven_five == -1.5);
76}
77
78test "mul f16" {
79 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest;
80
81 try testMul(f16);
82 try comptime testMul(f16);
83}
84
85test "mul f32/f64" {
86 try testMul(f32);
87 try comptime testMul(f32);
88 try testMul(f64);
89 try comptime testMul(f64);
90}
91
92test "mul f80/f128/c_longdouble" {
93 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
94
95 try testMul(f80);
96 try comptime testMul(f80);
97 try testMul(f128);
98 try comptime testMul(f128);
99 try testMul(c_longdouble);
100 try comptime testMul(c_longdouble);
101}
102
103fn testMul(comptime T: type) !void {
104 var one_point_two_five: T = 1.25;
105 var two_point_seven_five: T = 2.75;
106 try expect(one_point_two_five * two_point_seven_five == 3.4375);
107}
108
109test "cmp f16" {
110 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
111 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
112 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest;
113
114 try testCmp(f16);
115 try comptime testCmp(f16);
116}
117
118test "cmp f32/f64" {
25119 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
120 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest;
26121
27 try testFloatComparisons();
28 try comptime testFloatComparisons();
122 try testCmp(f32);
123 try comptime testCmp(f32);
124 try testCmp(f64);
125 try comptime testCmp(f64);
29126}
30127
31fn testFloatComparisons() !void {
32 inline for ([_]type{ f16, f32, f64, f128 }) |ty| {
128test "cmp f128" {
129 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
130 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
131 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
132 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
133 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
134
135 try testCmp(f128);
136 try comptime testCmp(f128);
137}
138
139test "cmp f80/c_longdouble" {
140 if (true) return error.SkipZigTest;
141
142 try testCmp(f80);
143 try comptime testCmp(f80);
144 try testCmp(c_longdouble);
145 try comptime testCmp(c_longdouble);
146}
147
148fn testCmp(comptime T: type) !void {
149 {
33150 // No decimal part
34 {
35 const x: ty = 1.0;
36 try expect(x == 1);
37 try expect(x != 0);
38 try expect(x > 0);
39 try expect(x < 2);
40 try expect(x >= 1);
41 try expect(x <= 1);
42 }
151 var x: T = 1.0;
152 try expect(x == 1.0);
153 try expect(x != 0.0);
154 try expect(x > 0.0);
155 try expect(x < 2.0);
156 try expect(x >= 1.0);
157 try expect(x <= 1.0);
158 }
159 {
43160 // Non-zero decimal part
44 {
45 const x: ty = 1.5;
46 try expect(x != 1);
47 try expect(x != 2);
48 try expect(x > 1);
49 try expect(x < 2);
50 try expect(x >= 1);
51 try expect(x <= 2);
161 var x: T = 1.5;
162 try expect(x != 1.0);
163 try expect(x != 2.0);
164 try expect(x > 1.0);
165 try expect(x < 2.0);
166 try expect(x >= 1.0);
167 try expect(x <= 2.0);
168 }
169
170 @setEvalBranchQuota(2_000);
171 var edges = [_]T{
172 -math.inf(T),
173 -math.floatMax(T),
174 -math.floatMin(T),
175 -math.floatTrueMin(T),
176 -0.0,
177 math.nan(T),
178 0.0,
179 math.floatTrueMin(T),
180 math.floatMin(T),
181 math.floatMax(T),
182 math.inf(T),
183 };
184 for (edges, 0..) |rhs, rhs_i| {
185 for (edges, 0..) |lhs, lhs_i| {
186 const no_nan = lhs_i != 5 and rhs_i != 5;
187 const lhs_order = if (lhs_i < 5) lhs_i else lhs_i - 2;
188 const rhs_order = if (rhs_i < 5) rhs_i else rhs_i - 2;
189 try expect((lhs == rhs) == (no_nan and lhs_order == rhs_order));
190 try expect((lhs != rhs) == !(no_nan and lhs_order == rhs_order));
191 try expect((lhs < rhs) == (no_nan and lhs_order < rhs_order));
192 try expect((lhs > rhs) == (no_nan and lhs_order > rhs_order));
193 try expect((lhs <= rhs) == (no_nan and lhs_order <= rhs_order));
194 try expect((lhs >= rhs) == (no_nan and lhs_order >= rhs_order));
52195 }
53196 }
54197}
55198
56199test "different sized float comparisons" {
57 if (no_x86_64_hardware_f16_support) return error.SkipZigTest; // TODO
58200 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
59201 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
60202 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
61203 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
204 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest;
62205
63206 try testDifferentSizedFloatComparisons();
64207 try comptime testDifferentSizedFloatComparisons();
......@@ -70,27 +213,6 @@ fn testDifferentSizedFloatComparisons() !void {
70213 try expect(a < b);
71214}
72215
73test "f80 comparisons" {
74 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
75 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
76 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
77 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
78 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
79
80 try expect(compareF80(0.0, .eq, -0.0));
81 try expect(compareF80(0.0, .lte, -0.0));
82 try expect(compareF80(0.0, .gte, -0.0));
83 try expect(compareF80(1.0, .neq, -1.0));
84 try expect(compareF80(2.0, .lt, 4.0));
85 try expect(compareF80(2.0, .lte, 4.0));
86 try expect(compareF80(-2.0, .gt, -4.0));
87 try expect(compareF80(-2.0, .gte, -4.0));
88}
89
90fn compareF80(x: f80, op: math.CompareOperator, y: f80) bool {
91 return math.compare(x, op, y);
92}
93
94216// TODO This is waiting on library support for the Windows build (not sure why the other's don't need it)
95217//test "@nearbyint" {
96218// comptime testNearbyInt();
......@@ -119,42 +241,93 @@ test "negative f128 intFromFloat at compile-time" {
119241 try expect(@as(i64, -2) == b);
120242}
121243
122test "@sqrt" {
244test "@sqrt f16" {
123245 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
124246 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
125247 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
126248 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
249 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest;
127250
128 try comptime testSqrt();
129 try testSqrt();
251 try testSqrt(f16);
252 try comptime testSqrt(f16);
130253}
131254
132fn testSqrt() !void {
133 try expect(@sqrt(@as(f16, 4)) == 2);
134 try expect(@sqrt(@as(f32, 9)) == 3);
135 try expect(@sqrt(@as(f64, 25)) == 5);
136 try expect(math.approxEqAbs(f32, @sqrt(@as(f32, 1.1)), 1.0488088481701516, epsilon));
137 try expect(math.approxEqAbs(f32, @sqrt(@as(f32, 2.0)), 1.4142135623730950, epsilon));
255test "@sqrt f32/f64" {
256 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
257 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
258 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
259 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
260 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest;
138261
139 if (false) {
140 if (has_f80_rt) {
141 // TODO https://github.com/ziglang/zig/issues/10875
142 if (builtin.os.tag != .freebsd) {
143 var a: f80 = 25;
144 try expect(@sqrt(a) == 5);
145 }
146 }
147 {
148 const a: comptime_float = 25.0;
149 try expect(@sqrt(a) == 5.0);
150 }
151 // TODO test f128, and c_longdouble
152 // https://github.com/ziglang/zig/issues/4026
153 //{
154 // var a: f128 = 49;
155 //try expect(@sqrt(a) == 7);
156 //}
262 try testSqrt(f32);
263 try comptime testSqrt(f32);
264 try testSqrt(f64);
265 try comptime testSqrt(f64);
266}
267
268test "@sqrt f80/f128/c_longdouble" {
269 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
270 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
271 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
272 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
273 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
274
275 if (builtin.os.tag == .freebsd) {
276 // TODO https://github.com/ziglang/zig/issues/10875
277 return error.SkipZigTest;
157278 }
279
280 try testSqrt(f80);
281 try comptime testSqrt(f80);
282 try testSqrt(f128);
283 try comptime testSqrt(f128);
284 try testSqrt(c_longdouble);
285 try comptime testSqrt(c_longdouble);
286}
287
288fn testSqrt(comptime T: type) !void {
289 const eps = epsForType(T);
290 var four: T = 4.0;
291 try expect(@sqrt(four) == 2.0);
292 var nine: T = 9.0;
293 try expect(@sqrt(nine) == 3.0);
294 var twenty_five: T = 25.0;
295 try expect(@sqrt(twenty_five) == 5.0);
296 var sixty_four: T = 64.0;
297 try expect(@sqrt(sixty_four) == 8.0);
298 var one_point_one: T = 1.1;
299
300 try expect(math.approxEqAbs(T, @sqrt(one_point_one), 1.0488088481701516, eps));
301 var two: T = 2.0;
302 try expect(math.approxEqAbs(T, @sqrt(two), 1.4142135623730950, eps));
303 var three_point_six: T = 3.6;
304 try expect(math.approxEqAbs(T, @sqrt(three_point_six), 1.8973665961010276, eps));
305 var sixty_four_point_one: T = 64.1;
306 try expect(math.approxEqAbs(T, @sqrt(sixty_four_point_one), 8.00624756049923802, eps));
307 var twelve: T = 12.0;
308 try expect(math.approxEqAbs(T, @sqrt(twelve), 3.46410161513775459, eps));
309 var thirteen: T = 13.0;
310 try expect(math.approxEqAbs(T, @sqrt(thirteen), 3.60555127546398929, eps));
311 var fourteen: T = 14.0;
312 try expect(math.approxEqAbs(T, @sqrt(fourteen), 3.74165738677394139, eps));
313 var a: T = 7.539840;
314 try expect(math.approxEqAbs(T, @sqrt(a), 2.74587690911300684, eps));
315 var b: T = 19.230934;
316 try expect(math.approxEqAbs(T, @sqrt(b), 4.38530888307767894, eps));
317 var c: T = 8942.230469;
318 try expect(math.approxEqAbs(T, @sqrt(c), 94.5633674791671111, eps));
319
320 // special cases
321 var inf: T = math.inf(T);
322 try expect(math.isPositiveInf(@sqrt(inf)));
323 var zero: T = 0.0;
324 try expect(@sqrt(zero) == 0.0);
325 var neg_zero: T = -0.0;
326 try expect(@sqrt(neg_zero) == 0.0);
327 var neg_one: T = -1.0;
328 try expect(math.isNan(@sqrt(neg_one)));
329 var nan: T = math.nan(T);
330 try expect(math.isNan(@sqrt(nan)));
158331}
159332
160333test "@sqrt with vectors" {
......@@ -163,8 +336,8 @@ test "@sqrt with vectors" {
163336 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
164337 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
165338
166 try comptime testSqrtWithVectors();
167339 try testSqrtWithVectors();
340 try comptime testSqrtWithVectors();
168341}
169342
170343fn testSqrtWithVectors() !void {
......@@ -176,88 +349,64 @@ fn testSqrtWithVectors() !void {
176349 try expect(math.approxEqAbs(f32, @sqrt(@as(f32, 4.4)), result[3], epsilon));
177350}
178351
179test "more @sqrt f16 tests" {
180 if (no_x86_64_hardware_f16_support) return error.SkipZigTest; // TODO
352test "@sin f16" {
181353 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
182354 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
183355 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
184356 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
357 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest;
185358
186 // TODO these are not all passing at comptime
187 try expect(@sqrt(@as(f16, 0.0)) == 0.0);
188 try expect(math.approxEqAbs(f16, @sqrt(@as(f16, 2.0)), 1.414214, epsilon));
189 try expect(math.approxEqAbs(f16, @sqrt(@as(f16, 3.6)), 1.897367, epsilon));
190 try expect(@sqrt(@as(f16, 4.0)) == 2.0);
191 try expect(math.approxEqAbs(f16, @sqrt(@as(f16, 7.539840)), 2.745877, epsilon));
192 try expect(math.approxEqAbs(f16, @sqrt(@as(f16, 19.230934)), 4.385309, epsilon));
193 try expect(@sqrt(@as(f16, 64.0)) == 8.0);
194 try expect(math.approxEqAbs(f16, @sqrt(@as(f16, 64.1)), 8.006248, epsilon));
195 try expect(math.approxEqAbs(f16, @sqrt(@as(f16, 8942.230469)), 94.563370, epsilon));
196
197 // special cases
198 try expect(math.isPositiveInf(@sqrt(@as(f16, math.inf(f16)))));
199 try expect(@sqrt(@as(f16, 0.0)) == 0.0);
200 try expect(@sqrt(@as(f16, -0.0)) == -0.0);
201 try expect(math.isNan(@sqrt(@as(f16, -1.0))));
202 try expect(math.isNan(@sqrt(@as(f16, math.nan(f16)))));
359 try testSin(f16);
360 try comptime testSin(f16);
203361}
204362
205test "another, possibly redundant @sqrt test" {
363test "@sin f32/f64" {
206364 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
207365 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
208 if (no_x86_64_hardware_f16_support) return error.SkipZigTest; // TODO
366 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
209367 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
368 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest;
210369
211 try testSqrtLegacy(f64, 12.0);
212 try comptime testSqrtLegacy(f64, 12.0);
213 try testSqrtLegacy(f32, 13.0);
214 try comptime testSqrtLegacy(f32, 13.0);
215 try testSqrtLegacy(f16, 13.0);
216 try comptime testSqrtLegacy(f16, 13.0);
217
218 // TODO: make this pass
219 if (false) {
220 const x = 14.0;
221 const y = x * x;
222 const z = @sqrt(y);
223 try comptime expect(z == x);
224 }
225}
226
227fn testSqrtLegacy(comptime T: type, x: T) !void {
228 try expect(@sqrt(x * x) == x);
370 try testSin(f32);
371 comptime try testSin(f32);
372 try testSin(f64);
373 comptime try testSin(f64);
229374}
230375
231test "@sin" {
232 if (no_x86_64_hardware_f16_support) return error.SkipZigTest; // TODO
376test "@sin f80/f128/c_longdouble" {
233377 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
234378 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
235379 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
236380 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
381 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
237382
238 try comptime testSin();
239 try testSin();
383 try testSin(f80);
384 comptime try testSin(f80);
385 try testSin(f128);
386 comptime try testSin(f128);
387 try testSin(c_longdouble);
388 comptime try testSin(c_longdouble);
240389}
241390
242fn testSin() !void {
243 inline for ([_]type{ f16, f32, f64 }) |ty| {
244 const eps = epsForType(ty);
245 try expect(@sin(@as(ty, 0)) == 0);
246 try expect(math.approxEqAbs(ty, @sin(@as(ty, std.math.pi)), 0, eps));
247 try expect(math.approxEqAbs(ty, @sin(@as(ty, std.math.pi / 2.0)), 1, eps));
248 try expect(math.approxEqAbs(ty, @sin(@as(ty, std.math.pi / 4.0)), 0.7071067811865475, eps));
249 }
391fn testSin(comptime T: type) !void {
392 const eps = epsForType(T);
393 var zero: T = 0;
394 try expect(@sin(zero) == 0);
395 var pi: T = math.pi;
396 try expect(math.approxEqAbs(T, @sin(pi), 0, eps));
397 try expect(math.approxEqAbs(T, @sin(pi / 2.0), 1, eps));
398 try expect(math.approxEqAbs(T, @sin(pi / 4.0), 0.7071067811865475, eps));
250399}
251400
252401test "@sin with vectors" {
253402 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
254 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
255403 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
256404 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
257405 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
406 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
258407
259 try comptime testSinWithVectors();
260408 try testSinWithVectors();
409 try comptime testSinWithVectors();
261410}
262411
263412fn testSinWithVectors() !void {
......@@ -269,36 +418,64 @@ fn testSinWithVectors() !void {
269418 try expect(math.approxEqAbs(f32, @sin(@as(f32, 4.4)), result[3], epsilon));
270419}
271420
272test "@cos" {
273 if (no_x86_64_hardware_f16_support) return error.SkipZigTest; // TODO
421test "@cos f16" {
274422 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
275423 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
276424 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
277425 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
426 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest;
278427
279 try comptime testCos();
280 try testCos();
428 try testCos(f16);
429 try comptime testCos(f16);
281430}
282431
283fn testCos() !void {
284 inline for ([_]type{ f16, f32, f64 }) |ty| {
285 const eps = epsForType(ty);
286 try expect(@cos(@as(ty, 0)) == 1);
287 try expect(math.approxEqAbs(ty, @cos(@as(ty, std.math.pi)), -1, eps));
288 try expect(math.approxEqAbs(ty, @cos(@as(ty, std.math.pi / 2.0)), 0, eps));
289 try expect(math.approxEqAbs(ty, @cos(@as(ty, std.math.pi / 4.0)), 0.7071067811865475, eps));
290 }
432test "@cos f32/f64" {
433 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
434 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
435 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
436 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
437 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest;
438
439 try testCos(f32);
440 try comptime testCos(f32);
441 try testCos(f64);
442 try comptime testCos(f64);
443}
444
445test "@cos f80/f128/c_longdouble" {
446 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
447 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
448 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
449 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
450 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
451
452 try testCos(f80);
453 try comptime testCos(f80);
454 try testCos(f128);
455 try comptime testCos(f128);
456 try testCos(c_longdouble);
457 try comptime testCos(c_longdouble);
458}
459
460fn testCos(comptime T: type) !void {
461 const eps = epsForType(T);
462 var zero: T = 0;
463 try expect(@cos(zero) == 1);
464 var pi: T = math.pi;
465 try expect(math.approxEqAbs(T, @cos(pi), -1, eps));
466 try expect(math.approxEqAbs(T, @cos(pi / 2.0), 0, eps));
467 try expect(math.approxEqAbs(T, @cos(pi / 4.0), 0.7071067811865475, eps));
291468}
292469
293470test "@cos with vectors" {
294471 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
295 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
296472 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
297473 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
298474 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
475 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
299476
300 try comptime testCosWithVectors();
301477 try testCosWithVectors();
478 try comptime testCosWithVectors();
302479}
303480
304481fn testCosWithVectors() !void {
......@@ -310,35 +487,133 @@ fn testCosWithVectors() !void {
310487 try expect(math.approxEqAbs(f32, @cos(@as(f32, 4.4)), result[3], epsilon));
311488}
312489
313test "@exp" {
314 if (no_x86_64_hardware_f16_support) return error.SkipZigTest; // TODO
490test "@tan f16" {
315491 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
316492 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
317493 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
318494 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
495 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest;
319496
320 try comptime testExp();
321 try testExp();
497 try testTan(f16);
498 try comptime testTan(f16);
322499}
323500
324fn testExp() !void {
325 inline for ([_]type{ f16, f32, f64 }) |ty| {
326 const eps = epsForType(ty);
327 try expect(@exp(@as(ty, 0)) == 1);
328 try expect(math.approxEqAbs(ty, @exp(@as(ty, 2)), 7.389056098930650, eps));
329 try expect(math.approxEqAbs(ty, @exp(@as(ty, 5)), 148.4131591025766, eps));
330 }
501test "@tan f32/f64" {
502 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
503 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
504 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
505 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
506 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest;
507
508 try testTan(f32);
509 try comptime testTan(f32);
510 try testTan(f64);
511 try comptime testTan(f64);
512}
513
514test "@tan f80/f128/c_longdouble" {
515 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
516 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
517 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
518 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
519 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
520
521 try testTan(f80);
522 try comptime testTan(f80);
523 try testTan(f128);
524 try comptime testTan(f128);
525 try testTan(c_longdouble);
526 try comptime testTan(c_longdouble);
527}
528
529fn testTan(comptime T: type) !void {
530 const eps = epsForType(T);
531 var zero: T = 0;
532 try expect(@tan(zero) == 0);
533 var pi: T = math.pi;
534 try expect(math.approxEqAbs(T, @tan(pi), 0, eps));
535 try expect(math.approxEqAbs(T, @tan(pi / 3.0), 1.732050807568878, eps));
536 try expect(math.approxEqAbs(T, @tan(pi / 4.0), 1, eps));
537}
538
539test "@tan with vectors" {
540 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
541 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
542 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
543 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
544 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
545
546 try testTanWithVectors();
547 try comptime testTanWithVectors();
548}
549
550fn testTanWithVectors() !void {
551 var v: @Vector(4, f32) = [_]f32{ 1.1, 2.2, 3.3, 4.4 };
552 var result = @tan(v);
553 try expect(math.approxEqAbs(f32, @tan(@as(f32, 1.1)), result[0], epsilon));
554 try expect(math.approxEqAbs(f32, @tan(@as(f32, 2.2)), result[1], epsilon));
555 try expect(math.approxEqAbs(f32, @tan(@as(f32, 3.3)), result[2], epsilon));
556 try expect(math.approxEqAbs(f32, @tan(@as(f32, 4.4)), result[3], epsilon));
557}
558
559test "@exp f16" {
560 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
561 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
562 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
563 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
564 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest;
565
566 try testExp(f16);
567 try comptime testExp(f16);
568}
569
570test "@exp f32/f64" {
571 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
572 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
573 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
574 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
575 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest;
576
577 try testExp(f32);
578 try comptime testExp(f32);
579 try testExp(f64);
580 try comptime testExp(f64);
581}
582
583test "@exp f80/f128/c_longdouble" {
584 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
585 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
586 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
587 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
588 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
589
590 try testExp(f80);
591 try comptime testExp(f80);
592 try testExp(f128);
593 try comptime testExp(f128);
594 try testExp(c_longdouble);
595 try comptime testExp(c_longdouble);
596}
597
598fn testExp(comptime T: type) !void {
599 const eps = epsForType(T);
600 var zero: T = 0;
601 try expect(@exp(zero) == 1);
602 var two: T = 2;
603 try expect(math.approxEqAbs(T, @exp(two), 7.389056098930650, eps));
604 var five: T = 5;
605 try expect(math.approxEqAbs(T, @exp(five), 148.4131591025766, eps));
331606}
332607
333608test "@exp with vectors" {
334609 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
335 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
336610 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
337611 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
338612 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
613 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
339614
340 try comptime testExpWithVectors();
341615 try testExpWithVectors();
616 try comptime testExpWithVectors();
342617}
343618
344619fn testExpWithVectors() !void {
......@@ -350,35 +625,64 @@ fn testExpWithVectors() !void {
350625 try expect(math.approxEqAbs(f32, @exp(@as(f32, 0.4)), result[3], epsilon));
351626}
352627
353test "@exp2" {
354 if (no_x86_64_hardware_f16_support) return error.SkipZigTest; // TODO
628test "@exp2 f16" {
355629 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
356630 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
357631 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
358632 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
633 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest;
359634
360 try comptime testExp2();
361 try testExp2();
635 try testExp2(f16);
636 try comptime testExp2(f16);
362637}
363638
364fn testExp2() !void {
365 inline for ([_]type{ f16, f32, f64 }) |ty| {
366 const eps = epsForType(ty);
367 try expect(@exp2(@as(ty, 2)) == 4);
368 try expect(math.approxEqAbs(ty, @exp2(@as(ty, 1.5)), 2.8284271247462, eps));
369 try expect(math.approxEqAbs(ty, @exp2(@as(ty, 4.5)), 22.627416997969, eps));
370 }
639test "@exp2 f32/f64" {
640 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
641 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
642 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
643 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
644 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest;
645
646 try testExp2(f32);
647 try comptime testExp2(f32);
648 try testExp2(f64);
649 try comptime testExp2(f64);
650}
651
652test "@exp2 f80/f128/c_longdouble" {
653 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
654 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
655 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
656 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
657 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
658
659 try testExp2(f80);
660 try comptime testExp2(f80);
661 try testExp2(f128);
662 try comptime testExp2(f128);
663 try testExp2(c_longdouble);
664 try comptime testExp2(c_longdouble);
665}
666
667fn testExp2(comptime T: type) !void {
668 const eps = epsForType(T);
669 var two: T = 2;
670 try expect(@exp2(two) == 4);
671 var one_point_five: T = 1.5;
672 try expect(math.approxEqAbs(T, @exp2(one_point_five), 2.8284271247462, eps));
673 var four_point_five: T = 4.5;
674 try expect(math.approxEqAbs(T, @exp2(four_point_five), 22.627416997969, eps));
371675}
372676
373677test "@exp2 with @vectors" {
374678 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
375 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
376679 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
377680 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
378681 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
682 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
379683
380 try comptime testExp2WithVectors();
381684 try testExp2WithVectors();
685 try comptime testExp2WithVectors();
382686}
383687
384688fn testExp2WithVectors() !void {
......@@ -390,44 +694,62 @@ fn testExp2WithVectors() !void {
390694 try expect(math.approxEqAbs(f32, @exp2(@as(f32, 0.4)), result[3], epsilon));
391695}
392696
393test "@log" {
394 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
697test "@log f16" {
395698 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
396699 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
397700 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
398701 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
702 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest;
399703
400 try comptime testLog();
401 try testLog();
704 try testLog(f16);
705 try comptime testLog(f16);
402706}
403707
404fn testLog() !void {
405 {
406 var a: f16 = e;
407 try expect(math.approxEqAbs(f16, @log(a), 1, epsilon));
408 }
409 {
410 var a: f32 = e;
411 try expect(@log(a) == 1 or @log(a) == @as(f32, @bitCast(@as(u32, 0x3f7fffff))));
412 }
413 {
414 var a: f64 = e;
415 try expect(@log(a) == 1 or @log(a) == @as(f64, @bitCast(@as(u64, 0x3ff0000000000000))));
416 }
417 inline for ([_]type{ f16, f32, f64 }) |ty| {
418 const eps = epsForType(ty);
419 try expect(math.approxEqAbs(ty, @log(@as(ty, 2)), 0.6931471805599, eps));
420 try expect(math.approxEqAbs(ty, @log(@as(ty, 5)), 1.6094379124341, eps));
421 }
708test "@log f32/f64" {
709 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
710 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
711 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
712 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
713 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest;
714
715 try testLog(f32);
716 try comptime testLog(f32);
717 try testLog(f64);
718 try comptime testLog(f64);
719}
720
721test "@log f80/f128/c_longdouble" {
722 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
723 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
724 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
725 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
726 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
727
728 try testLog(f80);
729 try comptime testLog(f80);
730 try testLog(f128);
731 try comptime testLog(f128);
732 try testLog(c_longdouble);
733 try comptime testLog(c_longdouble);
734}
735
736fn testLog(comptime T: type) !void {
737 const eps = epsForType(T);
738 var e: T = math.e;
739 try expect(math.approxEqAbs(T, @log(e), 1, eps));
740 var two: T = 2;
741 try expect(math.approxEqAbs(T, @log(two), 0.6931471805599, eps));
742 var five: T = 5;
743 try expect(math.approxEqAbs(T, @log(five), 1.6094379124341, eps));
422744}
423745
424746test "@log with @vectors" {
425747 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
426 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
427748 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
428749 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
429750 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
430751 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
752 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
431753
432754 {
433755 var v: @Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 };
......@@ -439,29 +761,57 @@ test "@log with @vectors" {
439761 }
440762}
441763
442test "@log2" {
443 if (no_x86_64_hardware_f16_support) return error.SkipZigTest; // TODO
764test "@log2 f16" {
444765 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
445766 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
446767 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
447768 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
769 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest;
448770
449 try comptime testLog2();
450 try testLog2();
771 try testLog2(f16);
772 try comptime testLog2(f16);
451773}
452774
453fn testLog2() !void {
454 inline for ([_]type{ f16, f32, f64 }) |ty| {
455 const eps = epsForType(ty);
456 try expect(@log2(@as(ty, 4)) == 2);
457 try expect(math.approxEqAbs(ty, @log2(@as(ty, 6)), 2.5849625007212, eps));
458 try expect(math.approxEqAbs(ty, @log2(@as(ty, 10)), 3.3219280948874, eps));
459 }
775test "@log2 f32/f64" {
776 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
777 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
778 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
779 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
780 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest;
781
782 try testLog2(f32);
783 try comptime testLog2(f32);
784 try testLog2(f64);
785 try comptime testLog2(f64);
786}
787
788test "@log2 f80/f128/c_longdouble" {
789 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
790 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
791 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
792 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
793 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
794
795 try testLog2(f80);
796 try comptime testLog2(f80);
797 try testLog2(f128);
798 try comptime testLog2(f128);
799 try testLog2(c_longdouble);
800 try comptime testLog2(c_longdouble);
801}
802
803fn testLog2(comptime T: type) !void {
804 const eps = epsForType(T);
805 var four: T = 4;
806 try expect(@log2(four) == 2);
807 var six: T = 6;
808 try expect(math.approxEqAbs(T, @log2(six), 2.5849625007212, eps));
809 var ten: T = 10;
810 try expect(math.approxEqAbs(T, @log2(ten), 3.3219280948874, eps));
460811}
461812
462813test "@log2 with vectors" {
463814 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
464 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
465815 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
466816 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
467817 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
......@@ -469,9 +819,10 @@ test "@log2 with vectors" {
469819 if (builtin.zig_backend == .stage2_llvm and
470820 builtin.cpu.arch == .aarch64 and
471821 builtin.os.tag == .windows) return error.SkipZigTest;
822 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
472823
473 try comptime testLog2WithVectors();
474824 try testLog2WithVectors();
825 try comptime testLog2WithVectors();
475826}
476827
477828fn testLog2WithVectors() !void {
......@@ -483,35 +834,64 @@ fn testLog2WithVectors() !void {
483834 try expect(@log2(@as(f32, 0.4)) == result[3]);
484835}
485836
486test "@log10" {
487 if (no_x86_64_hardware_f16_support) return error.SkipZigTest; // TODO
837test "@log10 f16" {
488838 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
489839 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
490840 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
491841 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
842 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest;
492843
493 try comptime testLog10();
494 try testLog10();
844 try testLog10(f16);
845 try comptime testLog10(f16);
495846}
496847
497fn testLog10() !void {
498 inline for ([_]type{ f16, f32, f64 }) |ty| {
499 const eps = epsForType(ty);
500 try expect(@log10(@as(ty, 100)) == 2);
501 try expect(math.approxEqAbs(ty, @log10(@as(ty, 15)), 1.176091259056, eps));
502 try expect(math.approxEqAbs(ty, @log10(@as(ty, 50)), 1.698970004336, eps));
503 }
848test "@log10 f32/f64" {
849 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
850 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
851 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
852 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
853 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest;
854
855 try testLog10(f32);
856 try comptime testLog10(f32);
857 try testLog10(f64);
858 try comptime testLog10(f64);
859}
860
861test "@log10 f80/f128/c_longdouble" {
862 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
863 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
864 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
865 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
866 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
867
868 try testLog10(f80);
869 try comptime testLog10(f80);
870 try testLog10(f128);
871 try comptime testLog10(f128);
872 try testLog10(c_longdouble);
873 try comptime testLog10(c_longdouble);
874}
875
876fn testLog10(comptime T: type) !void {
877 const eps = epsForType(T);
878 var hundred: T = 100;
879 try expect(@log10(hundred) == 2);
880 var fifteen: T = 15;
881 try expect(math.approxEqAbs(T, @log10(fifteen), 1.176091259056, eps));
882 var fifty: T = 50;
883 try expect(math.approxEqAbs(T, @log10(fifty), 1.698970004336, eps));
504884}
505885
506886test "@log10 with vectors" {
507887 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
508 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
509888 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
510889 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
511890 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
891 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
512892
513 try comptime testLog10WithVectors();
514893 try testLog10WithVectors();
894 try comptime testLog10WithVectors();
515895}
516896
517897fn testLog10WithVectors() !void {
......@@ -523,41 +903,94 @@ fn testLog10WithVectors() !void {
523903 try expect(@log10(@as(f32, 0.4)) == result[3]);
524904}
525905
526test "@abs" {
906test "@abs f16" {
527907 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
528908 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
529909 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
910 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest;
530911
531 try comptime testFabs();
532 try testFabs();
912 try testFabs(f16);
913 try comptime testFabs(f16);
533914}
534915
535fn testFabs() !void {
536 try expect(@abs(@as(f16, -2.5)) == 2.5);
537 try expect(@abs(@as(f16, 2.5)) == 2.5);
538 try expect(@abs(@as(f32, -2.5)) == 2.5);
539 try expect(@abs(@as(f32, 2.5)) == 2.5);
540 try expect(@abs(@as(f64, -2.5)) == 2.5);
541 try expect(@abs(@as(f64, 2.5)) == 2.5);
916test "@abs f32/f64" {
917 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
918 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
919 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
542920
543 // TODO test f128, and c_longdouble
544 // https://github.com/ziglang/zig/issues/4026
545 // {
546 // var a: f80 = -2.5;
547 // var b: f80 = 2.5;
548 // try expect(@abs(a) == 2.5);
549 // try expect(@abs(b) == 2.5);
550 // }
921 try testFabs(f32);
922 try comptime testFabs(f32);
923 try testFabs(f64);
924 try comptime testFabs(f64);
551925}
552926
553test "@abs with vectors" {
554 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
927test "@abs f80/f128/c_longdouble" {
555928 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
556929 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
930 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
931 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
932 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
933
934 try testFabs(f80);
935 try comptime testFabs(f80);
936 try testFabs(f128);
937 try comptime testFabs(f128);
938 try testFabs(c_longdouble);
939 try comptime testFabs(c_longdouble);
940}
941
942fn testFabs(comptime T: type) !void {
943 var two_point_five: T = 2.5;
944 try expect(@abs(two_point_five) == 2.5);
945 var neg_two_point_five: T = -2.5;
946 try expect(@abs(neg_two_point_five) == 2.5);
947
948 var twelve: T = 12.0;
949 try expect(@abs(twelve) == 12.0);
950 var neg_fourteen: T = -14.0;
951 try expect(@abs(neg_fourteen) == 14.0);
952
953 // normals
954 var one: T = 1.0;
955 try expect(@abs(one) == 1.0);
956 var neg_one: T = -1.0;
957 try expect(@abs(neg_one) == 1.0);
958 var min: T = math.floatMin(T);
959 try expect(@abs(min) == math.floatMin(T));
960 var neg_min: T = -math.floatMin(T);
961 try expect(@abs(neg_min) == math.floatMin(T));
962 var max: T = math.floatMax(T);
963 try expect(@abs(max) == math.floatMax(T));
964 var neg_max: T = -math.floatMax(T);
965 try expect(@abs(neg_max) == math.floatMax(T));
966
967 // subnormals
968 var zero: T = 0.0;
969 try expect(@abs(zero) == 0.0);
970 var neg_zero: T = -0.0;
971 try expect(@abs(neg_zero) == 0.0);
972 var true_min: T = math.floatTrueMin(T);
973 try expect(@abs(true_min) == math.floatTrueMin(T));
974 var neg_true_min: T = -math.floatTrueMin(T);
975 try expect(@abs(neg_true_min) == math.floatTrueMin(T));
976
977 // non-finite numbers
978 var inf: T = math.inf(T);
979 try expect(math.isPositiveInf(@abs(inf)));
980 var neg_inf: T = -math.inf(T);
981 try expect(math.isPositiveInf(@abs(neg_inf)));
982 var nan: T = math.nan(T);
983 try expect(math.isNan(@abs(nan)));
984}
985
986test "@abs with vectors" {
987 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
988 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
557989 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
990 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
558991
559 try comptime testFabsWithVectors();
560992 try testFabsWithVectors();
993 try comptime testFabsWithVectors();
561994}
562995
563996fn testFabsWithVectors() !void {
......@@ -569,109 +1002,77 @@ fn testFabsWithVectors() !void {
5691002 try expect(math.approxEqAbs(f32, @abs(@as(f32, -0.4)), result[3], epsilon));
5701003}
5711004
572test "another, possibly redundant, @abs test" {
573 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
574 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1005test "@floor f16" {
5751006 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
576 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
577 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
578 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
579
580 try testFabsLegacy(f128, 12.0);
581 try comptime testFabsLegacy(f128, 12.0);
582 try testFabsLegacy(f64, 12.0);
583 try comptime testFabsLegacy(f64, 12.0);
584 try testFabsLegacy(f32, 12.0);
585 try comptime testFabsLegacy(f32, 12.0);
586 try testFabsLegacy(f16, 12.0);
587 try comptime testFabsLegacy(f16, 12.0);
1007 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1008 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1009 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest;
5881010
589 const x = 14.0;
590 const y = -x;
591 const z = @abs(y);
592 try comptime std.testing.expectEqual(x, z);
1011 try testFloor(f16);
1012 try comptime testFloor(f16);
5931013}
5941014
595test "@abs f80" {
596 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
597 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1015test "@floor f32/f64" {
5981016 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
599 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
600 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
601 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
602
603 try testFabsLegacy(f80, 12.0);
604 try comptime testFabsLegacy(f80, 12.0);
605}
1017 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1018 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1019 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest;
6061020
607fn testFabsLegacy(comptime T: type, x: T) !void {
608 const y = -x;
609 const z = @abs(y);
610 try expect(x == z);
1021 try testFloor(f32);
1022 try comptime testFloor(f32);
1023 try testFloor(f64);
1024 try comptime testFloor(f64);
6111025}
6121026
613test "a third @abs test, surely there should not be three fabs tests" {
614 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
615 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1027test "@floor f80/f128/c_longdouble" {
6161028 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
617 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
618 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
619 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
620
621 inline for ([_]type{ f16, f32, f64, f80, f128, c_longdouble }) |T| {
622 // normals
623 try expect(@abs(@as(T, 1.0)) == 1.0);
624 try expect(@abs(@as(T, -1.0)) == 1.0);
625 try expect(@abs(math.floatMin(T)) == math.floatMin(T));
626 try expect(@abs(-math.floatMin(T)) == math.floatMin(T));
627 try expect(@abs(math.floatMax(T)) == math.floatMax(T));
628 try expect(@abs(-math.floatMax(T)) == math.floatMax(T));
629
630 // subnormals
631 try expect(@abs(@as(T, 0.0)) == 0.0);
632 try expect(@abs(@as(T, -0.0)) == 0.0);
633 try expect(@abs(math.floatTrueMin(T)) == math.floatTrueMin(T));
634 try expect(@abs(-math.floatTrueMin(T)) == math.floatTrueMin(T));
635
636 // non-finite numbers
637 try expect(math.isPositiveInf(@abs(math.inf(T))));
638 try expect(math.isPositiveInf(@abs(-math.inf(T))));
639 try expect(math.isNan(@abs(math.nan(T))));
640 }
641}
642
643test "@floor" {
6441029 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
645 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1030 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
6461031 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1032 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
6471033
648 try comptime testFloor();
649 try testFloor();
650}
651
652fn testFloor() !void {
653 try expect(@floor(@as(f16, 2.1)) == 2);
654 try expect(@floor(@as(f32, 2.1)) == 2);
655 try expect(@floor(@as(f64, 3.5)) == 3);
1034 if (builtin.zig_backend == .stage2_llvm and builtin.os.tag == .windows) {
1035 // https://github.com/ziglang/zig/issues/12602
1036 return error.SkipZigTest;
1037 }
6561038
657 // TODO test f128, and c_longdouble
658 // https://github.com/ziglang/zig/issues/4026
659 // {
660 // var a: f80 = 3.5;
661 // try expect(@floor(a) == 3);
662 // }
1039 try testFloor(f80);
1040 try comptime testFloor(f80);
1041 try testFloor(f128);
1042 try comptime testFloor(f128);
1043 try testFloor(c_longdouble);
1044 try comptime testFloor(c_longdouble);
1045}
1046
1047fn testFloor(comptime T: type) !void {
1048 var two_point_one: T = 2.1;
1049 try expect(@floor(two_point_one) == 2.0);
1050 var neg_two_point_one: T = -2.1;
1051 try expect(@floor(neg_two_point_one) == -3.0);
1052 var three_point_five: T = 3.5;
1053 try expect(@floor(three_point_five) == 3.0);
1054 var neg_three_point_five: T = -3.5;
1055 try expect(@floor(neg_three_point_five) == -4.0);
1056 var twelve: T = 12.0;
1057 try expect(@floor(twelve) == 12.0);
1058 var neg_twelve: T = -12.0;
1059 try expect(@floor(neg_twelve) == -12.0);
1060 var fourteen_point_seven: T = 14.7;
1061 try expect(@floor(fourteen_point_seven) == 14.0);
1062 var neg_fourteen_point_seven: T = -14.7;
1063 try expect(@floor(neg_fourteen_point_seven) == -15.0);
6631064}
6641065
6651066test "@floor with vectors" {
666 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
667 if (builtin.zig_backend == .stage2_x86_64 and
668 !comptime std.Target.x86.featureSetHas(builtin.cpu.features, .sse4_1)) return error.SkipZigTest; // TODO
669 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
6701067 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1068 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
6711069 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1070 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1071 if (builtin.zig_backend == .stage2_x86_64 and
1072 !comptime std.Target.x86.featureSetHas(builtin.cpu.features, .sse4_1)) return error.SkipZigTest;
6721073
673 try comptime testFloorWithVectors();
6741074 try testFloorWithVectors();
1075 try comptime testFloorWithVectors();
6751076}
6761077
6771078fn testFloorWithVectors() !void {
......@@ -683,90 +1084,77 @@ fn testFloorWithVectors() !void {
6831084 try expect(math.approxEqAbs(f32, @floor(@as(f32, -0.4)), result[3], epsilon));
6841085}
6851086
686test "another, possibly redundant, @floor test" {
687 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1087test "@ceil f16" {
6881088 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
689 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
690 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
691
692 try testFloorLegacy(f64, 12.0);
693 try comptime testFloorLegacy(f64, 12.0);
694 try testFloorLegacy(f32, 12.0);
695 try comptime testFloorLegacy(f32, 12.0);
696 try testFloorLegacy(f16, 12.0);
697 try comptime testFloorLegacy(f16, 12.0);
698
699 const x = 14.0;
700 const y = x + 0.7;
701 const z = @floor(y);
702 try comptime expect(x == z);
703}
704
705test "@floor f80" {
7061089 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
707 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
708 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
709 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
710 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
711
712 if (builtin.zig_backend == .stage2_llvm and builtin.os.tag == .windows) {
713 // https://github.com/ziglang/zig/issues/12602
714 return error.SkipZigTest;
715 }
1090 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1091 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest;
7161092
717 try testFloorLegacy(f80, 12.0);
718 try comptime testFloorLegacy(f80, 12.0);
1093 try testCeil(f16);
1094 try comptime testCeil(f16);
7191095}
7201096
721test "@floor f128" {
722 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1097test "@ceil f32/f64" {
7231098 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
724 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
725 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
726 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
727
728 try testFloorLegacy(f128, 12.0);
729 try comptime testFloorLegacy(f128, 12.0);
730}
1099 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1100 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1101 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest;
7311102
732fn testFloorLegacy(comptime T: type, x: T) !void {
733 const y = x + 0.6;
734 const z = @floor(y);
735 try expect(x == z);
1103 try testCeil(f32);
1104 try comptime testCeil(f32);
1105 try testCeil(f64);
1106 try comptime testCeil(f64);
7361107}
7371108
738test "@ceil" {
739 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1109test "@ceil f80/f128/c_longdouble" {
7401110 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1111 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1112 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
7411113 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1114 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
7421115
743 try comptime testCeil();
744 try testCeil();
745}
746
747fn testCeil() !void {
748 try expect(@ceil(@as(f16, 2.1)) == 3);
749 try expect(@ceil(@as(f32, 2.1)) == 3);
750 try expect(@ceil(@as(f64, 3.5)) == 4);
1116 if (builtin.zig_backend == .stage2_llvm and builtin.os.tag == .windows) {
1117 // https://github.com/ziglang/zig/issues/12602
1118 return error.SkipZigTest;
1119 }
7511120
752 // TODO test f128, and c_longdouble
753 // https://github.com/ziglang/zig/issues/4026
754 // {
755 // var a: f80 = 3.5;
756 // try expect(@ceil(a) == 4);
757 // }
1121 try testCeil(f80);
1122 try comptime testCeil(f80);
1123 try testCeil(f128);
1124 try comptime testCeil(f128);
1125 try testCeil(c_longdouble);
1126 try comptime testCeil(c_longdouble);
1127}
1128
1129fn testCeil(comptime T: type) !void {
1130 var two_point_one: T = 2.1;
1131 try expect(@ceil(two_point_one) == 3.0);
1132 var neg_two_point_one: T = -2.1;
1133 try expect(@ceil(neg_two_point_one) == -2.0);
1134 var three_point_five: T = 3.5;
1135 try expect(@ceil(three_point_five) == 4.0);
1136 var neg_three_point_five: T = -3.5;
1137 try expect(@ceil(neg_three_point_five) == -3.0);
1138 var twelve: T = 12.0;
1139 try expect(@ceil(twelve) == 12.0);
1140 var neg_twelve: T = -12.0;
1141 try expect(@ceil(neg_twelve) == -12.0);
1142 var fourteen_point_seven: T = 14.7;
1143 try expect(@ceil(fourteen_point_seven) == 15.0);
1144 var neg_fourteen_point_seven: T = -14.7;
1145 try expect(@ceil(neg_fourteen_point_seven) == -14.0);
7581146}
7591147
7601148test "@ceil with vectors" {
761 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
762 if (builtin.zig_backend == .stage2_x86_64 and
763 !comptime std.Target.x86.featureSetHas(builtin.cpu.features, .sse4_1)) return error.SkipZigTest; // TODO
764 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
7651149 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1150 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
7661151 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1152 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1153 if (builtin.zig_backend == .stage2_x86_64 and
1154 !comptime std.Target.x86.featureSetHas(builtin.cpu.features, .sse4_1)) return error.SkipZigTest;
7671155
768 try comptime testCeilWithVectors();
7691156 try testCeilWithVectors();
1157 try comptime testCeilWithVectors();
7701158}
7711159
7721160fn testCeilWithVectors() !void {
......@@ -778,90 +1166,87 @@ fn testCeilWithVectors() !void {
7781166 try expect(math.approxEqAbs(f32, @ceil(@as(f32, -0.4)), result[3], epsilon));
7791167}
7801168
781test "another, possibly redundant, @ceil test" {
782 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1169test "@trunc f16" {
7831170 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
784 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
785 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
786
787 try testCeilLegacy(f64, 12.0);
788 try comptime testCeilLegacy(f64, 12.0);
789 try testCeilLegacy(f32, 12.0);
790 try comptime testCeilLegacy(f32, 12.0);
791 try testCeilLegacy(f16, 12.0);
792 try comptime testCeilLegacy(f16, 12.0);
793
794 const x = 14.0;
795 const y = x - 0.7;
796 const z = @ceil(y);
797 try comptime expect(x == z);
798}
799
800test "@ceil f80" {
8011171 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
802 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
803 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
804 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
805 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
1172 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1173 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest;
8061174
807 if (builtin.zig_backend == .stage2_llvm and builtin.os.tag == .windows) {
808 // https://github.com/ziglang/zig/issues/12602
1175 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isMIPS()) {
1176 // https://github.com/ziglang/zig/issues/16846
8091177 return error.SkipZigTest;
8101178 }
8111179
812 try testCeilLegacy(f80, 12.0);
813 try comptime testCeilLegacy(f80, 12.0);
1180 try testTrunc(f16);
1181 try comptime testTrunc(f16);
8141182}
8151183
816test "@ceil f128" {
817 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1184test "@trunc f32/f64" {
8181185 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
819 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
820 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
821 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
1186 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1187 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1188 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest;
8221189
823 try testCeilLegacy(f128, 12.0);
824 try comptime testCeilLegacy(f128, 12.0);
825}
1190 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isMIPS()) {
1191 // https://github.com/ziglang/zig/issues/16846
1192 return error.SkipZigTest;
1193 }
8261194
827fn testCeilLegacy(comptime T: type, x: T) !void {
828 const y = x - 0.8;
829 const z = @ceil(y);
830 try expect(x == z);
1195 try testTrunc(f32);
1196 try comptime testTrunc(f32);
1197 try testTrunc(f64);
1198 try comptime testTrunc(f64);
8311199}
8321200
833test "@trunc" {
834 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1201test "@trunc f80/f128/c_longdouble" {
8351202 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1203 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1204 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
8361205 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1206 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
8371207
838 try comptime testTrunc();
839 try testTrunc();
840}
841
842fn testTrunc() !void {
843 try expect(@trunc(@as(f16, 2.1)) == 2);
844 try expect(@trunc(@as(f32, 2.1)) == 2);
845 try expect(@trunc(@as(f64, -3.5)) == -3);
1208 if (builtin.zig_backend == .stage2_llvm and builtin.os.tag == .windows) {
1209 // https://github.com/ziglang/zig/issues/12602
1210 return error.SkipZigTest;
1211 }
8461212
847 // TODO test f128, and c_longdouble
848 // https://github.com/ziglang/zig/issues/4026
849 // {
850 // var a: f80 = -3.5;
851 // try expect(@trunc(a) == -3);
852 // }
1213 try testTrunc(f80);
1214 try comptime testTrunc(f80);
1215 try testTrunc(f128);
1216 try comptime testTrunc(f128);
1217 try testTrunc(c_longdouble);
1218 try comptime testTrunc(c_longdouble);
1219}
1220
1221fn testTrunc(comptime T: type) !void {
1222 var two_point_one: T = 2.1;
1223 try expect(@trunc(two_point_one) == 2.0);
1224 var neg_two_point_one: T = -2.1;
1225 try expect(@trunc(neg_two_point_one) == -2.0);
1226 var three_point_five: T = 3.5;
1227 try expect(@trunc(three_point_five) == 3.0);
1228 var neg_three_point_five: T = -3.5;
1229 try expect(@trunc(neg_three_point_five) == -3.0);
1230 var twelve: T = 12.0;
1231 try expect(@trunc(twelve) == 12.0);
1232 var neg_twelve: T = -12.0;
1233 try expect(@trunc(neg_twelve) == -12.0);
1234 var fourteen_point_seven: T = 14.7;
1235 try expect(@trunc(fourteen_point_seven) == 14.0);
1236 var neg_fourteen_point_seven: T = -14.7;
1237 try expect(@trunc(neg_fourteen_point_seven) == -14.0);
8531238}
8541239
8551240test "@trunc with vectors" {
856 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
857 if (builtin.zig_backend == .stage2_x86_64 and
858 !comptime std.Target.x86.featureSetHas(builtin.cpu.features, .sse4_1)) return error.SkipZigTest; // TODO
859 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
8601241 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1242 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
8611243 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1244 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1245 if (builtin.zig_backend == .stage2_x86_64 and
1246 !comptime std.Target.x86.featureSetHas(builtin.cpu.features, .sse4_1)) return error.SkipZigTest;
8621247
863 try comptime testTruncWithVectors();
8641248 try testTruncWithVectors();
1249 try comptime testTruncWithVectors();
8651250}
8661251
8671252fn testTruncWithVectors() !void {
......@@ -873,183 +1258,98 @@ fn testTruncWithVectors() !void {
8731258 try expect(math.approxEqAbs(f32, @trunc(@as(f32, -0.4)), result[3], epsilon));
8741259}
8751260
876test "another, possibly redundant, @trunc test" {
877 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1261test "neg f16" {
8781262 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
879 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
880 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
881
882 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isMIPS()) {
883 // https://github.com/ziglang/zig/issues/16846
884 return error.SkipZigTest;
885 }
886
887 try testTruncLegacy(f64, 12.0);
888 try comptime testTruncLegacy(f64, 12.0);
889 try testTruncLegacy(f32, 12.0);
890 try comptime testTruncLegacy(f32, 12.0);
891 try testTruncLegacy(f16, 12.0);
892 try comptime testTruncLegacy(f16, 12.0);
893
894 const x = 14.0;
895 const y = x + 0.7;
896 const z = @trunc(y);
897 try comptime expect(x == z);
898}
899
900test "@trunc f80" {
901 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
902 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
903 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
904 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
905 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
906
907 if (builtin.zig_backend == .stage2_llvm and builtin.os.tag == .windows) {
908 // https://github.com/ziglang/zig/issues/12602
909 return error.SkipZigTest;
910 }
911
912 try testTruncLegacy(f80, 12.0);
913 try comptime testTruncLegacy(f80, 12.0);
914 comptime {
915 const x: f80 = 12.0;
916 const y = x + 0.8;
917 const z = @trunc(y);
918 try expect(x == z);
919 }
920}
921
922test "@trunc f128" {
923 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
924 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
925 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
926 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
927 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
928
929 try testTruncLegacy(f128, 12.0);
930 try comptime testTruncLegacy(f128, 12.0);
931}
932
933fn testTruncLegacy(comptime T: type, x: T) !void {
934 {
935 const y = x + 0.8;
936 const z = @trunc(y);
937 try expect(x == z);
938 }
939
940 {
941 const y = -x - 0.8;
942 const z = @trunc(y);
943 try expect(-x == z);
944 }
945}
946
947test "negation f16" {
948 if (no_x86_64_hardware_f16_support) return error.SkipZigTest; // TODO
9491263 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
950 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
9511264 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
9521265 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1266 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
1267 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest;
9531268
9541269 if (builtin.os.tag == .freebsd) {
9551270 // TODO file issue to track this failure
9561271 return error.SkipZigTest;
9571272 }
9581273
959 const S = struct {
960 fn doTheTest() !void {
961 var a: f16 = 1;
962 a = -a;
963 try expect(a == -1);
964 a = -a;
965 try expect(a == 1);
966 }
967 };
968
969 try S.doTheTest();
970 try comptime S.doTheTest();
1274 try testNeg(f16);
1275 try comptime testNeg(f16);
9711276}
9721277
973test "negation f32" {
974 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1278test "neg f32/f64" {
9751279 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
976 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
977 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
978
979 const S = struct {
980 fn doTheTest() !void {
981 var a: f32 = 1;
982 a = -a;
983 try expect(a == -1);
984 a = -a;
985 try expect(a == 1);
986 }
987 };
988
989 try S.doTheTest();
990 try comptime S.doTheTest();
991}
992
993test "negation f64" {
9941280 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
995 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
9961281 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
9971282 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1283 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
9981284
999 const S = struct {
1000 fn doTheTest() !void {
1001 var a: f64 = 1;
1002 a = -a;
1003 try expect(a == -1);
1004 a = -a;
1005 try expect(a == 1);
1006 }
1007 };
1008
1009 try S.doTheTest();
1010 try comptime S.doTheTest();
1285 try testNeg(f32);
1286 try comptime testNeg(f32);
1287 try testNeg(f64);
1288 try comptime testNeg(f64);
10111289}
10121290
1013test "negation f80" {
1014 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1015 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1291test "neg f80/f128/c_longdouble" {
10161292 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1017 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1018 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1019
1020 const S = struct {
1021 fn doTheTest() !void {
1022 var a: f80 = 1;
1023 a = -a;
1024 try expect(a == -1);
1025 a = -a;
1026 try expect(a == 1);
1027 }
1028 };
1029
1030 try S.doTheTest();
1031 try comptime S.doTheTest();
1032}
1033
1034test "negation f128" {
1035 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
10361293 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1037 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
10381294 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
10391295 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1040
1041 const S = struct {
1042 fn doTheTest() !void {
1043 var a: f128 = 1;
1044 a = -a;
1045 try expect(a == -1);
1046 a = -a;
1047 try expect(a == 1);
1048 }
1049 };
1050
1051 try S.doTheTest();
1052 try comptime S.doTheTest();
1296 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
1297 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
1298
1299 try testNeg(f80);
1300 try comptime testNeg(f80);
1301 try testNeg(f128);
1302 try comptime testNeg(f128);
1303 try testNeg(c_longdouble);
1304 try comptime testNeg(c_longdouble);
1305}
1306
1307fn testNeg(comptime T: type) !void {
1308 var two_point_five: T = 2.5;
1309 try expect(-two_point_five == -2.5);
1310 var neg_two_point_five: T = -2.5;
1311 try expect(-neg_two_point_five == 2.5);
1312
1313 var twelve: T = 12.0;
1314 try expect(-twelve == -12.0);
1315 var neg_fourteen: T = -14.0;
1316 try expect(-neg_fourteen == 14.0);
1317
1318 // normals
1319 var one: T = 1.0;
1320 try expect(-one == -1.0);
1321 var neg_one: T = -1.0;
1322 try expect(-neg_one == 1.0);
1323 var min: T = math.floatMin(T);
1324 try expect(-min == -math.floatMin(T));
1325 var neg_min: T = -math.floatMin(T);
1326 try expect(-neg_min == math.floatMin(T));
1327 var max: T = math.floatMax(T);
1328 try expect(-max == -math.floatMax(T));
1329 var neg_max: T = -math.floatMax(T);
1330 try expect(-neg_max == math.floatMax(T));
1331
1332 // subnormals
1333 var zero: T = 0.0;
1334 try expect(-zero == -0.0);
1335 var neg_zero: T = -0.0;
1336 try expect(-neg_zero == 0.0);
1337 var true_min: T = math.floatTrueMin(T);
1338 try expect(-true_min == -math.floatTrueMin(T));
1339 var neg_true_min: T = -math.floatTrueMin(T);
1340 try expect(-neg_true_min == math.floatTrueMin(T));
1341
1342 // non-finite numbers
1343 var inf: T = math.inf(T);
1344 try expect(math.isNegativeInf(-inf));
1345 var neg_inf: T = -math.inf(T);
1346 try expect(math.isPositiveInf(-neg_inf));
1347 var nan: T = math.nan(T);
1348 try expect(math.isNan(-nan));
1349 try expect(math.signbit(-nan));
1350 var neg_nan: T = -math.nan(T);
1351 try expect(math.isNan(-neg_nan));
1352 try expect(!math.signbit(-neg_nan));
10531353}
10541354
10551355test "eval @setFloatMode at compile-time" {
......@@ -1075,11 +1375,11 @@ test "f128 at compile time is lossy" {
10751375}
10761376
10771377test "comptime fixed-width float zero divided by zero produces NaN" {
1078 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
10791378 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
10801379 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
10811380 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
10821381 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1382 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
10831383
10841384 inline for (.{ f16, f32, f64, f80, f128 }) |F| {
10851385 try expect(math.isNan(@as(F, 0) / @as(F, 0)));
......@@ -1104,99 +1404,3 @@ test "comptime fixed-width float non-zero divided by zero produces signed Inf" {
11041404test "comptime_float zero divided by zero produces zero" {
11051405 try expect((0.0 / 0.0) == 0.0);
11061406}
1107
1108test "nan negation f16" {
1109 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1110 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1111 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1112 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1113
1114 const nan_comptime = comptime math.nan(f16);
1115 const neg_nan_comptime = -nan_comptime;
1116
1117 var nan_runtime = math.nan(f16);
1118 const neg_nan_runtime = -nan_runtime;
1119
1120 try expect(!math.signbit(nan_runtime));
1121 try expect(math.signbit(neg_nan_runtime));
1122
1123 try expect(!math.signbit(nan_comptime));
1124 try expect(math.signbit(neg_nan_comptime));
1125}
1126
1127test "nan negation f32" {
1128 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1129 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1130 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1131 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1132
1133 const nan_comptime = comptime math.nan(f32);
1134 const neg_nan_comptime = -nan_comptime;
1135
1136 var nan_runtime = math.nan(f32);
1137 const neg_nan_runtime = -nan_runtime;
1138
1139 try expect(!math.signbit(nan_runtime));
1140 try expect(math.signbit(neg_nan_runtime));
1141
1142 try expect(!math.signbit(nan_comptime));
1143 try expect(math.signbit(neg_nan_comptime));
1144}
1145
1146test "nan negation f64" {
1147 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1148 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1149 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1150 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1151
1152 const nan_comptime = comptime math.nan(f64);
1153 const neg_nan_comptime = -nan_comptime;
1154
1155 var nan_runtime = math.nan(f64);
1156 const neg_nan_runtime = -nan_runtime;
1157
1158 try expect(!math.signbit(nan_runtime));
1159 try expect(math.signbit(neg_nan_runtime));
1160
1161 try expect(!math.signbit(nan_comptime));
1162 try expect(math.signbit(neg_nan_comptime));
1163}
1164
1165test "nan negation f128" {
1166 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1167 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1168 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1169 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1170
1171 const nan_comptime = comptime math.nan(f128);
1172 const neg_nan_comptime = -nan_comptime;
1173
1174 var nan_runtime = math.nan(f128);
1175 const neg_nan_runtime = -nan_runtime;
1176
1177 try expect(!math.signbit(nan_runtime));
1178 try expect(math.signbit(neg_nan_runtime));
1179
1180 try expect(!math.signbit(nan_comptime));
1181 try expect(math.signbit(neg_nan_comptime));
1182}
1183
1184test "nan negation f80" {
1185 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1186 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1187 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1188 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1189 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1190
1191 const nan_comptime = comptime math.nan(f80);
1192 const neg_nan_comptime = -nan_comptime;
1193
1194 var nan_runtime = math.nan(f80);
1195 const neg_nan_runtime = -nan_runtime;
1196
1197 try expect(!math.signbit(nan_runtime));
1198 try expect(math.signbit(neg_nan_runtime));
1199
1200 try expect(!math.signbit(nan_comptime));
1201 try expect(math.signbit(neg_nan_comptime));
1202}
test/behavior/math.zig+16-11
......@@ -410,12 +410,11 @@ fn testBinaryNot128(comptime Type: type, x: Type) !void {
410410
411411test "division" {
412412 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
413 if (builtin.zig_backend == .stage2_x86_64 and
414 !comptime std.Target.x86.featureSetHas(builtin.cpu.features, .sse4_1)) return error.SkipZigTest; // TODO
415413 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
416414 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
417415 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
418416 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
417 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest;
419418
420419 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isMIPS()) {
421420 // https://github.com/ziglang/zig/issues/16846
......@@ -1437,19 +1436,28 @@ fn fmodOne(comptime T: type, a: T, b: T, c: T, epsilon: T) !void {
14371436 try expect(@abs(@mod(@as(T, a), @as(T, b)) - @as(T, c)) < epsilon);
14381437}
14391438
1440test "@round" {
1439test "@round f16" {
14411440 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
14421441 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1443 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
14441442 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
14451443 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1444 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest;
1445
1446 try testRound(f16, 12.0);
1447 try comptime testRound(f16, 12.0);
1448}
1449
1450test "@round f32/f64" {
1451 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1452 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1453 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1454 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1455 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest;
14461456
14471457 try testRound(f64, 12.0);
14481458 try comptime testRound(f64, 12.0);
14491459 try testRound(f32, 12.0);
14501460 try comptime testRound(f32, 12.0);
1451 try testRound(f16, 12.0);
1452 try comptime testRound(f16, 12.0);
14531461
14541462 const x = 14.0;
14551463 const y = x + 0.4;
......@@ -1464,6 +1472,7 @@ test "@round f80" {
14641472 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
14651473 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
14661474 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
1475 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest;
14671476
14681477 try testRound(f80, 12.0);
14691478 try comptime testRound(f80, 12.0);
......@@ -1476,6 +1485,7 @@ test "@round f128" {
14761485 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
14771486 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
14781487 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
1488 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest;
14791489
14801490 try testRound(f128, 12.0);
14811491 try comptime testRound(f128, 12.0);
......@@ -1608,11 +1618,6 @@ test "signed zeros are represented properly" {
16081618 try comptime S.doTheTest();
16091619}
16101620
1611test "comptime sin and ln" {
1612 const v = comptime (@sin(@as(f32, 1)) + @log(@as(f32, 5)));
1613 try expect(v == @sin(@as(f32, 1)) + @log(@as(f32, 5)));
1614}
1615
16161621test "absFloat" {
16171622 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
16181623 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
test/behavior/maximum_minimum.zig+7-8
......@@ -10,6 +10,7 @@ test "@max" {
1010 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1111 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1212 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
13 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
1314
1415 const S = struct {
1516 fn doTheTest() !void {
......@@ -25,12 +26,11 @@ test "@max" {
2526
2627test "@max on vectors" {
2728 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
28 if (builtin.zig_backend == .stage2_x86_64 and
29 !comptime std.Target.x86.featureSetHas(builtin.cpu.features, .sse4_1)) return error.SkipZigTest; // TODO
3029 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
3130 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
3231 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
3332 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
33 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
3434
3535 const S = struct {
3636 fn doTheTest() !void {
......@@ -74,12 +74,11 @@ test "@min" {
7474
7575test "@min for vectors" {
7676 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
77 if (builtin.zig_backend == .stage2_x86_64 and
78 !comptime std.Target.x86.featureSetHas(builtin.cpu.features, .sse4_1)) return error.SkipZigTest; // TODO
7977 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
8078 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
8179 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
8280 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
81 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
8382
8483 const S = struct {
8584 fn doTheTest() !void {
......@@ -104,12 +103,12 @@ test "@min for vectors" {
104103}
105104
106105test "@min/max for floats" {
107 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
108106 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
109107 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
110108 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
111109 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
112110 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
111 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
113112
114113 const S = struct {
115114 fn doTheTest(comptime T: type) !void {
......@@ -179,11 +178,11 @@ test "@min/@max notices bounds" {
179178
180179test "@min/@max notices vector bounds" {
181180 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
182 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
183181 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
184182 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
185183 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
186184 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
185 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
187186
188187 var x: @Vector(2, u16) = .{ 140, 40 };
189188 const y: @Vector(2, u64) = .{ 5, 100 };
......@@ -232,11 +231,11 @@ test "@min/@max notices bounds from types" {
232231
233232test "@min/@max notices bounds from vector types" {
234233 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
235 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
236234 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
237235 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
238236 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
239237 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
238 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
240239
241240 var x: @Vector(2, u16) = .{ 30, 67 };
242241 var y: @Vector(2, u32) = .{ 20, 500 };
......@@ -272,11 +271,11 @@ test "@min/@max notices bounds from types when comptime-known value is undef" {
272271
273272test "@min/@max notices bounds from vector types when element of comptime-known vector is undef" {
274273 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
275 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
276274 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
277275 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
278276 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
279277 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
278 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
280279
281280 var x: @Vector(2, u32) = .{ 1_000_000, 12345 };
282281 const y: @Vector(2, u16) = .{ 10, undefined };
test/behavior/struct.zig-2
......@@ -1651,7 +1651,6 @@ test "instantiate struct with comptime field" {
16511651test "struct field pointer has correct alignment" {
16521652 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
16531653 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1654 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
16551654 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
16561655 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
16571656 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
......@@ -1684,7 +1683,6 @@ test "struct field pointer has correct alignment" {
16841683test "extern struct field pointer has correct alignment" {
16851684 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
16861685 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1687 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
16881686 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
16891687 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
16901688 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
test/behavior/union.zig-3
......@@ -1534,7 +1534,6 @@ test "coerce enum literal to union in result loc" {
15341534test "defined-layout union field pointer has correct alignment" {
15351535 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
15361536 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1537 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
15381537 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
15391538 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
15401539 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
......@@ -1572,7 +1571,6 @@ test "defined-layout union field pointer has correct alignment" {
15721571test "undefined-layout union field pointer has correct alignment" {
15731572 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
15741573 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1575 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
15761574 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
15771575 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
15781576 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
......@@ -1610,7 +1608,6 @@ test "undefined-layout union field pointer has correct alignment" {
16101608test "packed union field pointer has correct alignment" {
16111609 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
16121610 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1613 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
16141611 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
16151612 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
16161613 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
test/behavior/vector.zig+4-10
......@@ -8,7 +8,6 @@ const expectEqual = std.testing.expectEqual;
88
99test "implicit cast vector to array - bool" {
1010 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
11 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1211 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1312 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1413 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
......@@ -27,12 +26,12 @@ test "implicit cast vector to array - bool" {
2726
2827test "vector wrap operators" {
2928 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
30 if (builtin.zig_backend == .stage2_x86_64 and
31 !comptime std.Target.x86.featureSetHas(builtin.cpu.features, .sse4_1)) return error.SkipZigTest; // TODO
3229 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
3330 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
3431 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
3532 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
33 if (builtin.zig_backend == .stage2_x86_64 and
34 !comptime std.Target.x86.featureSetHas(builtin.cpu.features, .sse4_1)) return error.SkipZigTest; // TODO
3635
3736 const S = struct {
3837 fn doTheTest() !void {
......@@ -214,13 +213,12 @@ test "array vector coercion - odd sizes" {
214213}
215214
216215test "array to vector with element type coercion" {
217 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
218 if (builtin.zig_backend == .stage2_x86_64 and
219 !comptime std.Target.x86.featureSetHas(builtin.cpu.features, .f16c)) return error.SkipZigTest; // TODO
220216 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
221217 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
222218 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
223219 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
220 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
221 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
224222
225223 const S = struct {
226224 fn doTheTest() !void {
......@@ -236,7 +234,6 @@ test "array to vector with element type coercion" {
236234
237235test "peer type resolution with coercible element types" {
238236 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
239 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
240237 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
241238 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
242239 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
......@@ -1440,7 +1437,6 @@ test "vector pointer is indexable" {
14401437 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
14411438 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
14421439 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1443 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
14441440 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
14451441 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
14461442
......@@ -1466,7 +1462,6 @@ test "boolean vector with 2 or more booleans" {
14661462 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
14671463 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
14681464 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1469 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
14701465 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
14711466
14721467 // TODO: try removing this after <https://github.com/ziglang/zig/issues/13782>:
......@@ -1483,7 +1478,6 @@ test "bitcast to vector with different child type" {
14831478 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
14841479 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
14851480 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1486 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
14871481 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
14881482 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
14891483