authorgravatar for alichraghi@proton.meAli Chraghi <alichraghi@proton.me> 2026-06-17 00:31:17+03:30
committergravatar for alichraghi@noreply.codeberg.orgAli Cheraghi <alichraghi@noreply.codeberg.org> 2026-06-18 13:38:58+02:00
log508cbec69455d82c0e9bb5ae47f064ab33460469
treea7dff5e985ff33474e1f5982767e4dd1a18749d1
parent4653794852923e08cceab69620b7d0bb5d11e42d

spirv: implement tuple types


8 files changed, 40 insertions(+), 29 deletions(-)

src/codegen/spirv/CodeGen.zig+17-1
......@@ -1286,7 +1286,23 @@ fn constant(cg: *CodeGen, ty: Type, val: Value, repr: Repr) Error!Id {
12861286 const comp_ty_id = try cg.resolveType(ty, .direct);
12871287 return try cg.constructComposite(comp_ty_id, constituents.items);
12881288 },
1289 .tuple_type => return cg.todo("implement tuple types", .{}),
1289 .tuple_type => |tuple| {
1290 var constituents: std.ArrayList(Id) = .empty;
1291 defer constituents.deinit(gpa);
1292
1293 for (tuple.types.get(ip), tuple.values.get(ip), 0..) |field_ty, field_val, i| {
1294 if (field_val != .none) continue;
1295 const ft: Type = .fromInterned(field_ty);
1296 if (!ft.hasRuntimeBits(zcu)) continue;
1297
1298 const fv = try val.fieldValue(pt, i);
1299 const field_id = try cg.constant(ft, fv, .indirect);
1300 try constituents.append(gpa, field_id);
1301 }
1302
1303 const comp_ty_id = try cg.resolveType(ty, .direct);
1304 return try cg.constructComposite(comp_ty_id, constituents.items);
1305 },
12901306 else => unreachable,
12911307 },
12921308 .un => |un| {
src/link/SpirV/lower_invocation_globals.zig+22-11
......@@ -457,21 +457,31 @@ const ModuleBuilder = struct {
457457 },
458458 .OpEntryPoint => {
459459 const original_id: ResultId = @enumFromInt(inst.operands[1]);
460 const new_id_index = info.entry_points.getIndex(original_id).?;
461 const new_id: ResultId = @enumFromInt(self.entry_point_new_id_base + new_id_index);
462 try self.section.emitRaw(self.arena, .OpEntryPoint, inst.operands.len);
463 self.section.writeWord(inst.operands[0]);
464 self.section.writeOperand(ResultId, new_id);
465 self.section.writeWords(inst.operands[2..]);
460 const fn_info = info.functions.get(original_id).?;
461 if (fn_info.invocation_globals.count() > 0) {
462 const new_id_index = info.entry_points.getIndex(original_id).?;
463 const new_id: ResultId = @enumFromInt(self.entry_point_new_id_base + new_id_index);
464 try self.section.emitRaw(self.arena, .OpEntryPoint, inst.operands.len);
465 self.section.writeWord(inst.operands[0]);
466 self.section.writeOperand(ResultId, new_id);
467 self.section.writeWords(inst.operands[2..]);
468 } else {
469 try self.section.emitRawInstruction(self.arena, inst.opcode, inst.operands);
470 }
466471 continue;
467472 },
468473 .OpExecutionMode, .OpExecutionModeId => {
469474 const original_id: ResultId = @enumFromInt(inst.operands[0]);
470 const new_id_index = info.entry_points.getIndex(original_id).?;
471 const new_id: ResultId = @enumFromInt(self.entry_point_new_id_base + new_id_index);
472 try self.section.emitRaw(self.arena, inst.opcode, inst.operands.len);
473 self.section.writeOperand(ResultId, new_id);
474 self.section.writeWords(inst.operands[1..]);
475 const fn_info = info.functions.get(original_id).?;
476 if (fn_info.invocation_globals.count() > 0) {
477 const new_id_index = info.entry_points.getIndex(original_id).?;
478 const new_id: ResultId = @enumFromInt(self.entry_point_new_id_base + new_id_index);
479 try self.section.emitRaw(self.arena, inst.opcode, inst.operands.len);
480 self.section.writeOperand(ResultId, new_id);
481 self.section.writeWords(inst.operands[1..]);
482 } else {
483 try self.section.emitRawInstruction(self.arena, inst.opcode, inst.operands);
484 }
475485 continue;
476486 },
477487 .OpTypeFunction => {
......@@ -652,6 +662,7 @@ const ModuleBuilder = struct {
652662
653663 for (info.entry_points.keys(), 0..) |func, entry_point_index| {
654664 const fn_info = info.functions.get(func).?;
665 if (fn_info.invocation_globals.count() == 0) continue;
655666 const ep_id: ResultId = @enumFromInt(self.entry_point_new_id_base + @as(u32, @intCast(entry_point_index)));
656667 const fn_type = self.function_types.get(.{
657668 .return_type = fn_info.return_type,
test/behavior/basic.zig-6
......@@ -302,9 +302,6 @@ test "compile time global reinterpret" {
302302}
303303
304304test "cast undefined" {
305 // if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
306 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
307
308305 const array: [100]u8 = undefined;
309306 const slice = @as([]const u8, &array);
310307 testCastUndefined(slice);
......@@ -374,9 +371,7 @@ fn fB() []const u8 {
374371test "call function pointer in struct" {
375372 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
376373 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
377
378374 try expect(mem.eql(u8, f3(true), "a"));
379 try expect(mem.eql(u8, f3(false), "b"));
380375}
381376
382377fn f3(x: bool) []const u8 {
......@@ -417,7 +412,6 @@ test "call result of if else expression" {
417412 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
418413
419414 try expect(mem.eql(u8, f2(true), "a"));
420 try expect(mem.eql(u8, f2(false), "b"));
421415}
422416fn f2(x: bool) []const u8 {
423417 return (if (x) &fA else &fB)();
test/behavior/cast.zig+1-1
......@@ -2541,7 +2541,7 @@ test "peer type resolution: many compatible pointers" {
25412541test "peer type resolution: tuples with comptime fields" {
25422542 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
25432543 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
2544 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
2544 // if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
25452545
25462546 const a = .{ 1, 2 };
25472547 const b = .{ @as(u32, 3), @as(i16, 4) };
test/behavior/eval.zig-3
......@@ -1159,8 +1159,6 @@ test "repeated value is correctly expanded" {
11591159}
11601160
11611161test "value in if block is comptime-known" {
1162 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1163
11641162 const first = blk: {
11651163 const s = if (false) "a" else "b";
11661164 break :blk "foo" ++ s;
......@@ -1196,7 +1194,6 @@ test "lazy value is resolved as slice operand" {
11961194 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
11971195 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
11981196 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1199
12001197 const A = struct { a: u32 };
12011198 var a: [512]u64 = undefined;
12021199
test/behavior/math.zig-3
......@@ -456,8 +456,6 @@ test "division" {
456456 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
457457 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
458458 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
459 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
460
461459 try testIntDivision();
462460 try comptime testIntDivision();
463461
......@@ -576,7 +574,6 @@ test "large integer division" {
576574 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
577575 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
578576 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
579 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
580577
581578 {
582579 var numerator: u256 = 99999999999999999997315645440;
test/behavior/struct.zig-3
......@@ -503,8 +503,6 @@ test "implicit cast packed struct field to const ptr" {
503503 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
504504 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
505505 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
506 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
507 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
508506
509507 const LevelUpMove = packed struct {
510508 move_id: u9,
......@@ -538,7 +536,6 @@ test "packed struct with non-ABI-aligned field" {
538536 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
539537 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
540538 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
541 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
542539
543540 const S = packed struct {
544541 x: u9,
test/behavior/tuple.zig-1
......@@ -225,7 +225,6 @@ test "initializing anon struct with mixed comptime-runtime fields" {
225225test "tuple in tuple passed to generic function" {
226226 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
227227 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
228 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
229228 const S = struct {
230229 fn pair(x: f32, y: f32) @Tuple(&.{ f32, f32 }) {
231230 return .{ x, y };