authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-01-02 13:37:58+00:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-01-03 15:45:11+00:00
logb3c498454b6006f64aecf96b181720c524d76ae8
tree1537f8a4d09db631191642301505510fd228c22b
parentf7f0b9d28f2d68f40fcfe79f85b4cc37ea9ba2e8
signaturelock-open Commit is signed but in an unrecognized format.

codegen.wasm: fix 64-bit saturating shl

Previously, 64-bit '<<|' operations were emitting 64-bit shifts with one 64-bit operand and one 32-bit operand, which is illegal. Instead, as in the lowering for regular shifts, we need to cast the RHS in this case.

1 files changed, 13 insertions(+), 2 deletions(-)

src/codegen/wasm/CodeGen.zig+13-2
......@@ -6973,9 +6973,20 @@ fn airShlSat(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
69736973 return cg.fail("TODO: Saturating shifting left for integers with bitsize '{d}'", .{int_info.bits});
69746974 }
69756975
6976 const lhs = try cg.resolveInst(bin_op.lhs);
6977 const rhs = try cg.resolveInst(bin_op.rhs);
69786976 const wasm_bits = toWasmBits(int_info.bits).?;
6977
6978 const lhs = try cg.resolveInst(bin_op.lhs);
6979 const rhs = rhs: {
6980 const rhs = try cg.resolveInst(bin_op.rhs);
6981 const rhs_ty = cg.typeOf(bin_op.rhs);
6982 // The type of `rhs` is the log2 int of the type of `lhs`, but WASM wants the lhs and rhs types to match.
6983 if (toWasmBits(@intCast(rhs_ty.bitSize(zcu))).? == wasm_bits) {
6984 break :rhs rhs; // the WASM types match, so no cast necessary
6985 }
6986 const casted = try cg.intcast(rhs, rhs_ty, ty);
6987 break :rhs try casted.toLocal(cg, ty);
6988 };
6989
69796990 const result = try cg.allocLocal(ty);
69806991
69816992 if (wasm_bits == int_info.bits) {