diff --git a/src/arch/wasm/CodeGen.zig b/src/arch/wasm/CodeGen.zig index 922fc4db07d3..a898d1838268 100644 --- a/src/arch/wasm/CodeGen.zig +++ b/src/arch/wasm/CodeGen.zig @@ -4353,9 +4353,21 @@ fn intcast(func: *CodeGen, operand: WValue, given: Type, wanted: Type) InnerErro if (op_bits > 32 and op_bits <= 64 and wanted_bits == 32) { try func.emitWValue(operand); try func.addTag(.i32_wrap_i64); + if (given.isSignedInt(mod) and wanted_bitsize < 32) + return func.wrapOperand(.{ .stack = {} }, wanted) + else + return WValue{ .stack = {} }; } else if (op_bits == 32 and wanted_bits > 32 and wanted_bits <= 64) { - try func.emitWValue(operand); + const operand32 = if (given_bitsize < 32 and wanted.isSignedInt(mod)) + try func.signExtendInt(operand, given) + else + operand; + try func.emitWValue(operand32); try func.addTag(if (wanted.isSignedInt(mod)) .i64_extend_i32_s else .i64_extend_i32_u); + if (given.isSignedInt(mod) and wanted_bitsize < 64) + return func.wrapOperand(.{ .stack = {} }, wanted) + else + return WValue{ .stack = {} }; } else if (wanted_bits == 128) { // for 128bit integers we store the integer in the virtual stack, rather than a local const stack_ptr = try func.allocStack(wanted); @@ -4381,8 +4393,6 @@ fn intcast(func: *CodeGen, operand: WValue, given: Type, wanted: Type) InnerErro } return stack_ptr; } else return func.load(operand, wanted, 0); - - return WValue{ .stack = {} }; } fn airIsNull(func: *CodeGen, inst: Air.Inst.Index, opcode: wasm.Opcode, op_kind: enum { value, ptr }) InnerError!void { diff --git a/test/behavior/cast_int.zig b/test/behavior/cast_int.zig index 989f3d3aa11e..60790c5d8085 100644 --- a/test/behavior/cast_int.zig +++ b/test/behavior/cast_int.zig @@ -1,6 +1,7 @@ const builtin = @import("builtin"); const std = @import("std"); const expect = std.testing.expect; +const expectEqual = std.testing.expectEqual; const maxInt = std.math.maxInt; test "@intCast i32 to u7" { @@ -28,3 +29,93 @@ test "coerce i8 to i32 and @intCast back" { var y2: i8 = -5; try expect(y2 == @as(i8, @intCast(x2))); } + +test "coerce non byte-sized integers accross 32bits boundary" { + { + var v: u21 = 6417; + const a: u32 = v; + const b: u64 = v; + const c: u64 = a; + var w: u64 = 0x1234567812345678; + const d: u21 = @truncate(w); + const e: u60 = d; + try expectEqual(@as(u32, 6417), a); + try expectEqual(@as(u64, 6417), b); + try expectEqual(@as(u64, 6417), c); + try expectEqual(@as(u21, 0x145678), d); + try expectEqual(@as(u60, 0x145678), e); + } + + { + var v: u10 = 234; + const a: u32 = v; + const b: u64 = v; + const c: u64 = a; + var w: u64 = 0x1234567812345678; + const d: u10 = @truncate(w); + const e: u60 = d; + try expectEqual(@as(u32, 234), a); + try expectEqual(@as(u64, 234), b); + try expectEqual(@as(u64, 234), c); + try expectEqual(@as(u21, 0x278), d); + try expectEqual(@as(u60, 0x278), e); + } + { + var v: u7 = 11; + const a: u32 = v; + const b: u64 = v; + const c: u64 = a; + var w: u64 = 0x1234567812345678; + const d: u7 = @truncate(w); + const e: u60 = d; + try expectEqual(@as(u32, 11), a); + try expectEqual(@as(u64, 11), b); + try expectEqual(@as(u64, 11), c); + try expectEqual(@as(u21, 0x78), d); + try expectEqual(@as(u60, 0x78), e); + } + + { + var v: i21 = -6417; + const a: i32 = v; + const b: i64 = v; + const c: i64 = a; + var w: i64 = -12345; + const d: i21 = @intCast(w); + const e: i60 = d; + try expectEqual(@as(i32, -6417), a); + try expectEqual(@as(i64, -6417), b); + try expectEqual(@as(i64, -6417), c); + try expectEqual(@as(i21, -12345), d); + try expectEqual(@as(i60, -12345), e); + } + + { + var v: i10 = -234; + const a: i32 = v; + const b: i64 = v; + const c: i64 = a; + var w: i64 = -456; + const d: i10 = @intCast(w); + const e: i60 = d; + try expectEqual(@as(i32, -234), a); + try expectEqual(@as(i64, -234), b); + try expectEqual(@as(i64, -234), c); + try expectEqual(@as(i10, -456), d); + try expectEqual(@as(i60, -456), e); + } + { + var v: i7 = -11; + const a: i32 = v; + const b: i64 = v; + const c: i64 = a; + var w: i64 = -42; + const d: i7 = @intCast(w); + const e: i60 = d; + try expectEqual(@as(i32, -11), a); + try expectEqual(@as(i64, -11), b); + try expectEqual(@as(i64, -11), c); + try expectEqual(@as(i7, -42), d); + try expectEqual(@as(i60, -42), e); + } +}