mirror of
https://github.com/ziglang/zig.git
synced 2025-12-06 14:23:09 +00:00
wasm: correctly intcast signed integers
When a signed integer's bitsize is not 32 or 64, but the given bitsize and wanted bitsize are either both represented by Wasm's i32 or i64, we must either sign extend or wrap the integer.
This commit is contained in:
parent
8924f81d8c
commit
619140c0d2
@ -4160,7 +4160,7 @@ fn airIntcast(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
|
|||||||
|
|
||||||
const op_bits = toWasmBits(@as(u16, @intCast(operand_ty.bitSize(mod)))).?;
|
const op_bits = toWasmBits(@as(u16, @intCast(operand_ty.bitSize(mod)))).?;
|
||||||
const wanted_bits = toWasmBits(@as(u16, @intCast(ty.bitSize(mod)))).?;
|
const wanted_bits = toWasmBits(@as(u16, @intCast(ty.bitSize(mod)))).?;
|
||||||
const result = if (op_bits == wanted_bits)
|
const result = if (op_bits == wanted_bits and !ty.isSignedInt(mod))
|
||||||
func.reuseOperand(ty_op.operand, operand)
|
func.reuseOperand(ty_op.operand, operand)
|
||||||
else
|
else
|
||||||
try (try func.intcast(operand, operand_ty, ty)).toLocal(func, ty);
|
try (try func.intcast(operand, operand_ty, ty)).toLocal(func, ty);
|
||||||
@ -4181,7 +4181,19 @@ fn intcast(func: *CodeGen, operand: WValue, given: Type, wanted: Type) InnerErro
|
|||||||
|
|
||||||
const op_bits = toWasmBits(given_bitsize).?;
|
const op_bits = toWasmBits(given_bitsize).?;
|
||||||
const wanted_bits = toWasmBits(wanted_bitsize).?;
|
const wanted_bits = toWasmBits(wanted_bitsize).?;
|
||||||
if (op_bits == wanted_bits) return operand;
|
if (op_bits == wanted_bits) {
|
||||||
|
if (given.isSignedInt(mod)) {
|
||||||
|
if (given_bitsize < wanted_bitsize) {
|
||||||
|
// signed integers are stored as two's complement,
|
||||||
|
// when we upcast from a smaller integer to larger
|
||||||
|
// integers, we must get its absolute value similar to
|
||||||
|
// i64_extend_i32_s instruction.
|
||||||
|
return func.signAbsValue(operand, given);
|
||||||
|
}
|
||||||
|
return func.wrapOperand(operand, wanted);
|
||||||
|
}
|
||||||
|
return operand;
|
||||||
|
}
|
||||||
|
|
||||||
if (op_bits > 32 and op_bits <= 64 and wanted_bits == 32) {
|
if (op_bits > 32 and op_bits <= 64 and wanted_bits == 32) {
|
||||||
try func.emitWValue(operand);
|
try func.emitWValue(operand);
|
||||||
|
|||||||
@ -14,3 +14,18 @@ test "@intCast i32 to u7" {
|
|||||||
var z = x >> @as(u7, @intCast(y));
|
var z = x >> @as(u7, @intCast(y));
|
||||||
try expect(z == 0xff);
|
try expect(z == 0xff);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "coerce i8 to i32 and @intCast back" {
|
||||||
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
||||||
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||||
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
||||||
|
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
|
||||||
|
|
||||||
|
var x: i8 = -5;
|
||||||
|
var y: i32 = -5;
|
||||||
|
try expect(y == x);
|
||||||
|
|
||||||
|
var x2: i32 = -5;
|
||||||
|
var y2: i8 = -5;
|
||||||
|
try expect(y2 == @as(i8, @intCast(x2)));
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user