commit 6e8a83282f10bcce7f80c9f213d2ae6407651163 (tree)
parent 64c5cc80471ccd167af2403741dc2037824e0c8c
Author: Ali Cheraghi <alichraghi@proton.me>
Date: Sun, 21 Jun 2026 08:31:03 +0330
Sema: implement `@typeInfo` for spirv types
Forgotten in #35461
Diffstat:
3 files changed, 90 insertions(+), 2 deletions(-)
diff --git a/src/Sema.zig b/src/Sema.zig
@@ -16793,7 +16793,43 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
.val = (try pt.aggregateValue(type_opaque_ty, &field_values)).toIntern(),
})));
},
- .spirv => unreachable, // TODO: ALI
+ .spirv => {
+ const spirv_info = ip.loadSpirvType(ty.toIntern());
+ const spirv_union_ty = try sema.getStdLangType(src, .@"Type.Spirv");
+ const spirv_tag_ty = spirv_union_ty.unionTagType(zcu).?;
+ const spirv_tag_val = try pt.enumValueFieldIndex(spirv_tag_ty, @intFromEnum(spirv_info.flags.tag));
+ const spirv_payload_val: Value = switch (spirv_info.flags.tag) {
+ .sampler => .void,
+ .sampled_image, .runtime_array => .fromInterned(spirv_info.ty),
+ .image => image: {
+ const image_ty = try sema.getStdLangType(src, .@"Type.Spirv.Image");
+ const usage_union_ty = try sema.getStdLangType(src, .@"Type.Spirv.Image.Usage");
+ const format_ty = try sema.getStdLangType(src, .@"Type.Spirv.Image.Format");
+ const dim_ty = try sema.getStdLangType(src, .@"Type.Spirv.Image.Dimensionality");
+ const depth_ty = try sema.getStdLangType(src, .@"Type.Spirv.Image.Depth");
+ const access_ty = try sema.getStdLangType(src, .@"Type.Spirv.Image.Access");
+ const usage_tag_ty = usage_union_ty.unionTagType(zcu).?;
+ const usage_tag_val = try pt.enumValueFieldIndex(usage_tag_ty, @intFromEnum(spirv_info.flags.usage));
+ const usage_val = try pt.unionValue(usage_union_ty, usage_tag_val, .fromInterned(spirv_info.ty));
+ const image_field_vals = [_]InternPool.Index{
+ usage_val.toIntern(),
+ (try pt.enumValueFieldIndex(format_ty, @intFromEnum(spirv_info.flags.format))).toIntern(),
+ (try pt.enumValueFieldIndex(dim_ty, @intFromEnum(spirv_info.flags.dim))).toIntern(),
+ (try pt.enumValueFieldIndex(depth_ty, @intFromEnum(spirv_info.flags.depth))).toIntern(),
+ (try pt.enumValueFieldIndex(access_ty, @intFromEnum(spirv_info.flags.access))).toIntern(),
+ Value.makeBool(spirv_info.flags.is_arrayed).toIntern(),
+ Value.makeBool(spirv_info.flags.is_multisampled).toIntern(),
+ };
+ break :image try pt.aggregateValue(image_ty, &image_field_vals);
+ },
+ };
+ const spirv_val = try pt.unionValue(spirv_union_ty, spirv_tag_val, spirv_payload_val);
+ return Air.internedToRef((try pt.internUnion(.{
+ .ty = type_info_ty.toIntern(),
+ .tag = (try pt.enumValueFieldIndex(type_info_tag_ty, @intFromEnum(std.lang.TypeId.spirv))).toIntern(),
+ .val = spirv_val.toIntern(),
+ })));
+ },
.frame => return sema.failWithUseOfAsync(block, src),
.@"anyframe" => return sema.failWithUseOfAsync(block, src),
}
diff --git a/src/Zcu.zig b/src/Zcu.zig
@@ -469,6 +469,12 @@ pub const StdLangDecl = enum {
@"Type.ContainerLayout",
@"Type.Opaque",
@"Type.Spirv",
+ @"Type.Spirv.Image",
+ @"Type.Spirv.Image.Usage",
+ @"Type.Spirv.Image.Format",
+ @"Type.Spirv.Image.Dimensionality",
+ @"Type.Spirv.Image.Depth",
+ @"Type.Spirv.Image.Access",
panic,
@"panic.call",
@@ -550,6 +556,12 @@ pub const StdLangDecl = enum {
.@"Type.ContainerLayout",
.@"Type.Opaque",
.@"Type.Spirv",
+ .@"Type.Spirv.Image",
+ .@"Type.Spirv.Image.Usage",
+ .@"Type.Spirv.Image.Format",
+ .@"Type.Spirv.Image.Dimensionality",
+ .@"Type.Spirv.Image.Depth",
+ .@"Type.Spirv.Image.Access",
=> .type,
.panic => .type,
@@ -603,7 +615,7 @@ pub const StdLangDecl = enum {
.VaList => .va_list,
.assembly, .@"assembly.Clobbers" => .assembly,
else => {
- if (@intFromEnum(decl) <= @intFromEnum(StdLangDecl.@"Type.Spirv")) {
+ if (@intFromEnum(decl) <= @intFromEnum(StdLangDecl.@"Type.Spirv.Image.Access")) {
return .main;
} else {
return .panic;
diff --git a/test/behavior/type_info.zig b/test/behavior/type_info.zig
@@ -613,3 +613,43 @@ test "@typeInfo function with generic return type and inferred error set" {
const ret_ty = @typeInfo(@TypeOf(S.testFn)).@"fn".return_type;
comptime assert(ret_ty == null);
}
+
+test "type info: spirv info" {
+ if (builtin.zig_backend != .stage2_spirv) return error.SkipZigTest;
+
+ try testSpirv();
+ try comptime testSpirv();
+}
+
+fn testSpirv() !void {
+ const image_info = @typeInfo(Image);
+ try expect(image_info.spirv.image.usage.sampled == f32);
+ try expect(image_info.spirv.image.format == .unknown);
+ try expect(image_info.spirv.image.dim == .@"2d");
+ try expect(image_info.spirv.image.depth == .not_depth);
+ try expect(image_info.spirv.image.arrayed == false);
+ try expect(image_info.spirv.image.multisampled == false);
+ try expect(image_info.spirv.image.access == .unknown);
+
+ const sampled_image_info = @typeInfo(SampledImage);
+ try expect(sampled_image_info.spirv.sampled_image == Image);
+
+ const sampler_info = @typeInfo(Sampler);
+ try expect(sampler_info.spirv.sampler == {});
+
+ const runtime_array_info = @typeInfo(RuntimeArray);
+ try expect(runtime_array_info.spirv.runtime_array == f32);
+}
+
+pub const Image = @SpirvType(.{ .image = .{
+ .usage = .{ .sampled = f32 },
+ .format = .unknown,
+ .dim = .@"2d",
+ .depth = .not_depth,
+ .arrayed = false,
+ .multisampled = false,
+ .access = .unknown,
+} });
+pub const SampledImage = @SpirvType(.{ .sampled_image = Image });
+pub const Sampler = @SpirvType(.sampler);
+pub const RuntimeArray = @SpirvType(.{ .runtime_array = f32 });