diff --git a/src/codegen/spirv.zig b/src/codegen/spirv.zig index 7a24ee3656..ec67d7fcfe 100644 --- a/src/codegen/spirv.zig +++ b/src/codegen/spirv.zig @@ -1331,6 +1331,20 @@ pub const DeclGen = struct { return try self.sizeType2(); }, }, + .Pointer => { + const ptr_info = ty.ptrInfo().data; + + const storage_class = spvStorageClass(ptr_info.@"addrspace"); + const child_ty_ref = try self.resolveType2(ptr_info.pointee_type, .indirect); + const ptr_ty_ref = try self.spv.resolve(.{ .ptr_type = .{ + .storage_class = storage_class, + .child_type = child_ty_ref, + } }); + if (ptr_info.size != .Slice) { + return ptr_ty_ref; + } + unreachable; // TODO + }, else => unreachable, // TODO } diff --git a/src/codegen/spirv/TypeConstantCache.zig b/src/codegen/spirv/TypeConstantCache.zig index f4668fab50..2a94359f15 100644 --- a/src/codegen/spirv/TypeConstantCache.zig +++ b/src/codegen/spirv/TypeConstantCache.zig @@ -19,6 +19,7 @@ const Module = @import("Module.zig"); const spec = @import("spec.zig"); const Opcode = spec.Opcode; const IdResult = spec.IdResult; +const StorageClass = spec.StorageClass; const Self = @This(); @@ -54,9 +55,21 @@ const Tag = enum { /// Array type /// data is payload to ArrayType type_array, - /// Function (proto)type. + /// Function (proto)type /// data is payload to FunctionType type_function, + /// Pointer type in the CrossWorkgroup storage class + /// data is child type + type_ptr_generic, + /// Pointer type in the CrossWorkgroup storage class + /// data is child type + type_ptr_crosswgp, + /// Pointer type in the Function storage class + /// data is child type + type_ptr_function, + /// Simple pointer type that does not have any decorations. + /// data is SimplePointerType + type_ptr_simple, // -- Values /// Value of type u8 @@ -100,6 +113,11 @@ const Tag = enum { return_type: Ref, }; + const SimplePointerType = struct { + storage_class: StorageClass, + child_type: Ref, + }; + const Float64 = struct { // Low-order 32 bits of the value. low: u32, @@ -182,6 +200,7 @@ pub const Key = union(enum) { vector_type: VectorType, array_type: ArrayType, function_type: FunctionType, + ptr_type: PointerType, // -- values int: Int, @@ -210,6 +229,15 @@ pub const Key = union(enum) { parameters: []const Ref, }; + pub const PointerType = struct { + storage_class: StorageClass, + child_type: Ref, + // TODO: Decorations: + // - Alignment + // - ArrayStride, + // - MaxByteOffset, + }; + pub const Int = struct { /// The type: any bitness integer. ty: Ref, @@ -406,6 +434,14 @@ fn emit( section.writeOperand(IdResult, self.resultId(param_type)); } }, + .ptr_type => |ptr| { + try section.emit(spv.gpa, .OpTypePointer, .{ + .id_result = result_id, + .storage_class = ptr.storage_class, + .type = self.resultId(ptr.child_type), + }); + // TODO: Decorations? + }, .int => |int| { const int_type = self.lookup(int.ty).int_type; const ty_id = self.resultId(int.ty); @@ -491,6 +527,31 @@ pub fn resolve(self: *Self, spv: *Module, key: Key) !Ref { .data = extra, }; }, + .ptr_type => |ptr| switch (ptr.storage_class) { + .Generic => Item{ + .tag = .type_ptr_generic, + .result_id = result_id, + .data = @enumToInt(ptr.child_type), + }, + .CrossWorkgroup => Item{ + .tag = .type_ptr_crosswgp, + .result_id = result_id, + .data = @enumToInt(ptr.child_type), + }, + .Function => Item{ + .tag = .type_ptr_function, + .result_id = result_id, + .data = @enumToInt(ptr.child_type), + }, + else => |storage_class| Item{ + .tag = .type_ptr_simple, + .result_id = result_id, + .data = try self.addExtra(spv, Tag.SimplePointerType{ + .storage_class = storage_class, + .child_type = ptr.child_type, + }), + }, + }, .int => |int| blk: { const int_type = self.lookup(int.ty).int_type; if (int_type.signedness == .unsigned and int_type.bits == 8) { @@ -599,6 +660,33 @@ pub fn lookup(self: *const Self, ref: Ref) Key { }, }; }, + .type_ptr_generic => .{ + .ptr_type = .{ + .storage_class = .Generic, + .child_type = @intToEnum(Ref, data), + }, + }, + .type_ptr_crosswgp => .{ + .ptr_type = .{ + .storage_class = .CrossWorkgroup, + .child_type = @intToEnum(Ref, data), + }, + }, + .type_ptr_function => .{ + .ptr_type = .{ + .storage_class = .Function, + .child_type = @intToEnum(Ref, data), + }, + }, + .type_ptr_simple => { + const payload = self.extraData(Tag.SimplePointerType, data); + return .{ + .ptr_type = .{ + .storage_class = payload.storage_class, + .child_type = payload.child_type, + }, + }; + }, .float16 => .{ .float = .{ .ty = self.get(.{ .float_type = .{ .bits = 16 } }), .value = .{ .float16 = @bitCast(f16, @intCast(u16, data)) }, @@ -677,6 +765,7 @@ fn addExtraAssumeCapacity(self: *Self, extra: anytype) !u32 { u32 => field_val, i32 => @bitCast(u32, field_val), Ref => @enumToInt(field_val), + StorageClass => @enumToInt(field_val), else => @compileError("Invalid type: " ++ @typeName(field.type)), }; self.extra.appendAssumeCapacity(word); @@ -697,6 +786,7 @@ fn extraDataTrail(self: Self, comptime T: type, offset: u32) struct { data: T, t u32 => word, i32 => @bitCast(i32, word), Ref => @intToEnum(Ref, word), + StorageClass => @intToEnum(StorageClass, word), else => @compileError("Invalid type: " ++ @typeName(field.type)), }; }