zig

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

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:
Msrc/codegen/spirv/CodeGen.zig | 18+++++++++++++++++-
Msrc/link/SpirV/lower_invocation_globals.zig | 33++++++++++++++++++++++-----------
Mtest/behavior/basic.zig | 6------
Mtest/behavior/cast.zig | 2+-
Mtest/behavior/eval.zig | 3---
Mtest/behavior/math.zig | 3---
Mtest/behavior/struct.zig | 3---
Mtest/behavior/tuple.zig | 1-
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 };