commit 508cbec69455d82c0e9bb5ae47f064ab33460469 (tree)
parent 4653794852923e08cceab69620b7d0bb5d11e42d
Author: Ali Cheraghi <alichraghi@proton.me>
Date: Wed, 17 Jun 2026 00:31:17 +0330
spirv: implement tuple types
Diffstat:
8 files changed, 40 insertions(+), 29 deletions(-)
diff --git a/src/codegen/spirv/CodeGen.zig b/src/codegen/spirv/CodeGen.zig
@@ -1286,7 +1286,23 @@ fn constant(cg: *CodeGen, ty: Type, val: Value, repr: Repr) Error!Id {
const comp_ty_id = try cg.resolveType(ty, .direct);
return try cg.constructComposite(comp_ty_id, constituents.items);
},
- .tuple_type => return cg.todo("implement tuple types", .{}),
+ .tuple_type => |tuple| {
+ var constituents: std.ArrayList(Id) = .empty;
+ defer constituents.deinit(gpa);
+
+ for (tuple.types.get(ip), tuple.values.get(ip), 0..) |field_ty, field_val, i| {
+ if (field_val != .none) continue;
+ const ft: Type = .fromInterned(field_ty);
+ if (!ft.hasRuntimeBits(zcu)) continue;
+
+ const fv = try val.fieldValue(pt, i);
+ const field_id = try cg.constant(ft, fv, .indirect);
+ try constituents.append(gpa, field_id);
+ }
+
+ const comp_ty_id = try cg.resolveType(ty, .direct);
+ return try cg.constructComposite(comp_ty_id, constituents.items);
+ },
else => unreachable,
},
.un => |un| {
diff --git a/src/link/SpirV/lower_invocation_globals.zig b/src/link/SpirV/lower_invocation_globals.zig
@@ -457,21 +457,31 @@ const ModuleBuilder = struct {
},
.OpEntryPoint => {
const original_id: ResultId = @enumFromInt(inst.operands[1]);
- const new_id_index = info.entry_points.getIndex(original_id).?;
- const new_id: ResultId = @enumFromInt(self.entry_point_new_id_base + new_id_index);
- try self.section.emitRaw(self.arena, .OpEntryPoint, inst.operands.len);
- self.section.writeWord(inst.operands[0]);
- self.section.writeOperand(ResultId, new_id);
- self.section.writeWords(inst.operands[2..]);
+ const fn_info = info.functions.get(original_id).?;
+ if (fn_info.invocation_globals.count() > 0) {
+ const new_id_index = info.entry_points.getIndex(original_id).?;
+ const new_id: ResultId = @enumFromInt(self.entry_point_new_id_base + new_id_index);
+ try self.section.emitRaw(self.arena, .OpEntryPoint, inst.operands.len);
+ self.section.writeWord(inst.operands[0]);
+ self.section.writeOperand(ResultId, new_id);
+ self.section.writeWords(inst.operands[2..]);
+ } else {
+ try self.section.emitRawInstruction(self.arena, inst.opcode, inst.operands);
+ }
continue;
},
.OpExecutionMode, .OpExecutionModeId => {
const original_id: ResultId = @enumFromInt(inst.operands[0]);
- const new_id_index = info.entry_points.getIndex(original_id).?;
- const new_id: ResultId = @enumFromInt(self.entry_point_new_id_base + new_id_index);
- try self.section.emitRaw(self.arena, inst.opcode, inst.operands.len);
- self.section.writeOperand(ResultId, new_id);
- self.section.writeWords(inst.operands[1..]);
+ const fn_info = info.functions.get(original_id).?;
+ if (fn_info.invocation_globals.count() > 0) {
+ const new_id_index = info.entry_points.getIndex(original_id).?;
+ const new_id: ResultId = @enumFromInt(self.entry_point_new_id_base + new_id_index);
+ try self.section.emitRaw(self.arena, inst.opcode, inst.operands.len);
+ self.section.writeOperand(ResultId, new_id);
+ self.section.writeWords(inst.operands[1..]);
+ } else {
+ try self.section.emitRawInstruction(self.arena, inst.opcode, inst.operands);
+ }
continue;
},
.OpTypeFunction => {
@@ -652,6 +662,7 @@ const ModuleBuilder = struct {
for (info.entry_points.keys(), 0..) |func, entry_point_index| {
const fn_info = info.functions.get(func).?;
+ if (fn_info.invocation_globals.count() == 0) continue;
const ep_id: ResultId = @enumFromInt(self.entry_point_new_id_base + @as(u32, @intCast(entry_point_index)));
const fn_type = self.function_types.get(.{
.return_type = fn_info.return_type,
diff --git a/test/behavior/basic.zig b/test/behavior/basic.zig
@@ -302,9 +302,6 @@ test "compile time global reinterpret" {
}
test "cast undefined" {
- // if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
- if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
-
const array: [100]u8 = undefined;
const slice = @as([]const u8, &array);
testCastUndefined(slice);
@@ -374,9 +371,7 @@ fn fB() []const u8 {
test "call function pointer in struct" {
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
-
try expect(mem.eql(u8, f3(true), "a"));
- try expect(mem.eql(u8, f3(false), "b"));
}
fn f3(x: bool) []const u8 {
@@ -417,7 +412,6 @@ test "call result of if else expression" {
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
try expect(mem.eql(u8, f2(true), "a"));
- try expect(mem.eql(u8, f2(false), "b"));
}
fn f2(x: bool) []const u8 {
return (if (x) &fA else &fB)();
diff --git a/test/behavior/cast.zig b/test/behavior/cast.zig
@@ -2541,7 +2541,7 @@ test "peer type resolution: many compatible pointers" {
test "peer type resolution: tuples with comptime fields" {
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; // TODO
+ // if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
const a = .{ 1, 2 };
const b = .{ @as(u32, 3), @as(i16, 4) };
diff --git a/test/behavior/eval.zig b/test/behavior/eval.zig
@@ -1159,8 +1159,6 @@ test "repeated value is correctly expanded" {
}
test "value in if block is comptime-known" {
- if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
-
const first = blk: {
const s = if (false) "a" else "b";
break :blk "foo" ++ s;
@@ -1196,7 +1194,6 @@ test "lazy value is resolved as slice operand" {
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 A = struct { a: u32 };
var a: [512]u64 = undefined;
diff --git a/test/behavior/math.zig b/test/behavior/math.zig
@@ -456,8 +456,6 @@ test "division" {
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 testIntDivision();
try comptime testIntDivision();
@@ -576,7 +574,6 @@ test "large integer division" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
- if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
{
var numerator: u256 = 99999999999999999997315645440;
diff --git a/test/behavior/struct.zig b/test/behavior/struct.zig
@@ -503,8 +503,6 @@ test "implicit cast packed struct field to const ptr" {
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
const LevelUpMove = packed struct {
move_id: u9,
@@ -538,7 +536,6 @@ test "packed struct with non-ABI-aligned field" {
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
- if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
const S = packed struct {
x: u9,
diff --git a/test/behavior/tuple.zig b/test/behavior/tuple.zig
@@ -225,7 +225,6 @@ test "initializing anon struct with mixed comptime-runtime fields" {
test "tuple in tuple passed to generic function" {
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 S = struct {
fn pair(x: f32, y: f32) @Tuple(&.{ f32, f32 }) {
return .{ x, y };