zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

commit 902b71eafa9c92d01a6c0195dfdc5a59294dfe20 (tree)
parent e0e145048d4b7b80bdbf15c78b33dea06edadc0a
Author: Ali Cheraghi <alichraghi@noreply.codeberg.org>
Date:   Sun, 28 Jun 2026 18:25:43 +0200

Merge pull request 'Type: allow vectors in externs for SPIR-V target' (#35953) from alichraghi/zig:master into master

Reviewed-on: https://codeberg.org/ziglang/zig/pulls/35953

Diffstat:
Mlib/std/Target/spirv.zig | 24++++++++++++++++++------
Msrc/Sema.zig | 1+
Msrc/Type.zig | 5++++-
Msrc/codegen/spirv/CodeGen.zig | 13++-----------
Mtest/behavior/align.zig | 1-
Mtest/behavior/array.zig | 1-
Mtest/behavior/cast.zig | 2--
Mtest/behavior/destructure.zig | 2--
Mtest/behavior/error.zig | 2--
Mtest/behavior/eval.zig | 2--
Mtest/behavior/fn.zig | 1-
Mtest/behavior/generics.zig | 1-
Mtest/behavior/globals.zig | 1-
Mtest/behavior/inline_switch.zig | 2+-
Mtest/behavior/math.zig | 1-
Mtest/behavior/muladd.zig | 1-
Mtest/behavior/optional.zig | 1-
Mtest/behavior/slice.zig | 3---
Mtest/behavior/struct.zig | 1-
Mtest/behavior/switch.zig | 3++-
Mtest/behavior/tuple.zig | 1-
Mtest/behavior/vector.zig | 1-
Mtools/update_cpu_features.zig | 15++++++++++++++-
23 files changed, 42 insertions(+), 43 deletions(-)

diff --git a/lib/std/Target/spirv.zig b/lib/std/Target/spirv.zig @@ -1766,32 +1766,44 @@ pub const all_features = blk: { result[@intFromEnum(Feature.v1_1)] = .{ .llvm_name = null, .description = "Enable v1_1 Extension.", - .dependencies = featureSet(&[_]Feature{}), + .dependencies = featureSet(&[_]Feature{ + .v1_0, + }), }; result[@intFromEnum(Feature.v1_2)] = .{ .llvm_name = null, .description = "Enable v1_2 Extension.", - .dependencies = featureSet(&[_]Feature{}), + .dependencies = featureSet(&[_]Feature{ + .v1_1, + }), }; result[@intFromEnum(Feature.v1_3)] = .{ .llvm_name = null, .description = "Enable v1_3 Extension.", - .dependencies = featureSet(&[_]Feature{}), + .dependencies = featureSet(&[_]Feature{ + .v1_2, + }), }; result[@intFromEnum(Feature.v1_4)] = .{ .llvm_name = null, .description = "Enable v1_4 Extension.", - .dependencies = featureSet(&[_]Feature{}), + .dependencies = featureSet(&[_]Feature{ + .v1_3, + }), }; result[@intFromEnum(Feature.v1_5)] = .{ .llvm_name = null, .description = "Enable v1_5 Extension.", - .dependencies = featureSet(&[_]Feature{}), + .dependencies = featureSet(&[_]Feature{ + .v1_4, + }), }; result[@intFromEnum(Feature.v1_6)] = .{ .llvm_name = null, .description = "Enable v1_6 Extension.", - .dependencies = featureSet(&[_]Feature{}), + .dependencies = featureSet(&[_]Feature{ + .v1_5, + }), }; result[@intFromEnum(Feature.variable_pointers)] = .{ .llvm_name = null, diff --git a/src/Sema.zig b/src/Sema.zig @@ -27032,6 +27032,7 @@ fn elemPtrOneLayerOnly( .vector => try sema.elemPtrVector(block, indexable_src, indexable, elem_index_src, elem_index, init), .array => try sema.elemPtrArray(block, src, indexable_src, indexable, elem_index_src, elem_index, init, oob_safety), .@"struct" => try sema.tupleElemPtr(block, indexable_src, indexable, elem_index, elem_index_src), + .spirv => try sema.elemPtrSpirvRuntimeArray(block, indexable, elem_index), else => unreachable, // Guaranteed by checkIndexable }; try sema.checkKnownAllocPtr(block, indexable, elem_ptr); diff --git a/src/Type.zig b/src/Type.zig @@ -3087,7 +3087,10 @@ pub fn validateExtern(ty: Type, position: ExternPosition, zcu: *const Zcu) bool .frame, => false, - .vector => position == .param_ty or position == .ret_ty, + .vector => { + if (zcu.getTarget().cpu.arch.isSpirV()) return true; + return position == .param_ty or position == .ret_ty; + }, .void => switch (position) { .ret_ty, diff --git a/src/codegen/spirv/CodeGen.zig b/src/codegen/spirv/CodeGen.zig @@ -1881,17 +1881,8 @@ fn derivePtr(cg: *CodeGen, derivation: Value.PointerDeriveStep) !Id { const parent_ptr_ty = try oac.parent.ptrType(pt); const result_ty_id = try cg.resolveType(oac.new_ptr_ty, .direct); - if (parent_ptr_ty.childType(zcu).isVector(zcu)) { - // Vector element ptr accesses are derived as offset_and_cast. - // We can just use OpAccessChain. - const child_size = oac.new_ptr_ty.childType(zcu).abiSize(zcu); - if (oac.byte_offset % child_size == 0) { - return cg.accessChain( - result_ty_id, - parent_ptr_id, - &.{@intCast(@divExact(oac.byte_offset, child_size))}, - ); - } + if (oac.new_ptr_ty.ptrInfo(zcu).flags.vector_index != .none) { + return parent_ptr_id; } if (oac.byte_offset == 0) { diff --git a/test/behavior/align.zig b/test/behavior/align.zig @@ -432,7 +432,6 @@ test "read 128-bit field from default aligned struct in stack memory" { if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; var default_aligned = DefaultAligned{ .nevermind = 1, diff --git a/test/behavior/array.zig b/test/behavior/array.zig @@ -1077,7 +1077,6 @@ test "initialize sentinel-terminated slice with reference to empty array initial } test "initialize sentinel-terminated many-pointer with reference to empty array initializer" { - if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; const a: [*:0]const u8 = &.{}; comptime assert(a[0] == 0); } diff --git a/test/behavior/cast.zig b/test/behavior/cast.zig @@ -433,8 +433,6 @@ test "implicit cast from *[N]T to [*c]T" { } test "*usize to *void" { - if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - var i = @as(usize, 0); const v: *void = @ptrCast(&i); v.* = {}; diff --git a/test/behavior/destructure.zig b/test/behavior/destructure.zig @@ -94,8 +94,6 @@ test "destructure from labeled block" { } test "destructure tuple value" { - if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - const tup: struct { f32, u32, i64 } = .{ 10.0, 20, 30 }; const x, const y, const z = tup; diff --git a/test/behavior/error.zig b/test/behavior/error.zig @@ -145,8 +145,6 @@ test "implicit cast to optional to error union to return result loc" { } test "fn returning empty error set can be passed as fn returning any error" { - if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - entry(); comptime entry(); } diff --git a/test/behavior/eval.zig b/test/behavior/eval.zig @@ -1445,8 +1445,6 @@ test "struct in comptime false branch is not evaluated" { } test "result of nested switch assigned to variable" { - if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO - var zds: u32 = 0; zds = switch (zds) { 0 => switch (zds) { diff --git a/test/behavior/fn.zig b/test/behavior/fn.zig @@ -292,7 +292,6 @@ fn voidFun(a: i32, b: void, c: i32, d: void) !void { test "call function with empty string" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; acceptsString(""); } diff --git a/test/behavior/generics.zig b/test/behavior/generics.zig @@ -519,7 +519,6 @@ test "call generic function with from function called by the generic function" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; const GET = struct { key: []const u8, diff --git a/test/behavior/globals.zig b/test/behavior/globals.zig @@ -16,7 +16,6 @@ var vpos = @Vector(2, f32){ 0.0, 0.0 }; test "store to global vector" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; try expect(vpos[1] == 0.0); vpos = @Vector(2, f32){ 0.0, 1.0 }; diff --git a/test/behavior/inline_switch.zig b/test/behavior/inline_switch.zig @@ -81,7 +81,7 @@ test "inline else bool" { test "inline else error" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; + const Err = error{ a, b, c }; var a = Err.a; _ = &a; diff --git a/test/behavior/math.zig b/test/behavior/math.zig @@ -1389,7 +1389,6 @@ fn testOr(comptime T: type, a: T, b: T, expected: T) !void { test "or > 128 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; try testOr(u140, 0, 1 << 139, 1 << 139); try testOr(u140, (1 << 70) | 0xa, (1 << 69) | 0x5, (1 << 70) | (1 << 69) | 0xf); diff --git a/test/behavior/muladd.zig b/test/behavior/muladd.zig @@ -101,7 +101,6 @@ test "vector f16" { 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; - if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; try comptime vector16(); try vector16(); diff --git a/test/behavior/optional.zig b/test/behavior/optional.zig @@ -426,7 +426,6 @@ test "optional pointer to zero bit optional payload" { 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; - if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; const B = struct { fn foo(_: *@This()) void {} diff --git a/test/behavior/slice.zig b/test/behavior/slice.zig @@ -787,8 +787,6 @@ test "slice bounds in comptime concatenation" { } test "slice sentinel access at comptime" { - if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - { const str0 = &[_:0]u8{ '1', '2', '3' }; const slice0: [:0]const u8 = str0; @@ -809,7 +807,6 @@ test "slice sentinel access at comptime" { test "slicing array with sentinel as end index" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - const S = struct { fn do() !void { var array = [_:0]u8{ 1, 2, 3, 4 }; diff --git a/test/behavior/struct.zig b/test/behavior/struct.zig @@ -567,7 +567,6 @@ test "bit field access" { 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 - if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO var data = bit_field_1; diff --git a/test/behavior/switch.zig b/test/behavior/switch.zig @@ -314,7 +314,6 @@ fn testSwitchEnumPtrCapture() !void { test "switch handles all cases of number" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; try testSwitchHandleAllCases(); try comptime testSwitchHandleAllCases(); @@ -1576,6 +1575,8 @@ test "repeated switch analysis overrides previous analysis results" { } test "union field pointer capture preserves alignment in inline prong" { + if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; + const U = union(enum) { a: u32, b: u32, diff --git a/test/behavior/tuple.zig b/test/behavior/tuple.zig @@ -242,7 +242,6 @@ test "tuple in tuple passed to generic function" { test "coerce tuple to tuple" { 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_spirv) return error.SkipZigTest; const T = @Tuple(&.{u8}); const S = struct { diff --git a/test/behavior/vector.zig b/test/behavior/vector.zig @@ -414,7 +414,6 @@ test "vector @splat" { } test "load vector elements via comptime index" { - if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO diff --git a/tools/update_cpu_features.zig b/tools/update_cpu_features.zig @@ -80,7 +80,20 @@ const spirv_extra_features = blk: { feature.* = .{ .zig_name = name, .desc = "Enable " ++ name ++ " extension", - .deps = &.{}, + .deps = if (std.mem.eql(u8, name, "v1_6")) + &.{"v1_5"} + else if (std.mem.eql(u8, name, "v1_5")) + &.{"v1_4"} + else if (std.mem.eql(u8, name, "v1_4")) + &.{"v1_3"} + else if (std.mem.eql(u8, name, "v1_3")) + &.{"v1_2"} + else if (std.mem.eql(u8, name, "v1_2")) + &.{"v1_1"} + else if (std.mem.eql(u8, name, "v1_1")) + &.{"v1_0"} + else + &.{}, }; }