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, _: ?...@@ -82,7 +82,7 @@ pub fn panic(msg: []const u8, error_return_trace: ?*std.builtin.StackTrace, _: ?
82/// need for extending them to wider fp types.82/// need for extending them to wider fp types.
83/// TODO remove this; do this type selection in the language rather than83/// TODO remove this; do this type selection in the language rather than
84/// here in compiler-rt.84/// here in compiler-rt.
85pub fn F16T(comptime other_type: type) type {85pub fn F16T(comptime OtherType: type) type {
86 return switch (builtin.cpu.arch) {86 return switch (builtin.cpu.arch) {
87 .arm, .armeb, .thumb, .thumbeb => if (std.Target.arm.featureSetHas(builtin.cpu.features, .has_v8))87 .arm, .armeb, .thumb, .thumbeb => if (std.Target.arm.featureSetHas(builtin.cpu.features, .has_v8))
88 switch (builtin.abi.floatAbi()) {88 switch (builtin.abi.floatAbi()) {
...@@ -93,7 +93,7 @@ pub fn F16T(comptime other_type: type) type {...@@ -93,7 +93,7 @@ pub fn F16T(comptime other_type: type) type {
93 u16,93 u16,
94 .aarch64, .aarch64_be, .aarch64_32 => f16,94 .aarch64, .aarch64_be, .aarch64_32 => f16,
95 .riscv64 => if (builtin.zig_backend == .stage1) u16 else f16,95 .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) {
97 // Starting with LLVM 16, Darwin uses different abi for f1697 // Starting with LLVM 16, Darwin uses different abi for f16
98 // depending on the type of the other return/argument..???98 // depending on the type of the other return/argument..???
99 f32, f64 => u16,99 f32, f64 => u16,
src/Compilation.zig+1-2
...@@ -1871,8 +1871,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {...@@ -1871,8 +1871,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
1871 comp.job_queued_compiler_rt_lib = true;1871 comp.job_queued_compiler_rt_lib = true;
1872 } else if (options.output_mode != .Obj) {1872 } else if (options.output_mode != .Obj) {
1873 log.debug("queuing a job to build compiler_rt_obj", .{});1873 log.debug("queuing a job to build compiler_rt_obj", .{});
1874 // If build-obj with -fcompiler-rt is requested, that is handled specially1874 // In this case we are making a static library, so we ask
1875 // elsewhere. In this case we are making a static library, so we ask
1876 // for a compiler-rt object to put in it.1875 // for a compiler-rt object to put in it.
1877 comp.job_queued_compiler_rt_obj = true;1876 comp.job_queued_compiler_rt_obj = true;
1878 }1877 }
src/InternPool.zig+10-15
...@@ -5407,19 +5407,19 @@ pub fn getAnonStructType(ip: *InternPool, gpa: Allocator, ini: AnonStructTypeIni...@@ -5407,19 +5407,19 @@ pub fn getAnonStructType(ip: *InternPool, gpa: Allocator, ini: AnonStructTypeIni
54075407
5408/// This is equivalent to `Key.FuncType` but adjusted to have a slice for `param_types`.5408/// This is equivalent to `Key.FuncType` but adjusted to have a slice for `param_types`.
5409pub const GetFuncTypeKey = struct {5409pub const GetFuncTypeKey = struct {
5410 param_types: []Index,5410 param_types: []const Index,
5411 return_type: Index,5411 return_type: Index,
5412 comptime_bits: u32,5412 comptime_bits: u32 = 0,
5413 noalias_bits: u32,5413 noalias_bits: u32 = 0,
5414 /// `null` means generic.5414 /// `null` means generic.
5415 alignment: ?Alignment,5415 alignment: ?Alignment = .none,
5416 /// `null` means generic.5416 /// `null` means generic.
5417 cc: ?std.builtin.CallingConvention,5417 cc: ?std.builtin.CallingConvention = .Unspecified,
5418 is_var_args: bool,5418 is_var_args: bool = false,
5419 is_generic: bool,5419 is_generic: bool = false,
5420 is_noinline: bool,5420 is_noinline: bool = false,
5421 section_is_generic: bool,5421 section_is_generic: bool = false,
5422 addrspace_is_generic: bool,5422 addrspace_is_generic: bool = false,
5423};5423};
54245424
5425pub fn getFuncType(ip: *InternPool, gpa: Allocator, key: GetFuncTypeKey) Allocator.Error!Index {5425pub fn getFuncType(ip: *InternPool, gpa: Allocator, key: GetFuncTypeKey) Allocator.Error!Index {
...@@ -5754,15 +5754,10 @@ pub fn getFuncInstance(ip: *InternPool, gpa: Allocator, arg: GetFuncInstanceKey)...@@ -5754,15 +5754,10 @@ pub fn getFuncInstance(ip: *InternPool, gpa: Allocator, arg: GetFuncInstanceKey)
5754 const func_ty = try ip.getFuncType(gpa, .{5754 const func_ty = try ip.getFuncType(gpa, .{
5755 .param_types = arg.param_types,5755 .param_types = arg.param_types,
5756 .return_type = arg.bare_return_type,5756 .return_type = arg.bare_return_type,
5757 .comptime_bits = 0,
5758 .noalias_bits = arg.noalias_bits,5757 .noalias_bits = arg.noalias_bits,
5759 .alignment = arg.alignment,5758 .alignment = arg.alignment,
5760 .cc = arg.cc,5759 .cc = arg.cc,
5761 .is_var_args = false,
5762 .is_generic = false,
5763 .is_noinline = arg.is_noinline,5760 .is_noinline = arg.is_noinline,
5764 .section_is_generic = false,
5765 .addrspace_is_generic = false,
5766 });5761 });
57675762
5768 const generic_owner = unwrapCoercedFunc(ip, arg.generic_owner);5763 const generic_owner = unwrapCoercedFunc(ip, arg.generic_owner);
src/Sema.zig+3-8
...@@ -7373,10 +7373,10 @@ fn analyzeCall(...@@ -7373,10 +7373,10 @@ fn analyzeCall(
7373 const memoized_arg_values = try sema.arena.alloc(InternPool.Index, func_ty_info.param_types.len);7373 const memoized_arg_values = try sema.arena.alloc(InternPool.Index, func_ty_info.param_types.len);
73747374
7375 const owner_info = mod.typeToFunc(fn_owner_decl.ty).?;7375 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);
7376 var new_fn_info: InternPool.GetFuncTypeKey = .{7377 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,
7378 .return_type = owner_info.return_type,7379 .return_type = owner_info.return_type,
7379 .comptime_bits = 0,
7380 .noalias_bits = owner_info.noalias_bits,7380 .noalias_bits = owner_info.noalias_bits,
7381 .alignment = if (owner_info.align_is_generic) null else owner_info.alignment,7381 .alignment = if (owner_info.align_is_generic) null else owner_info.alignment,
7382 .cc = if (owner_info.cc_is_generic) null else owner_info.cc,7382 .cc = if (owner_info.cc_is_generic) null else owner_info.cc,
...@@ -7403,7 +7403,7 @@ fn analyzeCall(...@@ -7403,7 +7403,7 @@ fn analyzeCall(
7403 block,7403 block,
7404 &child_block,7404 &child_block,
7405 inst,7405 inst,
7406 new_fn_info.param_types,7406 new_param_types,
7407 &arg_i,7407 &arg_i,
7408 args_info,7408 args_info,
7409 is_comptime_call,7409 is_comptime_call,
...@@ -21144,16 +21144,11 @@ fn zirReify(...@@ -21144,16 +21144,11 @@ fn zirReify(
2114421144
21145 const ty = try mod.funcType(.{21145 const ty = try mod.funcType(.{
21146 .param_types = param_types,21146 .param_types = param_types,
21147 .comptime_bits = 0,
21148 .noalias_bits = noalias_bits,21147 .noalias_bits = noalias_bits,
21149 .return_type = return_type.toIntern(),21148 .return_type = return_type.toIntern(),
21150 .alignment = alignment,21149 .alignment = alignment,
21151 .cc = cc,21150 .cc = cc,
21152 .is_var_args = is_var_args,21151 .is_var_args = is_var_args,
21153 .is_generic = false,
21154 .is_noinline = false,
21155 .section_is_generic = false,
21156 .addrspace_is_generic = false,
21157 });21152 });
21158 return Air.internedToRef(ty.toIntern());21153 return Air.internedToRef(ty.toIntern());
21159 },21154 },
src/arch/x86_64/CodeGen.zig+937-552
...@@ -215,6 +215,7 @@ pub const MCValue = union(enum) {...@@ -215,6 +215,7 @@ pub const MCValue = union(enum) {
215 /// but it has not been spilled there yet in the current control flow.215 /// but it has not been spilled there yet in the current control flow.
216 /// Payload is a frame index.216 /// Payload is a frame index.
217 reserved_frame: FrameIndex,217 reserved_frame: FrameIndex,
218 air_ref: Air.Inst.Ref,
218219
219 fn isMemory(mcv: MCValue) bool {220 fn isMemory(mcv: MCValue) bool {
220 return switch (mcv) {221 return switch (mcv) {
...@@ -278,6 +279,7 @@ pub const MCValue = union(enum) {...@@ -278,6 +279,7 @@ pub const MCValue = union(enum) {
278 .lea_tlv,279 .lea_tlv,
279 .lea_frame,280 .lea_frame,
280 .reserved_frame,281 .reserved_frame,
282 .air_ref,
281 => unreachable, // not in memory283 => unreachable, // not in memory
282 .memory => |addr| .{ .immediate = addr },284 .memory => |addr| .{ .immediate = addr },
283 .indirect => |reg_off| switch (reg_off.off) {285 .indirect => |reg_off| switch (reg_off.off) {
...@@ -306,6 +308,7 @@ pub const MCValue = union(enum) {...@@ -306,6 +308,7 @@ pub const MCValue = union(enum) {
306 .load_tlv,308 .load_tlv,
307 .load_frame,309 .load_frame,
308 .reserved_frame,310 .reserved_frame,
311 .air_ref,
309 => unreachable, // not dereferenceable312 => unreachable, // not dereferenceable
310 .immediate => |addr| .{ .memory = addr },313 .immediate => |addr| .{ .memory = addr },
311 .register => |reg| .{ .indirect = .{ .reg = reg } },314 .register => |reg| .{ .indirect = .{ .reg = reg } },
...@@ -335,6 +338,7 @@ pub const MCValue = union(enum) {...@@ -335,6 +338,7 @@ pub const MCValue = union(enum) {
335 .lea_tlv,338 .lea_tlv,
336 .load_frame,339 .load_frame,
337 .reserved_frame,340 .reserved_frame,
341 .air_ref,
338 => unreachable, // not offsettable342 => unreachable, // not offsettable
339 .immediate => |imm| .{ .immediate = @bitCast(@as(i64, @bitCast(imm)) +% off) },343 .immediate => |imm| .{ .immediate = @bitCast(@as(i64, @bitCast(imm)) +% off) },
340 .register => |reg| .{ .register_offset = .{ .reg = reg, .off = off } },344 .register => |reg| .{ .register_offset = .{ .reg = reg, .off = off } },
...@@ -366,6 +370,7 @@ pub const MCValue = union(enum) {...@@ -366,6 +370,7 @@ pub const MCValue = union(enum) {
366 .lea_tlv,370 .lea_tlv,
367 .lea_frame,371 .lea_frame,
368 .reserved_frame,372 .reserved_frame,
373 .air_ref,
369 => unreachable,374 => unreachable,
370 .memory => |addr| if (math.cast(i32, @as(i64, @bitCast(addr)))) |small_addr|375 .memory => |addr| if (math.cast(i32, @as(i64, @bitCast(addr)))) |small_addr|
371 Memory.sib(ptr_size, .{ .base = .{ .reg = .ds }, .disp = small_addr })376 Memory.sib(ptr_size, .{ .base = .{ .reg = .ds }, .disp = small_addr })
...@@ -405,6 +410,7 @@ pub const MCValue = union(enum) {...@@ -405,6 +410,7 @@ pub const MCValue = union(enum) {
405 .load_frame => |pl| try writer.print("[{} + 0x{x}]", .{ pl.index, pl.off }),410 .load_frame => |pl| try writer.print("[{} + 0x{x}]", .{ pl.index, pl.off }),
406 .lea_frame => |pl| try writer.print("{} + 0x{x}", .{ pl.index, pl.off }),411 .lea_frame => |pl| try writer.print("{} + 0x{x}", .{ pl.index, pl.off }),
407 .reserved_frame => |pl| try writer.print("(dead:{})", .{pl}),412 .reserved_frame => |pl| try writer.print("(dead:{})", .{pl}),
413 .air_ref => |pl| try writer.print("(air:0x{x})", .{@intFromEnum(pl)}),
408 }414 }
409 }415 }
410};416};
...@@ -433,6 +439,7 @@ const InstTracking = struct {...@@ -433,6 +439,7 @@ const InstTracking = struct {
433 => result,439 => result,
434 .dead,440 .dead,
435 .reserved_frame,441 .reserved_frame,
442 .air_ref,
436 => unreachable,443 => unreachable,
437 .eflags,444 .eflags,
438 .register,445 .register,
...@@ -491,6 +498,7 @@ const InstTracking = struct {...@@ -491,6 +498,7 @@ const InstTracking = struct {
491 .register_overflow,498 .register_overflow,
492 .indirect,499 .indirect,
493 .reserved_frame,500 .reserved_frame,
501 .air_ref,
494 => unreachable,502 => unreachable,
495 };503 };
496 }504 }
...@@ -531,6 +539,7 @@ const InstTracking = struct {...@@ -531,6 +539,7 @@ const InstTracking = struct {
531 .register_offset,539 .register_offset,
532 .register_overflow,540 .register_overflow,
533 .indirect,541 .indirect,
542 .air_ref,
534 => unreachable,543 => unreachable,
535 }544 }
536 }545 }
...@@ -1807,11 +1816,11 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -1807,11 +1816,11 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
1807 .log2,1816 .log2,
1808 .log10,1817 .log10,
1809 .round,1818 .round,
1810 => try self.airUnaryMath(inst),1819 => |tag| try self.airUnaryMath(inst, tag),
18111820
1812 .floor => try self.airRound(inst, 0b1_0_01),1821 .floor => try self.airRound(inst, .{ .mode = .down, .precision = .inexact }),
1813 .ceil => try self.airRound(inst, 0b1_0_10),1822 .ceil => try self.airRound(inst, .{ .mode = .up, .precision = .inexact }),
1814 .trunc_float => try self.airRound(inst, 0b1_0_11),1823 .trunc_float => try self.airRound(inst, .{ .mode = .zero, .precision = .inexact }),
1815 .sqrt => try self.airSqrt(inst),1824 .sqrt => try self.airSqrt(inst),
1816 .neg => try self.airFloatSign(inst),1825 .neg => try self.airFloatSign(inst),
18171826
...@@ -2439,7 +2448,7 @@ fn restoreState(self: *Self, state: State, deaths: []const Air.Inst.Index, compt...@@ -2439,7 +2448,7 @@ fn restoreState(self: *Self, state: State, deaths: []const Air.Inst.Index, compt
2439}2448}
24402449
2441pub fn spillInstruction(self: *Self, reg: Register, inst: Air.Inst.Index) !void {2450pub 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;
2443 assert(tracking.getReg().?.id() == reg.id());2452 assert(tracking.getReg().?.id() == reg.id());
2444 try tracking.spill(self, inst);2453 try tracking.spill(self, inst);
2445 tracking.trackSpill(self, inst);2454 tracking.trackSpill(self, inst);
...@@ -2515,63 +2524,96 @@ fn airFptrunc(self: *Self, inst: Air.Inst.Index) !void {...@@ -2515,63 +2524,96 @@ fn airFptrunc(self: *Self, inst: Air.Inst.Index) !void {
2515 const src_ty = self.typeOf(ty_op.operand);2524 const src_ty = self.typeOf(ty_op.operand);
2516 const src_bits = src_ty.floatBits(self.target.*);2525 const src_bits = src_ty.floatBits(self.target.*);
25172526
2518 const src_mcv = try self.resolveInst(ty_op.operand);2527 const result = result: {
2519 const dst_mcv = if (src_mcv.isRegister() and self.reuseOperand(inst, ty_op.operand, 0, src_mcv))2528 if (switch (dst_bits) {
2520 src_mcv2529 16 => switch (src_bits) {
2521 else2530 32 => !self.hasFeature(.f16c),
2522 try self.copyToRegisterWithInstTracking(inst, dst_ty, src_mcv);2531 64, 80, 128 => true,
2523 const dst_reg = dst_mcv.getReg().?.to128();2532 else => unreachable,
2524 const dst_lock = self.register_manager.lockReg(dst_reg);2533 },
2525 defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);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)) {2560 const src_mcv = try self.resolveInst(ty_op.operand);
2528 switch (src_bits) {2561 const dst_mcv = if (src_mcv.isRegister() and self.reuseOperand(inst, ty_op.operand, 0, src_mcv))
2529 32 => {2562 src_mcv
2530 const mat_src_reg = if (src_mcv.isRegister())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())
2531 src_mcv.getReg().?2598 src_mcv.getReg().?
2532 else2599 else
2533 try self.copyToTmpRegister(src_ty, src_mcv);2600 try self.copyToTmpRegister(src_ty, src_mcv)).to128(),
2534 try self.asmRegisterRegisterImmediate(2601 ) else if (src_mcv.isMemory()) try self.asmRegisterMemory(
2535 .{ .v_, .cvtps2ph },2602 .{ ._ss, .cvtsd2 },
2536 dst_reg,2603 dst_reg,
2537 mat_src_reg.to128(),2604 src_mcv.mem(.qword),
2538 Immediate.u(0b1_00),2605 ) else try self.asmRegisterRegister(
2539 );2606 .{ ._ss, .cvtsd2 },
2540 },2607 dst_reg,
2541 else => return self.fail("TODO implement airFptrunc from {} to {}", .{2608 (if (src_mcv.isRegister())
2542 src_ty.fmt(self.bin_file.options.module.?), dst_ty.fmt(self.bin_file.options.module.?),2609 src_mcv.getReg().?
2543 }),2610 else
2611 try self.copyToTmpRegister(src_ty, src_mcv)).to128(),
2612 );
2544 }2613 }
2545 } else if (src_bits == 64 and dst_bits == 32) {2614 break :result dst_mcv;
2546 if (self.hasFeature(.avx)) if (src_mcv.isMemory()) try self.asmRegisterRegisterMemory(2615 };
2547 .{ .v_ss, .cvtsd2 },2616 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
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 });
2575}2617}
25762618
2577fn airFpext(self: *Self, inst: Air.Inst.Index) !void {2619fn airFpext(self: *Self, inst: Air.Inst.Index) !void {
...@@ -2581,58 +2623,96 @@ fn airFpext(self: *Self, inst: Air.Inst.Index) !void {...@@ -2581,58 +2623,96 @@ fn airFpext(self: *Self, inst: Air.Inst.Index) !void {
2581 const src_ty = self.typeOf(ty_op.operand);2623 const src_ty = self.typeOf(ty_op.operand);
2582 const src_bits = src_ty.floatBits(self.target.*);2624 const src_bits = src_ty.floatBits(self.target.*);
25832625
2584 const src_mcv = try self.resolveInst(ty_op.operand);2626 const result = result: {
2585 const dst_mcv = if (src_mcv.isRegister() and self.reuseOperand(inst, ty_op.operand, 0, src_mcv))2627 if (switch (src_bits) {
2586 src_mcv2628 16 => switch (dst_bits) {
2587 else2629 32, 64 => !self.hasFeature(.f16c),
2588 try self.copyToRegisterWithInstTracking(inst, dst_ty, src_mcv);2630 80, 128 => true,
2589 const dst_reg = dst_mcv.getReg().?.to128();2631 else => unreachable,
2590 const dst_lock = self.register_manager.lockReg(dst_reg);2632 },
2591 defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);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)) {2659 const src_mcv = try self.resolveInst(ty_op.operand);
2594 const mat_src_reg = if (src_mcv.isRegister())2660 const dst_mcv = if (src_mcv.isRegister() and self.reuseOperand(inst, ty_op.operand, 0, src_mcv))
2595 src_mcv.getReg().?2661 src_mcv
2596 else2662 else
2597 try self.copyToTmpRegister(src_ty, src_mcv);2663 try self.copyToRegisterWithInstTracking(inst, dst_ty, src_mcv);
2598 try self.asmRegisterRegister(.{ .v_ps, .cvtph2 }, dst_reg, mat_src_reg.to128());2664 const dst_reg = dst_mcv.getReg().?.to128();
2599 switch (dst_bits) {2665 const dst_lock = self.register_manager.lockReg(dst_reg);
2600 32 => {},2666 defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);
2601 64 => try self.asmRegisterRegisterRegister(.{ .v_sd, .cvtss2 }, dst_reg, dst_reg, dst_reg),2667
2602 else => return self.fail("TODO implement airFpext from {} to {}", .{2668 if (src_bits == 16) {
2603 src_ty.fmt(self.bin_file.options.module.?), dst_ty.fmt(self.bin_file.options.module.?),2669 assert(self.hasFeature(.f16c));
2604 }),2670 const mat_src_reg = if (src_mcv.isRegister())
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())
2628 src_mcv.getReg().?2671 src_mcv.getReg().?
2629 else2672 else
2630 try self.copyToTmpRegister(src_ty, src_mcv)).to128(),2673 try self.copyToTmpRegister(src_ty, src_mcv);
2631 );2674 try self.asmRegisterRegister(.{ .v_ps, .cvtph2 }, dst_reg, mat_src_reg.to128());
2632 } else return self.fail("TODO implement airFpext from {} to {}", .{2675 switch (dst_bits) {
2633 src_ty.fmt(self.bin_file.options.module.?), dst_ty.fmt(self.bin_file.options.module.?),2676 32 => {},
2634 });2677 64 => try self.asmRegisterRegisterRegister(
2635 return self.finishAir(inst, dst_mcv, .{ ty_op.operand, .none, .none });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 });
2636}2716}
26372717
2638fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {2718fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {
...@@ -5002,7 +5082,26 @@ fn airFloatSign(self: *Self, inst: Air.Inst.Index) !void {...@@ -5002,7 +5082,26 @@ fn airFloatSign(self: *Self, inst: Air.Inst.Index) !void {
5002 return self.floatSign(inst, un_op, ty);5082 return self.floatSign(inst, un_op, ty);
5003}5083}
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 {
5006 const un_op = self.air.instructions.items(.data)[inst].un_op;5105 const un_op = self.air.instructions.items(.data)[inst].un_op;
5007 const ty = self.typeOf(un_op);5106 const ty = self.typeOf(un_op);
50085107
...@@ -5018,12 +5117,9 @@ fn airRound(self: *Self, inst: Air.Inst.Index, mode: u4) !void {...@@ -5018,12 +5117,9 @@ fn airRound(self: *Self, inst: Air.Inst.Index, mode: u4) !void {
5018 return self.finishAir(inst, dst_mcv, .{ un_op, .none, .none });5117 return self.finishAir(inst, dst_mcv, .{ un_op, .none, .none });
5019}5118}
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 {
5022 const mod = self.bin_file.options.module.?;5121 const mod = self.bin_file.options.module.?;
5023 if (!self.hasFeature(.sse4_1))5122 const mir_tag = @as(?Mir.Inst.FixedTag, if (self.hasFeature(.sse4_1)) switch (ty.zigTypeTag(mod)) {
5024 return self.fail("TODO implement genRound without sse4_1 feature", .{});
5025
5026 const mir_tag = @as(?Mir.Inst.FixedTag, switch (ty.zigTypeTag(mod)) {
5027 .Float => switch (ty.floatBits(self.target.*)) {5123 .Float => switch (ty.floatBits(self.target.*)) {
5028 32 => if (self.hasFeature(.avx)) .{ .v_ss, .round } else .{ ._ss, .round },5124 32 => if (self.hasFeature(.avx)) .{ .v_ss, .round } else .{ ._ss, .round },
5029 64 => if (self.hasFeature(.avx)) .{ .v_sd, .round } else .{ ._sd, .round },5125 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...@@ -5050,9 +5146,28 @@ fn genRound(self: *Self, ty: Type, dst_reg: Register, src_mcv: MCValue, mode: u4
5050 else => null,5146 else => null,
5051 },5147 },
5052 else => unreachable,5148 else => unreachable,
5053 }) orelse return self.fail("TODO implement genRound for {}", .{5149 } else null) orelse {
5054 ty.fmt(self.bin_file.options.module.?),5150 if (ty.zigTypeTag(mod) != .Float) return self.fail("TODO implement genRound for {}", .{
5055 });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 };
5056 const abi_size: u32 = @intCast(ty.abiSize(mod));5171 const abi_size: u32 = @intCast(ty.abiSize(mod));
5057 const dst_alias = registerAlias(dst_reg, abi_size);5172 const dst_alias = registerAlias(dst_reg, abi_size);
5058 switch (mir_tag[0]) {5173 switch (mir_tag[0]) {
...@@ -5061,7 +5176,7 @@ fn genRound(self: *Self, ty: Type, dst_reg: Register, src_mcv: MCValue, mode: u4...@@ -5061,7 +5176,7 @@ fn genRound(self: *Self, ty: Type, dst_reg: Register, src_mcv: MCValue, mode: u4
5061 dst_alias,5176 dst_alias,
5062 dst_alias,5177 dst_alias,
5063 src_mcv.mem(Memory.PtrSize.fromSize(abi_size)),5178 src_mcv.mem(Memory.PtrSize.fromSize(abi_size)),
5064 Immediate.u(mode),5179 Immediate.u(@as(u5, @bitCast(mode))),
5065 ) else try self.asmRegisterRegisterRegisterImmediate(5180 ) else try self.asmRegisterRegisterRegisterImmediate(
5066 mir_tag,5181 mir_tag,
5067 dst_alias,5182 dst_alias,
...@@ -5070,13 +5185,13 @@ fn genRound(self: *Self, ty: Type, dst_reg: Register, src_mcv: MCValue, mode: u4...@@ -5070,13 +5185,13 @@ fn genRound(self: *Self, ty: Type, dst_reg: Register, src_mcv: MCValue, mode: u4
5070 src_mcv.getReg().?5185 src_mcv.getReg().?
5071 else5186 else
5072 try self.copyToTmpRegister(ty, src_mcv), abi_size),5187 try self.copyToTmpRegister(ty, src_mcv), abi_size),
5073 Immediate.u(mode),5188 Immediate.u(@as(u5, @bitCast(mode))),
5074 ),5189 ),
5075 else => if (src_mcv.isMemory()) try self.asmRegisterMemoryImmediate(5190 else => if (src_mcv.isMemory()) try self.asmRegisterMemoryImmediate(
5076 mir_tag,5191 mir_tag,
5077 dst_alias,5192 dst_alias,
5078 src_mcv.mem(Memory.PtrSize.fromSize(abi_size)),5193 src_mcv.mem(Memory.PtrSize.fromSize(abi_size)),
5079 Immediate.u(mode),5194 Immediate.u(@as(u5, @bitCast(mode))),
5080 ) else try self.asmRegisterRegisterImmediate(5195 ) else try self.asmRegisterRegisterImmediate(
5081 mir_tag,5196 mir_tag,
5082 dst_alias,5197 dst_alias,
...@@ -5084,7 +5199,7 @@ fn genRound(self: *Self, ty: Type, dst_reg: Register, src_mcv: MCValue, mode: u4...@@ -5084,7 +5199,7 @@ fn genRound(self: *Self, ty: Type, dst_reg: Register, src_mcv: MCValue, mode: u4
5084 src_mcv.getReg().?5199 src_mcv.getReg().?
5085 else5200 else
5086 try self.copyToTmpRegister(ty, src_mcv), abi_size),5201 try self.copyToTmpRegister(ty, src_mcv), abi_size),
5087 Immediate.u(mode),5202 Immediate.u(@as(u5, @bitCast(mode))),
5088 ),5203 ),
5089 }5204 }
5090}5205}
...@@ -5244,9 +5359,21 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void {...@@ -5244,9 +5359,21 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void {
5244 else => unreachable,5359 else => unreachable,
5245 },5360 },
5246 else => unreachable,5361 else => unreachable,
5247 }) orelse return self.fail("TODO implement airSqrt for {}", .{5362 }) orelse {
5248 ty.fmt(mod),5363 if (ty.zigTypeTag(mod) != .Float) return self.fail("TODO implement airSqrt for {}", .{
5249 });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 };
5250 switch (mir_tag[0]) {5377 switch (mir_tag[0]) {
5251 .v_ss, .v_sd => if (src_mcv.isMemory()) try self.asmRegisterRegisterMemory(5378 .v_ss, .v_sd => if (src_mcv.isMemory()) try self.asmRegisterRegisterMemory(
5252 mir_tag,5379 mir_tag,
...@@ -5280,13 +5407,32 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void {...@@ -5280,13 +5407,32 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void {
5280 return self.finishAir(inst, result, .{ un_op, .none, .none });5407 return self.finishAir(inst, result, .{ un_op, .none, .none });
5281}5408}
52825409
5283fn airUnaryMath(self: *Self, inst: Air.Inst.Index) !void {5410fn airUnaryMath(self: *Self, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void {
5284 const un_op = self.air.instructions.items(.data)[inst].un_op;5411 const un_op = self.air.instructions.items(.data)[inst].un_op;
5285 _ = un_op;5412 const ty = self.typeOf(un_op);
5286 return self.fail("TODO implement airUnaryMath for {}", .{5413 var callee: ["__round?".len]u8 = undefined;
5287 self.air.instructions.items(.tag)[inst],5414 const result = try self.genCall(.{ .lib = .{
5288 });5415 .return_type = ty.toIntern(),
5289 //return self.finishAir(inst, result, .{ un_op, .none, .none });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 });
5290}5436}
52915437
5292fn reuseOperand(5438fn reuseOperand(
...@@ -5439,6 +5585,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) InnerErro...@@ -5439,6 +5585,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) InnerErro
54395585
5440 try self.genCopy(dst_ty, dst_mcv, .{ .indirect = .{ .reg = addr_reg } });5586 try self.genCopy(dst_ty, dst_mcv, .{ .indirect = .{ .reg = addr_reg } });
5441 },5587 },
5588 .air_ref => |ref| try self.load(dst_mcv, ptr_ty, try self.resolveInst(ref)),
5442 }5589 }
5443}5590}
54445591
...@@ -5584,6 +5731,7 @@ fn store(self: *Self, ptr_ty: Type, ptr_mcv: MCValue, src_mcv: MCValue) InnerErr...@@ -5584,6 +5731,7 @@ fn store(self: *Self, ptr_ty: Type, ptr_mcv: MCValue, src_mcv: MCValue) InnerErr
55845731
5585 try self.genCopy(src_ty, .{ .indirect = .{ .reg = addr_reg } }, src_mcv);5732 try self.genCopy(src_ty, .{ .indirect = .{ .reg = addr_reg } }, src_mcv);
5586 },5733 },
5734 .air_ref => |ref| try self.store(ptr_ty, ptr_mcv, try self.resolveInst(ref)),
5587 }5735 }
5588}5736}
55895737
...@@ -5925,6 +6073,7 @@ fn genUnOpMir(self: *Self, mir_tag: Mir.Inst.FixedTag, dst_ty: Type, dst_mcv: MC...@@ -5925,6 +6073,7 @@ fn genUnOpMir(self: *Self, mir_tag: Mir.Inst.FixedTag, dst_ty: Type, dst_mcv: MC
5925 .lea_tlv,6073 .lea_tlv,
5926 .lea_frame,6074 .lea_frame,
5927 .reserved_frame,6075 .reserved_frame,
6076 .air_ref,
5928 => unreachable, // unmodifiable destination6077 => unreachable, // unmodifiable destination
5929 .register => |dst_reg| try self.asmRegister(mir_tag, registerAlias(dst_reg, abi_size)),6078 .register => |dst_reg| try self.asmRegister(mir_tag, registerAlias(dst_reg, abi_size)),
5930 .memory, .load_got, .load_direct, .load_tlv => {6079 .memory, .load_got, .load_direct, .load_tlv => {
...@@ -6433,6 +6582,34 @@ fn genBinOp(...@@ -6433,6 +6582,34 @@ fn genBinOp(
6433 const lhs_ty = self.typeOf(lhs_air);6582 const lhs_ty = self.typeOf(lhs_air);
6434 const rhs_ty = self.typeOf(rhs_air);6583 const rhs_ty = self.typeOf(rhs_air);
6435 const abi_size: u32 = @intCast(lhs_ty.abiSize(mod));6584 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
6436 if ((lhs_ty.scalarType(mod).isRuntimeFloat() and6613 if ((lhs_ty.scalarType(mod).isRuntimeFloat() and
6437 lhs_ty.scalarType(mod).floatBits(self.target.*) == 80) or6614 lhs_ty.scalarType(mod).floatBits(self.target.*) == 80) or
6438 lhs_ty.abiSize(mod) > @as(u6, if (self.hasFeature(.avx)) 32 else 16))6615 lhs_ty.abiSize(mod) > @as(u6, if (self.hasFeature(.avx)) 32 else 16))
...@@ -6584,7 +6761,11 @@ fn genBinOp(...@@ -6584,7 +6761,11 @@ fn genBinOp(
6584 .min,6761 .min,
6585 .max,6762 .max,
6586 => {6763 => {
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) {
6588 .immediate,6769 .immediate,
6589 .eflags,6770 .eflags,
6590 .register_offset,6771 .register_offset,
...@@ -6598,7 +6779,10 @@ fn genBinOp(...@@ -6598,7 +6779,10 @@ fn genBinOp(
6598 => true,6779 => true,
6599 .memory => |addr| math.cast(i32, @as(i64, @bitCast(addr))) == null,6780 .memory => |addr| math.cast(i32, @as(i64, @bitCast(addr))) == null,
6600 else => false,6781 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;
6602 const mat_mcv_lock = switch (mat_src_mcv) {6786 const mat_mcv_lock = switch (mat_src_mcv) {
6603 .register => |reg| self.register_manager.lockReg(reg),6787 .register => |reg| self.register_manager.lockReg(reg),
6604 else => null,6788 else => null,
...@@ -6645,6 +6829,7 @@ fn genBinOp(...@@ -6645,6 +6829,7 @@ fn genBinOp(
6645 .lea_tlv,6829 .lea_tlv,
6646 .lea_frame,6830 .lea_frame,
6647 .reserved_frame,6831 .reserved_frame,
6832 .air_ref,
6648 => unreachable,6833 => unreachable,
6649 .register => |src_reg| try self.asmCmovccRegisterRegister(6834 .register => |src_reg| try self.asmCmovccRegisterRegister(
6650 registerAlias(tmp_reg, cmov_abi_size),6835 registerAlias(tmp_reg, cmov_abi_size),
...@@ -6685,7 +6870,8 @@ fn genBinOp(...@@ -6685,7 +6870,8 @@ fn genBinOp(
6685 const mir_tag = @as(?Mir.Inst.FixedTag, switch (lhs_ty.zigTypeTag(mod)) {6870 const mir_tag = @as(?Mir.Inst.FixedTag, switch (lhs_ty.zigTypeTag(mod)) {
6686 else => unreachable,6871 else => unreachable,
6687 .Float => switch (lhs_ty.floatBits(self.target.*)) {6872 .Float => switch (lhs_ty.floatBits(self.target.*)) {
6688 16 => if (self.hasFeature(.f16c)) {6873 16 => {
6874 assert(self.hasFeature(.f16c));
6689 const tmp_reg = (try self.register_manager.allocReg(null, sse)).to128();6875 const tmp_reg = (try self.register_manager.allocReg(null, sse)).to128();
6690 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);6876 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
6691 defer self.register_manager.unlockReg(tmp_lock);6877 defer self.register_manager.unlockReg(tmp_lock);
...@@ -6728,7 +6914,7 @@ fn genBinOp(...@@ -6728,7 +6914,7 @@ fn genBinOp(
6728 Immediate.u(0b1_00),6914 Immediate.u(0b1_00),
6729 );6915 );
6730 return dst_mcv;6916 return dst_mcv;
6731 } else null,6917 },
6732 32 => switch (air_tag) {6918 32 => switch (air_tag) {
6733 .add => if (self.hasFeature(.avx)) .{ .v_ss, .add } else .{ ._ss, .add },6919 .add => if (self.hasFeature(.avx)) .{ .v_ss, .add } else .{ ._ss, .add },
6734 .sub => if (self.hasFeature(.avx)) .{ .v_ss, .sub } else .{ ._ss, .sub },6920 .sub => if (self.hasFeature(.avx)) .{ .v_ss, .sub } else .{ ._ss, .sub },
...@@ -6989,181 +7175,184 @@ fn genBinOp(...@@ -6989,181 +7175,184 @@ fn genBinOp(
6989 else => null,7175 else => null,
6990 },7176 },
6991 .Float => switch (lhs_ty.childType(mod).floatBits(self.target.*)) {7177 .Float => switch (lhs_ty.childType(mod).floatBits(self.target.*)) {
6992 16 => if (self.hasFeature(.f16c)) switch (lhs_ty.vectorLen(mod)) {7178 16 => tag: {
6993 1 => {7179 assert(self.hasFeature(.f16c));
6994 const tmp_reg = (try self.register_manager.allocReg(null, sse)).to128();7180 switch (lhs_ty.vectorLen(mod)) {
6995 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);7181 1 => {
6996 defer self.register_manager.unlockReg(tmp_lock);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(7186 if (src_mcv.isMemory()) try self.asmRegisterRegisterMemoryImmediate(
6999 .{ .vp_w, .insr },7187 .{ .vp_w, .insr },
7000 dst_reg,7188 dst_reg,
7001 dst_reg,7189 dst_reg,
7002 src_mcv.mem(.word),7190 src_mcv.mem(.word),
7003 Immediate.u(1),7191 Immediate.u(1),
7004 ) else try self.asmRegisterRegisterRegister(7192 ) else try self.asmRegisterRegisterRegister(
7005 .{ .vp_, .unpcklwd },7193 .{ .vp_, .unpcklwd },
7006 dst_reg,7194 dst_reg,
7007 dst_reg,7195 dst_reg,
7008 (if (src_mcv.isRegister())7196 (if (src_mcv.isRegister())
7009 src_mcv.getReg().?7197 src_mcv.getReg().?
7010 else7198 else
7011 try self.copyToTmpRegister(rhs_ty, src_mcv)).to128(),7199 try self.copyToTmpRegister(rhs_ty, src_mcv)).to128(),
7012 );7200 );
7013 try self.asmRegisterRegister(.{ .v_ps, .cvtph2 }, dst_reg, dst_reg);7201 try self.asmRegisterRegister(.{ .v_ps, .cvtph2 }, dst_reg, dst_reg);
7014 try self.asmRegisterRegister(.{ .v_, .movshdup }, tmp_reg, dst_reg);7202 try self.asmRegisterRegister(.{ .v_, .movshdup }, tmp_reg, dst_reg);
7015 try self.asmRegisterRegisterRegister(7203 try self.asmRegisterRegisterRegister(
7016 switch (air_tag) {7204 switch (air_tag) {
7017 .add => .{ .v_ss, .add },7205 .add => .{ .v_ss, .add },
7018 .sub => .{ .v_ss, .sub },7206 .sub => .{ .v_ss, .sub },
7019 .mul => .{ .v_ss, .mul },7207 .mul => .{ .v_ss, .mul },
7020 .div_float, .div_trunc, .div_floor, .div_exact => .{ .v_ss, .div },7208 .div_float, .div_trunc, .div_floor, .div_exact => .{ .v_ss, .div },
7021 .max => .{ .v_ss, .max },7209 .max => .{ .v_ss, .max },
7022 .min => .{ .v_ss, .max },7210 .min => .{ .v_ss, .max },
7023 else => unreachable,7211 else => unreachable,
7024 },7212 },
7025 dst_reg,7213 dst_reg,
7026 dst_reg,7214 dst_reg,
7027 tmp_reg,7215 tmp_reg,
7028 );7216 );
7029 try self.asmRegisterRegisterImmediate(7217 try self.asmRegisterRegisterImmediate(
7030 .{ .v_, .cvtps2ph },7218 .{ .v_, .cvtps2ph },
7031 dst_reg,7219 dst_reg,
7032 dst_reg,7220 dst_reg,
7033 Immediate.u(0b1_00),7221 Immediate.u(0b1_00),
7034 );7222 );
7035 return dst_mcv;7223 return dst_mcv;
7036 },7224 },
7037 2 => {7225 2 => {
7038 const tmp_reg = (try self.register_manager.allocReg(null, sse)).to128();7226 const tmp_reg = (try self.register_manager.allocReg(null, sse)).to128();
7039 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);7227 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
7040 defer self.register_manager.unlockReg(tmp_lock);7228 defer self.register_manager.unlockReg(tmp_lock);
70417229
7042 if (src_mcv.isMemory()) try self.asmRegisterMemoryImmediate(7230 if (src_mcv.isMemory()) try self.asmRegisterMemoryImmediate(
7043 .{ .vp_d, .insr },7231 .{ .vp_d, .insr },
7044 dst_reg,7232 dst_reg,
7045 src_mcv.mem(.dword),7233 src_mcv.mem(.dword),
7046 Immediate.u(1),7234 Immediate.u(1),
7047 ) else try self.asmRegisterRegisterRegister(7235 ) else try self.asmRegisterRegisterRegister(
7048 .{ .v_ps, .unpckl },7236 .{ .v_ps, .unpckl },
7049 dst_reg,7237 dst_reg,
7050 dst_reg,7238 dst_reg,
7051 (if (src_mcv.isRegister())7239 (if (src_mcv.isRegister())
7052 src_mcv.getReg().?7240 src_mcv.getReg().?
7053 else7241 else
7054 try self.copyToTmpRegister(rhs_ty, src_mcv)).to128(),7242 try self.copyToTmpRegister(rhs_ty, src_mcv)).to128(),
7055 );7243 );
7056 try self.asmRegisterRegister(.{ .v_ps, .cvtph2 }, dst_reg, dst_reg);7244 try self.asmRegisterRegister(.{ .v_ps, .cvtph2 }, dst_reg, dst_reg);
7057 try self.asmRegisterRegisterRegister(7245 try self.asmRegisterRegisterRegister(
7058 .{ .v_ps, .movhl },7246 .{ .v_ps, .movhl },
7059 tmp_reg,7247 tmp_reg,
7060 dst_reg,7248 dst_reg,
7061 dst_reg,7249 dst_reg,
7062 );7250 );
7063 try self.asmRegisterRegisterRegister(7251 try self.asmRegisterRegisterRegister(
7064 switch (air_tag) {7252 switch (air_tag) {
7065 .add => .{ .v_ps, .add },7253 .add => .{ .v_ps, .add },
7066 .sub => .{ .v_ps, .sub },7254 .sub => .{ .v_ps, .sub },
7067 .mul => .{ .v_ps, .mul },7255 .mul => .{ .v_ps, .mul },
7068 .div_float, .div_trunc, .div_floor, .div_exact => .{ .v_ps, .div },7256 .div_float, .div_trunc, .div_floor, .div_exact => .{ .v_ps, .div },
7069 .max => .{ .v_ps, .max },7257 .max => .{ .v_ps, .max },
7070 .min => .{ .v_ps, .max },7258 .min => .{ .v_ps, .max },
7071 else => unreachable,7259 else => unreachable,
7072 },7260 },
7073 dst_reg,7261 dst_reg,
7074 dst_reg,7262 dst_reg,
7075 tmp_reg,7263 tmp_reg,
7076 );7264 );
7077 try self.asmRegisterRegisterImmediate(7265 try self.asmRegisterRegisterImmediate(
7078 .{ .v_, .cvtps2ph },7266 .{ .v_, .cvtps2ph },
7079 dst_reg,7267 dst_reg,
7080 dst_reg,7268 dst_reg,
7081 Immediate.u(0b1_00),7269 Immediate.u(0b1_00),
7082 );7270 );
7083 return dst_mcv;7271 return dst_mcv;
7084 },7272 },
7085 3...4 => {7273 3...4 => {
7086 const tmp_reg = (try self.register_manager.allocReg(null, sse)).to128();7274 const tmp_reg = (try self.register_manager.allocReg(null, sse)).to128();
7087 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);7275 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
7088 defer self.register_manager.unlockReg(tmp_lock);7276 defer self.register_manager.unlockReg(tmp_lock);
70897277
7090 try self.asmRegisterRegister(.{ .v_ps, .cvtph2 }, dst_reg, dst_reg);7278 try self.asmRegisterRegister(.{ .v_ps, .cvtph2 }, dst_reg, dst_reg);
7091 if (src_mcv.isMemory()) try self.asmRegisterMemory(7279 if (src_mcv.isMemory()) try self.asmRegisterMemory(
7092 .{ .v_ps, .cvtph2 },7280 .{ .v_ps, .cvtph2 },
7093 tmp_reg,7281 tmp_reg,
7094 src_mcv.mem(.qword),7282 src_mcv.mem(.qword),
7095 ) else try self.asmRegisterRegister(7283 ) else try self.asmRegisterRegister(
7096 .{ .v_ps, .cvtph2 },7284 .{ .v_ps, .cvtph2 },
7097 tmp_reg,7285 tmp_reg,
7098 (if (src_mcv.isRegister())7286 (if (src_mcv.isRegister())
7099 src_mcv.getReg().?7287 src_mcv.getReg().?
7100 else7288 else
7101 try self.copyToTmpRegister(rhs_ty, src_mcv)).to128(),7289 try self.copyToTmpRegister(rhs_ty, src_mcv)).to128(),
7102 );7290 );
7103 try self.asmRegisterRegisterRegister(7291 try self.asmRegisterRegisterRegister(
7104 switch (air_tag) {7292 switch (air_tag) {
7105 .add => .{ .v_ps, .add },7293 .add => .{ .v_ps, .add },
7106 .sub => .{ .v_ps, .sub },7294 .sub => .{ .v_ps, .sub },
7107 .mul => .{ .v_ps, .mul },7295 .mul => .{ .v_ps, .mul },
7108 .div_float, .div_trunc, .div_floor, .div_exact => .{ .v_ps, .div },7296 .div_float, .div_trunc, .div_floor, .div_exact => .{ .v_ps, .div },
7109 .max => .{ .v_ps, .max },7297 .max => .{ .v_ps, .max },
7110 .min => .{ .v_ps, .max },7298 .min => .{ .v_ps, .max },
7111 else => unreachable,7299 else => unreachable,
7112 },7300 },
7113 dst_reg,7301 dst_reg,
7114 dst_reg,7302 dst_reg,
7115 tmp_reg,7303 tmp_reg,
7116 );7304 );
7117 try self.asmRegisterRegisterImmediate(7305 try self.asmRegisterRegisterImmediate(
7118 .{ .v_, .cvtps2ph },7306 .{ .v_, .cvtps2ph },
7119 dst_reg,7307 dst_reg,
7120 dst_reg,7308 dst_reg,
7121 Immediate.u(0b1_00),7309 Immediate.u(0b1_00),
7122 );7310 );
7123 return dst_mcv;7311 return dst_mcv;
7124 },7312 },
7125 5...8 => {7313 5...8 => {
7126 const tmp_reg = (try self.register_manager.allocReg(null, sse)).to256();7314 const tmp_reg = (try self.register_manager.allocReg(null, sse)).to256();
7127 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);7315 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
7128 defer self.register_manager.unlockReg(tmp_lock);7316 defer self.register_manager.unlockReg(tmp_lock);
71297317
7130 try self.asmRegisterRegister(.{ .v_ps, .cvtph2 }, dst_reg.to256(), dst_reg);7318 try self.asmRegisterRegister(.{ .v_ps, .cvtph2 }, dst_reg.to256(), dst_reg);
7131 if (src_mcv.isMemory()) try self.asmRegisterMemory(7319 if (src_mcv.isMemory()) try self.asmRegisterMemory(
7132 .{ .v_ps, .cvtph2 },7320 .{ .v_ps, .cvtph2 },
7133 tmp_reg,7321 tmp_reg,
7134 src_mcv.mem(.xword),7322 src_mcv.mem(.xword),
7135 ) else try self.asmRegisterRegister(7323 ) else try self.asmRegisterRegister(
7136 .{ .v_ps, .cvtph2 },7324 .{ .v_ps, .cvtph2 },
7137 tmp_reg,7325 tmp_reg,
7138 (if (src_mcv.isRegister())7326 (if (src_mcv.isRegister())
7139 src_mcv.getReg().?7327 src_mcv.getReg().?
7140 else7328 else
7141 try self.copyToTmpRegister(rhs_ty, src_mcv)).to128(),7329 try self.copyToTmpRegister(rhs_ty, src_mcv)).to128(),
7142 );7330 );
7143 try self.asmRegisterRegisterRegister(7331 try self.asmRegisterRegisterRegister(
7144 switch (air_tag) {7332 switch (air_tag) {
7145 .add => .{ .v_ps, .add },7333 .add => .{ .v_ps, .add },
7146 .sub => .{ .v_ps, .sub },7334 .sub => .{ .v_ps, .sub },
7147 .mul => .{ .v_ps, .mul },7335 .mul => .{ .v_ps, .mul },
7148 .div_float, .div_trunc, .div_floor, .div_exact => .{ .v_ps, .div },7336 .div_float, .div_trunc, .div_floor, .div_exact => .{ .v_ps, .div },
7149 .max => .{ .v_ps, .max },7337 .max => .{ .v_ps, .max },
7150 .min => .{ .v_ps, .max },7338 .min => .{ .v_ps, .max },
7151 else => unreachable,7339 else => unreachable,
7152 },7340 },
7153 dst_reg.to256(),7341 dst_reg.to256(),
7154 dst_reg.to256(),7342 dst_reg.to256(),
7155 tmp_reg,7343 tmp_reg,
7156 );7344 );
7157 try self.asmRegisterRegisterImmediate(7345 try self.asmRegisterRegisterImmediate(
7158 .{ .v_, .cvtps2ph },7346 .{ .v_, .cvtps2ph },
7159 dst_reg,7347 dst_reg,
7160 dst_reg.to256(),7348 dst_reg.to256(),
7161 Immediate.u(0b1_00),7349 Immediate.u(0b1_00),
7162 );7350 );
7163 return dst_mcv;7351 return dst_mcv;
7164 },7352 },
7165 else => null,7353 else => break :tag null,
7166 } else null,7354 }
7355 },
7167 32 => switch (lhs_ty.vectorLen(mod)) {7356 32 => switch (lhs_ty.vectorLen(mod)) {
7168 1 => switch (air_tag) {7357 1 => switch (air_tag) {
7169 .add => if (self.hasFeature(.avx)) .{ .v_ss, .add } else .{ ._ss, .add },7358 .add => if (self.hasFeature(.avx)) .{ .v_ss, .add } else .{ ._ss, .add },
...@@ -7290,18 +7479,16 @@ fn genBinOp(...@@ -7290,18 +7479,16 @@ fn genBinOp(
72907479
7291 switch (air_tag) {7480 switch (air_tag) {
7292 .add, .add_wrap, .sub, .sub_wrap, .mul, .mul_wrap, .div_float, .div_exact => {},7481 .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(
7294 lhs_ty,7483 lhs_ty,
7295 dst_reg,7484 dst_reg,
7296 .{ .register = dst_reg },7485 .{ .register = dst_reg },
7297 switch (air_tag) {7486 .{ .mode = switch (air_tag) {
7298 .div_trunc => 0b1_0_11,7487 .div_trunc => .zero,
7299 .div_floor => 0b1_0_01,7488 .div_floor => .down,
7300 else => unreachable,7489 else => unreachable,
7301 },7490 }, .precision = .inexact },
7302 ) else return self.fail("TODO implement genBinOp for {s} {} without sse4_1 feature", .{7491 ),
7303 @tagName(air_tag), lhs_ty.fmt(self.bin_file.options.module.?),
7304 }),
7305 .bit_and, .bit_or, .xor => {},7492 .bit_and, .bit_or, .xor => {},
7306 .max, .min => if (maybe_mask_reg) |mask_reg| if (self.hasFeature(.avx)) {7493 .max, .min => if (maybe_mask_reg) |mask_reg| if (self.hasFeature(.avx)) {
7307 const rhs_copy_reg = registerAlias(src_mcv.getReg().?, abi_size);7494 const rhs_copy_reg = registerAlias(src_mcv.getReg().?, abi_size);
...@@ -7558,6 +7745,7 @@ fn genBinOpMir(...@@ -7558,6 +7745,7 @@ fn genBinOpMir(
7558 .lea_tlv,7745 .lea_tlv,
7559 .lea_frame,7746 .lea_frame,
7560 .reserved_frame,7747 .reserved_frame,
7748 .air_ref,
7561 => unreachable, // unmodifiable destination7749 => unreachable, // unmodifiable destination
7562 .register, .register_offset => {7750 .register, .register_offset => {
7563 assert(dst_mcv.isRegister());7751 assert(dst_mcv.isRegister());
...@@ -7673,6 +7861,7 @@ fn genBinOpMir(...@@ -7673,6 +7861,7 @@ fn genBinOpMir(
7673 else => unreachable,7861 else => unreachable,
7674 }7862 }
7675 },7863 },
7864 .air_ref => |ref| try self.genBinOpMir(mir_tag, ty, dst_mcv, try self.resolveInst(ref)),
7676 }7865 }
7677 },7866 },
7678 .memory, .indirect, .load_got, .load_direct, .load_tlv, .load_frame => {7867 .memory, .indirect, .load_got, .load_direct, .load_tlv, .load_frame => {
...@@ -7696,13 +7885,18 @@ fn genBinOpMir(...@@ -7696,13 +7885,18 @@ fn genBinOpMir(
7696 };7885 };
7697 defer if (dst_info) |info| self.register_manager.unlockReg(info.addr_lock);7886 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) {
7700 .none,7893 .none,
7701 .unreach,7894 .unreach,
7702 .dead,7895 .dead,
7703 .undef,7896 .undef,
7704 .register_overflow,7897 .register_overflow,
7705 .reserved_frame,7898 .reserved_frame,
7899 .air_ref,
7706 => unreachable,7900 => unreachable,
7707 .immediate,7901 .immediate,
7708 .register,7902 .register,
...@@ -7716,7 +7910,7 @@ fn genBinOpMir(...@@ -7716,7 +7910,7 @@ fn genBinOpMir(
7716 .lea_frame,7910 .lea_frame,
7717 => null,7911 => null,
7718 .memory, .load_got, .load_direct, .load_tlv => src: {7912 .memory, .load_got, .load_direct, .load_tlv => src: {
7719 switch (src_mcv) {7913 switch (resolved_src_mcv) {
7720 .memory => |addr| if (math.cast(i32, @as(i64, @bitCast(addr))) != null and7914 .memory => |addr| if (math.cast(i32, @as(i64, @bitCast(addr))) != null and
7721 math.cast(i32, @as(i64, @bitCast(addr)) + abi_size - limb_abi_size) != null)7915 math.cast(i32, @as(i64, @bitCast(addr)) + abi_size - limb_abi_size) != null)
7722 break :src null,7916 break :src null,
...@@ -7728,7 +7922,7 @@ fn genBinOpMir(...@@ -7728,7 +7922,7 @@ fn genBinOpMir(
7728 const src_addr_lock = self.register_manager.lockRegAssumeUnused(src_addr_reg);7922 const src_addr_lock = self.register_manager.lockRegAssumeUnused(src_addr_reg);
7729 errdefer self.register_manager.unlockReg(src_addr_lock);7923 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());
7732 break :src .{7926 break :src .{
7733 .addr_reg = src_addr_reg,7927 .addr_reg = src_addr_reg,
7734 .addr_lock = src_addr_lock,7928 .addr_lock = src_addr_lock,
...@@ -7775,13 +7969,14 @@ fn genBinOpMir(...@@ -7775,13 +7969,14 @@ fn genBinOpMir(
7775 else => unreachable,7969 else => unreachable,
7776 },7970 },
7777 );7971 );
7778 switch (src_mcv) {7972 switch (resolved_src_mcv) {
7779 .none,7973 .none,
7780 .unreach,7974 .unreach,
7781 .dead,7975 .dead,
7782 .undef,7976 .undef,
7783 .register_overflow,7977 .register_overflow,
7784 .reserved_frame,7978 .reserved_frame,
7979 .air_ref,
7785 => unreachable,7980 => unreachable,
7786 .register => |src_reg| switch (off) {7981 .register => |src_reg| switch (off) {
7787 0 => try self.asmMemoryRegister(7982 0 => try self.asmMemoryRegister(
...@@ -7857,7 +8052,7 @@ fn genBinOpMir(...@@ -7857,7 +8052,7 @@ fn genBinOpMir(
7857 => {8052 => {
7858 const src_limb_reg = try self.copyToTmpRegister(limb_ty, if (src_info) |info| .{8053 const src_limb_reg = try self.copyToTmpRegister(limb_ty, if (src_info) |info| .{
7859 .indirect = .{ .reg = info.addr_reg, .off = off },8054 .indirect = .{ .reg = info.addr_reg, .off = off },
7860 } else switch (src_mcv) {8055 } else switch (resolved_src_mcv) {
7861 .eflags,8056 .eflags,
7862 .register_offset,8057 .register_offset,
7863 .lea_direct,8058 .lea_direct,
...@@ -7865,7 +8060,7 @@ fn genBinOpMir(...@@ -7865,7 +8060,7 @@ fn genBinOpMir(
7865 .lea_tlv,8060 .lea_tlv,
7866 .lea_frame,8061 .lea_frame,
7867 => switch (off) {8062 => switch (off) {
7868 0 => src_mcv,8063 0 => resolved_src_mcv,
7869 else => .{ .immediate = 0 },8064 else => .{ .immediate = 0 },
7870 },8065 },
7871 .memory => |addr| .{ .memory = @bitCast(@as(i64, @bitCast(addr)) + off) },8066 .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...@@ -7910,19 +8105,25 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M
7910 .lea_tlv,8105 .lea_tlv,
7911 .lea_frame,8106 .lea_frame,
7912 .reserved_frame,8107 .reserved_frame,
8108 .air_ref,
7913 => unreachable, // unmodifiable destination8109 => unreachable, // unmodifiable destination
7914 .register => |dst_reg| {8110 .register => |dst_reg| {
7915 const dst_alias = registerAlias(dst_reg, abi_size);8111 const dst_alias = registerAlias(dst_reg, abi_size);
7916 const dst_lock = self.register_manager.lockReg(dst_reg);8112 const dst_lock = self.register_manager.lockReg(dst_reg);
7917 defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);8113 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) {
7920 .none,8120 .none,
7921 .unreach,8121 .unreach,
7922 .dead,8122 .dead,
7923 .undef,8123 .undef,
7924 .register_overflow,8124 .register_overflow,
7925 .reserved_frame,8125 .reserved_frame,
8126 .air_ref,
7926 => unreachable,8127 => unreachable,
7927 .register => |src_reg| try self.asmRegisterRegister(8128 .register => |src_reg| try self.asmRegisterRegister(
7928 .{ .i_, .mul },8129 .{ .i_, .mul },
...@@ -7938,7 +8139,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M...@@ -7938,7 +8139,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M
7938 Immediate.s(small),8139 Immediate.s(small),
7939 );8140 );
7940 } else {8141 } else {
7941 const src_reg = try self.copyToTmpRegister(dst_ty, src_mcv);8142 const src_reg = try self.copyToTmpRegister(dst_ty, resolved_src_mcv);
7942 return self.genIntMulComplexOpMir(dst_ty, dst_mcv, MCValue{ .register = src_reg });8143 return self.genIntMulComplexOpMir(dst_ty, dst_mcv, MCValue{ .register = src_reg });
7943 }8144 }
7944 },8145 },
...@@ -7954,19 +8155,22 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M...@@ -7954,19 +8155,22 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M
7954 => try self.asmRegisterRegister(8155 => try self.asmRegisterRegister(
7955 .{ .i_, .mul },8156 .{ .i_, .mul },
7956 dst_alias,8157 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),
7958 ),8159 ),
7959 .memory, .indirect, .load_frame => try self.asmRegisterMemory(8160 .memory, .indirect, .load_frame => try self.asmRegisterMemory(
7960 .{ .i_, .mul },8161 .{ .i_, .mul },
7961 dst_alias,8162 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) {
7963 .memory => |addr| .{8164 .memory => |addr| .{
7964 .base = .{ .reg = .ds },8165 .base = .{ .reg = .ds },
7965 .disp = math.cast(i32, @as(i64, @bitCast(addr))) orelse8166 .disp = math.cast(i32, @as(i64, @bitCast(addr))) orelse
7966 return self.asmRegisterRegister(8167 return self.asmRegisterRegister(
7967 .{ .i_, .mul },8168 .{ .i_, .mul },
7968 dst_alias,8169 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 ),
7970 ),8174 ),
7971 },8175 },
7972 .indirect => |reg_off| .{8176 .indirect => |reg_off| .{
...@@ -8124,31 +8328,85 @@ fn airFence(self: *Self, inst: Air.Inst.Index) !void {...@@ -8124,31 +8328,85 @@ fn airFence(self: *Self, inst: Air.Inst.Index) !void {
8124}8328}
81258329
8126fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier) !void {8330fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier) !void {
8127 const mod = self.bin_file.options.module.?;
8128 if (modifier == .always_tail) return self.fail("TODO implement tail calls for x86_64", .{});8331 if (modifier == .always_tail) return self.fail("TODO implement tail calls for x86_64", .{});
8332
8129 const pl_op = self.air.instructions.items(.data)[inst].pl_op;8333 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
8130 const callee = pl_op.operand;
8131 const extra = self.air.extraData(Air.Call, pl_op.payload);8334 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]);8335 const arg_refs: []const Air.Inst.Ref =
8133 const ty = self.typeOf(callee);8336 @ptrCast(self.air.extra[extra.end..][0..extra.data.args_len]);
81348337
8135 const fn_ty = switch (ty.zigTypeTag(mod)) {8338 const ExpectedContents = extern struct {
8136 .Fn => ty,8339 tys: [16][@sizeOf(Type)]u8 align(@alignOf(Type)),
8137 .Pointer => ty.childType(mod),8340 vals: [16][@sizeOf(MCValue)]u8 align(@alignOf(MCValue)),
8138 else => unreachable,
8139 };8341 };
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 };
8141 const fn_info = mod.typeToFunc(fn_ty).?;8390 const fn_info = mod.typeToFunc(fn_ty).?;
81428391
8143 var info = try self.resolveCallingConventionValues(fn_info, args[fn_info.param_types.len..], .call_frame);8392 const ExpectedContents = [16]Type;
8144 defer info.deinit(self);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
8146 // We need a properly aligned and sized call frame to be able to call this function.8405 // We need a properly aligned and sized call frame to be able to call this function.
8147 {8406 {
8148 const needed_call_frame =8407 const needed_call_frame = FrameAlloc.init(.{
8149 FrameAlloc.init(.{8408 .size = call_info.stack_byte_count,
8150 .size = info.stack_byte_count,8409 .alignment = call_info.stack_align,
8151 .alignment = info.stack_align,
8152 });8410 });
8153 const frame_allocs_slice = self.frame_allocs.slice();8411 const frame_allocs_slice = self.frame_allocs.slice();
8154 const stack_frame_size =8412 const stack_frame_size =
...@@ -8164,24 +8422,20 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier...@@ -8164,24 +8422,20 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
81648422
8165 // set stack arguments first because this can clobber registers8423 // set stack arguments first because this can clobber registers
8166 // also clobber spill arguments as we go8424 // also clobber spill arguments as we go
8167 switch (info.return_value.long) {8425 switch (call_info.return_value.long) {
8168 .none, .unreach => {},8426 .none, .unreach => {},
8169 .indirect => |reg_off| try self.spillRegisters(&.{reg_off.reg}),8427 .indirect => |reg_off| try self.spillRegisters(&.{reg_off.reg}),
8170 else => unreachable,8428 else => unreachable,
8171 }8429 }
8172 for (args, info.args) |arg, mc_arg| {8430 for (call_info.args, arg_types, args) |dst_arg, arg_ty, src_arg| switch (dst_arg) {
8173 const arg_ty = self.typeOf(arg);8431 .none => {},
8174 const arg_mcv = try self.resolveInst(arg);8432 .register => |reg| try self.spillRegisters(&.{reg}),
8175 switch (mc_arg) {8433 .load_frame => try self.genCopy(arg_ty, dst_arg, src_arg),
8176 .none => {},8434 else => unreachable,
8177 .register => |reg| try self.spillRegisters(&.{reg}),8435 };
8178 .load_frame => try self.genCopy(arg_ty, mc_arg, arg_mcv),
8179 else => unreachable,
8180 }
8181 }
81828436
8183 // now we are free to set register arguments8437 // 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) {
8185 .none, .unreach => null,8439 .none, .unreach => null,
8186 .indirect => |reg_off| lock: {8440 .indirect => |reg_off| lock: {
8187 const ret_ty = fn_info.return_type.toType();8441 const ret_ty = fn_info.return_type.toType();
...@@ -8189,125 +8443,80 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier...@@ -8189,125 +8443,80 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
8189 try self.genSetReg(reg_off.reg, Type.usize, .{8443 try self.genSetReg(reg_off.reg, Type.usize, .{
8190 .lea_frame = .{ .index = frame_index, .off = -reg_off.off },8444 .lea_frame = .{ .index = frame_index, .off = -reg_off.off },
8191 });8445 });
8192 info.return_value.short = .{ .load_frame = .{ .index = frame_index } };8446 call_info.return_value.short = .{ .load_frame = .{ .index = frame_index } };
8193 break :lock self.register_manager.lockRegAssumeUnused(reg_off.reg);8447 break :lock self.register_manager.lockRegAssumeUnused(reg_off.reg);
8194 },8448 },
8195 else => unreachable,8449 else => unreachable,
8196 };8450 };
8197 defer if (ret_lock) |lock| self.register_manager.unlockReg(lock);8451 defer if (ret_lock) |lock| self.register_manager.unlockReg(lock);
81988452
8199 for (args, info.args) |arg, mc_arg| {8453 for (call_info.args, arg_types, args) |dst_arg, arg_ty, src_arg| {
8200 const arg_ty = self.typeOf(arg);8454 switch (dst_arg) {
8201 const arg_mcv = try self.resolveInst(arg);
8202 switch (mc_arg) {
8203 .none, .load_frame => {},8455 .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),
8205 else => unreachable,8457 else => unreachable,
8206 }8458 }
8207 }8459 }
82088460
8209 // Due to incremental compilation, how function calls are generated depends8461 // Due to incremental compilation, how function calls are generated depends
8210 // on linking.8462 // on linking.
8211 if (try self.air.value(callee, mod)) |func_value| {8463 switch (info) {
8212 const func_key = mod.intern_pool.indexToKey(func_value.ip_index);8464 .air => |callee| if (try self.air.value(callee, mod)) |func_value| {
8213 if (switch (func_key) {8465 const func_key = mod.intern_pool.indexToKey(func_value.ip_index);
8214 .func => |func| func.owner_decl,8466 if (switch (func_key) {
8215 .ptr => |ptr| switch (ptr.addr) {8467 .func => |func| func.owner_decl,
8216 .decl => |decl| decl,8468 .ptr => |ptr| switch (ptr.addr) {
8469 .decl => |decl| decl,
8470 else => null,
8471 },
8217 else => null,8472 else => null,
8218 },8473 }) |owner_decl| {
8219 else => null,8474 if (self.bin_file.cast(link.File.Elf)) |elf_file| {
8220 }) |owner_decl| {8475 const sym_index = try elf_file.getOrCreateMetadataForDecl(owner_decl);
8221 if (self.bin_file.cast(link.File.Elf)) |elf_file| {8476 const sym = elf_file.symbol(sym_index);
8222 const sym_index = try elf_file.getOrCreateMetadataForDecl(owner_decl);8477 sym.flags.needs_got = true;
8223 const sym = elf_file.symbol(sym_index);8478 _ = try sym.getOrCreateGotEntry(sym_index, elf_file);
8224 sym.flags.needs_got = true;8479 _ = try self.addInst(.{
8225 _ = try sym.getOrCreateGotEntry(sym_index, elf_file);8480 .tag = .call,
8226 _ = try self.addInst(.{8481 .ops = .direct_got_reloc,
8227 .tag = .call,8482 .data = .{ .reloc = .{
8228 .ops = .direct_got_reloc,8483 .atom_index = try self.owner.getSymbolIndex(self),
8229 .data = .{ .reloc = .{8484 .sym_index = sym.esym_index,
8230 .atom_index = try self.owner.getSymbolIndex(self),8485 } },
8231 .sym_index = sym.esym_index,8486 });
8232 } },8487 } else if (self.bin_file.cast(link.File.Coff)) |coff_file| {
8233 });8488 const atom = try coff_file.getOrCreateAtomForDecl(owner_decl);
8234 } else if (self.bin_file.cast(link.File.Coff)) |coff_file| {8489 const sym_index = coff_file.getAtom(atom).getSymbolIndex().?;
8235 const atom = try coff_file.getOrCreateAtomForDecl(owner_decl);8490 try self.genSetReg(.rax, Type.usize, .{ .lea_got = sym_index });
8236 const sym_index = coff_file.getAtom(atom).getSymbolIndex().?;8491 try self.asmRegister(.{ ._, .call }, .rax);
8237 try self.genSetReg(.rax, Type.usize, .{ .lea_got = sym_index });8492 } else if (self.bin_file.cast(link.File.MachO)) |macho_file| {
8238 try self.asmRegister(.{ ._, .call }, .rax);8493 const atom = try macho_file.getOrCreateAtomForDecl(owner_decl);
8239 } else if (self.bin_file.cast(link.File.MachO)) |macho_file| {8494 const sym_index = macho_file.getAtom(atom).getSymbolIndex().?;
8240 const atom = try macho_file.getOrCreateAtomForDecl(owner_decl);8495 try self.genSetReg(.rax, Type.usize, .{ .lea_got = sym_index });
8241 const sym_index = macho_file.getAtom(atom).getSymbolIndex().?;8496 try self.asmRegister(.{ ._, .call }, .rax);
8242 try self.genSetReg(.rax, Type.usize, .{ .lea_got = sym_index });8497 } else if (self.bin_file.cast(link.File.Plan9)) |p9| {
8243 try self.asmRegister(.{ ._, .call }, .rax);8498 const atom_index = try p9.seeDecl(owner_decl);
8244 } else if (self.bin_file.cast(link.File.Plan9)) |p9| {8499 const atom = p9.getAtom(atom_index);
8245 const atom_index = try p9.seeDecl(owner_decl);8500 try self.asmMemory(.{ ._, .call }, Memory.sib(.qword, .{
8246 const atom = p9.getAtom(atom_index);8501 .base = .{ .reg = .ds },
8247 try self.asmMemory(.{ ._, .call }, Memory.sib(.qword, .{8502 .disp = @intCast(atom.getOffsetTableAddress(p9)),
8248 .base = .{ .reg = .ds },8503 }));
8249 .disp = @intCast(atom.getOffsetTableAddress(p9)),8504 } else unreachable;
8250 }));8505 } else if (func_value.getExternFunc(mod)) |extern_func| {
8251 } else unreachable;8506 const lib_name = mod.intern_pool.stringToSliceUnwrap(extern_func.lib_name);
8252 } else if (func_value.getExternFunc(mod)) |extern_func| {8507 const decl_name = mod.intern_pool.stringToSlice(mod.declPtr(extern_func.decl).name);
8253 const decl_name = mod.intern_pool.stringToSlice(mod.declPtr(extern_func.decl).name);8508 try self.genExternSymbolRef(.call, lib_name, 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 });
8292 } else {8509 } else {
8293 return self.fail("TODO implement calling extern functions", .{});8510 return self.fail("TODO implement calling bitcasted functions", .{});
8294 }8511 }
8295 } else {8512 } else {
8296 return self.fail("TODO implement calling bitcasted functions", .{});8513 assert(self.typeOf(callee).zigTypeTag(mod) == .Pointer);
8297 }8514 try self.genSetReg(.rax, Type.usize, .{ .air_ref = callee });
8298 } else {8515 try self.asmRegister(.{ ._, .call }, .rax);
8299 assert(ty.zigTypeTag(mod) == .Pointer);8516 },
8300 const mcv = try self.resolveInst(callee);8517 .lib => |lib| try self.genExternSymbolRef(.call, lib.lib, lib.callee),
8301 try self.genSetReg(.rax, Type.usize, mcv);
8302 try self.asmRegister(.{ ._, .call }, .rax);
8303 }8518 }
83048519 return call_info.return_value.short;
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);
8311}8520}
83128521
8313fn airRet(self: *Self, inst: Air.Inst.Index) !void {8522fn airRet(self: *Self, inst: Air.Inst.Index) !void {
...@@ -8357,26 +8566,64 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {...@@ -8357,26 +8566,64 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
8357 const bin_op = self.air.instructions.items(.data)[inst].bin_op;8566 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
8358 const ty = self.typeOf(bin_op.lhs);8567 const ty = self.typeOf(bin_op.lhs);
83598568
8360 try self.spillEflagsIfOccupied();8569 const result: Condition = result: {
8361 self.eflags_inst = inst;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);8609 try self.spillEflagsIfOccupied();
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);
83698610
8370 const rhs_mcv = try self.resolveInst(bin_op.rhs);8611 const lhs_mcv = try self.resolveInst(bin_op.lhs);
8371 const rhs_lock = switch (rhs_mcv) {8612 const lhs_lock = switch (lhs_mcv) {
8372 .register => |reg| self.register_manager.lockReg(reg),8613 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
8373 else => null,8614 else => null,
8374 };8615 };
8375 defer if (rhs_lock) |lock| self.register_manager.unlockReg(lock);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{8625 switch (ty.zigTypeTag(mod)) {
8378 .eflags = switch (ty.zigTypeTag(mod)) {8626 else => {
8379 else => result: {
8380 const abi_size: u16 = @intCast(ty.abiSize(mod));8627 const abi_size: u16 = @intCast(ty.abiSize(mod));
8381 const may_flip: enum {8628 const may_flip: enum {
8382 may_flip,8629 may_flip,
...@@ -8478,7 +8725,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {...@@ -8478,7 +8725,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
8478 },8725 },
8479 );8726 );
8480 },8727 },
8481 .Float => result: {8728 .Float => {
8482 const flipped = switch (op) {8729 const flipped = switch (op) {
8483 .lt, .lte => true,8730 .lt, .lte => true,
8484 .eq, .gte, .gt, .neq => false,8731 .eq, .gte, .gt, .neq => false,
...@@ -8494,7 +8741,8 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {...@@ -8494,7 +8741,8 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
8494 const src_mcv = if (flipped) lhs_mcv else rhs_mcv;8741 const src_mcv = if (flipped) lhs_mcv else rhs_mcv;
84958742
8496 switch (ty.floatBits(self.target.*)) {8743 switch (ty.floatBits(self.target.*)) {
8497 16 => if (self.hasFeature(.f16c)) {8744 16 => {
8745 assert(self.hasFeature(.f16c));
8498 const tmp1_reg = (try self.register_manager.allocReg(null, sse)).to128();8746 const tmp1_reg = (try self.register_manager.allocReg(null, sse)).to128();
8499 const tmp1_mcv = MCValue{ .register = tmp1_reg };8747 const tmp1_mcv = MCValue{ .register = tmp1_reg };
8500 const tmp1_lock = self.register_manager.lockRegAssumeUnused(tmp1_reg);8748 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 {...@@ -8523,9 +8771,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
8523 try self.asmRegisterRegister(.{ .v_ps, .cvtph2 }, tmp1_reg, tmp1_reg);8771 try self.asmRegisterRegister(.{ .v_ps, .cvtph2 }, tmp1_reg, tmp1_reg);
8524 try self.asmRegisterRegister(.{ .v_, .movshdup }, tmp2_reg, tmp1_reg);8772 try self.asmRegisterRegister(.{ .v_, .movshdup }, tmp2_reg, tmp1_reg);
8525 try self.genBinOpMir(.{ ._ss, .ucomi }, ty, tmp1_mcv, tmp2_mcv);8773 try self.genBinOpMir(.{ ._ss, .ucomi }, ty, tmp1_mcv, tmp2_mcv);
8526 } else return self.fail("TODO implement airCmp for {}", .{8774 },
8527 ty.fmt(mod),
8528 }),
8529 32 => try self.genBinOpMir(8775 32 => try self.genBinOpMir(
8530 .{ ._ss, .ucomi },8776 .{ ._ss, .ucomi },
8531 ty,8777 ty,
...@@ -8538,9 +8784,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {...@@ -8538,9 +8784,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
8538 .{ .register = dst_reg },8784 .{ .register = dst_reg },
8539 src_mcv,8785 src_mcv,
8540 ),8786 ),
8541 else => return self.fail("TODO implement airCmp for {}", .{8787 else => unreachable,
8542 ty.fmt(mod),
8543 }),
8544 }8788 }
85458789
8546 break :result switch (if (flipped) op.reverse() else op) {8790 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 {...@@ -8551,9 +8795,11 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
8551 .neq => .nz_or_p,8795 .neq => .nz_or_p,
8552 };8796 };
8553 },8797 },
8554 },8798 }
8555 };8799 };
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 });
8557}8803}
85588804
8559fn airCmpVector(self: *Self, inst: Air.Inst.Index) !void {8805fn airCmpVector(self: *Self, inst: Air.Inst.Index) !void {
...@@ -8571,7 +8817,6 @@ fn airCmpLtErrorsLen(self: *Self, inst: Air.Inst.Index) !void {...@@ -8571,7 +8817,6 @@ fn airCmpLtErrorsLen(self: *Self, inst: Air.Inst.Index) !void {
8571 try self.genLazySymbolRef(.lea, addr_reg, link.File.LazySymbol.initDecl(.const_data, null, mod));8817 try self.genLazySymbolRef(.lea, addr_reg, link.File.LazySymbol.initDecl(.const_data, null, mod));
85728818
8573 try self.spillEflagsIfOccupied();8819 try self.spillEflagsIfOccupied();
8574 self.eflags_inst = inst;
85758820
8576 const op_ty = self.typeOf(un_op);8821 const op_ty = self.typeOf(un_op);
8577 const op_abi_size: u32 = @intCast(op_ty.abiSize(mod));8822 const op_abi_size: u32 = @intCast(op_ty.abiSize(mod));
...@@ -8585,8 +8830,9 @@ fn airCmpLtErrorsLen(self: *Self, inst: Air.Inst.Index) !void {...@@ -8585,8 +8830,9 @@ fn airCmpLtErrorsLen(self: *Self, inst: Air.Inst.Index) !void {
8585 registerAlias(dst_reg, op_abi_size),8830 registerAlias(dst_reg, op_abi_size),
8586 Memory.sib(Memory.PtrSize.fromSize(op_abi_size), .{ .base = .{ .reg = addr_reg } }),8831 Memory.sib(Memory.PtrSize.fromSize(op_abi_size), .{ .base = .{ .reg = addr_reg } }),
8587 );8832 );
8588 const result = MCValue{ .eflags = .b };8833
8589 return self.finishAir(inst, result, .{ un_op, .none, .none });8834 self.eflags_inst = inst;
8835 return self.finishAir(inst, .{ .eflags = .b }, .{ un_op, .none, .none });
8590}8836}
85918837
8592fn airTry(self: *Self, inst: Air.Inst.Index) !void {8838fn 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...@@ -8776,7 +9022,6 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC
8776 }9022 }
87779023
8778 try self.spillEflagsIfOccupied();9024 try self.spillEflagsIfOccupied();
8779 self.eflags_inst = inst;
87809025
8781 const pl_ty = opt_ty.optionalChild(mod);9026 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...@@ -8785,6 +9030,7 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC
8785 else9030 else
8786 .{ .off = @intCast(pl_ty.abiSize(mod)), .ty = Type.bool };9031 .{ .off = @intCast(pl_ty.abiSize(mod)), .ty = Type.bool };
87879032
9033 self.eflags_inst = inst;
8788 switch (opt_mcv) {9034 switch (opt_mcv) {
8789 .none,9035 .none,
8790 .unreach,9036 .unreach,
...@@ -8799,6 +9045,7 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC...@@ -8799,6 +9045,7 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC
8799 .lea_tlv,9045 .lea_tlv,
8800 .lea_frame,9046 .lea_frame,
8801 .reserved_frame,9047 .reserved_frame,
9048 .air_ref,
8802 => unreachable,9049 => unreachable,
88039050
8804 .register => |opt_reg| {9051 .register => |opt_reg| {
...@@ -8866,7 +9113,6 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC...@@ -8866,7 +9113,6 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC
8866fn isNullPtr(self: *Self, inst: Air.Inst.Index, ptr_ty: Type, ptr_mcv: MCValue) !MCValue {9113fn isNullPtr(self: *Self, inst: Air.Inst.Index, ptr_ty: Type, ptr_mcv: MCValue) !MCValue {
8867 const mod = self.bin_file.options.module.?;9114 const mod = self.bin_file.options.module.?;
8868 try self.spillEflagsIfOccupied();9115 try self.spillEflagsIfOccupied();
8869 self.eflags_inst = inst;
88709116
8871 const opt_ty = ptr_ty.childType(mod);9117 const opt_ty = ptr_ty.childType(mod);
8872 const pl_ty = opt_ty.optionalChild(mod);9118 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)...@@ -8892,6 +9138,8 @@ fn isNullPtr(self: *Self, inst: Air.Inst.Index, ptr_ty: Type, ptr_mcv: MCValue)
8892 }),9138 }),
8893 Immediate.u(0),9139 Immediate.u(0),
8894 );9140 );
9141
9142 self.eflags_inst = inst;
8895 return .{ .eflags = .e };9143 return .{ .eflags = .e };
8896}9144}
88979145
...@@ -8904,9 +9152,6 @@ fn isErr(self: *Self, maybe_inst: ?Air.Inst.Index, ty: Type, operand: MCValue) !...@@ -8904,9 +9152,6 @@ fn isErr(self: *Self, maybe_inst: ?Air.Inst.Index, ty: Type, operand: MCValue) !
8904 }9152 }
89059153
8906 try self.spillEflagsIfOccupied();9154 try self.spillEflagsIfOccupied();
8907 if (maybe_inst) |inst| {
8908 self.eflags_inst = inst;
8909 }
89109155
8911 const err_off = errUnionErrorOffset(ty.errorUnionPayload(mod), mod);9156 const err_off = errUnionErrorOffset(ty.errorUnionPayload(mod), mod);
8912 switch (operand) {9157 switch (operand) {
...@@ -8944,6 +9189,7 @@ fn isErr(self: *Self, maybe_inst: ?Air.Inst.Index, ty: Type, operand: MCValue) !...@@ -8944,6 +9189,7 @@ fn isErr(self: *Self, maybe_inst: ?Air.Inst.Index, ty: Type, operand: MCValue) !
8944 else => return self.fail("TODO implement isErr for {}", .{operand}),9189 else => return self.fail("TODO implement isErr for {}", .{operand}),
8945 }9190 }
89469191
9192 if (maybe_inst) |inst| self.eflags_inst = inst;
8947 return MCValue{ .eflags = .a };9193 return MCValue{ .eflags = .a };
8948}9194}
89499195
...@@ -9825,6 +10071,7 @@ fn genCopy(self: *Self, ty: Type, dst_mcv: MCValue, src_mcv: MCValue) InnerError...@@ -9825,6 +10071,7 @@ fn genCopy(self: *Self, ty: Type, dst_mcv: MCValue, src_mcv: MCValue) InnerError
9825 .lea_tlv,10071 .lea_tlv,
9826 .lea_frame,10072 .lea_frame,
9827 .reserved_frame,10073 .reserved_frame,
10074 .air_ref,
9828 => unreachable, // unmodifiable destination10075 => unreachable, // unmodifiable destination
9829 .register => |reg| try self.genSetReg(reg, ty, src_mcv),10076 .register => |reg| try self.genSetReg(reg, ty, src_mcv),
9830 .register_offset => |dst_reg_off| try self.genSetReg(dst_reg_off.reg, ty, switch (src_mcv) {10077 .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...@@ -10150,6 +10397,7 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr
10150 @tagName(self.bin_file.tag),10397 @tagName(self.bin_file.tag),
10151 });10398 });
10152 },10399 },
10400 .air_ref => |ref| try self.genSetReg(dst_reg, ty, try self.resolveInst(ref)),
10153 }10401 }
10154}10402}
1015510403
...@@ -10262,6 +10510,7 @@ fn genSetMem(self: *Self, base: Memory.Base, disp: i32, ty: Type, src_mcv: MCVal...@@ -10262,6 +10510,7 @@ fn genSetMem(self: *Self, base: Memory.Base, disp: i32, ty: Type, src_mcv: MCVal
10262 },10510 },
10263 else => try self.genInlineMemcpy(dst_ptr_mcv, src_mcv.address(), .{ .immediate = abi_size }),10511 else => try self.genInlineMemcpy(dst_ptr_mcv, src_mcv.address(), .{ .immediate = abi_size }),
10264 },10512 },
10513 .air_ref => |ref| try self.genSetMem(base, disp, ty, try self.resolveInst(ref)),
10265 }10514 }
10266}10515}
1026710516
...@@ -10281,6 +10530,51 @@ fn genInlineMemset(self: *Self, dst_ptr: MCValue, value: MCValue, len: MCValue)...@@ -10281,6 +10530,51 @@ fn genInlineMemset(self: *Self, dst_ptr: MCValue, value: MCValue, len: MCValue)
10281 try self.asmOpOnly(.{ .@"rep _sb", .sto });10530 try self.asmOpOnly(.{ .@"rep _sb", .sto });
10282}10531}
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
10284fn genLazySymbolRef(10578fn genLazySymbolRef(
10285 self: *Self,10579 self: *Self,
10286 comptime tag: Mir.Inst.Tag,10580 comptime tag: Mir.Inst.Tag,
...@@ -10480,106 +10774,150 @@ fn airFloatFromInt(self: *Self, inst: Air.Inst.Index) !void {...@@ -10480,106 +10774,150 @@ fn airFloatFromInt(self: *Self, inst: Air.Inst.Index) !void {
10480 const mod = self.bin_file.options.module.?;10774 const mod = self.bin_file.options.module.?;
10481 const ty_op = self.air.instructions.items(.data)[inst].ty_op;10775 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
10483 const src_ty = self.typeOf(ty_op.operand);10780 const src_ty = self.typeOf(ty_op.operand);
10484 const src_bits: u32 = @intCast(src_ty.bitSize(mod));10781 const src_bits: u32 = @intCast(src_ty.bitSize(mod));
10485 const src_signedness =10782 const src_signedness =
10486 if (src_ty.isAbiInt(mod)) src_ty.intInfo(mod).signedness else .unsigned;10783 if (src_ty.isAbiInt(mod)) src_ty.intInfo(mod).signedness else .unsigned;
10487 const dst_ty = self.typeOfIndex(inst);
10488
10489 const src_size = math.divCeil(u32, @max(switch (src_signedness) {10784 const src_size = math.divCeil(u32, @max(switch (src_signedness) {
10490 .signed => src_bits,10785 .signed => src_bits,
10491 .unsigned => src_bits + 1,10786 .unsigned => src_bits + 1,
10492 }, 32), 8) catch unreachable;10787 }, 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);10789 const result = result: {
10498 const src_reg = if (src_mcv.isRegister())10790 if (switch (dst_bits) {
10499 src_mcv.getReg().?10791 16, 80, 128 => true,
10500 else10792 32, 64 => src_size > 8 and src_size < 16,
10501 try self.copyToTmpRegister(src_ty, src_mcv);10793 else => unreachable,
10502 const src_lock = self.register_manager.lockRegAssumeUnused(src_reg);10794 }) {
10503 defer self.register_manager.unlockReg(src_lock);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));10814 const src_mcv = try self.resolveInst(ty_op.operand);
10508 const dst_mcv = MCValue{ .register = dst_reg };10815 const src_reg = if (src_mcv.isRegister())
10509 const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg);10816 src_mcv.getReg().?
10510 defer self.register_manager.unlockReg(dst_lock);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)) {10822 if (src_bits < src_size * 8) try self.truncateRegister(src_ty, src_reg);
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 }
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 });
10531}10850}
1053210851
10533fn airIntFromFloat(self: *Self, inst: Air.Inst.Index) !void {10852fn airIntFromFloat(self: *Self, inst: Air.Inst.Index) !void {
10534 const mod = self.bin_file.options.module.?;10853 const mod = self.bin_file.options.module.?;
10535 const ty_op = self.air.instructions.items(.data)[inst].ty_op;10854 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
1053610855
10537 const src_ty = self.typeOf(ty_op.operand);
10538 const dst_ty = self.typeOfIndex(inst);10856 const dst_ty = self.typeOfIndex(inst);
10539 const dst_bits: u32 = @intCast(dst_ty.bitSize(mod));10857 const dst_bits: u32 = @intCast(dst_ty.bitSize(mod));
10540 const dst_signedness =10858 const dst_signedness =
10541 if (dst_ty.isAbiInt(mod)) dst_ty.intInfo(mod).signedness else .unsigned;10859 if (dst_ty.isAbiInt(mod)) dst_ty.intInfo(mod).signedness else .unsigned;
10542
10543 const dst_size = math.divCeil(u32, @max(switch (dst_signedness) {10860 const dst_size = math.divCeil(u32, @max(switch (dst_signedness) {
10544 .signed => dst_bits,10861 .signed => dst_bits,
10545 .unsigned => dst_bits + 1,10862 .unsigned => dst_bits + 1,
10546 }, 32), 8) catch unreachable;10863 }, 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);10865 const src_ty = self.typeOf(ty_op.operand);
10552 const src_reg = if (src_mcv.isRegister())10866 const src_bits = src_ty.floatBits(self.target.*);
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);
1055810867
10559 const dst_reg = try self.register_manager.allocReg(inst, regClassForType(dst_ty, mod));10868 const result = result: {
10560 const dst_mcv = MCValue{ .register = dst_reg };10869 if (switch (src_bits) {
10561 const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg);10870 16, 80, 128 => true,
10562 defer self.register_manager.unlockReg(dst_lock);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(10889 if (dst_size > 8) return self.fail("TODO implement airIntFromFloat from {} to {}", .{
10565 @as(?Mir.Inst.FixedTag, switch (src_ty.zigTypeTag(mod)) {10890 src_ty.fmt(mod), dst_ty.fmt(mod),
10566 .Float => switch (src_ty.floatBits(self.target.*)) {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) {
10567 32 => if (self.hasFeature(.avx)) .{ .v_, .cvttss2si } else .{ ._, .cvttss2si },10908 32 => if (self.hasFeature(.avx)) .{ .v_, .cvttss2si } else .{ ._, .cvttss2si },
10568 64 => if (self.hasFeature(.avx)) .{ .v_, .cvttsd2si } else .{ ._, .cvttsd2si },10909 64 => if (self.hasFeature(.avx)) .{ .v_, .cvttsd2si } else .{ ._, .cvttsd2si },
10569 16, 80, 128 => null,
10570 else => unreachable,10910 else => unreachable,
10571 },10911 },
10572 else => null,10912 registerAlias(dst_reg, dst_size),
10573 }) orelse return self.fail("TODO implement airIntFromFloat from {} to {}", .{10913 src_reg.to128(),
10574 src_ty.fmt(self.bin_file.options.module.?), dst_ty.fmt(self.bin_file.options.module.?),10914 );
10575 }),
10576 registerAlias(dst_reg, dst_size),
10577 src_reg.to128(),
10578 );
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 });
10583}10921}
1058410922
10585fn airCmpxchg(self: *Self, inst: Air.Inst.Index) !void {10923fn airCmpxchg(self: *Self, inst: Air.Inst.Index) !void {
...@@ -11906,7 +12244,7 @@ const CallMCValues = struct {...@@ -11906,7 +12244,7 @@ const CallMCValues = struct {
11906fn resolveCallingConventionValues(12244fn resolveCallingConventionValues(
11907 self: *Self,12245 self: *Self,
11908 fn_info: InternPool.Key.FuncType,12246 fn_info: InternPool.Key.FuncType,
11909 var_args: []const Air.Inst.Ref,12247 var_args: []const Type,
11910 stack_frame_base: FrameIndex,12248 stack_frame_base: FrameIndex,
11911) !CallMCValues {12249) !CallMCValues {
11912 const mod = self.bin_file.options.module.?;12250 const mod = self.bin_file.options.module.?;
...@@ -11919,9 +12257,7 @@ fn resolveCallingConventionValues(...@@ -11919,9 +12257,7 @@ fn resolveCallingConventionValues(
11919 dest.* = src.toType();12257 dest.* = src.toType();
11920 }12258 }
11921 // TODO: promote var arg types12259 // TODO: promote var arg types
11922 for (param_types[fn_info.param_types.len..], var_args) |*param_ty, arg| {12260 for (param_types[fn_info.param_types.len..], var_args) |*param_ty, arg_ty| param_ty.* = arg_ty;
11923 param_ty.* = self.typeOf(arg);
11924 }
1192512261
11926 var result: CallMCValues = .{12262 var result: CallMCValues = .{
11927 .args = try self.gpa.alloc(MCValue, param_types.len),12263 .args = try self.gpa.alloc(MCValue, param_types.len),
...@@ -12230,3 +12566,52 @@ fn typeOfIndex(self: *Self, inst: Air.Inst.Index) Type {...@@ -12230,3 +12566,52 @@ fn typeOfIndex(self: *Self, inst: Air.Inst.Index) Type {
12230 const mod = self.bin_file.options.module.?;12566 const mod = self.bin_file.options.module.?;
12231 return self.air.typeOfIndex(inst, &mod.intern_pool);12567 return self.air.typeOfIndex(inst, &mod.intern_pool);
12232}12568}
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 {...@@ -444,7 +444,7 @@ pub const SysV = struct {
444 /// These registers need to be preserved (saved on the stack) and restored by the caller before444 /// These registers need to be preserved (saved on the stack) and restored by the caller before
445 /// the caller relinquishes control to a subroutine via call instruction (or similar).445 /// the caller relinquishes control to a subroutine via call instruction (or similar).
446 /// In other words, these registers are free to use by the callee.446 /// 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
449 pub const c_abi_int_param_regs = [_]Register{ .rdi, .rsi, .rdx, .rcx, .r8, .r9 };449 pub const c_abi_int_param_regs = [_]Register{ .rdi, .rsi, .rdx, .rcx, .r8, .r9 };
450 pub const c_abi_int_return_regs = [_]Register{ .rax, .rdx };450 pub const c_abi_int_return_regs = [_]Register{ .rax, .rdx };
...@@ -457,7 +457,7 @@ pub const Win64 = struct {...@@ -457,7 +457,7 @@ pub const Win64 = struct {
457 /// These registers need to be preserved (saved on the stack) and restored by the caller before457 /// These registers need to be preserved (saved on the stack) and restored by the caller before
458 /// the caller relinquishes control to a subroutine via call instruction (or similar).458 /// the caller relinquishes control to a subroutine via call instruction (or similar).
459 /// In other words, these registers are free to use by the callee.459 /// 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
462 pub const c_abi_int_param_regs = [_]Register{ .rcx, .rdx, .r8, .r9 };462 pub const c_abi_int_param_regs = [_]Register{ .rcx, .rdx, .r8, .r9 };
463 pub const c_abi_int_return_regs = [_]Register{.rax};463 pub const c_abi_int_return_regs = [_]Register{.rax};
src/codegen/llvm.zig-9
...@@ -6394,15 +6394,6 @@ pub const FuncGen = struct {...@@ -6394,15 +6394,6 @@ pub const FuncGen = struct {
6394 const fn_ty = try mod.funcType(.{6394 const fn_ty = try mod.funcType(.{
6395 .param_types = &.{},6395 .param_types = &.{},
6396 .return_type = .void_type,6396 .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,
6406 });6397 });
6407 const fn_di_ty = try o.lowerDebugType(fn_ty, .full);6398 const fn_di_ty = try o.lowerDebugType(fn_ty, .full);
6408 const subprogram = dib.createFunction(6399 const subprogram = dib.createFunction(
test/behavior/abs.zig+2-1
...@@ -86,9 +86,10 @@ test "@abs floats" {...@@ -86,9 +86,10 @@ test "@abs floats" {
86 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO86 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
87 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO87 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
88 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;88 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
90 try comptime testAbsFloats(f16);91 try comptime testAbsFloats(f16);
91 if (builtin.zig_backend != .stage2_x86_64) try testAbsFloats(f16);92 try testAbsFloats(f16);
92 try comptime testAbsFloats(f32);93 try comptime testAbsFloats(f32);
93 try testAbsFloats(f32);94 try testAbsFloats(f32);
94 try comptime testAbsFloats(f64);95 try comptime testAbsFloats(f64);
test/behavior/asm.zig-2
...@@ -85,7 +85,6 @@ test "alternative constraints" {...@@ -85,7 +85,6 @@ test "alternative constraints" {
8585
86test "sized integer/float in asm input" {86test "sized integer/float in asm input" {
87 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO87 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
88 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
89 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO88 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
90 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO89 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
91 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO90 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
...@@ -137,7 +136,6 @@ test "sized integer/float in asm input" {...@@ -137,7 +136,6 @@ test "sized integer/float in asm input" {
137136
138test "struct/array/union types as input values" {137test "struct/array/union types as input values" {
139 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO138 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
140 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
141 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO139 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
142 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO140 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
143 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO141 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" {...@@ -470,7 +470,6 @@ test "@bitCast of packed struct of bools all true" {
470 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO470 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
471 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO471 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
472 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO472 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
473 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
474 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO473 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
475 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO474 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
476475
...@@ -492,7 +491,6 @@ test "@bitCast of packed struct of bools all false" {...@@ -492,7 +491,6 @@ test "@bitCast of packed struct of bools all false" {
492 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO491 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
493 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO492 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
494 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO493 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
495 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
496 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO494 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
497 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO495 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" {...@@ -9,9 +9,10 @@ test "export a function twice" {
9 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;9 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
10 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;10 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
11 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;11 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
12 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
13 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO12 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
14 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;13 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
15 if (builtin.os.tag == .macos and builtin.zig_backend == .stage2_c) {16 if (builtin.os.tag == .macos and builtin.zig_backend == .stage2_c) {
16 // TODO: test.c: error: aliases are not supported on darwin17 // TODO: test.c: error: aliases are not supported on darwin
17 return error.SkipZigTest;18 return error.SkipZigTest;
test/behavior/bugs/529.zig+1-1
...@@ -11,11 +11,11 @@ comptime {...@@ -11,11 +11,11 @@ comptime {
11const builtin = @import("builtin");11const builtin = @import("builtin");
1212
13test "issue 529 fixed" {13test "issue 529 fixed" {
14 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
15 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO14 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
16 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO15 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
17 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO16 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
18 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;17 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
20 @import("529_other_file.zig").issue529(null);20 @import("529_other_file.zig").issue529(null);
21 issue529(null);21 issue529(null);
test/behavior/cast.zig-23
...@@ -1611,7 +1611,6 @@ test "coercion from single-item pointer to @as to slice" {...@@ -1611,7 +1611,6 @@ test "coercion from single-item pointer to @as to slice" {
1611test "peer type resolution: const sentinel slice and mutable non-sentinel slice" {1611test "peer type resolution: const sentinel slice and mutable non-sentinel slice" {
1612 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1612 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1613 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1613 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1614 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1615 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO1614 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1616 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1615 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1617 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO1616 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" {...@@ -1664,7 +1663,6 @@ test "peer type resolution: float and comptime-known fixed-width integer" {
1664test "peer type resolution: same array type with sentinel" {1663test "peer type resolution: same array type with sentinel" {
1665 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1664 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1666 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1665 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1667 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1668 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO1666 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1669 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1667 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1670 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO1668 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
...@@ -1687,7 +1685,6 @@ test "peer type resolution: same array type with sentinel" {...@@ -1687,7 +1685,6 @@ test "peer type resolution: same array type with sentinel" {
1687test "peer type resolution: array with sentinel and array without sentinel" {1685test "peer type resolution: array with sentinel and array without sentinel" {
1688 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1686 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1689 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1687 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1690 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1691 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO1688 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1692 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1689 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1693 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO1690 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" {...@@ -1710,7 +1707,6 @@ test "peer type resolution: array with sentinel and array without sentinel" {
1710test "peer type resolution: array and vector with same child type" {1707test "peer type resolution: array and vector with same child type" {
1711 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1708 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1712 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1709 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1713 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1714 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO1710 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1715 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1711 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1716 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO1712 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...@@ -1756,7 +1752,6 @@ test "peer type resolution: array with smaller child type and vector with larger
1756test "peer type resolution: error union and optional of same type" {1752test "peer type resolution: error union and optional of same type" {
1757 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1753 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1758 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1754 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1759 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1760 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO1755 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1761 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1756 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1762 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO1757 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" {...@@ -1780,7 +1775,6 @@ test "peer type resolution: error union and optional of same type" {
1780test "peer type resolution: C pointer and @TypeOf(null)" {1775test "peer type resolution: C pointer and @TypeOf(null)" {
1781 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1776 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1782 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1777 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1783 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1784 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO1778 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1785 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1779 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1786 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO1780 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
...@@ -1803,7 +1797,6 @@ test "peer type resolution: C pointer and @TypeOf(null)" {...@@ -1803,7 +1797,6 @@ test "peer type resolution: C pointer and @TypeOf(null)" {
1803test "peer type resolution: three-way resolution combines error set and optional" {1797test "peer type resolution: three-way resolution combines error set and optional" {
1804 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1798 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1805 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1799 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1806 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1807 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO1800 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1808 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1801 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1809 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO1802 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...@@ -1846,7 +1839,6 @@ test "peer type resolution: three-way resolution combines error set and optional
1846test "peer type resolution: vector and optional vector" {1839test "peer type resolution: vector and optional vector" {
1847 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1840 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1848 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1841 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1849 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1850 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO1842 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1851 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1843 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1852 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO1844 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
...@@ -1869,7 +1861,6 @@ test "peer type resolution: vector and optional vector" {...@@ -1869,7 +1861,6 @@ test "peer type resolution: vector and optional vector" {
1869test "peer type resolution: optional fixed-width int and comptime_int" {1861test "peer type resolution: optional fixed-width int and comptime_int" {
1870 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1862 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1871 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1863 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1872 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1873 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO1864 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1874 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1865 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1875 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO1866 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" {...@@ -1892,7 +1883,6 @@ test "peer type resolution: optional fixed-width int and comptime_int" {
1892test "peer type resolution: array and tuple" {1883test "peer type resolution: array and tuple" {
1893 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1884 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1894 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1885 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1895 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1896 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO1886 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1897 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1887 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1898 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO1888 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
...@@ -1916,7 +1906,6 @@ test "peer type resolution: array and tuple" {...@@ -1916,7 +1906,6 @@ test "peer type resolution: array and tuple" {
1916test "peer type resolution: vector and tuple" {1906test "peer type resolution: vector and tuple" {
1917 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1907 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1918 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1908 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1919 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1920 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO1909 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1921 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1910 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1922 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO1911 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
...@@ -1940,7 +1929,6 @@ test "peer type resolution: vector and tuple" {...@@ -1940,7 +1929,6 @@ test "peer type resolution: vector and tuple" {
1940test "peer type resolution: vector and array and tuple" {1929test "peer type resolution: vector and array and tuple" {
1941 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1930 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1942 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1931 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1943 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1944 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO1932 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1945 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1933 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1946 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO1934 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
...@@ -1983,7 +1971,6 @@ test "peer type resolution: vector and array and tuple" {...@@ -1983,7 +1971,6 @@ test "peer type resolution: vector and array and tuple" {
1983test "peer type resolution: empty tuple pointer and slice" {1971test "peer type resolution: empty tuple pointer and slice" {
1984 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1972 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1985 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1973 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1986 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1987 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO1974 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1988 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1975 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1989 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO1976 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
...@@ -2005,7 +1992,6 @@ test "peer type resolution: empty tuple pointer and slice" {...@@ -2005,7 +1992,6 @@ test "peer type resolution: empty tuple pointer and slice" {
2005test "peer type resolution: tuple pointer and slice" {1992test "peer type resolution: tuple pointer and slice" {
2006 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1993 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
2007 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1994 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2008 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
2009 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO1995 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
2010 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1996 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
2011 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO1997 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
...@@ -2027,7 +2013,6 @@ test "peer type resolution: tuple pointer and slice" {...@@ -2027,7 +2013,6 @@ test "peer type resolution: tuple pointer and slice" {
2027test "peer type resolution: tuple pointer and optional slice" {2013test "peer type resolution: tuple pointer and optional slice" {
2028 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO2014 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
2029 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO2015 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2030 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
2031 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO2016 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
2032 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO2017 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
2033 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO2018 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
...@@ -2049,7 +2034,6 @@ test "peer type resolution: tuple pointer and optional slice" {...@@ -2049,7 +2034,6 @@ test "peer type resolution: tuple pointer and optional slice" {
2049test "peer type resolution: many compatible pointers" {2034test "peer type resolution: many compatible pointers" {
2050 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO2035 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
2051 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO2036 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2052 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
2053 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO2037 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
2054 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO2038 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
2055 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO2039 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
...@@ -2116,7 +2100,6 @@ test "peer type resolution: many compatible pointers" {...@@ -2116,7 +2100,6 @@ test "peer type resolution: many compatible pointers" {
2116test "peer type resolution: tuples with comptime fields" {2100test "peer type resolution: tuples with comptime fields" {
2117 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO2101 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
2118 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO2102 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2119 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
2120 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO2103 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
2121 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO2104 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
2122 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO2105 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
...@@ -2149,7 +2132,6 @@ test "peer type resolution: tuples with comptime fields" {...@@ -2149,7 +2132,6 @@ test "peer type resolution: tuples with comptime fields" {
2149test "peer type resolution: C pointer and many pointer" {2132test "peer type resolution: C pointer and many pointer" {
2150 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO2133 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
2151 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO2134 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2152 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
2153 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO2135 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
2154 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO2136 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
2155 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO2137 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
...@@ -2173,7 +2155,6 @@ test "peer type resolution: C pointer and many pointer" {...@@ -2173,7 +2155,6 @@ test "peer type resolution: C pointer and many pointer" {
2173test "peer type resolution: pointer attributes are combined correctly" {2155test "peer type resolution: pointer attributes are combined correctly" {
2174 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO2156 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
2175 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO2157 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2176 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
2177 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO2158 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
2178 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO2159 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
2179 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO2160 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
...@@ -2218,7 +2199,6 @@ test "peer type resolution: pointer attributes are combined correctly" {...@@ -2218,7 +2199,6 @@ test "peer type resolution: pointer attributes are combined correctly" {
2218test "cast builtins can wrap result in optional" {2199test "cast builtins can wrap result in optional" {
2219 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO2200 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
2220 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO2201 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2221 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
2222 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO2202 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
2223 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO2203 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
2224 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO2204 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
...@@ -2258,7 +2238,6 @@ test "cast builtins can wrap result in optional" {...@@ -2258,7 +2238,6 @@ test "cast builtins can wrap result in optional" {
2258test "cast builtins can wrap result in error union" {2238test "cast builtins can wrap result in error union" {
2259 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO2239 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
2260 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO2240 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2261 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
2262 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO2241 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
2263 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO2242 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
22642243
...@@ -2298,7 +2277,6 @@ test "cast builtins can wrap result in error union" {...@@ -2298,7 +2277,6 @@ test "cast builtins can wrap result in error union" {
2298test "cast builtins can wrap result in error union and optional" {2277test "cast builtins can wrap result in error union and optional" {
2299 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO2278 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
2300 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO2279 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2301 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
2302 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO2280 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
2303 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO2281 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
2304 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO2282 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
...@@ -2496,7 +2474,6 @@ test "@as does not corrupt values with incompatible representations" {...@@ -2496,7 +2474,6 @@ test "@as does not corrupt values with incompatible representations" {
24962474
2497test "result information is preserved through many nested structures" {2475test "result information is preserved through many nested structures" {
2498 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO2476 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
2499 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
2500 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO2477 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
2501 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO2478 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2502 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO2479 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
test/behavior/defer.zig-1
...@@ -133,7 +133,6 @@ test "errdefer with payload" {...@@ -133,7 +133,6 @@ test "errdefer with payload" {
133}133}
134134
135test "reference to errdefer payload" {135test "reference to errdefer payload" {
136 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
137 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO136 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
138 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO137 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
139 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO138 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
test/behavior/floatop.zig+907-703
...@@ -2,16 +2,8 @@ const std = @import("std");...@@ -2,16 +2,8 @@ const std = @import("std");
2const builtin = @import("builtin");2const builtin = @import("builtin");
3const expect = std.testing.expect;3const expect = std.testing.expect;
4const math = std.math;4const math = std.math;
5const pi = std.math.pi;5
6const e = std.math.e;6const epsilon_16 = 0.002;
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;
15const epsilon = 0.000001;7const epsilon = 0.000001;
168
17fn epsForType(comptime T: type) T {9fn epsForType(comptime T: type) T {
...@@ -21,44 +13,195 @@ fn epsForType(comptime T: type) T {...@@ -21,44 +13,195 @@ fn epsForType(comptime T: type) T {
21 };13 };
22}14}
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" {
25 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO119 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();122 try testCmp(f32);
28 try comptime testFloatComparisons();123 try comptime testCmp(f32);
124 try testCmp(f64);
125 try comptime testCmp(f64);
29}126}
30127
31fn testFloatComparisons() !void {128test "cmp f128" {
32 inline for ([_]type{ f16, f32, f64, f128 }) |ty| {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 {
33 // No decimal part150 // No decimal part
34 {151 var x: T = 1.0;
35 const x: ty = 1.0;152 try expect(x == 1.0);
36 try expect(x == 1);153 try expect(x != 0.0);
37 try expect(x != 0);154 try expect(x > 0.0);
38 try expect(x > 0);155 try expect(x < 2.0);
39 try expect(x < 2);156 try expect(x >= 1.0);
40 try expect(x >= 1);157 try expect(x <= 1.0);
41 try expect(x <= 1);158 }
42 }159 {
43 // Non-zero decimal part160 // Non-zero decimal part
44 {161 var x: T = 1.5;
45 const x: ty = 1.5;162 try expect(x != 1.0);
46 try expect(x != 1);163 try expect(x != 2.0);
47 try expect(x != 2);164 try expect(x > 1.0);
48 try expect(x > 1);165 try expect(x < 2.0);
49 try expect(x < 2);166 try expect(x >= 1.0);
50 try expect(x >= 1);167 try expect(x <= 2.0);
51 try expect(x <= 2);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));
52 }195 }
53 }196 }
54}197}
55198
56test "different sized float comparisons" {199test "different sized float comparisons" {
57 if (no_x86_64_hardware_f16_support) return error.SkipZigTest; // TODO
58 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO200 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
59 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO201 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
60 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO202 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
61 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;203 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
63 try testDifferentSizedFloatComparisons();206 try testDifferentSizedFloatComparisons();
64 try comptime testDifferentSizedFloatComparisons();207 try comptime testDifferentSizedFloatComparisons();
...@@ -70,27 +213,6 @@ fn testDifferentSizedFloatComparisons() !void {...@@ -70,27 +213,6 @@ fn testDifferentSizedFloatComparisons() !void {
70 try expect(a < b);213 try expect(a < b);
71}214}
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
94// TODO This is waiting on library support for the Windows build (not sure why the other's don't need it)216// TODO This is waiting on library support for the Windows build (not sure why the other's don't need it)
95//test "@nearbyint" {217//test "@nearbyint" {
96// comptime testNearbyInt();218// comptime testNearbyInt();
...@@ -119,42 +241,93 @@ test "negative f128 intFromFloat at compile-time" {...@@ -119,42 +241,93 @@ test "negative f128 intFromFloat at compile-time" {
119 try expect(@as(i64, -2) == b);241 try expect(@as(i64, -2) == b);
120}242}
121243
122test "@sqrt" {244test "@sqrt f16" {
123 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO245 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
124 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO246 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
125 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO247 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
126 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;248 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();251 try testSqrt(f16);
129 try testSqrt();252 try comptime testSqrt(f16);
130}253}
131254
132fn testSqrt() !void {255test "@sqrt f32/f64" {
133 try expect(@sqrt(@as(f16, 4)) == 2);256 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
134 try expect(@sqrt(@as(f32, 9)) == 3);257 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
135 try expect(@sqrt(@as(f64, 25)) == 5);258 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
136 try expect(math.approxEqAbs(f32, @sqrt(@as(f32, 1.1)), 1.0488088481701516, epsilon));259 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
137 try expect(math.approxEqAbs(f32, @sqrt(@as(f32, 2.0)), 1.4142135623730950, epsilon));260 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest;
138261
139 if (false) {262 try testSqrt(f32);
140 if (has_f80_rt) {263 try comptime testSqrt(f32);
141 // TODO https://github.com/ziglang/zig/issues/10875264 try testSqrt(f64);
142 if (builtin.os.tag != .freebsd) {265 try comptime testSqrt(f64);
143 var a: f80 = 25;266}
144 try expect(@sqrt(a) == 5);267
145 }268test "@sqrt f80/f128/c_longdouble" {
146 }269 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
147 {270 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
148 const a: comptime_float = 25.0;271 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
149 try expect(@sqrt(a) == 5.0);272 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
150 }273 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
151 // TODO test f128, and c_longdouble274
152 // https://github.com/ziglang/zig/issues/4026275 if (builtin.os.tag == .freebsd) {
153 //{276 // TODO https://github.com/ziglang/zig/issues/10875
154 // var a: f128 = 49;277 return error.SkipZigTest;
155 //try expect(@sqrt(a) == 7);
156 //}
157 }278 }
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)));
158}331}
159332
160test "@sqrt with vectors" {333test "@sqrt with vectors" {
...@@ -163,8 +336,8 @@ test "@sqrt with vectors" {...@@ -163,8 +336,8 @@ test "@sqrt with vectors" {
163 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO336 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
164 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;337 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
165338
166 try comptime testSqrtWithVectors();
167 try testSqrtWithVectors();339 try testSqrtWithVectors();
340 try comptime testSqrtWithVectors();
168}341}
169342
170fn testSqrtWithVectors() !void {343fn testSqrtWithVectors() !void {
...@@ -176,88 +349,64 @@ fn testSqrtWithVectors() !void {...@@ -176,88 +349,64 @@ fn testSqrtWithVectors() !void {
176 try expect(math.approxEqAbs(f32, @sqrt(@as(f32, 4.4)), result[3], epsilon));349 try expect(math.approxEqAbs(f32, @sqrt(@as(f32, 4.4)), result[3], epsilon));
177}350}
178351
179test "more @sqrt f16 tests" {352test "@sin f16" {
180 if (no_x86_64_hardware_f16_support) return error.SkipZigTest; // TODO
181 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO353 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
182 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO354 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
183 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO355 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
184 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;356 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 comptime359 try testSin(f16);
187 try expect(@sqrt(@as(f16, 0.0)) == 0.0);360 try comptime testSin(f16);
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)))));
203}361}
204362
205test "another, possibly redundant @sqrt test" {363test "@sin f32/f64" {
206 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO364 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
207 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO365 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
208 if (no_x86_64_hardware_f16_support) return error.SkipZigTest; // TODO366 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
209 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;367 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);370 try testSin(f32);
212 try comptime testSqrtLegacy(f64, 12.0);371 comptime try testSin(f32);
213 try testSqrtLegacy(f32, 13.0);372 try testSin(f64);
214 try comptime testSqrtLegacy(f32, 13.0);373 comptime try testSin(f64);
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);
229}374}
230375
231test "@sin" {376test "@sin f80/f128/c_longdouble" {
232 if (no_x86_64_hardware_f16_support) return error.SkipZigTest; // TODO
233 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO377 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
234 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO378 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
235 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO379 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
236 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;380 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();383 try testSin(f80);
239 try testSin();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);
240}389}
241390
242fn testSin() !void {391fn testSin(comptime T: type) !void {
243 inline for ([_]type{ f16, f32, f64 }) |ty| {392 const eps = epsForType(T);
244 const eps = epsForType(ty);393 var zero: T = 0;
245 try expect(@sin(@as(ty, 0)) == 0);394 try expect(@sin(zero) == 0);
246 try expect(math.approxEqAbs(ty, @sin(@as(ty, std.math.pi)), 0, eps));395 var pi: T = math.pi;
247 try expect(math.approxEqAbs(ty, @sin(@as(ty, std.math.pi / 2.0)), 1, eps));396 try expect(math.approxEqAbs(T, @sin(pi), 0, eps));
248 try expect(math.approxEqAbs(ty, @sin(@as(ty, std.math.pi / 4.0)), 0.7071067811865475, eps));397 try expect(math.approxEqAbs(T, @sin(pi / 2.0), 1, eps));
249 }398 try expect(math.approxEqAbs(T, @sin(pi / 4.0), 0.7071067811865475, eps));
250}399}
251400
252test "@sin with vectors" {401test "@sin with vectors" {
253 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO402 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
254 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
255 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO403 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
256 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO404 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
257 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;405 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();
260 try testSinWithVectors();408 try testSinWithVectors();
409 try comptime testSinWithVectors();
261}410}
262411
263fn testSinWithVectors() !void {412fn testSinWithVectors() !void {
...@@ -269,36 +418,64 @@ fn testSinWithVectors() !void {...@@ -269,36 +418,64 @@ fn testSinWithVectors() !void {
269 try expect(math.approxEqAbs(f32, @sin(@as(f32, 4.4)), result[3], epsilon));418 try expect(math.approxEqAbs(f32, @sin(@as(f32, 4.4)), result[3], epsilon));
270}419}
271420
272test "@cos" {421test "@cos f16" {
273 if (no_x86_64_hardware_f16_support) return error.SkipZigTest; // TODO
274 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO422 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
275 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO423 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
276 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO424 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
277 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;425 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();428 try testCos(f16);
280 try testCos();429 try comptime testCos(f16);
281}430}
282431
283fn testCos() !void {432test "@cos f32/f64" {
284 inline for ([_]type{ f16, f32, f64 }) |ty| {433 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
285 const eps = epsForType(ty);434 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
286 try expect(@cos(@as(ty, 0)) == 1);435 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
287 try expect(math.approxEqAbs(ty, @cos(@as(ty, std.math.pi)), -1, eps));436 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
288 try expect(math.approxEqAbs(ty, @cos(@as(ty, std.math.pi / 2.0)), 0, eps));437 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest;
289 try expect(math.approxEqAbs(ty, @cos(@as(ty, std.math.pi / 4.0)), 0.7071067811865475, eps));438
290 }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));
291}468}
292469
293test "@cos with vectors" {470test "@cos with vectors" {
294 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO471 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
295 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
296 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO472 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
297 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO473 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
298 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;474 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();
301 try testCosWithVectors();477 try testCosWithVectors();
478 try comptime testCosWithVectors();
302}479}
303480
304fn testCosWithVectors() !void {481fn testCosWithVectors() !void {
...@@ -310,35 +487,133 @@ fn testCosWithVectors() !void {...@@ -310,35 +487,133 @@ fn testCosWithVectors() !void {
310 try expect(math.approxEqAbs(f32, @cos(@as(f32, 4.4)), result[3], epsilon));487 try expect(math.approxEqAbs(f32, @cos(@as(f32, 4.4)), result[3], epsilon));
311}488}
312489
313test "@exp" {490test "@tan f16" {
314 if (no_x86_64_hardware_f16_support) return error.SkipZigTest; // TODO
315 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO491 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
316 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO492 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
317 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO493 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
318 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;494 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();497 try testTan(f16);
321 try testExp();498 try comptime testTan(f16);
322}499}
323500
324fn testExp() !void {501test "@tan f32/f64" {
325 inline for ([_]type{ f16, f32, f64 }) |ty| {502 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
326 const eps = epsForType(ty);503 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
327 try expect(@exp(@as(ty, 0)) == 1);504 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
328 try expect(math.approxEqAbs(ty, @exp(@as(ty, 2)), 7.389056098930650, eps));505 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
329 try expect(math.approxEqAbs(ty, @exp(@as(ty, 5)), 148.4131591025766, eps));506 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest;
330 }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));
331}606}
332607
333test "@exp with vectors" {608test "@exp with vectors" {
334 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO609 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
335 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
336 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO610 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
337 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO611 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
338 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;612 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();
341 try testExpWithVectors();615 try testExpWithVectors();
616 try comptime testExpWithVectors();
342}617}
343618
344fn testExpWithVectors() !void {619fn testExpWithVectors() !void {
...@@ -350,35 +625,64 @@ fn testExpWithVectors() !void {...@@ -350,35 +625,64 @@ fn testExpWithVectors() !void {
350 try expect(math.approxEqAbs(f32, @exp(@as(f32, 0.4)), result[3], epsilon));625 try expect(math.approxEqAbs(f32, @exp(@as(f32, 0.4)), result[3], epsilon));
351}626}
352627
353test "@exp2" {628test "@exp2 f16" {
354 if (no_x86_64_hardware_f16_support) return error.SkipZigTest; // TODO
355 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO629 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
356 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO630 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
357 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO631 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
358 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;632 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();635 try testExp2(f16);
361 try testExp2();636 try comptime testExp2(f16);
362}637}
363638
364fn testExp2() !void {639test "@exp2 f32/f64" {
365 inline for ([_]type{ f16, f32, f64 }) |ty| {640 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
366 const eps = epsForType(ty);641 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
367 try expect(@exp2(@as(ty, 2)) == 4);642 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
368 try expect(math.approxEqAbs(ty, @exp2(@as(ty, 1.5)), 2.8284271247462, eps));643 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
369 try expect(math.approxEqAbs(ty, @exp2(@as(ty, 4.5)), 22.627416997969, eps));644 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest;
370 }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));
371}675}
372676
373test "@exp2 with @vectors" {677test "@exp2 with @vectors" {
374 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO678 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
375 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
376 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO679 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
377 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO680 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
378 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;681 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();
381 try testExp2WithVectors();684 try testExp2WithVectors();
685 try comptime testExp2WithVectors();
382}686}
383687
384fn testExp2WithVectors() !void {688fn testExp2WithVectors() !void {
...@@ -390,44 +694,62 @@ fn testExp2WithVectors() !void {...@@ -390,44 +694,62 @@ fn testExp2WithVectors() !void {
390 try expect(math.approxEqAbs(f32, @exp2(@as(f32, 0.4)), result[3], epsilon));694 try expect(math.approxEqAbs(f32, @exp2(@as(f32, 0.4)), result[3], epsilon));
391}695}
392696
393test "@log" {697test "@log f16" {
394 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
395 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO698 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
396 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO699 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
397 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO700 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
398 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;701 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();704 try testLog(f16);
401 try testLog();705 try comptime testLog(f16);
402}706}
403707
404fn testLog() !void {708test "@log f32/f64" {
405 {709 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
406 var a: f16 = e;710 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
407 try expect(math.approxEqAbs(f16, @log(a), 1, epsilon));711 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
408 }712 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
409 {713 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest;
410 var a: f32 = e;714
411 try expect(@log(a) == 1 or @log(a) == @as(f32, @bitCast(@as(u32, 0x3f7fffff))));715 try testLog(f32);
412 }716 try comptime testLog(f32);
413 {717 try testLog(f64);
414 var a: f64 = e;718 try comptime testLog(f64);
415 try expect(@log(a) == 1 or @log(a) == @as(f64, @bitCast(@as(u64, 0x3ff0000000000000))));719}
416 }720
417 inline for ([_]type{ f16, f32, f64 }) |ty| {721test "@log f80/f128/c_longdouble" {
418 const eps = epsForType(ty);722 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
419 try expect(math.approxEqAbs(ty, @log(@as(ty, 2)), 0.6931471805599, eps));723 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
420 try expect(math.approxEqAbs(ty, @log(@as(ty, 5)), 1.6094379124341, eps));724 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
421 }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));
422}744}
423745
424test "@log with @vectors" {746test "@log with @vectors" {
425 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO747 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
426 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
427 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO748 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
428 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO749 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
429 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO750 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
430 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;751 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
752 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
431753
432 {754 {
433 var v: @Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 };755 var v: @Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 };
...@@ -439,29 +761,57 @@ test "@log with @vectors" {...@@ -439,29 +761,57 @@ test "@log with @vectors" {
439 }761 }
440}762}
441763
442test "@log2" {764test "@log2 f16" {
443 if (no_x86_64_hardware_f16_support) return error.SkipZigTest; // TODO
444 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO765 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
445 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO766 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
446 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO767 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
447 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;768 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();771 try testLog2(f16);
450 try testLog2();772 try comptime testLog2(f16);
451}773}
452774
453fn testLog2() !void {775test "@log2 f32/f64" {
454 inline for ([_]type{ f16, f32, f64 }) |ty| {776 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
455 const eps = epsForType(ty);777 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
456 try expect(@log2(@as(ty, 4)) == 2);778 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
457 try expect(math.approxEqAbs(ty, @log2(@as(ty, 6)), 2.5849625007212, eps));779 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
458 try expect(math.approxEqAbs(ty, @log2(@as(ty, 10)), 3.3219280948874, eps));780 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest;
459 }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));
460}811}
461812
462test "@log2 with vectors" {813test "@log2 with vectors" {
463 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO814 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
464 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
465 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO815 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
466 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO816 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
467 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;817 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
...@@ -469,9 +819,10 @@ test "@log2 with vectors" {...@@ -469,9 +819,10 @@ test "@log2 with vectors" {
469 if (builtin.zig_backend == .stage2_llvm and819 if (builtin.zig_backend == .stage2_llvm and
470 builtin.cpu.arch == .aarch64 and820 builtin.cpu.arch == .aarch64 and
471 builtin.os.tag == .windows) return error.SkipZigTest;821 builtin.os.tag == .windows) return error.SkipZigTest;
822 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
472823
473 try comptime testLog2WithVectors();
474 try testLog2WithVectors();824 try testLog2WithVectors();
825 try comptime testLog2WithVectors();
475}826}
476827
477fn testLog2WithVectors() !void {828fn testLog2WithVectors() !void {
...@@ -483,35 +834,64 @@ fn testLog2WithVectors() !void {...@@ -483,35 +834,64 @@ fn testLog2WithVectors() !void {
483 try expect(@log2(@as(f32, 0.4)) == result[3]);834 try expect(@log2(@as(f32, 0.4)) == result[3]);
484}835}
485836
486test "@log10" {837test "@log10 f16" {
487 if (no_x86_64_hardware_f16_support) return error.SkipZigTest; // TODO
488 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO838 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
489 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO839 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
490 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO840 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
491 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;841 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();844 try testLog10(f16);
494 try testLog10();845 try comptime testLog10(f16);
495}846}
496847
497fn testLog10() !void {848test "@log10 f32/f64" {
498 inline for ([_]type{ f16, f32, f64 }) |ty| {849 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
499 const eps = epsForType(ty);850 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
500 try expect(@log10(@as(ty, 100)) == 2);851 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
501 try expect(math.approxEqAbs(ty, @log10(@as(ty, 15)), 1.176091259056, eps));852 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
502 try expect(math.approxEqAbs(ty, @log10(@as(ty, 50)), 1.698970004336, eps));853 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest;
503 }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));
504}884}
505885
506test "@log10 with vectors" {886test "@log10 with vectors" {
507 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO887 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
508 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
509 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO888 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
510 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO889 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
511 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;890 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();
514 try testLog10WithVectors();893 try testLog10WithVectors();
894 try comptime testLog10WithVectors();
515}895}
516896
517fn testLog10WithVectors() !void {897fn testLog10WithVectors() !void {
...@@ -523,41 +903,94 @@ fn testLog10WithVectors() !void {...@@ -523,41 +903,94 @@ fn testLog10WithVectors() !void {
523 try expect(@log10(@as(f32, 0.4)) == result[3]);903 try expect(@log10(@as(f32, 0.4)) == result[3]);
524}904}
525905
526test "@abs" {906test "@abs f16" {
527 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO907 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
528 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO908 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
529 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO909 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();912 try testFabs(f16);
532 try testFabs();913 try comptime testFabs(f16);
533}914}
534915
535fn testFabs() !void {916test "@abs f32/f64" {
536 try expect(@abs(@as(f16, -2.5)) == 2.5);917 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
537 try expect(@abs(@as(f16, 2.5)) == 2.5);918 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
538 try expect(@abs(@as(f32, -2.5)) == 2.5);919 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
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);
542920
543 // TODO test f128, and c_longdouble921 try testFabs(f32);
544 // https://github.com/ziglang/zig/issues/4026922 try comptime testFabs(f32);
545 // {923 try testFabs(f64);
546 // var a: f80 = -2.5;924 try comptime testFabs(f64);
547 // var b: f80 = 2.5;
548 // try expect(@abs(a) == 2.5);
549 // try expect(@abs(b) == 2.5);
550 // }
551}925}
552926
553test "@abs with vectors" {927test "@abs f80/f128/c_longdouble" {
554 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
555 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO928 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
556 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO929 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
557 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;989 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();
560 try testFabsWithVectors();992 try testFabsWithVectors();
993 try comptime testFabsWithVectors();
561}994}
562995
563fn testFabsWithVectors() !void {996fn testFabsWithVectors() !void {
...@@ -569,109 +1002,77 @@ fn testFabsWithVectors() !void {...@@ -569,109 +1002,77 @@ fn testFabsWithVectors() !void {
569 try expect(math.approxEqAbs(f32, @abs(@as(f32, -0.4)), result[3], epsilon));1002 try expect(math.approxEqAbs(f32, @abs(@as(f32, -0.4)), result[3], epsilon));
570}1003}
5711004
572test "another, possibly redundant, @abs test" {1005test "@floor f16" {
573 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
574 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
575 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1006 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
576 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO1007 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
577 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;1008 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
578 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;1009 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) 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);
5881010
589 const x = 14.0;1011 try testFloor(f16);
590 const y = -x;1012 try comptime testFloor(f16);
591 const z = @abs(y);
592 try comptime std.testing.expectEqual(x, z);
593}1013}
5941014
595test "@abs f80" {1015test "@floor f32/f64" {
596 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
597 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
598 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1016 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
599 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO1017 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
600 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;1018 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
601 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;1019 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest;
602
603 try testFabsLegacy(f80, 12.0);
604 try comptime testFabsLegacy(f80, 12.0);
605}
6061020
607fn testFabsLegacy(comptime T: type, x: T) !void {1021 try testFloor(f32);
608 const y = -x;1022 try comptime testFloor(f32);
609 const z = @abs(y);1023 try testFloor(f64);
610 try expect(x == z);1024 try comptime testFloor(f64);
611}1025}
6121026
613test "a third @abs test, surely there should not be three fabs tests" {1027test "@floor f80/f128/c_longdouble" {
614 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
615 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
616 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1028 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" {
644 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1029 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
645 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1030 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
646 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1031 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();1034 if (builtin.zig_backend == .stage2_llvm and builtin.os.tag == .windows) {
649 try testFloor();1035 // https://github.com/ziglang/zig/issues/12602
650}1036 return error.SkipZigTest;
6511037 }
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);
6561038
657 // TODO test f128, and c_longdouble1039 try testFloor(f80);
658 // https://github.com/ziglang/zig/issues/40261040 try comptime testFloor(f80);
659 // {1041 try testFloor(f128);
660 // var a: f80 = 3.5;1042 try comptime testFloor(f128);
661 // try expect(@floor(a) == 3);1043 try testFloor(c_longdouble);
662 // }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);
663}1064}
6641065
665test "@floor with vectors" {1066test "@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
670 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1067 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1068 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
671 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;1069 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();
674 try testFloorWithVectors();1074 try testFloorWithVectors();
1075 try comptime testFloorWithVectors();
675}1076}
6761077
677fn testFloorWithVectors() !void {1078fn testFloorWithVectors() !void {
...@@ -683,90 +1084,77 @@ fn testFloorWithVectors() !void {...@@ -683,90 +1084,77 @@ fn testFloorWithVectors() !void {
683 try expect(math.approxEqAbs(f32, @floor(@as(f32, -0.4)), result[3], epsilon));1084 try expect(math.approxEqAbs(f32, @floor(@as(f32, -0.4)), result[3], epsilon));
684}1085}
6851086
686test "another, possibly redundant, @floor test" {1087test "@ceil f16" {
687 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
688 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1088 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" {
706 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1089 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
707 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1090 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
708 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO1091 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest;
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 }
7161092
717 try testFloorLegacy(f80, 12.0);1093 try testCeil(f16);
718 try comptime testFloorLegacy(f80, 12.0);1094 try comptime testCeil(f16);
719}1095}
7201096
721test "@floor f128" {1097test "@ceil f32/f64" {
722 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
723 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1098 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
724 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO1099 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
725 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;1100 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
726 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;1101 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest;
727
728 try testFloorLegacy(f128, 12.0);
729 try comptime testFloorLegacy(f128, 12.0);
730}
7311102
732fn testFloorLegacy(comptime T: type, x: T) !void {1103 try testCeil(f32);
733 const y = x + 0.6;1104 try comptime testCeil(f32);
734 const z = @floor(y);1105 try testCeil(f64);
735 try expect(x == z);1106 try comptime testCeil(f64);
736}1107}
7371108
738test "@ceil" {1109test "@ceil f80/f128/c_longdouble" {
739 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
740 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1110 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;
741 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1113 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();1116 if (builtin.zig_backend == .stage2_llvm and builtin.os.tag == .windows) {
744 try testCeil();1117 // https://github.com/ziglang/zig/issues/12602
745}1118 return error.SkipZigTest;
7461119 }
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);
7511120
752 // TODO test f128, and c_longdouble1121 try testCeil(f80);
753 // https://github.com/ziglang/zig/issues/40261122 try comptime testCeil(f80);
754 // {1123 try testCeil(f128);
755 // var a: f80 = 3.5;1124 try comptime testCeil(f128);
756 // try expect(@ceil(a) == 4);1125 try testCeil(c_longdouble);
757 // }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);
758}1146}
7591147
760test "@ceil with vectors" {1148test "@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
765 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1149 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1150 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
766 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;1151 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();
769 try testCeilWithVectors();1156 try testCeilWithVectors();
1157 try comptime testCeilWithVectors();
770}1158}
7711159
772fn testCeilWithVectors() !void {1160fn testCeilWithVectors() !void {
...@@ -778,90 +1166,87 @@ fn testCeilWithVectors() !void {...@@ -778,90 +1166,87 @@ fn testCeilWithVectors() !void {
778 try expect(math.approxEqAbs(f32, @ceil(@as(f32, -0.4)), result[3], epsilon));1166 try expect(math.approxEqAbs(f32, @ceil(@as(f32, -0.4)), result[3], epsilon));
779}1167}
7801168
781test "another, possibly redundant, @ceil test" {1169test "@trunc f16" {
782 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
783 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1170 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" {
801 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1171 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
802 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1172 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
803 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO1173 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest;
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;
8061174
807 if (builtin.zig_backend == .stage2_llvm and builtin.os.tag == .windows) {1175 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isMIPS()) {
808 // https://github.com/ziglang/zig/issues/126021176 // https://github.com/ziglang/zig/issues/16846
809 return error.SkipZigTest;1177 return error.SkipZigTest;
810 }1178 }
8111179
812 try testCeilLegacy(f80, 12.0);1180 try testTrunc(f16);
813 try comptime testCeilLegacy(f80, 12.0);1181 try comptime testTrunc(f16);
814}1182}
8151183
816test "@ceil f128" {1184test "@trunc f32/f64" {
817 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
818 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1185 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
819 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO1186 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
820 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;1187 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
821 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;1188 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest;
8221189
823 try testCeilLegacy(f128, 12.0);1190 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isMIPS()) {
824 try comptime testCeilLegacy(f128, 12.0);1191 // https://github.com/ziglang/zig/issues/16846
825}1192 return error.SkipZigTest;
1193 }
8261194
827fn testCeilLegacy(comptime T: type, x: T) !void {1195 try testTrunc(f32);
828 const y = x - 0.8;1196 try comptime testTrunc(f32);
829 const z = @ceil(y);1197 try testTrunc(f64);
830 try expect(x == z);1198 try comptime testTrunc(f64);
831}1199}
8321200
833test "@trunc" {1201test "@trunc f80/f128/c_longdouble" {
834 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
835 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1202 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;
836 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1205 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();1208 if (builtin.zig_backend == .stage2_llvm and builtin.os.tag == .windows) {
839 try testTrunc();1209 // https://github.com/ziglang/zig/issues/12602
840}1210 return error.SkipZigTest;
8411211 }
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);
8461212
847 // TODO test f128, and c_longdouble1213 try testTrunc(f80);
848 // https://github.com/ziglang/zig/issues/40261214 try comptime testTrunc(f80);
849 // {1215 try testTrunc(f128);
850 // var a: f80 = -3.5;1216 try comptime testTrunc(f128);
851 // try expect(@trunc(a) == -3);1217 try testTrunc(c_longdouble);
852 // }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);
853}1238}
8541239
855test "@trunc with vectors" {1240test "@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
860 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1241 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1242 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
861 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;1243 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();
864 try testTruncWithVectors();1248 try testTruncWithVectors();
1249 try comptime testTruncWithVectors();
865}1250}
8661251
867fn testTruncWithVectors() !void {1252fn testTruncWithVectors() !void {
...@@ -873,183 +1258,98 @@ fn testTruncWithVectors() !void {...@@ -873,183 +1258,98 @@ fn testTruncWithVectors() !void {
873 try expect(math.approxEqAbs(f32, @trunc(@as(f32, -0.4)), result[3], epsilon));1258 try expect(math.approxEqAbs(f32, @trunc(@as(f32, -0.4)), result[3], epsilon));
874}1259}
8751260
876test "another, possibly redundant, @trunc test" {1261test "neg f16" {
877 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
878 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1262 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
949 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1263 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
950 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
951 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1264 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
952 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;1265 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
954 if (builtin.os.tag == .freebsd) {1269 if (builtin.os.tag == .freebsd) {
955 // TODO file issue to track this failure1270 // TODO file issue to track this failure
956 return error.SkipZigTest;1271 return error.SkipZigTest;
957 }1272 }
9581273
959 const S = struct {1274 try testNeg(f16);
960 fn doTheTest() !void {1275 try comptime testNeg(f16);
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();
971}1276}
9721277
973test "negation f32" {1278test "neg f32/f64" {
974 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
975 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1279 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" {
994 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1280 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
995 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
996 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1281 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
997 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;1282 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1283 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
9981284
999 const S = struct {1285 try testNeg(f32);
1000 fn doTheTest() !void {1286 try comptime testNeg(f32);
1001 var a: f64 = 1;1287 try testNeg(f64);
1002 a = -a;1288 try comptime testNeg(f64);
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();
1011}1289}
10121290
1013test "negation f80" {1291test "neg f80/f128/c_longdouble" {
1014 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1015 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1016 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1292 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
1036 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1293 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1037 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1038 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1294 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1039 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;1295 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
10401296 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
1041 const S = struct {1297 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
1042 fn doTheTest() !void {1298
1043 var a: f128 = 1;1299 try testNeg(f80);
1044 a = -a;1300 try comptime testNeg(f80);
1045 try expect(a == -1);1301 try testNeg(f128);
1046 a = -a;1302 try comptime testNeg(f128);
1047 try expect(a == 1);1303 try testNeg(c_longdouble);
1048 }1304 try comptime testNeg(c_longdouble);
1049 };1305}
10501306
1051 try S.doTheTest();1307fn testNeg(comptime T: type) !void {
1052 try comptime S.doTheTest();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));
1053}1353}
10541354
1055test "eval @setFloatMode at compile-time" {1355test "eval @setFloatMode at compile-time" {
...@@ -1075,11 +1375,11 @@ test "f128 at compile time is lossy" {...@@ -1075,11 +1375,11 @@ test "f128 at compile time is lossy" {
1075}1375}
10761376
1077test "comptime fixed-width float zero divided by zero produces NaN" {1377test "comptime fixed-width float zero divided by zero produces NaN" {
1078 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1079 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1378 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1080 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1379 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1081 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1380 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1082 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;1381 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1382 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
10831383
1084 inline for (.{ f16, f32, f64, f80, f128 }) |F| {1384 inline for (.{ f16, f32, f64, f80, f128 }) |F| {
1085 try expect(math.isNan(@as(F, 0) / @as(F, 0)));1385 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" {...@@ -1104,99 +1404,3 @@ test "comptime fixed-width float non-zero divided by zero produces signed Inf" {
1104test "comptime_float zero divided by zero produces zero" {1404test "comptime_float zero divided by zero produces zero" {
1105 try expect((0.0 / 0.0) == 0.0);1405 try expect((0.0 / 0.0) == 0.0);
1106}1406}
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 {...@@ -410,12 +410,11 @@ fn testBinaryNot128(comptime Type: type, x: Type) !void {
410410
411test "division" {411test "division" {
412 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO412 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
415 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO413 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
416 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO414 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
417 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO415 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
418 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;416 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
420 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isMIPS()) {419 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isMIPS()) {
421 // https://github.com/ziglang/zig/issues/16846420 // 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 {...@@ -1437,19 +1436,28 @@ fn fmodOne(comptime T: type, a: T, b: T, c: T, epsilon: T) !void {
1437 try expect(@abs(@mod(@as(T, a), @as(T, b)) - @as(T, c)) < epsilon);1436 try expect(@abs(@mod(@as(T, a), @as(T, b)) - @as(T, c)) < epsilon);
1438}1437}
14391438
1440test "@round" {1439test "@round f16" {
1441 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1440 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1442 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1441 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1443 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1444 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1442 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1445 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;1443 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
1447 try testRound(f64, 12.0);1457 try testRound(f64, 12.0);
1448 try comptime testRound(f64, 12.0);1458 try comptime testRound(f64, 12.0);
1449 try testRound(f32, 12.0);1459 try testRound(f32, 12.0);
1450 try comptime testRound(f32, 12.0);1460 try comptime testRound(f32, 12.0);
1451 try testRound(f16, 12.0);
1452 try comptime testRound(f16, 12.0);
14531461
1454 const x = 14.0;1462 const x = 14.0;
1455 const y = x + 0.4;1463 const y = x + 0.4;
...@@ -1464,6 +1472,7 @@ test "@round f80" {...@@ -1464,6 +1472,7 @@ test "@round f80" {
1464 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1472 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1465 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;1473 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1466 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;1474 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
1468 try testRound(f80, 12.0);1477 try testRound(f80, 12.0);
1469 try comptime testRound(f80, 12.0);1478 try comptime testRound(f80, 12.0);
...@@ -1476,6 +1485,7 @@ test "@round f128" {...@@ -1476,6 +1485,7 @@ test "@round f128" {
1476 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1485 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1477 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;1486 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1478 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;1487 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
1480 try testRound(f128, 12.0);1490 try testRound(f128, 12.0);
1481 try comptime testRound(f128, 12.0);1491 try comptime testRound(f128, 12.0);
...@@ -1608,11 +1618,6 @@ test "signed zeros are represented properly" {...@@ -1608,11 +1618,6 @@ test "signed zeros are represented properly" {
1608 try comptime S.doTheTest();1618 try comptime S.doTheTest();
1609}1619}
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
1616test "absFloat" {1621test "absFloat" {
1617 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1622 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1618 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1623 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
test/behavior/maximum_minimum.zig+7-8
...@@ -10,6 +10,7 @@ test "@max" {...@@ -10,6 +10,7 @@ test "@max" {
10 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO10 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
11 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO11 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
12 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;12 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
13 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
1314
14 const S = struct {15 const S = struct {
15 fn doTheTest() !void {16 fn doTheTest() !void {
...@@ -25,12 +26,11 @@ test "@max" {...@@ -25,12 +26,11 @@ test "@max" {
2526
26test "@max on vectors" {27test "@max on vectors" {
27 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO28 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
30 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO29 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
31 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO30 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
32 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO31 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
33 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;32 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
33 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
3434
35 const S = struct {35 const S = struct {
36 fn doTheTest() !void {36 fn doTheTest() !void {
...@@ -74,12 +74,11 @@ test "@min" {...@@ -74,12 +74,11 @@ test "@min" {
7474
75test "@min for vectors" {75test "@min for vectors" {
76 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO76 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
79 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO77 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
80 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO78 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
81 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO79 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
82 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;80 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
81 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
8382
84 const S = struct {83 const S = struct {
85 fn doTheTest() !void {84 fn doTheTest() !void {
...@@ -104,12 +103,12 @@ test "@min for vectors" {...@@ -104,12 +103,12 @@ test "@min for vectors" {
104}103}
105104
106test "@min/max for floats" {105test "@min/max for floats" {
107 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
108 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO106 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
109 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO107 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
110 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO108 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
111 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;109 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
112 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;110 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
114 const S = struct {113 const S = struct {
115 fn doTheTest(comptime T: type) !void {114 fn doTheTest(comptime T: type) !void {
...@@ -179,11 +178,11 @@ test "@min/@max notices bounds" {...@@ -179,11 +178,11 @@ test "@min/@max notices bounds" {
179178
180test "@min/@max notices vector bounds" {179test "@min/@max notices vector bounds" {
181 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO180 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
182 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
183 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO181 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
184 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO182 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
185 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO183 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
186 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;184 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
185 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
187186
188 var x: @Vector(2, u16) = .{ 140, 40 };187 var x: @Vector(2, u16) = .{ 140, 40 };
189 const y: @Vector(2, u64) = .{ 5, 100 };188 const y: @Vector(2, u64) = .{ 5, 100 };
...@@ -232,11 +231,11 @@ test "@min/@max notices bounds from types" {...@@ -232,11 +231,11 @@ test "@min/@max notices bounds from types" {
232231
233test "@min/@max notices bounds from vector types" {232test "@min/@max notices bounds from vector types" {
234 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO233 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
235 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
236 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO234 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
237 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO235 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
238 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO236 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
239 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;237 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
238 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
240239
241 var x: @Vector(2, u16) = .{ 30, 67 };240 var x: @Vector(2, u16) = .{ 30, 67 };
242 var y: @Vector(2, u32) = .{ 20, 500 };241 var y: @Vector(2, u32) = .{ 20, 500 };
...@@ -272,11 +271,11 @@ test "@min/@max notices bounds from types when comptime-known value is undef" {...@@ -272,11 +271,11 @@ test "@min/@max notices bounds from types when comptime-known value is undef" {
272271
273test "@min/@max notices bounds from vector types when element of comptime-known vector is undef" {272test "@min/@max notices bounds from vector types when element of comptime-known vector is undef" {
274 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO273 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
275 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
276 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO274 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
277 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO275 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
278 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO276 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
279 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;277 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
278 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
280279
281 var x: @Vector(2, u32) = .{ 1_000_000, 12345 };280 var x: @Vector(2, u32) = .{ 1_000_000, 12345 };
282 const y: @Vector(2, u16) = .{ 10, undefined };281 const y: @Vector(2, u16) = .{ 10, undefined };
test/behavior/struct.zig-2
...@@ -1651,7 +1651,6 @@ test "instantiate struct with comptime field" {...@@ -1651,7 +1651,6 @@ test "instantiate struct with comptime field" {
1651test "struct field pointer has correct alignment" {1651test "struct field pointer has correct alignment" {
1652 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO1652 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1653 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO1653 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1654 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1655 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1654 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1656 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1655 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1657 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1656 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
...@@ -1684,7 +1683,6 @@ test "struct field pointer has correct alignment" {...@@ -1684,7 +1683,6 @@ test "struct field pointer has correct alignment" {
1684test "extern struct field pointer has correct alignment" {1683test "extern struct field pointer has correct alignment" {
1685 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO1684 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1686 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO1685 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1687 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1688 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1686 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1689 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1687 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1690 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1688 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" {...@@ -1534,7 +1534,6 @@ test "coerce enum literal to union in result loc" {
1534test "defined-layout union field pointer has correct alignment" {1534test "defined-layout union field pointer has correct alignment" {
1535 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO1535 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1536 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO1536 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1537 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1538 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1537 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1539 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1538 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1540 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1539 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
...@@ -1572,7 +1571,6 @@ test "defined-layout union field pointer has correct alignment" {...@@ -1572,7 +1571,6 @@ test "defined-layout union field pointer has correct alignment" {
1572test "undefined-layout union field pointer has correct alignment" {1571test "undefined-layout union field pointer has correct alignment" {
1573 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO1572 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1574 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO1573 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1575 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1576 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1574 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1577 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1575 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1578 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1576 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
...@@ -1610,7 +1608,6 @@ test "undefined-layout union field pointer has correct alignment" {...@@ -1610,7 +1608,6 @@ test "undefined-layout union field pointer has correct alignment" {
1610test "packed union field pointer has correct alignment" {1608test "packed union field pointer has correct alignment" {
1611 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO1609 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1612 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO1610 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1613 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1614 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1611 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1615 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1612 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1616 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1613 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;...@@ -8,7 +8,6 @@ const expectEqual = std.testing.expectEqual;
88
9test "implicit cast vector to array - bool" {9test "implicit cast vector to array - bool" {
10 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO10 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
11 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
12 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO11 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
13 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO12 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
14 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO13 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
...@@ -27,12 +26,12 @@ test "implicit cast vector to array - bool" {...@@ -27,12 +26,12 @@ test "implicit cast vector to array - bool" {
2726
28test "vector wrap operators" {27test "vector wrap operators" {
29 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO28 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
32 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO29 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
33 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO30 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
34 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO31 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
35 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;32 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
37 const S = struct {36 const S = struct {
38 fn doTheTest() !void {37 fn doTheTest() !void {
...@@ -214,13 +213,12 @@ test "array vector coercion - odd sizes" {...@@ -214,13 +213,12 @@ test "array vector coercion - odd sizes" {
214}213}
215214
216test "array to vector with element type coercion" {215test "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
220 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO216 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
221 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO217 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
222 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO218 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
223 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;219 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
225 const S = struct {223 const S = struct {
226 fn doTheTest() !void {224 fn doTheTest() !void {
...@@ -236,7 +234,6 @@ test "array to vector with element type coercion" {...@@ -236,7 +234,6 @@ test "array to vector with element type coercion" {
236234
237test "peer type resolution with coercible element types" {235test "peer type resolution with coercible element types" {
238 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO236 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
239 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
240 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO237 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
241 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO238 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
242 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO239 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
...@@ -1440,7 +1437,6 @@ test "vector pointer is indexable" {...@@ -1440,7 +1437,6 @@ test "vector pointer is indexable" {
1440 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1437 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1441 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1438 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1442 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO1439 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1443 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1444 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1440 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1445 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO1441 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
14461442
...@@ -1466,7 +1462,6 @@ test "boolean vector with 2 or more booleans" {...@@ -1466,7 +1462,6 @@ test "boolean vector with 2 or more booleans" {
1466 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1462 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1467 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1463 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1468 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO1464 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1469 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1470 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1465 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
14711466
1472 // TODO: try removing this after <https://github.com/ziglang/zig/issues/13782>:1467 // TODO: try removing this after <https://github.com/ziglang/zig/issues/13782>:
...@@ -1483,7 +1478,6 @@ test "bitcast to vector with different child type" {...@@ -1483,7 +1478,6 @@ test "bitcast to vector with different child type" {
1483 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1478 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1484 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1479 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1485 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO1480 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1486 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1487 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1481 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1488 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO1482 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
14891483