Allow more operators on bool vectors (#24131)

* Sema: allow binary operations and boolean not on vectors of bool

* langref: Clarify use of operators on vectors (`and` and `or` not allowed)

closes #24093
This commit is contained in:
Daniel Kongsgaard
2025-06-13 00:16:23 +02:00
committed by GitHub
parent 4a02e080d1
commit 5e3c0b7af7
5 changed files with 79 additions and 50 deletions
+46 -10
View File
@@ -152,12 +152,22 @@ test "vector bit operators" {
const S = struct {
fn doTheTest() !void {
var v: @Vector(4, u8) = [4]u8{ 0b10101010, 0b10101010, 0b10101010, 0b10101010 };
var x: @Vector(4, u8) = [4]u8{ 0b11110000, 0b00001111, 0b10101010, 0b01010101 };
_ = .{ &v, &x };
try expect(mem.eql(u8, &@as([4]u8, v ^ x), &[4]u8{ 0b01011010, 0b10100101, 0b00000000, 0b11111111 }));
try expect(mem.eql(u8, &@as([4]u8, v | x), &[4]u8{ 0b11111010, 0b10101111, 0b10101010, 0b11111111 }));
try expect(mem.eql(u8, &@as([4]u8, v & x), &[4]u8{ 0b10100000, 0b00001010, 0b10101010, 0b00000000 }));
{
var v: @Vector(4, bool) = [4]bool{ false, false, true, true };
var x: @Vector(4, bool) = [4]bool{ true, false, true, false };
_ = .{ &v, &x };
try expect(mem.eql(bool, &@as([4]bool, v ^ x), &[4]bool{ true, false, false, true }));
try expect(mem.eql(bool, &@as([4]bool, v | x), &[4]bool{ true, false, true, true }));
try expect(mem.eql(bool, &@as([4]bool, v & x), &[4]bool{ false, false, true, false }));
}
{
var v: @Vector(4, u8) = [4]u8{ 0b10101010, 0b10101010, 0b10101010, 0b10101010 };
var x: @Vector(4, u8) = [4]u8{ 0b11110000, 0b00001111, 0b10101010, 0b01010101 };
_ = .{ &v, &x };
try expect(mem.eql(u8, &@as([4]u8, v ^ x), &[4]u8{ 0b01011010, 0b10100101, 0b00000000, 0b11111111 }));
try expect(mem.eql(u8, &@as([4]u8, v | x), &[4]u8{ 0b11111010, 0b10101111, 0b10101010, 0b11111111 }));
try expect(mem.eql(u8, &@as([4]u8, v & x), &[4]u8{ 0b10100000, 0b00001010, 0b10101010, 0b00000000 }));
}
}
};
try S.doTheTest();
@@ -659,15 +669,41 @@ test "vector bitwise not operator" {
}
}
fn doTheTest() !void {
try doTheTestNot(u8, [_]u8{ 0, 2, 4, 255 });
try doTheTestNot(u16, [_]u16{ 0, 2, 4, 255 });
try doTheTestNot(u32, [_]u32{ 0, 2, 4, 255 });
try doTheTestNot(u64, [_]u64{ 0, 2, 4, 255 });
try doTheTestNot(bool, [_]bool{ true, false, true, false });
try doTheTestNot(u8, [_]u8{ 0, 2, 4, 255 });
try doTheTestNot(u16, [_]u16{ 0, 2, 4, 255 });
try doTheTestNot(u32, [_]u32{ 0, 2, 4, 255 });
try doTheTestNot(u64, [_]u64{ 0, 2, 4, 255 });
try doTheTestNot(i8, [_]i8{ 0, 2, 4, 127 });
try doTheTestNot(i16, [_]i16{ 0, 2, 4, 127 });
try doTheTestNot(i32, [_]i32{ 0, 2, 4, 127 });
try doTheTestNot(i64, [_]i64{ 0, 2, 4, 127 });
}
};
try S.doTheTest();
try comptime S.doTheTest();
}
test "vector boolean not operator" {
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
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_riscv64) return error.SkipZigTest;
const S = struct {
fn doTheTestNot(comptime T: type, x: @Vector(4, T)) !void {
const y = !x;
for (@as([4]T, y), 0..) |v, i| {
try expect(!x[i] == v);
}
}
fn doTheTest() !void {
try doTheTestNot(bool, [_]bool{ true, false, true, false });
}
};