| ... | ... | @@ -443,32 +443,43 @@ pub const DeclGen = struct { |
| 443 | 443 | return self.spv.typeResultId(type_ref); |
| 444 | 444 | } |
| 445 | 445 | |
| 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 | 462 | /// Turn a Zig type into a SPIR-V Type, and return a reference to it. |
| 447 | 463 | fn resolveType(self: *DeclGen, ty: Type) Error!SpvType.Ref { |
| 448 | 464 | 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 => { |
| 452 | 468 | // TODO: SPIR-V booleans are opaque. For local variables this is fine, but for structs |
| 453 | 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 | 473 | 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); |
| 470 | 481 | }, |
| 471 | | .Float => blk: { |
| 482 | .Float => { |
| 472 | 483 | // We can (and want) not really emulate floating points with other floating point types like with the integer types, |
| 473 | 484 | // so if the float is not supported, just return an error. |
| 474 | 485 | const bits = ty.floatBits(target); |
| ... | ... | @@ -488,9 +499,9 @@ pub const DeclGen = struct { |
| 488 | 499 | payload.* = .{ |
| 489 | 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 | 505 | // TODO: Put this somewhere in Sema.zig |
| 495 | 506 | if (ty.fnIsVarArgs()) |
| 496 | 507 | return self.fail("VarArgs functions are unsupported for SPIR-V", .{}); |
| ... | ... | @@ -504,9 +515,9 @@ pub const DeclGen = struct { |
| 504 | 515 | |
| 505 | 516 | const payload = try self.spv.arena.create(SpvType.Payload.Function); |
| 506 | 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 | 521 | const payload = try self.spv.arena.create(SpvType.Payload.Pointer); |
| 511 | 522 | payload.* = .{ |
| 512 | 523 | .storage_class = spirvStorageClass(ty.ptrAddressSpace()), |
| ... | ... | @@ -516,9 +527,9 @@ pub const DeclGen = struct { |
| 516 | 527 | .alignment = null, |
| 517 | 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 | 533 | // Although not 100% the same, Zig vectors map quite neatly to SPIR-V vectors (including many integer and float operations |
| 523 | 534 | // which work on them), so simply use those. |
| 524 | 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 | 544 | .component_type = try self.resolveType(ty.elemType()), |
| 534 | 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 | }, |
| 538 | 549 | |
| 539 | 550 | .Null, |
| ... | ... | @@ -545,7 +556,7 @@ pub const DeclGen = struct { |
| 545 | 556 | => unreachable, // Must be comptime. |
| 546 | 557 | |
| 547 | 558 | else => |tag| return self.todo("Implement zig type '{}'", .{tag}), |
| 548 | | }; |
| 559 | } |
| 549 | 560 | } |
| 550 | 561 | |
| 551 | 562 | fn spirvStorageClass(as: std.builtin.AddressSpace) spec.StorageClass { |