authorgravatar for robin@voetter.nlRobin Voetter <robin@voetter.nl> 2022-11-26 00:48:42+01:00
committergravatar for robin@voetter.nlRobin Voetter <robin@voetter.nl> 2023-04-09 01:51:48+02:00
loga60308f87c658a210e9b3bd619e908368db6f24e
tree622157fd5bedf660e97f0cfe0d78d2bbc5a70e2f
parentdf5577c28bf1cc26f8bcf21ed1201e31987ac009
signaturelock-open Commit is signed but in an unrecognized format.

spirv: enum type

This gives the spir-v backend the power to emit enum types. These are simply lowered to their backing integer type.

1 files changed, 37 insertions(+), 26 deletions(-)

src/codegen/spirv.zig+37-26
...@@ -443,32 +443,43 @@ pub const DeclGen = struct {...@@ -443,32 +443,43 @@ pub const DeclGen = struct {
443 return self.spv.typeResultId(type_ref);443 return self.spv.typeResultId(type_ref);
444 }444 }
445445
446 /// Create an integer type suitable for storing at least 'bits' bits.
447 fn intType(self: *DeclGen, signedness: std.builtin.Signedness, bits: u16) !SpvType.Ref {
448 const backing_bits = self.backingIntBits(bits) orelse {
449 // TODO: Integers too big for any native type are represented as "composite integers":
450 // An array of largestSupportedIntBits.
451 return self.todo("Implement {s} composite int type of {} bits", .{ @tagName(signedness), bits });
452 };
453
454 const payload = try self.spv.arena.create(SpvType.Payload.Int);
455 payload.* = .{
456 .width = backing_bits,
457 .signedness = signedness,
458 };
459 return try self.spv.resolveType(SpvType.initPayload(&payload.base));
460 }
461
446 /// Turn a Zig type into a SPIR-V Type, and return a reference to it.462 /// Turn a Zig type into a SPIR-V Type, and return a reference to it.
447 fn resolveType(self: *DeclGen, ty: Type) Error!SpvType.Ref {463 fn resolveType(self: *DeclGen, ty: Type) Error!SpvType.Ref {
448 const target = self.getTarget();464 const target = self.getTarget();
449 return switch (ty.zigTypeTag()) {465 switch (ty.zigTypeTag()) {
450 .Void => try self.spv.resolveType(SpvType.initTag(.void)),466 .Void, .NoReturn => return try self.spv.resolveType(SpvType.initTag(.void)),
451 .Bool => blk: {467 .Bool => {
452 // TODO: SPIR-V booleans are opaque. For local variables this is fine, but for structs468 // TODO: SPIR-V booleans are opaque. For local variables this is fine, but for structs
453 // members we want to use integer types instead.469 // members we want to use integer types instead.
454 break :blk try self.spv.resolveType(SpvType.initTag(.bool));470 return try self.spv.resolveType(SpvType.initTag(.bool));
455 },471 },
456 .Int => blk: {472 .Int => {
457 const int_info = ty.intInfo(target);473 const int_info = ty.intInfo(target);
458 const backing_bits = self.backingIntBits(int_info.bits) orelse {474 return try self.intType(int_info.signedness, int_info.bits);
459 // TODO: Integers too big for any native type are represented as "composite integers":475 },
460 // An array of largestSupportedIntBits.476 .Enum => {
461 return self.todo("Implement composite int type {}", .{ty.fmtDebug()});477 var buffer: Type.Payload.Bits = undefined;
462 };478 const int_ty = ty.intTagType(&buffer);
463479 const int_info = int_ty.intInfo(target);
464 const payload = try self.spv.arena.create(SpvType.Payload.Int);480 return try self.intType(.unsigned, int_info.bits);
465 payload.* = .{
466 .width = backing_bits,
467 .signedness = int_info.signedness,
468 };
469 break :blk try self.spv.resolveType(SpvType.initPayload(&payload.base));
470 },481 },
471 .Float => blk: {482 .Float => {
472 // We can (and want) not really emulate floating points with other floating point types like with the integer types,483 // We can (and want) not really emulate floating points with other floating point types like with the integer types,
473 // so if the float is not supported, just return an error.484 // so if the float is not supported, just return an error.
474 const bits = ty.floatBits(target);485 const bits = ty.floatBits(target);
...@@ -488,9 +499,9 @@ pub const DeclGen = struct {...@@ -488,9 +499,9 @@ pub const DeclGen = struct {
488 payload.* = .{499 payload.* = .{
489 .width = bits,500 .width = bits,
490 };501 };
491 break :blk try self.spv.resolveType(SpvType.initPayload(&payload.base));502 return try self.spv.resolveType(SpvType.initPayload(&payload.base));
492 },503 },
493 .Fn => blk: {504 .Fn => {
494 // TODO: Put this somewhere in Sema.zig505 // TODO: Put this somewhere in Sema.zig
495 if (ty.fnIsVarArgs())506 if (ty.fnIsVarArgs())
496 return self.fail("VarArgs functions are unsupported for SPIR-V", .{});507 return self.fail("VarArgs functions are unsupported for SPIR-V", .{});
...@@ -504,9 +515,9 @@ pub const DeclGen = struct {...@@ -504,9 +515,9 @@ pub const DeclGen = struct {
504515
505 const payload = try self.spv.arena.create(SpvType.Payload.Function);516 const payload = try self.spv.arena.create(SpvType.Payload.Function);
506 payload.* = .{ .return_type = return_type, .parameters = param_types };517 payload.* = .{ .return_type = return_type, .parameters = param_types };
507 break :blk try self.spv.resolveType(SpvType.initPayload(&payload.base));518 return try self.spv.resolveType(SpvType.initPayload(&payload.base));
508 },519 },
509 .Pointer => blk: {520 .Pointer => {
510 const payload = try self.spv.arena.create(SpvType.Payload.Pointer);521 const payload = try self.spv.arena.create(SpvType.Payload.Pointer);
511 payload.* = .{522 payload.* = .{
512 .storage_class = spirvStorageClass(ty.ptrAddressSpace()),523 .storage_class = spirvStorageClass(ty.ptrAddressSpace()),
...@@ -516,9 +527,9 @@ pub const DeclGen = struct {...@@ -516,9 +527,9 @@ pub const DeclGen = struct {
516 .alignment = null,527 .alignment = null,
517 .max_byte_offset = null,528 .max_byte_offset = null,
518 };529 };
519 break :blk try self.spv.resolveType(SpvType.initPayload(&payload.base));530 return try self.spv.resolveType(SpvType.initPayload(&payload.base));
520 },531 },
521 .Vector => blk: {532 .Vector => {
522 // Although not 100% the same, Zig vectors map quite neatly to SPIR-V vectors (including many integer and float operations533 // Although not 100% the same, Zig vectors map quite neatly to SPIR-V vectors (including many integer and float operations
523 // which work on them), so simply use those.534 // which work on them), so simply use those.
524 // Note: SPIR-V vectors only support bools, ints and floats, so pointer vectors need to be supported another way.535 // 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 {...@@ -533,7 +544,7 @@ pub const DeclGen = struct {
533 .component_type = try self.resolveType(ty.elemType()),544 .component_type = try self.resolveType(ty.elemType()),
534 .component_count = @intCast(u32, ty.vectorLen()),545 .component_count = @intCast(u32, ty.vectorLen()),
535 };546 };
536 break :blk try self.spv.resolveType(SpvType.initPayload(&payload.base));547 return try self.spv.resolveType(SpvType.initPayload(&payload.base));
537 },548 },
538549
539 .Null,550 .Null,
...@@ -545,7 +556,7 @@ pub const DeclGen = struct {...@@ -545,7 +556,7 @@ pub const DeclGen = struct {
545 => unreachable, // Must be comptime.556 => unreachable, // Must be comptime.
546557
547 else => |tag| return self.todo("Implement zig type '{}'", .{tag}),558 else => |tag| return self.todo("Implement zig type '{}'", .{tag}),
548 };559 }
549 }560 }
550561
551 fn spirvStorageClass(as: std.builtin.AddressSpace) spec.StorageClass {562 fn spirvStorageClass(as: std.builtin.AddressSpace) spec.StorageClass {