| author | |
| committer | |
| log | 4b89a4c7cbd3653518ecf743ed707f516d187e78 |
| tree | 1e3d86f4d668a71c0e4dd721d7c3da415c355302 |
| parent | b00cbecfd3f75f3148f6c8d4ef159ba144f1a362 |
2 files changed, 29 insertions(+), 27 deletions(-)
src/arch/wasm/CodeGen.zig+29-21| ... | ... | @@ -2783,6 +2783,7 @@ const FloatOp = enum { |
| 2783 | 2783 | .sqrt => .sqrt, |
| 2784 | 2784 | .sub => .sub, |
| 2785 | 2785 | .trunc => .trunc, |
| 2786 | .rem => .fmod, | |
| 2786 | 2787 | else => unreachable, |
| 2787 | 2788 | }; |
| 2788 | 2789 | } |
| ... | ... | @@ -6808,30 +6809,37 @@ fn airMod(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 6808 | 6809 | const lhs = try func.resolveInst(bin_op.lhs); |
| 6809 | 6810 | const rhs = try func.resolveInst(bin_op.rhs); |
| 6810 | 6811 | |
| 6811 | if (ty.isUnsignedInt(zcu)) { | |
| 6812 | _ = try func.binOp(lhs, rhs, ty, .rem); | |
| 6813 | } else if (ty.isSignedInt(zcu)) { | |
| 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}); | |
| 6812 | const result = result: { | |
| 6813 | if (ty.isUnsignedInt(zcu)) { | |
| 6814 | break :result try func.binOp(lhs, rhs, ty, .rem); | |
| 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 | }; | |
| 6826 | 6825 | |
| 6827 | _ = try func.binOp(lhs, rhs, ty, .rem); | |
| 6828 | _ = try func.binOp(.stack, rhs, ty, .add); | |
| 6829 | _ = try func.binOp(.stack, rhs, ty, .rem); | |
| 6830 | } else { | |
| 6831 | return func.fail("TODO: implement `@mod` on floating point types for {}", .{func.target.cpu.arch}); | |
| 6832 | } | |
| 6826 | if (wasm_bits > 64) { | |
| 6827 | return func.fail("TODO: `@mod` for signed integers larger than 64 bits ({d} bits requested)", .{int_bits}); | |
| 6828 | } | |
| 6833 | 6829 | |
| 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 | } |
| 6836 | 6844 | |
| 6837 | 6845 | fn 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 | 167 | } |
| 168 | 168 | |
| 169 | 169 | test "@ctz 128-bit integers" { |
| 170 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | |
| 171 | 170 | if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest; |
| 172 | 171 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 173 | 172 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| ... | ... | @@ -776,7 +775,6 @@ fn should_not_be_zero(x: f128) !void { |
| 776 | 775 | } |
| 777 | 776 | |
| 778 | 777 | test "128-bit multiplication" { |
| 779 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | |
| 780 | 778 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 781 | 779 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 782 | 780 | 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 | 1202 | } |
| 1205 | 1203 | |
| 1206 | 1204 | test "quad hex float literal parsing accurate" { |
| 1207 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | |
| 1208 | 1205 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 1209 | 1206 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1210 | 1207 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| ... | ... | @@ -1363,7 +1360,6 @@ test "comptime float rem int" { |
| 1363 | 1360 | } |
| 1364 | 1361 | |
| 1365 | 1362 | test "remainder division" { |
| 1366 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | |
| 1367 | 1363 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1368 | 1364 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 1369 | 1365 | 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 | 1399 | } |
| 1404 | 1400 | |
| 1405 | 1401 | test "float remainder division using @rem" { |
| 1406 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | |
| 1407 | 1402 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1408 | 1403 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 1409 | 1404 | 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 | 1442 | } |
| 1448 | 1443 | |
| 1449 | 1444 | test "float modulo division using @mod" { |
| 1450 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | |
| 1451 | 1445 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1452 | 1446 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 1453 | 1447 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |