authorgravatar for alichraghi@proton.meAli Chraghi <alichraghi@proton.me> 2025-02-19 00:06:10+03:30
committergravatar for robin@voetter.nlRobin Voetter <robin@voetter.nl> 2025-02-24 19:12:33+01:00
loga0eec9ce9e2f4ae40729949957bef98a2513fef7
treef17a4ac38256a6b0601a68439f562dc477c57989
parent1cc388d5263058f9e9eecc410eea825a9a58e143
signaturebadge-check Signed by SSH key SHA256:ZS52FNyUv2WUXvO4njmVaFVO46RHojFuOrxRc4LuKzg

spirv: replace some unreachables with compile errors


4 files changed, 76 insertions(+), 42 deletions(-)

lib/std/Target/spirv.zig+24-18
......@@ -17,6 +17,7 @@ pub const Feature = enum {
1717 float64,
1818 addresses,
1919 matrix,
20 storage_push_constant16,
2021 kernel,
2122 generic_pointer,
2223 vector16,
......@@ -35,92 +36,97 @@ pub const all_features = blk: {
3536 var result: [len]CpuFeature = undefined;
3637 result[@intFromEnum(Feature.v1_0)] = .{
3738 .llvm_name = null,
38 .description = "SPIR-V version 1.0",
39 .description = "Enable version 1.0",
3940 .dependencies = featureSet(&[_]Feature{}),
4041 };
4142 result[@intFromEnum(Feature.v1_1)] = .{
4243 .llvm_name = null,
43 .description = "SPIR-V version 1.1",
44 .description = "Enable version 1.1",
4445 .dependencies = featureSet(&[_]Feature{.v1_0}),
4546 };
4647 result[@intFromEnum(Feature.v1_2)] = .{
4748 .llvm_name = null,
48 .description = "SPIR-V version 1.2",
49 .description = "Enable version 1.2",
4950 .dependencies = featureSet(&[_]Feature{.v1_1}),
5051 };
5152 result[@intFromEnum(Feature.v1_3)] = .{
5253 .llvm_name = null,
53 .description = "SPIR-V version 1.3",
54 .description = "Enable version 1.3",
5455 .dependencies = featureSet(&[_]Feature{.v1_2}),
5556 };
5657 result[@intFromEnum(Feature.v1_4)] = .{
5758 .llvm_name = null,
58 .description = "SPIR-V version 1.4",
59 .description = "Enable version 1.4",
5960 .dependencies = featureSet(&[_]Feature{.v1_3}),
6061 };
6162 result[@intFromEnum(Feature.v1_5)] = .{
6263 .llvm_name = null,
63 .description = "SPIR-V version 1.5",
64 .description = "Enable version 1.5",
6465 .dependencies = featureSet(&[_]Feature{.v1_4}),
6566 };
6667 result[@intFromEnum(Feature.v1_6)] = .{
6768 .llvm_name = null,
68 .description = "SPIR-V version 1.6",
69 .description = "Enable version 1.6",
6970 .dependencies = featureSet(&[_]Feature{.v1_5}),
7071 };
7172 result[@intFromEnum(Feature.int8)] = .{
7273 .llvm_name = null,
73 .description = "Enable SPIR-V capability Int8",
74 .description = "Enable Int8 capability",
7475 .dependencies = featureSet(&[_]Feature{.v1_0}),
7576 };
7677 result[@intFromEnum(Feature.int16)] = .{
7778 .llvm_name = null,
78 .description = "Enable SPIR-V capability Int16",
79 .description = "Enable Int16 capability",
7980 .dependencies = featureSet(&[_]Feature{.v1_0}),
8081 };
8182 result[@intFromEnum(Feature.int64)] = .{
8283 .llvm_name = null,
83 .description = "Enable SPIR-V capability Int64",
84 .description = "Enable Int64 capability",
8485 .dependencies = featureSet(&[_]Feature{.v1_0}),
8586 };
8687 result[@intFromEnum(Feature.float16)] = .{
8788 .llvm_name = null,
88 .description = "Enable SPIR-V capability Float16",
89 .description = "Enable Float16 capability",
8990 .dependencies = featureSet(&[_]Feature{.v1_0}),
9091 };
9192 result[@intFromEnum(Feature.float64)] = .{
9293 .llvm_name = null,
93 .description = "Enable SPIR-V capability Float64",
94 .description = "Enable Float64 capability",
9495 .dependencies = featureSet(&[_]Feature{.v1_0}),
9596 };
9697 result[@intFromEnum(Feature.addresses)] = .{
9798 .llvm_name = null,
98 .description = "Enable SPIR-V capability Addresses",
99 .description = "Enable either the Addresses capability or, SPV_KHR_physical_storage_buffer extension and the PhysicalStorageBufferAddresses capability",
99100 .dependencies = featureSet(&[_]Feature{.v1_0}),
100101 };
101102 result[@intFromEnum(Feature.matrix)] = .{
102103 .llvm_name = null,
103 .description = "Enable SPIR-V capability Matrix",
104 .description = "Enable Matrix capability",
104105 .dependencies = featureSet(&[_]Feature{.v1_0}),
105106 };
107 result[@intFromEnum(Feature.storage_push_constant16)] = .{
108 .llvm_name = null,
109 .description = "Enable SPV_KHR_16bit_storage extension and the StoragePushConstant16 capability",
110 .dependencies = featureSet(&[_]Feature{.v1_3}),
111 };
106112 result[@intFromEnum(Feature.kernel)] = .{
107113 .llvm_name = null,
108 .description = "Enable SPIR-V capability Kernel",
114 .description = "Enable Kernel capability",
109115 .dependencies = featureSet(&[_]Feature{.v1_0}),
110116 };
111117 result[@intFromEnum(Feature.generic_pointer)] = .{
112118 .llvm_name = null,
113 .description = "Enable SPIR-V capability GenericPointer",
119 .description = "Enable GenericPointer capability",
114120 .dependencies = featureSet(&[_]Feature{ .v1_0, .addresses }),
115121 };
116122 result[@intFromEnum(Feature.vector16)] = .{
117123 .llvm_name = null,
118 .description = "Enable SPIR-V capability Vector16",
124 .description = "Enable Vector16 capability",
119125 .dependencies = featureSet(&[_]Feature{ .v1_0, .kernel }),
120126 };
121127 result[@intFromEnum(Feature.shader)] = .{
122128 .llvm_name = null,
123 .description = "Enable SPIR-V capability Shader",
129 .description = "Enable Shader capability",
124130 .dependencies = featureSet(&[_]Feature{ .v1_0, .matrix }),
125131 };
126132 const ti = @typeInfo(Feature);
src/Zcu.zig+8
......@@ -3463,7 +3463,15 @@ fn clearCachedResolvedReferences(zcu: *Zcu) void {
34633463}
34643464
34653465pub fn errorSetBits(zcu: *const Zcu) u16 {
3466 const target = zcu.getTarget();
3467
34663468 if (zcu.error_limit == 0) return 0;
3469 if (target.cpu.arch == .spirv64) {
3470 if (!std.Target.spirv.featureSetHas(target.cpu.features, .storage_push_constant16)) {
3471 return 32;
3472 }
3473 }
3474
34673475 return @as(u16, std.math.log2_int(ErrorInt, zcu.error_limit)) + 1;
34683476}
34693477
src/codegen/spirv.zig+34-22
......@@ -1018,7 +1018,7 @@ const NavGen = struct {
10181018 const comp_ty_id = try self.resolveType(ty, .direct);
10191019 return try self.constructComposite(comp_ty_id, constituents.items);
10201020 },
1021 .tuple_type => unreachable, // TODO
1021 .tuple_type => return self.todo("implement tuple types", .{}),
10221022 else => unreachable,
10231023 },
10241024 .un => |un| {
......@@ -1255,6 +1255,7 @@ const NavGen = struct {
12551255
12561256 fn ptrType(self: *NavGen, child_ty: Type, storage_class: StorageClass, child_repr: Repr) !IdRef {
12571257 const zcu = self.pt.zcu;
1258 const ip = &zcu.intern_pool;
12581259 const key = .{ child_ty.toIntern(), storage_class, child_repr };
12591260 const entry = try self.ptr_types.getOrPut(self.gpa, key);
12601261 if (entry.found_existing) {
......@@ -1285,7 +1286,12 @@ const NavGen = struct {
12851286 }
12861287 }
12871288
1288 try self.spv.decorate(result_id, .{ .ArrayStride = .{ .array_stride = @intCast(child_ty.abiSize(zcu)) } });
1289 switch (ip.indexToKey(child_ty.toIntern())) {
1290 .func_type, .opaque_type => {},
1291 else => {
1292 try self.spv.decorate(result_id, .{ .ArrayStride = .{ .array_stride = @intCast(child_ty.abiSize(zcu)) } });
1293 },
1294 }
12891295 }
12901296
12911297 try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpTypePointer, .{
......@@ -1704,7 +1710,10 @@ const NavGen = struct {
17041710 return result_id;
17051711 },
17061712 .@"union" => return try self.resolveUnionType(ty),
1707 .error_set => return try self.resolveType(Type.u16, repr),
1713 .error_set => {
1714 const err_int_ty = try pt.errorIntType();
1715 return try self.resolveType(err_int_ty, repr);
1716 },
17081717 .error_union => {
17091718 const payload_ty = ty.errorUnionPayload(zcu);
17101719 const error_ty_id = try self.resolveType(Type.anyerror, .indirect);
......@@ -2329,7 +2338,7 @@ const NavGen = struct {
23292338 // NOTE: Vulkan's FMA instruction does *NOT* produce the right values!
23302339 // its precision guarantees do NOT match zigs and it does NOT match OpenCLs!
23312340 // it needs to be emulated!
2332 .vulkan, .opengl => unreachable, // TODO: See above
2341 .vulkan, .opengl => return self.todo("implement fma operation for {s} os", .{@tagName(target.os.tag)}),
23332342 else => unreachable,
23342343 };
23352344
......@@ -2529,12 +2538,12 @@ const NavGen = struct {
25292538 .vulkan, .opengl => switch (op) {
25302539 .i_abs => 5, // SAbs
25312540 .f_abs => 4, // FAbs
2532 .clz => unreachable, // TODO
2533 .ctz => unreachable, // TODO
25342541 .floor => 8, // Floor
25352542 .ceil => 9, // Ceil
25362543 .trunc => 3, // Trunc
25372544 .round => 1, // Round
2545 .clz,
2546 .ctz,
25382547 .sqrt,
25392548 .sin,
25402549 .cos,
......@@ -2544,7 +2553,7 @@ const NavGen = struct {
25442553 .log,
25452554 .log2,
25462555 .log10,
2547 => unreachable, // TODO
2556 => return self.todo("implement unary operation '{s}' for {s} os", .{ @tagName(op), @tagName(target.os.tag) }),
25482557 else => unreachable,
25492558 },
25502559 else => unreachable,
......@@ -2810,6 +2819,8 @@ const NavGen = struct {
28102819 /// TODO is to also write out the error as a function call parameter, and to somehow fetch
28112820 /// the name of an error in the text executor.
28122821 fn generateTestEntryPoint(self: *NavGen, name: []const u8, spv_test_decl_index: SpvModule.Decl.Index) !void {
2822 const target = self.spv.target;
2823
28132824 const anyerror_ty_id = try self.resolveType(Type.anyerror, .direct);
28142825 const ptr_anyerror_ty = try self.pt.ptrType(.{
28152826 .child = Type.anyerror.toIntern(),
......@@ -2819,12 +2830,12 @@ const NavGen = struct {
28192830
28202831 const spv_decl_index = try self.spv.allocDecl(.func);
28212832 const kernel_id = self.spv.declPtr(spv_decl_index).result_id;
2822 // for some reason we don't need to decorate the push constant here...
2823 try self.spv.declareDeclDeps(spv_decl_index, &.{spv_test_decl_index});
28242833
2825 const section = &self.spv.sections.functions;
2834 var decl_deps = std.ArrayList(SpvModule.Decl.Index).init(self.gpa);
2835 defer decl_deps.deinit();
2836 try decl_deps.append(spv_test_decl_index);
28262837
2827 const target = self.spv.target;
2838 const section = &self.spv.sections.functions;
28282839
28292840 const p_error_id = self.spv.allocId();
28302841 switch (target.os.tag) {
......@@ -2904,6 +2915,7 @@ const NavGen = struct {
29042915
29052916 const spv_err_decl_index = self.object.error_push_constant.?.push_constant_ptr;
29062917 const push_constant_id = self.spv.declPtr(spv_err_decl_index).result_id;
2918 try decl_deps.append(spv_err_decl_index);
29072919
29082920 const zero_id = try self.constInt(Type.u32, 0);
29092921 // We cannot use OpInBoundsAccessChain to dereference cross-storage class, so we have to use
......@@ -2953,6 +2965,7 @@ const NavGen = struct {
29532965 else => unreachable,
29542966 };
29552967
2968 try self.spv.declareDeclDeps(spv_decl_index, decl_deps.items);
29562969 try self.spv.declareEntryPoint(spv_decl_index, test_name, execution_mode);
29572970 }
29582971
......@@ -3372,6 +3385,7 @@ const NavGen = struct {
33723385 .switch_br => return self.airSwitchBr(inst),
33733386 .unreach, .trap => return self.airUnreach(),
33743387
3388 .dbg_empty_stmt => return,
33753389 .dbg_stmt => return self.airDbgStmt(inst),
33763390 .dbg_inline_block => try self.airDbgInlineBlock(inst),
33773391 .dbg_var_ptr, .dbg_var_val, .dbg_arg_inline => return self.airDbgVar(inst),
......@@ -3651,6 +3665,7 @@ const NavGen = struct {
36513665 }
36523666
36533667 fn abs(self: *NavGen, result_ty: Type, value: Temporary) !Temporary {
3668 const zcu = self.pt.zcu;
36543669 const operand_info = self.arithmeticTypeInfo(value.ty);
36553670
36563671 switch (operand_info.class) {
......@@ -3658,11 +3673,9 @@ const NavGen = struct {
36583673 .integer, .strange_integer => {
36593674 const abs_value = try self.buildUnary(.i_abs, value);
36603675
3661 // TODO: We may need to bitcast the result to a uint
3662 // depending on the result type. Do that when
3663 // bitCast is implemented for vectors.
3664 // This is only relevant for Vulkan
3665 assert(self.spv.hasFeature(.kernel)); // TODO
3676 if (value.ty.intInfo(zcu).signedness == .signed and self.spv.hasFeature(.shader)) {
3677 return self.todo("perform bitcast after @abs", .{});
3678 }
36663679
36673680 return try self.normalize(abs_value, self.arithmeticTypeInfo(result_ty));
36683681 },
......@@ -3980,8 +3993,6 @@ const NavGen = struct {
39803993 .float, .bool => unreachable,
39813994 }
39823995
3983 assert(self.spv.hasFeature(.kernel)); // TODO
3984
39853996 const count = try self.buildUnary(op, operand);
39863997
39873998 // Result of OpenCL ctz/clz returns operand.ty, and we want result_ty.
......@@ -4307,7 +4318,8 @@ const NavGen = struct {
43074318 },
43084319 .error_set => {
43094320 assert(!is_vector);
4310 return try self.cmp(op, lhs.pun(Type.u16), rhs.pun(Type.u16));
4321 const err_int_ty = try pt.errorIntType();
4322 return try self.cmp(op, lhs.pun(err_int_ty), rhs.pun(err_int_ty));
43114323 },
43124324 .pointer => {
43134325 assert(!is_vector);
......@@ -4411,7 +4423,7 @@ const NavGen = struct {
44114423 else => unreachable,
44124424 };
44134425 },
4414 else => unreachable,
4426 else => |ty| return self.todo("implement cmp operation for '{s}' type", .{@tagName(ty)}),
44154427 }
44164428
44174429 const info = self.arithmeticTypeInfo(scalar_ty);
......@@ -5233,13 +5245,13 @@ const NavGen = struct {
52335245 return self.accessChain(result_ty_id, object_ptr, &.{field_index});
52345246 },
52355247 .@"struct" => switch (object_ty.containerLayout(zcu)) {
5236 .@"packed" => unreachable, // TODO
5248 .@"packed" => return self.todo("implement field access for packed structs", .{}),
52375249 else => {
52385250 return try self.accessChain(result_ty_id, object_ptr, &.{field_index});
52395251 },
52405252 },
52415253 .@"union" => switch (object_ty.containerLayout(zcu)) {
5242 .@"packed" => unreachable, // TODO
5254 .@"packed" => return self.todo("implement field access for packed unions", .{}),
52435255 else => {
52445256 const layout = self.unionLayout(object_ty);
52455257 if (!layout.has_payload) {
src/codegen/spirv/Module.zig+10-2
......@@ -345,22 +345,30 @@ pub fn finalize(self: *Module, a: Allocator) ![]Word {
345345 if (self.target.cpu.features.isEnabled(feature.index)) {
346346 const feature_tag: std.Target.spirv.Feature = @enumFromInt(feature.index);
347347 switch (feature_tag) {
348 // Versions
348349 .v1_0, .v1_1, .v1_2, .v1_3, .v1_4, .v1_5, .v1_6 => {},
350 // Features with no dependencies
349351 .int8 => try self.addCapability(.Int8),
350352 .int16 => try self.addCapability(.Int16),
351353 .int64 => try self.addCapability(.Int64),
352354 .float16 => try self.addCapability(.Float16),
353355 .float64 => try self.addCapability(.Float64),
356 .matrix => try self.addCapability(.Matrix),
357 .storage_push_constant16 => {
358 try self.addExtension("SPV_KHR_16bit_storage");
359 try self.addCapability(.StoragePushConstant16);
360 },
354361 .addresses => if (self.hasFeature(.shader)) {
355 try self.addCapability(.PhysicalStorageBufferAddresses);
356362 try self.addExtension("SPV_KHR_physical_storage_buffer");
363 try self.addCapability(.PhysicalStorageBufferAddresses);
357364 } else {
358365 try self.addCapability(.Addresses);
359366 },
360 .matrix => try self.addCapability(.Matrix),
367 // Kernel
361368 .kernel => try self.addCapability(.Kernel),
362369 .generic_pointer => try self.addCapability(.GenericPointer),
363370 .vector16 => try self.addCapability(.Vector16),
371 // Shader
364372 .shader => try self.addCapability(.Shader),
365373 }
366374 }