From a60308f87c658a210e9b3bd619e908368db6f24e Mon Sep 17 00:00:00 2001 From: Robin Voetter Date: Sat, 26 Nov 2022 00:48:42 +0100 Subject: spirv: enum type This gives the spir-v backend the power to emit enum types. These are simply lowered to their backing integer type. --- src/codegen/spirv.zig | 63 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 37 insertions(+), 26 deletions(-) (limited to 'src/codegen/spirv.zig') diff --git a/src/codegen/spirv.zig b/src/codegen/spirv.zig index 3e2e202fc6..93bb7b19f8 100644 --- a/src/codegen/spirv.zig +++ b/src/codegen/spirv.zig @@ -443,32 +443,43 @@ pub const DeclGen = struct { return self.spv.typeResultId(type_ref); } + /// Create an integer type suitable for storing at least 'bits' bits. + fn intType(self: *DeclGen, signedness: std.builtin.Signedness, bits: u16) !SpvType.Ref { + const backing_bits = self.backingIntBits(bits) orelse { + // TODO: Integers too big for any native type are represented as "composite integers": + // An array of largestSupportedIntBits. + return self.todo("Implement {s} composite int type of {} bits", .{ @tagName(signedness), bits }); + }; + + const payload = try self.spv.arena.create(SpvType.Payload.Int); + payload.* = .{ + .width = backing_bits, + .signedness = signedness, + }; + return try self.spv.resolveType(SpvType.initPayload(&payload.base)); + } + /// Turn a Zig type into a SPIR-V Type, and return a reference to it. fn resolveType(self: *DeclGen, ty: Type) Error!SpvType.Ref { const target = self.getTarget(); - return switch (ty.zigTypeTag()) { - .Void => try self.spv.resolveType(SpvType.initTag(.void)), - .Bool => blk: { + switch (ty.zigTypeTag()) { + .Void, .NoReturn => return try self.spv.resolveType(SpvType.initTag(.void)), + .Bool => { // TODO: SPIR-V booleans are opaque. For local variables this is fine, but for structs // members we want to use integer types instead. - break :blk try self.spv.resolveType(SpvType.initTag(.bool)); + return try self.spv.resolveType(SpvType.initTag(.bool)); }, - .Int => blk: { + .Int => { const int_info = ty.intInfo(target); - const backing_bits = self.backingIntBits(int_info.bits) orelse { - // TODO: Integers too big for any native type are represented as "composite integers": - // An array of largestSupportedIntBits. - return self.todo("Implement composite int type {}", .{ty.fmtDebug()}); - }; - - const payload = try self.spv.arena.create(SpvType.Payload.Int); - payload.* = .{ - .width = backing_bits, - .signedness = int_info.signedness, - }; - break :blk try self.spv.resolveType(SpvType.initPayload(&payload.base)); + return try self.intType(int_info.signedness, int_info.bits); + }, + .Enum => { + var buffer: Type.Payload.Bits = undefined; + const int_ty = ty.intTagType(&buffer); + const int_info = int_ty.intInfo(target); + return try self.intType(.unsigned, int_info.bits); }, - .Float => blk: { + .Float => { // We can (and want) not really emulate floating points with other floating point types like with the integer types, // so if the float is not supported, just return an error. const bits = ty.floatBits(target); @@ -488,9 +499,9 @@ pub const DeclGen = struct { payload.* = .{ .width = bits, }; - break :blk try self.spv.resolveType(SpvType.initPayload(&payload.base)); + return try self.spv.resolveType(SpvType.initPayload(&payload.base)); }, - .Fn => blk: { + .Fn => { // TODO: Put this somewhere in Sema.zig if (ty.fnIsVarArgs()) return self.fail("VarArgs functions are unsupported for SPIR-V", .{}); @@ -504,9 +515,9 @@ pub const DeclGen = struct { const payload = try self.spv.arena.create(SpvType.Payload.Function); payload.* = .{ .return_type = return_type, .parameters = param_types }; - break :blk try self.spv.resolveType(SpvType.initPayload(&payload.base)); + return try self.spv.resolveType(SpvType.initPayload(&payload.base)); }, - .Pointer => blk: { + .Pointer => { const payload = try self.spv.arena.create(SpvType.Payload.Pointer); payload.* = .{ .storage_class = spirvStorageClass(ty.ptrAddressSpace()), @@ -516,9 +527,9 @@ pub const DeclGen = struct { .alignment = null, .max_byte_offset = null, }; - break :blk try self.spv.resolveType(SpvType.initPayload(&payload.base)); + return try self.spv.resolveType(SpvType.initPayload(&payload.base)); }, - .Vector => blk: { + .Vector => { // Although not 100% the same, Zig vectors map quite neatly to SPIR-V vectors (including many integer and float operations // which work on them), so simply use those. // Note: SPIR-V vectors only support bools, ints and floats, so pointer vectors need to be supported another way. @@ -533,7 +544,7 @@ pub const DeclGen = struct { .component_type = try self.resolveType(ty.elemType()), .component_count = @intCast(u32, ty.vectorLen()), }; - break :blk try self.spv.resolveType(SpvType.initPayload(&payload.base)); + return try self.spv.resolveType(SpvType.initPayload(&payload.base)); }, .Null, @@ -545,7 +556,7 @@ pub const DeclGen = struct { => unreachable, // Must be comptime. else => |tag| return self.todo("Implement zig type '{}'", .{tag}), - }; + } } fn spirvStorageClass(as: std.builtin.AddressSpace) spec.StorageClass { -- cgit v1.2.3