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 {
443443 return self.spv.typeResultId(type_ref);
444444 }
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
446462 /// Turn a Zig type into a SPIR-V Type, and return a reference to it.
447463 fn resolveType(self: *DeclGen, ty: Type) Error!SpvType.Ref {
448464 const target = self.getTarget();
449 return switch (ty.zigTypeTag()) {
450 .Void => try self.spv.resolveType(SpvType.initTag(.void)),
451 .Bool => blk: {
465 switch (ty.zigTypeTag()) {
466 .Void, .NoReturn => return try self.spv.resolveType(SpvType.initTag(.void)),
467 .Bool => {
452468 // TODO: SPIR-V booleans are opaque. For local variables this is fine, but for structs
453469 // 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));
455471 },
456 .Int => blk: {
472 .Int => {
457473 const int_info = ty.intInfo(target);
458 const backing_bits = self.backingIntBits(int_info.bits) orelse {
459 // TODO: Integers too big for any native type are represented as "composite integers":
460 // An array of largestSupportedIntBits.
461 return self.todo("Implement composite int type {}", .{ty.fmtDebug()});
462 };
463
464 const payload = try self.spv.arena.create(SpvType.Payload.Int);
465 payload.* = .{
466 .width = backing_bits,
467 .signedness = int_info.signedness,
468 };
469 break :blk try self.spv.resolveType(SpvType.initPayload(&payload.base));
474 return try self.intType(int_info.signedness, int_info.bits);
475 },
476 .Enum => {
477 var buffer: Type.Payload.Bits = undefined;
478 const int_ty = ty.intTagType(&buffer);
479 const int_info = int_ty.intInfo(target);
480 return try self.intType(.unsigned, int_info.bits);
470481 },
471 .Float => blk: {
482 .Float => {
472483 // We can (and want) not really emulate floating points with other floating point types like with the integer types,
473484 // so if the float is not supported, just return an error.
474485 const bits = ty.floatBits(target);
......@@ -488,9 +499,9 @@ pub const DeclGen = struct {
488499 payload.* = .{
489500 .width = bits,
490501 };
491 break :blk try self.spv.resolveType(SpvType.initPayload(&payload.base));
502 return try self.spv.resolveType(SpvType.initPayload(&payload.base));
492503 },
493 .Fn => blk: {
504 .Fn => {
494505 // TODO: Put this somewhere in Sema.zig
495506 if (ty.fnIsVarArgs())
496507 return self.fail("VarArgs functions are unsupported for SPIR-V", .{});
......@@ -504,9 +515,9 @@ pub const DeclGen = struct {
504515
505516 const payload = try self.spv.arena.create(SpvType.Payload.Function);
506517 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));
508519 },
509 .Pointer => blk: {
520 .Pointer => {
510521 const payload = try self.spv.arena.create(SpvType.Payload.Pointer);
511522 payload.* = .{
512523 .storage_class = spirvStorageClass(ty.ptrAddressSpace()),
......@@ -516,9 +527,9 @@ pub const DeclGen = struct {
516527 .alignment = null,
517528 .max_byte_offset = null,
518529 };
519 break :blk try self.spv.resolveType(SpvType.initPayload(&payload.base));
530 return try self.spv.resolveType(SpvType.initPayload(&payload.base));
520531 },
521 .Vector => blk: {
532 .Vector => {
522533 // Although not 100% the same, Zig vectors map quite neatly to SPIR-V vectors (including many integer and float operations
523534 // which work on them), so simply use those.
524535 // 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 {
533544 .component_type = try self.resolveType(ty.elemType()),
534545 .component_count = @intCast(u32, ty.vectorLen()),
535546 };
536 break :blk try self.spv.resolveType(SpvType.initPayload(&payload.base));
547 return try self.spv.resolveType(SpvType.initPayload(&payload.base));
537548 },
538549
539550 .Null,
......@@ -545,7 +556,7 @@ pub const DeclGen = struct {
545556 => unreachable, // Must be comptime.
546557
547558 else => |tag| return self.todo("Implement zig type '{}'", .{tag}),
548 };
559 }
549560 }
550561
551562 fn spirvStorageClass(as: std.builtin.AddressSpace) spec.StorageClass {