mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-06 13:54:21 +00:00
compiler: require comptime vector indexes
This commit is contained in:
parent
14bda4130a
commit
426af68b7d
13 changed files with 55 additions and 104 deletions
|
|
@ -1187,7 +1187,7 @@ pub const Cpu = struct {
|
|||
pub const Index = std.math.Log2Int(std.meta.Int(.unsigned, usize_count * @bitSizeOf(usize)));
|
||||
pub const ShiftInt = std.math.Log2Int(usize);
|
||||
|
||||
pub const empty = Set{ .ints = [1]usize{0} ** usize_count };
|
||||
pub const empty: Set = .{ .ints = @splat(0) };
|
||||
|
||||
pub fn isEmpty(set: Set) bool {
|
||||
return for (set.ints) |x| {
|
||||
|
|
|
|||
|
|
@ -216,7 +216,7 @@ fn ChaChaVecImpl(comptime rounds_nb: usize, comptime degree: comptime_int) type
|
|||
}
|
||||
|
||||
fn hashToBytes(comptime dm: usize, out: *[64 * dm]u8, x: BlockVec) void {
|
||||
for (0..dm) |d| {
|
||||
inline for (0..dm) |d| {
|
||||
for (0..4) |i| {
|
||||
mem.writeInt(u32, out[64 * d + 16 * i + 0 ..][0..4], x[i][0 + 4 * d], .little);
|
||||
mem.writeInt(u32, out[64 * d + 16 * i + 4 ..][0..4], x[i][1 + 4 * d], .little);
|
||||
|
|
|
|||
|
|
@ -389,7 +389,7 @@ pub fn innerParse(
|
|||
switch (try source.peekNextTokenType()) {
|
||||
.array_begin => {
|
||||
// Typical array.
|
||||
return internalParseArray(T, arrayInfo.child, arrayInfo.len, allocator, source, options);
|
||||
return internalParseArray(T, arrayInfo.child, allocator, source, options);
|
||||
},
|
||||
.string => {
|
||||
if (arrayInfo.child != u8) return error.UnexpectedToken;
|
||||
|
|
@ -443,7 +443,7 @@ pub fn innerParse(
|
|||
.vector => |vecInfo| {
|
||||
switch (try source.peekNextTokenType()) {
|
||||
.array_begin => {
|
||||
return internalParseArray(T, vecInfo.child, vecInfo.len, allocator, source, options);
|
||||
return internalParseVector(T, vecInfo.child, vecInfo.len, allocator, source, options);
|
||||
},
|
||||
else => return error.UnexpectedToken,
|
||||
}
|
||||
|
|
@ -517,6 +517,25 @@ pub fn innerParse(
|
|||
}
|
||||
|
||||
fn internalParseArray(
|
||||
comptime T: type,
|
||||
comptime Child: type,
|
||||
allocator: Allocator,
|
||||
source: anytype,
|
||||
options: ParseOptions,
|
||||
) !T {
|
||||
assert(.array_begin == try source.next());
|
||||
|
||||
var r: T = undefined;
|
||||
for (&r) |*elem| {
|
||||
elem.* = try innerParse(Child, allocator, source, options);
|
||||
}
|
||||
|
||||
if (.array_end != try source.next()) return error.UnexpectedToken;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
fn internalParseVector(
|
||||
comptime T: type,
|
||||
comptime Child: type,
|
||||
comptime len: comptime_int,
|
||||
|
|
@ -527,8 +546,7 @@ fn internalParseArray(
|
|||
assert(.array_begin == try source.next());
|
||||
|
||||
var r: T = undefined;
|
||||
var i: usize = 0;
|
||||
while (i < len) : (i += 1) {
|
||||
inline for (0..len) |i| {
|
||||
r[i] = try innerParse(Child, allocator, source, options);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -743,9 +743,8 @@ pub fn eql(a: anytype, b: @TypeOf(a)) bool {
|
|||
return true;
|
||||
},
|
||||
.vector => |info| {
|
||||
var i: usize = 0;
|
||||
while (i < info.len) : (i += 1) {
|
||||
if (!eql(a[i], b[i])) return false;
|
||||
inline for (0..info.len) |i| {
|
||||
if (a[i] != b[i]) return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
|
|
|
|||
|
|
@ -135,9 +135,8 @@ fn expectEqualInner(comptime T: type, expected: T, actual: T) !void {
|
|||
.array => |array| try expectEqualSlices(array.child, &expected, &actual),
|
||||
|
||||
.vector => |info| {
|
||||
var i: usize = 0;
|
||||
while (i < info.len) : (i += 1) {
|
||||
if (!std.meta.eql(expected[i], actual[i])) {
|
||||
inline for (0..info.len) |i| {
|
||||
if (expected[i] != actual[i]) {
|
||||
print("index {d} incorrect. expected {any}, found {any}\n", .{
|
||||
i, expected[i], actual[i],
|
||||
});
|
||||
|
|
@ -828,8 +827,7 @@ fn expectEqualDeepInner(comptime T: type, expected: T, actual: T) error{TestExpe
|
|||
print("Vector len not the same, expected {d}, found {d}\n", .{ info.len, @typeInfo(@TypeOf(actual)).vector.len });
|
||||
return error.TestExpectedEqual;
|
||||
}
|
||||
var i: usize = 0;
|
||||
while (i < info.len) : (i += 1) {
|
||||
inline for (0..info.len) |i| {
|
||||
expectEqualDeep(expected[i], actual[i]) catch |e| {
|
||||
print("index {d} incorrect. expected {any}, found {any}\n", .{
|
||||
i, expected[i], actual[i],
|
||||
|
|
|
|||
|
|
@ -235,7 +235,7 @@ pub fn valueArbitraryDepth(self: *Serializer, val: anytype, options: ValueOption
|
|||
var container = try self.beginTuple(
|
||||
.{ .whitespace_style = .{ .fields = vector.len } },
|
||||
);
|
||||
for (0..vector.len) |i| {
|
||||
inline for (0..vector.len) |i| {
|
||||
try container.fieldArbitraryDepth(val[i], options);
|
||||
}
|
||||
try container.end();
|
||||
|
|
|
|||
|
|
@ -446,7 +446,7 @@ pub fn free(gpa: Allocator, value: anytype) void {
|
|||
.optional => if (value) |some| {
|
||||
free(gpa, some);
|
||||
},
|
||||
.vector => |vector| for (0..vector.len) |i| free(gpa, value[i]),
|
||||
.vector => |vector| inline for (0..vector.len) |i| free(gpa, value[i]),
|
||||
.void => {},
|
||||
else => comptime unreachable,
|
||||
}
|
||||
|
|
@ -998,11 +998,7 @@ const Parser = struct {
|
|||
}
|
||||
}
|
||||
|
||||
fn parseVector(
|
||||
self: *@This(),
|
||||
T: type,
|
||||
node: Zoir.Node.Index,
|
||||
) !T {
|
||||
fn parseVector(self: *@This(), T: type, node: Zoir.Node.Index) !T {
|
||||
const vector_info = @typeInfo(T).vector;
|
||||
|
||||
const nodes: Zoir.Node.Index.Range = switch (node.get(self.zoir)) {
|
||||
|
|
@ -1021,8 +1017,8 @@ const Parser = struct {
|
|||
);
|
||||
}
|
||||
|
||||
for (0..vector_info.len) |i| {
|
||||
errdefer for (0..i) |j| free(self.gpa, result[j]);
|
||||
inline for (0..vector_info.len) |i| {
|
||||
errdefer inline for (0..i) |j| free(self.gpa, result[j]);
|
||||
result[i] = try self.parseExpr(vector_info.child, nodes.at(@intCast(i)));
|
||||
}
|
||||
|
||||
|
|
|
|||
18
src/Sema.zig
18
src/Sema.zig
|
|
@ -27972,6 +27972,7 @@ fn elemVal(
|
|||
}
|
||||
}
|
||||
|
||||
/// Called when the index or indexable is runtime known.
|
||||
fn validateRuntimeElemAccess(
|
||||
sema: *Sema,
|
||||
block: *Block,
|
||||
|
|
@ -28236,6 +28237,10 @@ fn elemPtrArray(
|
|||
try sema.validateRuntimeValue(block, array_ptr_src, array_ptr);
|
||||
}
|
||||
|
||||
if (offset == null and array_ty.zigTypeTag(zcu) == .vector) {
|
||||
return sema.fail(block, elem_index_src, "vector index not comptime known", .{});
|
||||
}
|
||||
|
||||
// Runtime check is only needed if unable to comptime check.
|
||||
if (oob_safety and block.wantSafety() and offset == null) {
|
||||
const len_inst = try pt.intRef(.usize, array_len);
|
||||
|
|
@ -31425,19 +31430,6 @@ fn analyzeLoad(
|
|||
}
|
||||
}
|
||||
|
||||
if (ptr_ty.ptrInfo(zcu).flags.vector_index == .runtime) {
|
||||
const ptr_inst = ptr.toIndex().?;
|
||||
const air_tags = sema.air_instructions.items(.tag);
|
||||
if (air_tags[@intFromEnum(ptr_inst)] == .ptr_elem_ptr) {
|
||||
const ty_pl = sema.air_instructions.items(.data)[@intFromEnum(ptr_inst)].ty_pl;
|
||||
const bin_op = sema.getTmpAir().extraData(Air.Bin, ty_pl.payload).data;
|
||||
return block.addBinOp(.ptr_elem_val, bin_op.lhs, bin_op.rhs);
|
||||
}
|
||||
return sema.fail(block, ptr_src, "unable to determine vector element index of type '{f}'", .{
|
||||
ptr_ty.fmt(pt),
|
||||
});
|
||||
}
|
||||
|
||||
return block.addTyOp(.load, elem_ty, ptr);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -140,8 +140,7 @@ fn expectVectorsEqual(a: anytype, b: anytype) !void {
|
|||
const len_b = @typeInfo(@TypeOf(b)).vector.len;
|
||||
try expect(len_a == len_b);
|
||||
|
||||
var i: usize = 0;
|
||||
while (i < len_a) : (i += 1) {
|
||||
inline for (0..len_a) |i| {
|
||||
try expect(a[i] == b[i]);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -441,49 +441,6 @@ test "store vector elements via comptime index" {
|
|||
try comptime S.doTheTest();
|
||||
}
|
||||
|
||||
test "load vector elements via runtime index" {
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
||||
|
||||
const S = struct {
|
||||
fn doTheTest() !void {
|
||||
var v: @Vector(4, i32) = [_]i32{ 1, 2, 3, undefined };
|
||||
_ = &v;
|
||||
var i: u32 = 0;
|
||||
try expect(v[i] == 1);
|
||||
i += 1;
|
||||
try expect(v[i] == 2);
|
||||
i += 1;
|
||||
try expect(v[i] == 3);
|
||||
}
|
||||
};
|
||||
|
||||
try S.doTheTest();
|
||||
try comptime S.doTheTest();
|
||||
}
|
||||
|
||||
test "store vector elements via runtime index" {
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
||||
|
||||
const S = struct {
|
||||
fn doTheTest() !void {
|
||||
var v: @Vector(4, i32) = [_]i32{ 1, 5, 3, undefined };
|
||||
var i: u32 = 2;
|
||||
v[i] = 1;
|
||||
try expect(v[1] == 5);
|
||||
try expect(v[2] == 1);
|
||||
i += 1;
|
||||
v[i] = -364;
|
||||
try expect(-364 == v[3]);
|
||||
}
|
||||
};
|
||||
|
||||
try S.doTheTest();
|
||||
try comptime S.doTheTest();
|
||||
}
|
||||
|
||||
test "initialize vector which is a struct field" {
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
||||
|
|
@ -567,20 +524,20 @@ test "vector division operators" {
|
|||
};
|
||||
if (!is_signed_int) {
|
||||
const d0 = x / y;
|
||||
for (@as([4]T, d0), 0..) |v, i| {
|
||||
inline for (@as([4]T, d0), 0..) |v, i| {
|
||||
try expect(x[i] / y[i] == v);
|
||||
}
|
||||
}
|
||||
const d1 = @divExact(x, y);
|
||||
for (@as([4]T, d1), 0..) |v, i| {
|
||||
inline for (@as([4]T, d1), 0..) |v, i| {
|
||||
try expect(@divExact(x[i], y[i]) == v);
|
||||
}
|
||||
const d2 = @divFloor(x, y);
|
||||
for (@as([4]T, d2), 0..) |v, i| {
|
||||
inline for (@as([4]T, d2), 0..) |v, i| {
|
||||
try expect(@divFloor(x[i], y[i]) == v);
|
||||
}
|
||||
const d3 = @divTrunc(x, y);
|
||||
for (@as([4]T, d3), 0..) |v, i| {
|
||||
inline for (@as([4]T, d3), 0..) |v, i| {
|
||||
try expect(@divTrunc(x[i], y[i]) == v);
|
||||
}
|
||||
}
|
||||
|
|
@ -592,16 +549,16 @@ test "vector division operators" {
|
|||
};
|
||||
if (!is_signed_int and @typeInfo(T) != .float) {
|
||||
const r0 = x % y;
|
||||
for (@as([4]T, r0), 0..) |v, i| {
|
||||
inline for (@as([4]T, r0), 0..) |v, i| {
|
||||
try expect(x[i] % y[i] == v);
|
||||
}
|
||||
}
|
||||
const r1 = @mod(x, y);
|
||||
for (@as([4]T, r1), 0..) |v, i| {
|
||||
inline for (@as([4]T, r1), 0..) |v, i| {
|
||||
try expect(@mod(x[i], y[i]) == v);
|
||||
}
|
||||
const r2 = @rem(x, y);
|
||||
for (@as([4]T, r2), 0..) |v, i| {
|
||||
inline for (@as([4]T, r2), 0..) |v, i| {
|
||||
try expect(@rem(x[i], y[i]) == v);
|
||||
}
|
||||
}
|
||||
|
|
@ -654,7 +611,7 @@ test "vector bitwise not operator" {
|
|||
const S = struct {
|
||||
fn doTheTestNot(comptime T: type, x: @Vector(4, T)) !void {
|
||||
const y = ~x;
|
||||
for (@as([4]T, y), 0..) |v, i| {
|
||||
inline for (@as([4]T, y), 0..) |v, i| {
|
||||
try expect(~x[i] == v);
|
||||
}
|
||||
}
|
||||
|
|
@ -688,7 +645,7 @@ test "vector boolean not operator" {
|
|||
const S = struct {
|
||||
fn doTheTestNot(comptime T: type, x: @Vector(4, T)) !void {
|
||||
const y = !x;
|
||||
for (@as([4]T, y), 0..) |v, i| {
|
||||
inline for (@as([4]T, y), 0..) |v, i| {
|
||||
try expect(!x[i] == v);
|
||||
}
|
||||
}
|
||||
|
|
@ -1530,8 +1487,7 @@ test "store packed vector element" {
|
|||
|
||||
var v = @Vector(4, u1){ 1, 1, 1, 1 };
|
||||
try expectEqual(@Vector(4, u1){ 1, 1, 1, 1 }, v);
|
||||
var index: usize = 0;
|
||||
_ = &index;
|
||||
const index: usize = 0;
|
||||
v[index] = 0;
|
||||
try expectEqual(@Vector(4, u1){ 0, 1, 1, 1 }, v);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,22 +52,15 @@ fn accessVector(comptime init: anytype) !void {
|
|||
var vector: Vector = undefined;
|
||||
vector = init;
|
||||
inline for (0..@typeInfo(Vector).vector.len) |ct_index| {
|
||||
var rt_index: usize = undefined;
|
||||
rt_index = ct_index;
|
||||
if (&vector[rt_index] != &vector[ct_index]) return error.Unexpected;
|
||||
if (vector[rt_index] != init[ct_index]) return error.Unexpected;
|
||||
if (&vector[ct_index] != &vector[ct_index]) return error.Unexpected;
|
||||
if (vector[ct_index] != init[ct_index]) return error.Unexpected;
|
||||
vector[rt_index] = rt_vals[0];
|
||||
if (vector[rt_index] != ct_vals[0]) return error.Unexpected;
|
||||
vector[ct_index] = rt_vals[0];
|
||||
if (vector[ct_index] != ct_vals[0]) return error.Unexpected;
|
||||
vector[rt_index] = ct_vals[1];
|
||||
if (vector[rt_index] != ct_vals[1]) return error.Unexpected;
|
||||
vector[ct_index] = ct_vals[1];
|
||||
if (vector[ct_index] != ct_vals[1]) return error.Unexpected;
|
||||
vector[ct_index] = ct_vals[0];
|
||||
if (vector[rt_index] != ct_vals[0]) return error.Unexpected;
|
||||
if (vector[ct_index] != ct_vals[0]) return error.Unexpected;
|
||||
vector[ct_index] = rt_vals[1];
|
||||
if (vector[rt_index] != ct_vals[1]) return error.Unexpected;
|
||||
if (vector[ct_index] != ct_vals[1]) return error.Unexpected;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,4 +12,4 @@ fn loadv(ptr: anytype) i31 {
|
|||
|
||||
// error
|
||||
//
|
||||
// :10:15: error: unable to determine vector element index of type '*align(16:0:4:?) i31'
|
||||
// :5:22: error: vector index not comptime known
|
||||
|
|
|
|||
|
|
@ -12,4 +12,4 @@ fn storev(ptr: anytype, val: i31) void {
|
|||
|
||||
// error
|
||||
//
|
||||
// :10:8: error: unable to determine vector element index of type '*align(16:0:4:?) i31'
|
||||
// :6:15: error: vector index not comptime known
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue