diff --git a/lib/std/Target.zig b/lib/std/Target.zig index 5773faa5f2..027872de54 100644 --- a/lib/std/Target.zig +++ b/lib/std/Target.zig @@ -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| { diff --git a/lib/std/crypto/chacha20.zig b/lib/std/crypto/chacha20.zig index c4e84aad53..17fb7e7ab3 100644 --- a/lib/std/crypto/chacha20.zig +++ b/lib/std/crypto/chacha20.zig @@ -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); diff --git a/lib/std/json/static.zig b/lib/std/json/static.zig index ced6894027..4de5676bd6 100644 --- a/lib/std/json/static.zig +++ b/lib/std/json/static.zig @@ -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); } diff --git a/lib/std/meta.zig b/lib/std/meta.zig index 7b12094d8a..222d3276d5 100644 --- a/lib/std/meta.zig +++ b/lib/std/meta.zig @@ -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; }, diff --git a/lib/std/testing.zig b/lib/std/testing.zig index b2dd271dc0..1cc1c4b4b5 100644 --- a/lib/std/testing.zig +++ b/lib/std/testing.zig @@ -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], diff --git a/lib/std/zon/Serializer.zig b/lib/std/zon/Serializer.zig index b65b13bf97..5515cc2f06 100644 --- a/lib/std/zon/Serializer.zig +++ b/lib/std/zon/Serializer.zig @@ -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(); diff --git a/lib/std/zon/parse.zig b/lib/std/zon/parse.zig index 6644f1114e..5dfb95b072 100644 --- a/lib/std/zon/parse.zig +++ b/lib/std/zon/parse.zig @@ -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))); } diff --git a/src/Sema.zig b/src/Sema.zig index 385e1ae74a..38897cde1c 100644 --- a/src/Sema.zig +++ b/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); } diff --git a/test/behavior/math.zig b/test/behavior/math.zig index 914c47ba69..5e844af619 100644 --- a/test/behavior/math.zig +++ b/test/behavior/math.zig @@ -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]); } } diff --git a/test/behavior/vector.zig b/test/behavior/vector.zig index bf430f41bb..033e91484e 100644 --- a/test/behavior/vector.zig +++ b/test/behavior/vector.zig @@ -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); } diff --git a/test/behavior/x86_64/access.zig b/test/behavior/x86_64/access.zig index 5c6cbe0301..86a20ae124 100644 --- a/test/behavior/x86_64/access.zig +++ b/test/behavior/x86_64/access.zig @@ -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; } } diff --git a/test/cases/compile_errors/load_vector_pointer_with_unknown_runtime_index.zig b/test/cases/compile_errors/load_vector_pointer_with_unknown_runtime_index.zig index 053dfde525..f72f44ca21 100644 --- a/test/cases/compile_errors/load_vector_pointer_with_unknown_runtime_index.zig +++ b/test/cases/compile_errors/load_vector_pointer_with_unknown_runtime_index.zig @@ -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 diff --git a/test/cases/compile_errors/store_vector_pointer_with_unknown_runtime_index.zig b/test/cases/compile_errors/store_vector_pointer_with_unknown_runtime_index.zig index ee587b09ae..32a595d877 100644 --- a/test/cases/compile_errors/store_vector_pointer_with_unknown_runtime_index.zig +++ b/test/cases/compile_errors/store_vector_pointer_with_unknown_runtime_index.zig @@ -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