authorgravatar for alichraghi@proton.meAli Chraghi <alichraghi@proton.me> 2025-05-07 20:25:06+03:30
committergravatar for alichraghi@proton.meAli Chraghi <alichraghi@proton.me> 2025-05-21 13:01:20+03:30
logdacd70fbe41d959bb7b48b5bad8612e74231524b
tree6370ef5fa121ecb9aa44cf64d3b6a11530c3d008
parent0901328f12e7ea3d05dc1d5b4a588e595c4bc0bc

spirv: super basic composite int support


10 files changed, 120 insertions(+), 72 deletions(-)

src/Zcu.zig+1-1
...@@ -3693,7 +3693,7 @@ pub fn errorSetBits(zcu: *const Zcu) u16 {...@@ -3693,7 +3693,7 @@ pub fn errorSetBits(zcu: *const Zcu) u16 {
3693 const target = zcu.getTarget();3693 const target = zcu.getTarget();
36943694
3695 if (zcu.error_limit == 0) return 0;3695 if (zcu.error_limit == 0) return 0;
3696 if (target.cpu.arch == .spirv64) {3696 if (target.cpu.arch.isSpirV()) {
3697 if (!std.Target.spirv.featureSetHas(target.cpu.features, .storage_push_constant16)) {3697 if (!std.Target.spirv.featureSetHas(target.cpu.features, .storage_push_constant16)) {
3698 return 32;3698 return 32;
3699 }3699 }
src/codegen/spirv.zig+103-59
...@@ -30,6 +30,7 @@ const SpvAssembler = @import("spirv/Assembler.zig");...@@ -30,6 +30,7 @@ const SpvAssembler = @import("spirv/Assembler.zig");
30const InstMap = std.AutoHashMapUnmanaged(Air.Inst.Index, IdRef);30const InstMap = std.AutoHashMapUnmanaged(Air.Inst.Index, IdRef);
3131
32pub const zig_call_abi_ver = 3;32pub const zig_call_abi_ver = 3;
33pub const big_int_bits = 32;
3334
34const InternMap = std.AutoHashMapUnmanaged(struct { InternPool.Index, NavGen.Repr }, IdResult);35const InternMap = std.AutoHashMapUnmanaged(struct { InternPool.Index, NavGen.Repr }, IdResult);
35const PtrTypeMap = std.AutoHashMapUnmanaged(36const PtrTypeMap = std.AutoHashMapUnmanaged(
...@@ -376,7 +377,7 @@ const NavGen = struct {...@@ -376,7 +377,7 @@ const NavGen = struct {
376 /// The number of bits required to store the type.377 /// The number of bits required to store the type.
377 /// For `integer` and `float`, this is equal to `bits`.378 /// For `integer` and `float`, this is equal to `bits`.
378 /// For `strange_integer` and `bool` this is the size of the backing integer.379 /// For `strange_integer` and `bool` this is the size of the backing integer.
379 /// For `composite_integer` this is 0 (TODO)380 /// For `composite_integer` this is the elements count.
380 backing_bits: u16,381 backing_bits: u16,
381382
382 /// Null if this type is a scalar, or the length383 /// Null if this type is a scalar, or the length
...@@ -579,11 +580,13 @@ const NavGen = struct {...@@ -579,11 +580,13 @@ const NavGen = struct {
579 /// The backing type will be chosen as the smallest supported integer larger or equal to it in number of bits.580 /// The backing type will be chosen as the smallest supported integer larger or equal to it in number of bits.
580 /// The result is valid to be used with OpTypeInt.581 /// The result is valid to be used with OpTypeInt.
581 /// TODO: Should the result of this function be cached?582 /// TODO: Should the result of this function be cached?
582 fn backingIntBits(self: *NavGen, bits: u16) ?u16 {583 fn backingIntBits(self: *NavGen, bits: u16) struct { u16, bool } {
583 // The backend will never be asked to compiler a 0-bit integer, so we won't have to handle those in this function.584 // The backend will never be asked to compiler a 0-bit integer, so we won't have to handle those in this function.
584 assert(bits != 0);585 assert(bits != 0);
585586
586 if (self.spv.hasFeature(.arbitrary_precision_integers) and bits <= 32) return bits;587 if (self.spv.hasFeature(.arbitrary_precision_integers) and bits <= 32) {
588 return .{ bits, false };
589 }
587590
588 // We require Int8 and Int16 capabilities and benefit Int64 when available.591 // We require Int8 and Int16 capabilities and benefit Int64 when available.
589 // 32-bit integers are always supported (see spec, 2.16.1, Data rules).592 // 32-bit integers are always supported (see spec, 2.16.1, Data rules).
...@@ -596,10 +599,11 @@ const NavGen = struct {...@@ -596,10 +599,11 @@ const NavGen = struct {
596599
597 for (ints) |int| {600 for (ints) |int| {
598 const has_feature = if (int.feature) |feature| self.spv.hasFeature(feature) else true;601 const has_feature = if (int.feature) |feature| self.spv.hasFeature(feature) else true;
599 if (bits <= int.bits and has_feature) return int.bits;602 if (bits <= int.bits and has_feature) return .{ int.bits, false };
600 }603 }
601604
602 return null;605 // Big int
606 return .{ std.mem.alignForward(u16, bits, big_int_bits), true };
603 }607 }
604608
605 /// Return the amount of bits in the largest supported integer type. This is either 32 (always supported), or 64 (if609 /// Return the amount of bits in the largest supported integer type. This is either 32 (always supported), or 64 (if
...@@ -623,7 +627,7 @@ const NavGen = struct {...@@ -623,7 +627,7 @@ const NavGen = struct {
623 return switch (scalar_ty.zigTypeTag(zcu)) {627 return switch (scalar_ty.zigTypeTag(zcu)) {
624 .bool => .{628 .bool => .{
625 .bits = 1, // Doesn't matter for this class.629 .bits = 1, // Doesn't matter for this class.
626 .backing_bits = self.backingIntBits(1).?,630 .backing_bits = self.backingIntBits(1).@"0",
627 .vector_len = vector_len,631 .vector_len = vector_len,
628 .signedness = .unsigned, // Technically, but doesn't matter for this class.632 .signedness = .unsigned, // Technically, but doesn't matter for this class.
629 .class = .bool,633 .class = .bool,
...@@ -638,19 +642,16 @@ const NavGen = struct {...@@ -638,19 +642,16 @@ const NavGen = struct {
638 .int => blk: {642 .int => blk: {
639 const int_info = scalar_ty.intInfo(zcu);643 const int_info = scalar_ty.intInfo(zcu);
640 // TODO: Maybe it's useful to also return this value.644 // TODO: Maybe it's useful to also return this value.
641 const maybe_backing_bits = self.backingIntBits(int_info.bits);645 const backing_bits, const big_int = self.backingIntBits(int_info.bits);
642 break :blk .{646 break :blk .{
643 .bits = int_info.bits,647 .bits = int_info.bits,
644 .backing_bits = maybe_backing_bits orelse 0,648 .backing_bits = backing_bits,
645 .vector_len = vector_len,649 .vector_len = vector_len,
646 .signedness = int_info.signedness,650 .signedness = int_info.signedness,
647 .class = if (maybe_backing_bits) |backing_bits|651 .class = class: {
648 if (backing_bits == int_info.bits)652 if (big_int) break :class .composite_integer;
649 .integer653 break :class if (backing_bits == int_info.bits) .integer else .strange_integer;
650 else654 },
651 .strange_integer
652 else
653 .composite_integer,
654 };655 };
655 },656 },
656 .@"enum" => unreachable,657 .@"enum" => unreachable,
...@@ -659,6 +660,34 @@ const NavGen = struct {...@@ -659,6 +660,34 @@ const NavGen = struct {
659 };660 };
660 }661 }
661662
663 /// Checks whether the type can be directly translated to SPIR-V vectors
664 fn isSpvVector(self: *NavGen, ty: Type) bool {
665 const zcu = self.pt.zcu;
666 if (ty.zigTypeTag(zcu) != .vector) return false;
667
668 // TODO: This check must be expanded for types that can be represented
669 // as integers (enums / packed structs?) and types that are represented
670 // by multiple SPIR-V values.
671 const scalar_ty = ty.scalarType(zcu);
672 switch (scalar_ty.zigTypeTag(zcu)) {
673 .bool,
674 .int,
675 .float,
676 => {},
677 else => return false,
678 }
679
680 const elem_ty = ty.childType(zcu);
681 const len = ty.vectorLen(zcu);
682
683 if (elem_ty.isNumeric(zcu) or elem_ty.toIntern() == .bool_type) {
684 if (len > 1 and len <= 4) return true;
685 if (self.spv.hasFeature(.vector16)) return (len == 8 or len == 16);
686 }
687
688 return false;
689 }
690
662 /// Emits a bool constant in a particular representation.691 /// Emits a bool constant in a particular representation.
663 fn constBool(self: *NavGen, value: bool, repr: Repr) !IdRef {692 fn constBool(self: *NavGen, value: bool, repr: Repr) !IdRef {
664 return switch (repr) {693 return switch (repr) {
...@@ -675,14 +704,26 @@ const NavGen = struct {...@@ -675,14 +704,26 @@ const NavGen = struct {
675 const scalar_ty = ty.scalarType(zcu);704 const scalar_ty = ty.scalarType(zcu);
676 const int_info = scalar_ty.intInfo(zcu);705 const int_info = scalar_ty.intInfo(zcu);
677 // Use backing bits so that negatives are sign extended706 // Use backing bits so that negatives are sign extended
678 const backing_bits = self.backingIntBits(int_info.bits).?; // Assertion failure means big int707 const backing_bits, const big_int = self.backingIntBits(int_info.bits);
679 assert(backing_bits != 0); // u0 is comptime708 assert(backing_bits != 0); // u0 is comptime
680709
710 const result_ty_id = try self.resolveType(scalar_ty, .indirect);
681 const signedness: Signedness = switch (@typeInfo(@TypeOf(value))) {711 const signedness: Signedness = switch (@typeInfo(@TypeOf(value))) {
682 .int => |int| int.signedness,712 .int => |int| int.signedness,
683 .comptime_int => if (value < 0) .signed else .unsigned,713 .comptime_int => if (value < 0) .signed else .unsigned,
684 else => unreachable,714 else => unreachable,
685 };715 };
716 if (@sizeOf(@TypeOf(value)) >= 4 and big_int) {
717 const value64: u64 = switch (signedness) {
718 .signed => @bitCast(@as(i64, @intCast(value))),
719 .unsigned => @as(u64, @intCast(value)),
720 };
721 assert(backing_bits == 64);
722 return self.constructComposite(result_ty_id, &.{
723 try self.constInt(.u32, @as(u32, @truncate(value64))),
724 try self.constInt(.u32, @as(u32, @truncate(value64 << 32))),
725 });
726 }
686727
687 const final_value: spec.LiteralContextDependentNumber = blk: {728 const final_value: spec.LiteralContextDependentNumber = blk: {
688 if (self.spv.hasFeature(.kernel)) {729 if (self.spv.hasFeature(.kernel)) {
...@@ -700,18 +741,17 @@ const NavGen = struct {...@@ -700,18 +741,17 @@ const NavGen = struct {
700 break :blk switch (backing_bits) {741 break :blk switch (backing_bits) {
701 1...32 => .{ .uint32 = @truncate(truncated_value) },742 1...32 => .{ .uint32 = @truncate(truncated_value) },
702 33...64 => .{ .uint64 = truncated_value },743 33...64 => .{ .uint64 = truncated_value },
703 else => unreachable, // TODO: Large integer constants744 else => unreachable,
704 };745 };
705 }746 }
706747
707 break :blk switch (backing_bits) {748 break :blk switch (backing_bits) {
708 1...32 => if (signedness == .signed) .{ .int32 = @intCast(value) } else .{ .uint32 = @intCast(value) },749 1...32 => if (signedness == .signed) .{ .int32 = @intCast(value) } else .{ .uint32 = @intCast(value) },
709 33...64 => if (signedness == .signed) .{ .int64 = value } else .{ .uint64 = value },750 33...64 => if (signedness == .signed) .{ .int64 = value } else .{ .uint64 = value },
710 else => unreachable, // TODO: Large integer constants751 else => unreachable,
711 };752 };
712 };753 };
713754
714 const result_ty_id = try self.resolveType(scalar_ty, .indirect);
715 const result_id = try self.spv.constant(result_ty_id, final_value);755 const result_id = try self.spv.constant(result_ty_id, final_value);
716756
717 if (!ty.isVector(zcu)) return result_id;757 if (!ty.isVector(zcu)) return result_id;
...@@ -949,7 +989,7 @@ const NavGen = struct {...@@ -949,7 +989,7 @@ const NavGen = struct {
949 // TODO: composite int989 // TODO: composite int
950 // TODO: endianness990 // TODO: endianness
951 const bits: u16 = @intCast(ty.bitSize(zcu));991 const bits: u16 = @intCast(ty.bitSize(zcu));
952 const bytes = std.mem.alignForward(u16, self.backingIntBits(bits).?, 8) / 8;992 const bytes = std.mem.alignForward(u16, self.backingIntBits(bits).@"0", 8) / 8;
953 var limbs: [8]u8 = undefined;993 var limbs: [8]u8 = undefined;
954 @memset(&limbs, 0);994 @memset(&limbs, 0);
955 val.writeToPackedMemory(ty, pt, limbs[0..bytes], 0) catch unreachable;995 val.writeToPackedMemory(ty, pt, limbs[0..bytes], 0) catch unreachable;
...@@ -1068,19 +1108,11 @@ const NavGen = struct {...@@ -1068,19 +1108,11 @@ const NavGen = struct {
1068 const parent_ptr_id = try self.derivePtr(oac.parent.*);1108 const parent_ptr_id = try self.derivePtr(oac.parent.*);
1069 const parent_ptr_ty = try oac.parent.ptrType(pt);1109 const parent_ptr_ty = try oac.parent.ptrType(pt);
1070 const result_ty_id = try self.resolveType(oac.new_ptr_ty, .direct);1110 const result_ty_id = try self.resolveType(oac.new_ptr_ty, .direct);
1111 const child_size = oac.new_ptr_ty.childType(zcu).abiSize(zcu);
10711112
1072 if (oac.byte_offset != 0) {1113 if (parent_ptr_ty.childType(zcu).isVector(zcu) and oac.byte_offset % child_size == 0) {
1073 const child_size = oac.new_ptr_ty.childType(zcu).abiSize(zcu);
1074 if (oac.byte_offset % child_size != 0) {
1075 return self.fail("cannot perform pointer cast: '{}' to '{}'", .{
1076 parent_ptr_ty.fmt(pt),
1077 oac.new_ptr_ty.fmt(pt),
1078 });
1079 }
1080
1081 // Vector element ptr accesses are derived as offset_and_cast.1114 // Vector element ptr accesses are derived as offset_and_cast.
1082 // We can just use OpAccessChain.1115 // We can just use OpAccessChain.
1083 assert(parent_ptr_ty.childType(zcu).zigTypeTag(zcu) == .vector);
1084 return self.accessChain(1116 return self.accessChain(
1085 result_ty_id,1117 result_ty_id,
1086 parent_ptr_id,1118 parent_ptr_id,
...@@ -1088,15 +1120,22 @@ const NavGen = struct {...@@ -1088,15 +1120,22 @@ const NavGen = struct {
1088 );1120 );
1089 }1121 }
10901122
1091 // Allow changing the pointer type child only to restructure arrays.1123 if (oac.byte_offset == 0) {
1092 // e.g. [3][2]T to T is fine, as is [2]T -> [2][1]T.1124 // Allow changing the pointer type child only to restructure arrays.
1093 const result_ptr_id = self.spv.allocId();1125 // e.g. [3][2]T to T is fine, as is [2]T -> [2][1]T.
1094 try self.func.body.emit(self.spv.gpa, .OpBitcast, .{1126 const result_ptr_id = self.spv.allocId();
1095 .id_result_type = result_ty_id,1127 try self.func.body.emit(self.spv.gpa, .OpBitcast, .{
1096 .id_result = result_ptr_id,1128 .id_result_type = result_ty_id,
1097 .operand = parent_ptr_id,1129 .id_result = result_ptr_id,
1130 .operand = parent_ptr_id,
1131 });
1132 return result_ptr_id;
1133 }
1134
1135 return self.fail("cannot perform pointer cast: '{}' to '{}'", .{
1136 parent_ptr_ty.fmt(pt),
1137 oac.new_ptr_ty.fmt(pt),
1098 });1138 });
1099 return result_ptr_id;
1100 },1139 },
1101 }1140 }
1102 }1141 }
...@@ -1217,11 +1256,14 @@ const NavGen = struct {...@@ -1217,11 +1256,14 @@ const NavGen = struct {
1217 /// actual operations (as well as store) a Zig type of a particular number of bits. To create1256 /// actual operations (as well as store) a Zig type of a particular number of bits. To create
1218 /// a type with an exact size, use SpvModule.intType.1257 /// a type with an exact size, use SpvModule.intType.
1219 fn intType(self: *NavGen, signedness: std.builtin.Signedness, bits: u16) !IdRef {1258 fn intType(self: *NavGen, signedness: std.builtin.Signedness, bits: u16) !IdRef {
1220 const backing_bits = self.backingIntBits(bits) orelse {1259 const backing_bits, const big_int = self.backingIntBits(bits);
1221 // TODO: Integers too big for any native type are represented as "composite integers":1260 if (big_int) {
1222 // An array of largestSupportedIntBits.1261 if (backing_bits > 64) {
1223 return self.todo("Implement {s} composite int type of {} bits", .{ @tagName(signedness), bits });1262 return self.fail("composite integers larger than 64bit aren't supported", .{});
1224 };1263 }
1264 const int_ty = try self.resolveType(.u32, .direct);
1265 return self.arrayType(backing_bits / big_int_bits, int_ty);
1266 }
12251267
1226 // Kernel only supports unsigned ints.1268 // Kernel only supports unsigned ints.
1227 if (self.spv.hasFeature(.kernel)) {1269 if (self.spv.hasFeature(.kernel)) {
...@@ -1509,6 +1551,17 @@ const NavGen = struct {...@@ -1509,6 +1551,17 @@ const NavGen = struct {
1509 return result_id;1551 return result_id;
1510 }1552 }
1511 },1553 },
1554 .vector => {
1555 const elem_ty = ty.childType(zcu);
1556 const elem_ty_id = try self.resolveType(elem_ty, repr);
1557 const len = ty.vectorLen(zcu);
1558
1559 if (self.isSpvVector(ty)) {
1560 return try self.spv.vectorType(len, elem_ty_id);
1561 } else {
1562 return try self.arrayType(len, elem_ty_id);
1563 }
1564 },
1512 .@"fn" => switch (repr) {1565 .@"fn" => switch (repr) {
1513 .direct => {1566 .direct => {
1514 const fn_info = zcu.typeToFunc(ty).?;1567 const fn_info = zcu.typeToFunc(ty).?;
...@@ -1577,12 +1630,6 @@ const NavGen = struct {...@@ -1577,12 +1630,6 @@ const NavGen = struct {
1577 );1630 );
1578 return result_id;1631 return result_id;
1579 },1632 },
1580 .vector => {
1581 const elem_ty = ty.childType(zcu);
1582 const elem_ty_id = try self.resolveType(elem_ty, repr);
1583 const len = ty.vectorLen(zcu);
1584 return self.arrayType(len, elem_ty_id);
1585 },
1586 .@"struct" => {1633 .@"struct" => {
1587 const struct_type = switch (ip.indexToKey(ty.toIntern())) {1634 const struct_type = switch (ip.indexToKey(ty.toIntern())) {
1588 .tuple_type => |tuple| {1635 .tuple_type => |tuple| {
...@@ -3378,8 +3425,7 @@ const NavGen = struct {...@@ -3378,8 +3425,7 @@ const NavGen = struct {
3378 const zcu = self.pt.zcu;3425 const zcu = self.pt.zcu;
3379 const ty = value.ty;3426 const ty = value.ty;
3380 switch (info.class) {3427 switch (info.class) {
3381 .integer, .bool, .float => return value,3428 .composite_integer, .integer, .bool, .float => return value,
3382 .composite_integer => unreachable, // TODO
3383 .strange_integer => switch (info.signedness) {3429 .strange_integer => switch (info.signedness) {
3384 .unsigned => {3430 .unsigned => {
3385 const mask_value = if (info.bits == 64) 0xFFFF_FFFF_FFFF_FFFF else (@as(u64, 1) << @as(u6, @intCast(info.bits))) - 1;3431 const mask_value = if (info.bits == 64) 0xFFFF_FFFF_FFFF_FFFF else (@as(u64, 1) << @as(u6, @intCast(info.bits))) - 1;
...@@ -5039,7 +5085,7 @@ const NavGen = struct {...@@ -5039,7 +5085,7 @@ const NavGen = struct {
5039 const mask_id = try self.constInt(object_ty, (@as(u64, 1) << @as(u6, @intCast(field_bit_size))) - 1);5085 const mask_id = try self.constInt(object_ty, (@as(u64, 1) << @as(u6, @intCast(field_bit_size))) - 1);
5040 const masked = try self.buildBinary(.bit_and, shift, .{ .ty = object_ty, .value = .{ .singleton = mask_id } });5086 const masked = try self.buildBinary(.bit_and, shift, .{ .ty = object_ty, .value = .{ .singleton = mask_id } });
5041 const result_id = blk: {5087 const result_id = blk: {
5042 if (self.backingIntBits(field_bit_size).? == self.backingIntBits(@intCast(object_ty.bitSize(zcu))).?)5088 if (self.backingIntBits(field_bit_size).@"0" == self.backingIntBits(@intCast(object_ty.bitSize(zcu))).@"0")
5043 break :blk try self.bitCast(field_int_ty, object_ty, try masked.materialize(self));5089 break :blk try self.bitCast(field_int_ty, object_ty, try masked.materialize(self));
5044 const trunc = try self.buildConvert(field_int_ty, masked);5090 const trunc = try self.buildConvert(field_int_ty, masked);
5045 break :blk try trunc.materialize(self);5091 break :blk try trunc.materialize(self);
...@@ -5063,7 +5109,7 @@ const NavGen = struct {...@@ -5063,7 +5109,7 @@ const NavGen = struct {
5063 .{ .ty = backing_int_ty, .value = .{ .singleton = mask_id } },5109 .{ .ty = backing_int_ty, .value = .{ .singleton = mask_id } },
5064 );5110 );
5065 const result_id = blk: {5111 const result_id = blk: {
5066 if (self.backingIntBits(field_bit_size).? == self.backingIntBits(@intCast(backing_int_ty.bitSize(zcu))).?)5112 if (self.backingIntBits(field_bit_size).@"0" == self.backingIntBits(@intCast(backing_int_ty.bitSize(zcu))).@"0")
5067 break :blk try self.bitCast(int_ty, backing_int_ty, try masked.materialize(self));5113 break :blk try self.bitCast(int_ty, backing_int_ty, try masked.materialize(self));
5068 const trunc = try self.buildConvert(int_ty, masked);5114 const trunc = try self.buildConvert(int_ty, masked);
5069 break :blk try trunc.materialize(self);5115 break :blk try trunc.materialize(self);
...@@ -6100,17 +6146,15 @@ const NavGen = struct {...@@ -6100,17 +6146,15 @@ const NavGen = struct {
6100 .bool, .error_set => 1,6146 .bool, .error_set => 1,
6101 .int => blk: {6147 .int => blk: {
6102 const bits = cond_ty.intInfo(zcu).bits;6148 const bits = cond_ty.intInfo(zcu).bits;
6103 const backing_bits = self.backingIntBits(bits) orelse {6149 const backing_bits, const big_int = self.backingIntBits(bits);
6104 return self.todo("implement composite int switch", .{});6150 if (big_int) return self.todo("implement composite int switch", .{});
6105 };
6106 break :blk if (backing_bits <= 32) 1 else 2;6151 break :blk if (backing_bits <= 32) 1 else 2;
6107 },6152 },
6108 .@"enum" => blk: {6153 .@"enum" => blk: {
6109 const int_ty = cond_ty.intTagType(zcu);6154 const int_ty = cond_ty.intTagType(zcu);
6110 const int_info = int_ty.intInfo(zcu);6155 const int_info = int_ty.intInfo(zcu);
6111 const backing_bits = self.backingIntBits(int_info.bits) orelse {6156 const backing_bits, const big_int = self.backingIntBits(int_info.bits);
6112 return self.todo("implement composite int switch", .{});6157 if (big_int) return self.todo("implement composite int switch", .{});
6113 };
6114 break :blk if (backing_bits <= 32) 1 else 2;6158 break :blk if (backing_bits <= 32) 1 else 2;
6115 },6159 },
6116 .pointer => blk: {6160 .pointer => blk: {
src/codegen/spirv/Module.zig+5-2
...@@ -369,8 +369,11 @@ pub fn finalize(self: *Module, a: Allocator) ![]Word {...@@ -369,8 +369,11 @@ pub fn finalize(self: *Module, a: Allocator) ![]Word {
369 // Emit memory model369 // Emit memory model
370 const addressing_model: spec.AddressingModel = blk: {370 const addressing_model: spec.AddressingModel = blk: {
371 if (self.hasFeature(.shader)) {371 if (self.hasFeature(.shader)) {
372 assert(self.target.cpu.arch == .spirv64);372 if (self.hasFeature(.physical_storage_buffer)) {
373 if (self.hasFeature(.physical_storage_buffer)) break :blk .PhysicalStorageBuffer64;373 assert(self.target.cpu.arch == .spirv64);
374 break :blk .PhysicalStorageBuffer64;
375 }
376 assert(self.target.cpu.arch == .spirv);
374 break :blk .Logical;377 break :blk .Logical;
375 }378 }
376379
src/target.zig+2-1
...@@ -807,7 +807,8 @@ pub fn zigBackend(target: std.Target, use_llvm: bool) std.builtin.CompilerBacken...@@ -807,7 +807,8 @@ pub fn zigBackend(target: std.Target, use_llvm: bool) std.builtin.CompilerBacken
807 .powerpc, .powerpcle, .powerpc64, .powerpc64le => .stage2_powerpc,807 .powerpc, .powerpcle, .powerpc64, .powerpc64le => .stage2_powerpc,
808 .riscv64 => .stage2_riscv64,808 .riscv64 => .stage2_riscv64,
809 .sparc64 => .stage2_sparc64,809 .sparc64 => .stage2_sparc64,
810 .spirv64 => .stage2_spirv64,810 .spirv32 => if (target.os.tag == .opencl) .stage2_spirv64 else .other,
811 .spirv, .spirv64 => .stage2_spirv64,
811 .wasm32, .wasm64 => .stage2_wasm,812 .wasm32, .wasm64 => .stage2_wasm,
812 .x86 => .stage2_x86,813 .x86 => .stage2_x86,
813 .x86_64 => .stage2_x86_64,814 .x86_64 => .stage2_x86_64,
test/cases/compile_errors/@import_zon_bad_type.zig+3-3
...@@ -117,9 +117,9 @@ export fn testMutablePointer() void {...@@ -117,9 +117,9 @@ export fn testMutablePointer() void {
117// tmp.zig:37:38: note: imported here117// tmp.zig:37:38: note: imported here
118// neg_inf.zon:1:1: error: expected type '?u8'118// neg_inf.zon:1:1: error: expected type '?u8'
119// tmp.zig:57:28: note: imported here119// tmp.zig:57:28: note: imported here
120// neg_inf.zon:1:1: error: expected type 'tmp.testNonExhaustiveEnum__enum_499'120// neg_inf.zon:1:1: error: expected type 'tmp.testNonExhaustiveEnum__enum_501'
121// tmp.zig:62:39: note: imported here121// tmp.zig:62:39: note: imported here
122// neg_inf.zon:1:1: error: expected type 'tmp.testUntaggedUnion__union_501'122// neg_inf.zon:1:1: error: expected type 'tmp.testUntaggedUnion__union_503'
123// tmp.zig:67:44: note: imported here123// tmp.zig:67:44: note: imported here
124// neg_inf.zon:1:1: error: expected type 'tmp.testTaggedUnionVoid__union_504'124// neg_inf.zon:1:1: error: expected type 'tmp.testTaggedUnionVoid__union_506'
125// tmp.zig:72:50: note: imported here125// tmp.zig:72:50: note: imported here
test/cases/compile_errors/anytype_param_requires_comptime.zig+1-1
...@@ -15,6 +15,6 @@ pub export fn entry() void {...@@ -15,6 +15,6 @@ pub export fn entry() void {
15// error15// error
16//16//
17// :7:25: error: unable to resolve comptime value17// :7:25: error: unable to resolve comptime value
18// :7:25: note: initializer of comptime-only struct 'tmp.S.foo__anon_473.C' must be comptime-known18// :7:25: note: initializer of comptime-only struct 'tmp.S.foo__anon_475.C' must be comptime-known
19// :4:16: note: struct requires comptime because of this field19// :4:16: note: struct requires comptime because of this field
20// :4:16: note: types are not available at runtime20// :4:16: note: types are not available at runtime
test/cases/compile_errors/bogus_method_call_on_slice.zig+1-1
...@@ -16,5 +16,5 @@ pub export fn entry2() void {...@@ -16,5 +16,5 @@ pub export fn entry2() void {
16//16//
17// :3:6: error: no field or member function named 'copy' in '[]const u8'17// :3:6: error: no field or member function named 'copy' in '[]const u8'
18// :9:8: error: no field or member function named 'bar' in '@TypeOf(.{})'18// :9:8: error: no field or member function named 'bar' in '@TypeOf(.{})'
19// :12:18: error: no field or member function named 'bar' in 'tmp.entry2__struct_477'19// :12:18: error: no field or member function named 'bar' in 'tmp.entry2__struct_479'
20// :12:6: note: struct declared here20// :12:6: note: struct declared here
test/cases/compile_errors/coerce_anon_struct.zig+1-1
...@@ -6,6 +6,6 @@ export fn foo() void {...@@ -6,6 +6,6 @@ export fn foo() void {
66
7// error7// error
8//8//
9// :4:16: error: expected type 'tmp.T', found 'tmp.foo__struct_466'9// :4:16: error: expected type 'tmp.T', found 'tmp.foo__struct_468'
10// :3:16: note: struct declared here10// :3:16: note: struct declared here
11// :1:11: note: struct declared here11// :1:11: note: struct declared here
test/cases/compile_errors/redundant_try.zig+2-2
...@@ -44,9 +44,9 @@ comptime {...@@ -44,9 +44,9 @@ comptime {
44//44//
45// :5:23: error: expected error union type, found 'comptime_int'45// :5:23: error: expected error union type, found 'comptime_int'
46// :10:23: error: expected error union type, found '@TypeOf(.{})'46// :10:23: error: expected error union type, found '@TypeOf(.{})'
47// :15:23: error: expected error union type, found 'tmp.test2__struct_503'47// :15:23: error: expected error union type, found 'tmp.test2__struct_505'
48// :15:23: note: struct declared here48// :15:23: note: struct declared here
49// :20:27: error: expected error union type, found 'tmp.test3__struct_505'49// :20:27: error: expected error union type, found 'tmp.test3__struct_507'
50// :20:27: note: struct declared here50// :20:27: note: struct declared here
51// :25:23: error: expected error union type, found 'struct { comptime *const [5:0]u8 = "hello" }'51// :25:23: error: expected error union type, found 'struct { comptime *const [5:0]u8 = "hello" }'
52// :31:13: error: expected error union type, found 'u32'52// :31:13: error: expected error union type, found 'u32'
test/tests.zig+1-1
...@@ -145,7 +145,7 @@ const test_targets = blk: {...@@ -145,7 +145,7 @@ const test_targets = blk: {
145 .{145 .{
146 .target = std.Target.Query.parse(.{146 .target = std.Target.Query.parse(.{
147 .arch_os_abi = "spirv64-vulkan",147 .arch_os_abi = "spirv64-vulkan",
148 .cpu_features = "vulkan_v1_2+int64+float16+float64",148 .cpu_features = "vulkan_v1_2+physical_storage_buffer+int64+float16+float64",
149 }) catch unreachable,149 }) catch unreachable,
150 .use_llvm = false,150 .use_llvm = false,
151 .use_lld = false,151 .use_lld = false,