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:
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
+ &.{},
};
}