authorgravatar for paul.verigo@gmail.comPavel Verigo <paul.verigo@gmail.com> 2024-10-08 16:44:19+02:00
committergravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2024-10-08 20:58:15+02:00
log4b89a4c7cbd3653518ecf743ed707f516d187e78
tree1e3d86f4d668a71c0e4dd721d7c3da415c355302
parentb00cbecfd3f75f3148f6c8d4ef159ba144f1a362

stage2-wasm: airRem + airMod for floats


2 files changed, 29 insertions(+), 27 deletions(-)

src/arch/wasm/CodeGen.zig+29-21
...@@ -2783,6 +2783,7 @@ const FloatOp = enum {...@@ -2783,6 +2783,7 @@ const FloatOp = enum {
2783 .sqrt => .sqrt,2783 .sqrt => .sqrt,
2784 .sub => .sub,2784 .sub => .sub,
2785 .trunc => .trunc,2785 .trunc => .trunc,
2786 .rem => .fmod,
2786 else => unreachable,2787 else => unreachable,
2787 };2788 };
2788 }2789 }
...@@ -6808,30 +6809,37 @@ fn airMod(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -6808,30 +6809,37 @@ fn airMod(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
6808 const lhs = try func.resolveInst(bin_op.lhs);6809 const lhs = try func.resolveInst(bin_op.lhs);
6809 const rhs = try func.resolveInst(bin_op.rhs);6810 const rhs = try func.resolveInst(bin_op.rhs);
68106811
6811 if (ty.isUnsignedInt(zcu)) {6812 const result = result: {
6812 _ = try func.binOp(lhs, rhs, ty, .rem);6813 if (ty.isUnsignedInt(zcu)) {
6813 } else if (ty.isSignedInt(zcu)) {6814 break :result try func.binOp(lhs, rhs, ty, .rem);
6814 // The wasm rem instruction gives the remainder after truncating division (rounding towards
6815 // 0), equivalent to @rem.
6816 // We make use of the fact that:
6817 // @mod(a, b) = @rem(@rem(a, b) + b, b)
6818 const int_bits = ty.intInfo(zcu).bits;
6819 const wasm_bits = toWasmBits(int_bits) orelse {
6820 return func.fail("TODO: `@mod` for signed integers larger than 64 bits ({d} bits requested)", .{int_bits});
6821 };
6822
6823 if (wasm_bits > 64) {
6824 return func.fail("TODO: `@mod` for signed integers larger than 64 bits ({d} bits requested)", .{int_bits});
6825 }6815 }
6816 if (ty.isSignedInt(zcu)) {
6817 // The wasm rem instruction gives the remainder after truncating division (rounding towards
6818 // 0), equivalent to @rem.
6819 // We make use of the fact that:
6820 // @mod(a, b) = @rem(@rem(a, b) + b, b)
6821 const int_bits = ty.intInfo(zcu).bits;
6822 const wasm_bits = toWasmBits(int_bits) orelse {
6823 return func.fail("TODO: `@mod` for signed integers larger than 64 bits ({d} bits requested)", .{int_bits});
6824 };
68266825
6827 _ = try func.binOp(lhs, rhs, ty, .rem);6826 if (wasm_bits > 64) {
6828 _ = try func.binOp(.stack, rhs, ty, .add);6827 return func.fail("TODO: `@mod` for signed integers larger than 64 bits ({d} bits requested)", .{int_bits});
6829 _ = try func.binOp(.stack, rhs, ty, .rem);6828 }
6830 } else {
6831 return func.fail("TODO: implement `@mod` on floating point types for {}", .{func.target.cpu.arch});
6832 }
68336829
6834 return func.finishAir(inst, .stack, &.{ bin_op.lhs, bin_op.rhs });6830 _ = try func.binOp(lhs, rhs, ty, .rem);
6831 _ = try func.binOp(.stack, rhs, ty, .add);
6832 break :result try func.binOp(.stack, rhs, ty, .rem);
6833 }
6834 if (ty.isAnyFloat()) {
6835 const rem = try func.binOp(lhs, rhs, ty, .rem);
6836 const add = try func.binOp(rem, rhs, ty, .add);
6837 break :result try func.binOp(add, rhs, ty, .rem);
6838 }
6839 return func.fail("TODO: @mod for {}", .{ty.fmt(pt)});
6840 };
6841
6842 return func.finishAir(inst, result, &.{ bin_op.lhs, bin_op.rhs });
6835}6843}
68366844
6837fn airSatMul(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {6845fn airSatMul(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
test/behavior/math.zig-6
...@@ -167,7 +167,6 @@ fn testOneCtz(comptime T: type, x: T) u32 {...@@ -167,7 +167,6 @@ fn testOneCtz(comptime T: type, x: T) u32 {
167}167}
168168
169test "@ctz 128-bit integers" {169test "@ctz 128-bit integers" {
170 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
171 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;170 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
172 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO171 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
173 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO172 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
...@@ -776,7 +775,6 @@ fn should_not_be_zero(x: f128) !void {...@@ -776,7 +775,6 @@ fn should_not_be_zero(x: f128) !void {
776}775}
777776
778test "128-bit multiplication" {777test "128-bit multiplication" {
779 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
780 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO778 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
781 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO779 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
782 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO780 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
...@@ -1204,7 +1202,6 @@ test "allow signed integer division/remainder when values are comptime-known and...@@ -1204,7 +1202,6 @@ test "allow signed integer division/remainder when values are comptime-known and
1204}1202}
12051203
1206test "quad hex float literal parsing accurate" {1204test "quad hex float literal parsing accurate" {
1207 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1208 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1205 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1209 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1206 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1210 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1207 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
...@@ -1363,7 +1360,6 @@ test "comptime float rem int" {...@@ -1363,7 +1360,6 @@ test "comptime float rem int" {
1363}1360}
13641361
1365test "remainder division" {1362test "remainder division" {
1366 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1367 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1363 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1368 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1364 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1369 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1365 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
...@@ -1403,7 +1399,6 @@ fn remdivOne(comptime T: type, a: T, b: T, c: T) !void {...@@ -1403,7 +1399,6 @@ fn remdivOne(comptime T: type, a: T, b: T, c: T) !void {
1403}1399}
14041400
1405test "float remainder division using @rem" {1401test "float remainder division using @rem" {
1406 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1407 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1402 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1408 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1403 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1409 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1404 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
...@@ -1447,7 +1442,6 @@ fn fremOne(comptime T: type, a: T, b: T, c: T, epsilon: T) !void {...@@ -1447,7 +1442,6 @@ fn fremOne(comptime T: type, a: T, b: T, c: T, epsilon: T) !void {
1447}1442}
14481443
1449test "float modulo division using @mod" {1444test "float modulo division using @mod" {
1450 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1451 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1445 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1452 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1446 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1453 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1447 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO