From 4e22f811e746ab5771ea7355ed8dfbfcda0420c2 Mon Sep 17 00:00:00 2001 From: Robin Voetter Date: Sat, 23 Sep 2023 01:31:07 +0200 Subject: spirv: opaque types --- src/codegen/spirv/Cache.zig | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'src/codegen/spirv/Cache.zig') diff --git a/src/codegen/spirv/Cache.zig b/src/codegen/spirv/Cache.zig index 68fea5c47a..7f5590344c 100644 --- a/src/codegen/spirv/Cache.zig +++ b/src/codegen/spirv/Cache.zig @@ -81,6 +81,9 @@ const Tag = enum { /// have member names trailing. /// data is payload to SimpleStructType type_struct_simple_with_member_names, + /// Opaque type. + /// data is name string. + type_opaque, // -- Values /// Value of type u8 @@ -235,6 +238,7 @@ pub const Key = union(enum) { function_type: FunctionType, ptr_type: PointerType, struct_type: StructType, + opaque_type: OpaqueType, // -- values int: Int, @@ -289,6 +293,10 @@ pub const Key = union(enum) { } }; + pub const OpaqueType = struct { + name: String = .none, + }; + pub const Int = struct { /// The type: any bitness integer. ty: Ref, @@ -539,6 +547,13 @@ fn emit( } // TODO: Decorations? }, + .opaque_type => |opaque_type| { + const name = if (self.getString(opaque_type.name)) |name| name else ""; + try section.emit(spv.gpa, .OpTypeOpaque, .{ + .id_result = result_id, + .literal_string = name, + }); + }, .int => |int| { const int_type = self.lookup(int.ty).int_type; const ty_id = self.resultId(int.ty); @@ -697,6 +712,11 @@ pub fn resolve(self: *Self, spv: *Module, key: Key) !Ref { }; } }, + .opaque_type => |opaque_type| Item{ + .tag = .type_opaque, + .result_id = result_id, + .data = @intFromEnum(opaque_type.name), + }, .int => |int| blk: { const int_type = self.lookup(int.ty).int_type; if (int_type.signedness == .unsigned and int_type.bits == 8) { @@ -874,6 +894,11 @@ pub fn lookup(self: *const Self, ref: Ref) Key { }, }; }, + .type_opaque => .{ + .opaque_type = .{ + .name = @as(String, @enumFromInt(data)), + }, + }, .float16 => .{ .float = .{ .ty = self.get(.{ .float_type = .{ .bits = 16 } }), .value = .{ .float16 = @as(f16, @bitCast(@as(u16, @intCast(data)))) }, -- cgit v1.2.3 From f858bf161602d72584da9e950c5a9eeadfe8b29d Mon Sep 17 00:00:00 2001 From: Robin Voetter Date: Sun, 8 Oct 2023 12:09:25 +0200 Subject: spirv: air bitcast for non-numeric non-pointer types --- src/codegen/spirv.zig | 35 +++++++++++++++++++++++++++++++---- src/codegen/spirv/Cache.zig | 7 +++++++ test/behavior/cast.zig | 2 -- 3 files changed, 38 insertions(+), 6 deletions(-) (limited to 'src/codegen/spirv/Cache.zig') diff --git a/src/codegen/spirv.zig b/src/codegen/spirv.zig index 638bf7b187..62f945dd81 100644 --- a/src/codegen/spirv.zig +++ b/src/codegen/spirv.zig @@ -2578,25 +2578,52 @@ const DeclGen = struct { return src_id; } - const result_id = self.spv.allocId(); - // TODO: Some more cases are missing here // See fn bitCast in llvm.zig if (src_ty.zigTypeTag(mod) == .Int and dst_ty.isPtrAtRuntime(mod)) { + const result_id = self.spv.allocId(); try self.func.body.emit(self.spv.gpa, .OpConvertUToPtr, .{ .id_result_type = self.typeId(dst_ty_ref), .id_result = result_id, .integer_value = src_id, }); - } else { + return result_id; + } + + // We can only use OpBitcast for specific conversions: between numerical types, and + // between pointers. If the resolved spir-v types fall into this category then emit OpBitcast, + // otherwise use a temporary and perform a pointer cast. + const src_key = self.spv.cache.lookup(src_ty_ref); + const dst_key = self.spv.cache.lookup(dst_ty_ref); + + if ((src_key.isNumericalType() and dst_key.isNumericalType()) or (src_key == .ptr_type and dst_key == .ptr_type)) { + const result_id = self.spv.allocId(); try self.func.body.emit(self.spv.gpa, .OpBitcast, .{ .id_result_type = self.typeId(dst_ty_ref), .id_result = result_id, .operand = src_id, }); + return result_id; } - return result_id; + + const src_ptr_ty_ref = try self.spv.ptrType(src_ty_ref, .Function); + const dst_ptr_ty_ref = try self.spv.ptrType(dst_ty_ref, .Function); + + const tmp_id = self.spv.allocId(); + try self.func.prologue.emit(self.spv.gpa, .OpVariable, .{ + .id_result_type = self.typeId(src_ptr_ty_ref), + .id_result = tmp_id, + .storage_class = .Function, + }); + try self.store(src_ty, tmp_id, src_id, false); + const casted_ptr_id = self.spv.allocId(); + try self.func.body.emit(self.spv.gpa, .OpBitcast, .{ + .id_result_type = self.typeId(dst_ptr_ty_ref), + .id_result = casted_ptr_id, + .operand = tmp_id, + }); + return try self.load(dst_ty, casted_ptr_id, false); } fn airBitCast(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { diff --git a/src/codegen/spirv/Cache.zig b/src/codegen/spirv/Cache.zig index 7f5590344c..ad2d3442e5 100644 --- a/src/codegen/spirv/Cache.zig +++ b/src/codegen/spirv/Cache.zig @@ -435,6 +435,13 @@ pub const Key = union(enum) { else => unreachable, }; } + + pub fn isNumericalType(self: Key) bool { + return switch (self) { + .int_type, .float_type => true, + else => false, + }; + } }; pub fn deinit(self: *Self, spv: *const Module) void { diff --git a/test/behavior/cast.zig b/test/behavior/cast.zig index ca491a0a22..20867fa7e8 100644 --- a/test/behavior/cast.zig +++ b/test/behavior/cast.zig @@ -899,7 +899,6 @@ test "peer cast [:x]T to []T" { test "peer cast [N:x]T to [N]T" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; const S = struct { fn doTheTest() !void { @@ -1728,7 +1727,6 @@ test "peer type resolution: error union and optional of same type" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO 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_spirv64) return error.SkipZigTest; // TODO const E = error{Foo}; var a: E!*u8 = error.Foo; -- cgit v1.2.3