authorgravatar for alichraghi@proton.meAli Chraghi <alichraghi@proton.me> 2026-10-09 23:10:32+03:30
committergravatar for alichraghi@proton.meAli Chraghi <alichraghi@proton.me> 2026-10-23 09:18:03+03:30
log2bbac862018599c121281f2ca5658f3879c0c0a3
treee623382ca7e637dce46749617853a30e9173f1a7
parent0a01fe2bc6748b5fa2b03cebdcaae0e655501ad4

spirv: use `addrSpaceIsLogical` instead of switching on target os


17 files changed, 163 insertions(+), 191 deletions(-)

src/Sema.zig+17-42
......@@ -8695,19 +8695,17 @@ fn checkParamType(
86958695 if (param_is_noalias and !param_ty.isGenericPoison() and !param_ty.isPtrAtRuntime(zcu) and !param_ty.isSliceAtRuntime(zcu)) {
86968696 return sema.fail(block, param_src, "non-pointer parameter declared noalias", .{});
86978697 }
8698 switch (target.os.tag) {
8699 .vulkan, .opengl => if (cc != .@"inline" and param_ty.isPtrAtRuntime(zcu)) {
8700 switch (param_ty.ptrAddressSpace(zcu)) {
8701 .input, .output => |as| return sema.failWithOwnedErrorMsg(block, msg: {
8702 const msg = try sema.errMsg(param_src, "function parameter cannot be a pointer in '{s}' address space", .{@tagName(as)});
8703 errdefer msg.destroy(sema.gpa);
8704 try sema.errNote(param_src, msg, "mark the function as 'inline' so the parameter is substituted at call sites", .{});
8705 break :msg msg;
8706 }),
8707 else => {},
8708 }
8709 },
8710 else => {},
8698 if (cc != .@"inline" and param_ty.isPtrAtRuntime(zcu)) {
8699 const as = param_ty.ptrAddressSpace(zcu);
8700 if (target_util.addrSpaceIsLogical(target, as)) switch (as) {
8701 .input, .output => return sema.failWithOwnedErrorMsg(block, msg: {
8702 const msg = try sema.errMsg(param_src, "function parameter cannot be a pointer in '{s}' address space", .{@tagName(as)});
8703 errdefer msg.destroy(sema.gpa);
8704 try sema.errNote(param_src, msg, "mark the function as 'inline' so the parameter is substituted at call sites", .{});
8705 break :msg msg;
8706 }),
8707 else => {},
8708 };
87118709 }
87128710}
87138711
......@@ -8944,9 +8942,7 @@ fn checkMergeAllowed(sema: *Sema, block: *Block, src: LazySrcLoc, peer_ty: Type)
89448942 }
89458943
89468944 const as = peer_ty.ptrAddressSpace(zcu);
8947 if (!target_util.shouldBlockPointerOps(target, as)) {
8948 return;
8949 }
8945 if (!target_util.addrSpaceIsLogical(target, as)) return;
89508946
89518947 return sema.failWithOwnedErrorMsg(block, msg: {
89528948 const msg = try sema.errMsg(src, "value with non-mergable pointer type '{f}' depends on runtime control flow", .{peer_ty.fmt(zcu)});
......@@ -22245,7 +22241,7 @@ fn ptrCastFull(
2224522241 try sema.validateRuntimeValue(block, operand_src, operand);
2224622242 try sema.checkLogicalPtrCast(block, src, operand_ty, dest_ty);
2224722243
22248 const can_cast_to_int = !target_util.shouldBlockPointerOps(zcu.getTarget(), operand_ty.ptrAddressSpace(zcu));
22244 const can_cast_to_int = !target_util.addrSpaceIsLogical(zcu.getTarget(), operand_ty.ptrAddressSpace(zcu));
2224922245 const need_null_check = can_cast_to_int and block.wantSafety() and operand_ty.ptrAllowsZero(zcu) and !dest_ty.ptrAllowsZero(zcu);
2225022246 const need_align_check = can_cast_to_int and block.wantSafety() and dest_align.compare(.gt, src_align);
2225122247
......@@ -22791,7 +22787,7 @@ fn checkLogicalPtrOperation(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Typ
2279122787 if (zcu.intern_pool.indexToKey(ty.toIntern()) == .ptr_type) {
2279222788 const target = zcu.getTarget();
2279322789 const as = ty.ptrAddressSpace(zcu);
22794 if (target_util.shouldBlockPointerOps(target, as)) {
22790 if (target_util.addrSpaceIsLogical(target, as)) {
2279522791 return sema.failWithOwnedErrorMsg(block, msg: {
2279622792 const msg = try sema.errMsg(src, "illegal operation on logical pointer of type '{f}'", .{ty.fmt(zcu)});
2279722793 errdefer msg.destroy(sema.gpa);
......@@ -22822,11 +22818,7 @@ fn checkLogicalPtrCast(
2282222818 const dest_child: Type = .fromInterned(dest_info.child);
2282322819
2282422820 if (block.isComptime() or block.is_typeof) return;
22825 switch (zcu.getTarget().os.tag) {
22826 .vulkan, .opengl => {},
22827 else => return,
22828 }
22829 if (src_info.flags.address_space == .physical_storage_buffer) return;
22821 if (!target_util.addrSpaceIsLogical(zcu.getTarget(), src_info.flags.address_space)) return;
2283022822 if (!dest_child.hasRuntimeBits(zcu)) return;
2283122823
2283222824 var cur = src_child;
......@@ -30297,25 +30289,8 @@ fn checkSpirvSliceAllowed(
3029730289 if (!target.cpu.arch.isSpirV()) return;
3029830290 if (block.isComptime()) return;
3029930291
30300 // This probably lets some invalid OpPtrAccessChains slip through, but it's better than nothing
30301 if (!target.cpu.has(.spirv, .variable_pointers) and !target.cpu.has(.spirv, .variable_pointers_storage_buffer)) {
30302 return sema.failWithOwnedErrorMsg(
30303 block,
30304 try sema.errMsg(src, "cannot construct slices without the 'variable_pointers' or 'variable_pointers_storage_buffer' features", .{}),
30305 );
30306 }
30307
30308 switch (address_space) {
30309 .shared, .storage_buffer => {},
30310 else => {
30311 return sema.failWithOwnedErrorMsg(block, msg: {
30312 const msg = try sema.errMsg(src, "cannot construct slice from address space '{t}'", .{address_space});
30313 errdefer msg.destroy(sema.gpa);
30314 try sema.errNote(src, msg, "only 'shared' and 'storage_buffer' address spaces support slicing on SPIR-V", .{});
30315 break :msg msg;
30316 });
30317 },
30318 }
30292 if (!target_util.addrSpaceIsLogical(target, address_space)) return;
30293 return sema.fail(block, src, "cannot construct slice from logical address space '{t}'", .{address_space});
3031930294}
3032030295
3032130296fn coerceArrayPtrToSlice(
src/codegen/spirv/CodeGen.zig+84-109
......@@ -816,21 +816,20 @@ pub fn memberDebugName(cg: *CodeGen, target: Id, member: u32, name: []const u8)
816816pub fn storageClass(cg: *const CodeGen, as: std.lang.AddressSpace) spec.StorageClass {
817817 const target = cg.zcu.getTarget();
818818 return switch (as) {
819 .generic => .function,
820819 .global => switch (target.os.tag) {
821820 .opencl, .amdhsa => .cross_workgroup,
822 else => .storage_buffer,
821 else => unreachable,
823822 },
823 .local, .generic => .function,
824824 .push_constant => .push_constant,
825 .output => .output,
826825 .uniform => .uniform,
827826 .storage_buffer => .storage_buffer,
828827 .physical_storage_buffer => .physical_storage_buffer,
829828 .constant => .uniform_constant,
830829 .shared => .workgroup,
831 .local => .function,
832830 .private => .private,
833831 .input => .input,
832 .output => .output,
834833 .gs,
835834 .fs,
836835 .ss,
......@@ -1689,14 +1688,14 @@ fn constantPtr(cg: *CodeGen, ptr_val: Value) !Id {
16891688/// This function emits instructions on every call, and they stay in the module whether or not they
16901689/// are read, so it should only be called where the resulting type is used: a buffer struct emitted
16911690/// without `Block` fails validation even when nothing refers to it.
1692fn derivedPtrType(cg: *CodeGen, @"addrspace": std.lang.AddressSpace, derivation: Value.PointerDerivation) !Id {
1691fn derivedPtrType(cg: *CodeGen, as: std.lang.AddressSpace, derivation: Value.PointerDerivation) !Id {
16931692 return cg.ptrType(
1694 try cg.pointeeType(@"addrspace", derivation.elem_ty, false),
1695 cg.storageClass(@"addrspace"),
1693 try cg.pointeeType(as, derivation.elem_ty, false),
1694 cg.storageClass(as),
16961695 );
16971696}
16981697
1699fn derivePtr(cg: *CodeGen, @"addrspace": std.lang.AddressSpace, derivation: Value.PointerDerivation) !Id {
1698fn derivePtr(cg: *CodeGen, as: std.lang.AddressSpace, derivation: Value.PointerDerivation) !Id {
17001699 const gpa = cg.gpa;
17011700 const zcu = cg.zcu;
17021701 const target = zcu.getTarget();
......@@ -1704,18 +1703,16 @@ fn derivePtr(cg: *CodeGen, @"addrspace": std.lang.AddressSpace, derivation: Valu
17041703 switch (derivation.addr) {
17051704 .comptime_alloc, .comptime_field => unreachable,
17061705 .int => |int| {
1707 if (target.os.tag != .opencl) {
1708 if (@"addrspace" != .physical_storage_buffer) {
1709 return cg.fail(
1710 "cannot cast integer to pointer with address space '{s}'",
1711 .{@tagName(@"addrspace")},
1712 );
1713 }
1706 if (target_util.addrSpaceIsLogical(target, as)) {
1707 return cg.fail(
1708 "cannot cast integer to pointer with address space '{s}'",
1709 .{@tagName(as)},
1710 );
17141711 }
17151712 // TODO: This can probably be an OpSpecConstantOp Bitcast, but
17161713 // that is not implemented by Mesa yet. Therefore, just generate it
17171714 // as a runtime operation.
1718 const result_ty_id = try cg.derivedPtrType(@"addrspace", derivation);
1715 const result_ty_id = try cg.derivedPtrType(as, derivation);
17191716 const result_ptr_id = cg.allocId();
17201717 const value_id = try cg.constInt(.usize, int);
17211718 try cg.body.emit(gpa, .OpConvertUToPtr, .{
......@@ -1735,30 +1732,26 @@ fn derivePtr(cg: *CodeGen, @"addrspace": std.lang.AddressSpace, derivation: Valu
17351732
17361733 if (ip.isFunctionType(nav_ty.toIntern())) {
17371734 if (is_extern) return try cg.resolveExternFn(nav_index);
1738 return try cg.constUndef(try cg.derivedPtrType(@"addrspace", derivation));
1735 return try cg.constUndef(try cg.derivedPtrType(as, derivation));
17391736 }
17401737 if (!nav_ty.hasRuntimeBits(zcu) and nav_ty.zigTypeTag(zcu) != .spirv) {
1741 return cg.constUndef(try cg.derivedPtrType(@"addrspace", derivation));
1738 return cg.constUndef(try cg.derivedPtrType(as, derivation));
17421739 }
17431740 if (!is_extern) {
17441741 return cg.todo("pointer to constant '{f}'", .{nav.fqn.fmt(ip)});
17451742 }
17461743
1747 const as = nav.resolved.?.@"addrspace";
1748 assert(as != .generic);
1744 assert(nav.resolved.?.@"addrspace" != .generic);
17491745
17501746 const var_id = try cg.resolveNav(nav_index);
17511747 if (cg.needsLayout(as, nav_ty)) {
17521748 try cg.block_var_ids.put(gpa, var_id, {});
17531749 }
1754 switch (target.os.tag) {
1755 .vulkan, .opengl => return var_id,
1756 else => {},
1757 }
1750 if (target_util.addrSpaceIsLogical(target, as)) return var_id;
17581751
17591752 const nav_ty_id = try cg.resolveType(nav_ty, .indirect);
17601753 const decl_ptr_ty_id = try cg.ptrType(nav_ty_id, cg.storageClass(as));
1761 const result_ty_id = try cg.derivedPtrType(@"addrspace", derivation);
1754 const result_ty_id = try cg.derivedPtrType(as, derivation);
17621755 if (decl_ptr_ty_id == result_ty_id) return var_id;
17631756
17641757 const casted_ptr_id = cg.allocId();
......@@ -1780,10 +1773,10 @@ fn derivePtr(cg: *CodeGen, @"addrspace": std.lang.AddressSpace, derivation: Valu
17801773 }
17811774
17821775 if (!uav_ty.hasRuntimeBits(zcu) and uav_ty.zigTypeTag(zcu) != .spirv) {
1783 return cg.constUndef(try cg.derivedPtrType(@"addrspace", derivation));
1776 return cg.constUndef(try cg.derivedPtrType(as, derivation));
17841777 }
17851778
1786 if (cg.storageClass(@"addrspace") != .function) {
1779 if (cg.storageClass(as) != .function) {
17871780 return cg.todo("pointer to an anonymous constant of type '{f}'", .{uav_ty.fmt(zcu)});
17881781 }
17891782
......@@ -1796,11 +1789,11 @@ fn derivePtr(cg: *CodeGen, @"addrspace": std.lang.AddressSpace, derivation: Valu
17961789 .eu_payload => @panic("TODO"),
17971790 .opt_payload => @panic("TODO"),
17981791 .field => |derived| return cg.structFieldPtr(
1799 @"addrspace",
1800 try cg.derivedPtrType(@"addrspace", derivation),
1792 as,
1793 try cg.derivedPtrType(as, derivation),
18011794 derivation.elem_ty,
18021795 derived.parent.elem_ty,
1803 try cg.derivePtr(@"addrspace", derived.parent.*),
1796 try cg.derivePtr(as, derived.parent.*),
18041797 derived.field_index,
18051798 ),
18061799 .elem => |derived| return cg.ptrElemPtr(
......@@ -1808,13 +1801,13 @@ fn derivePtr(cg: *CodeGen, @"addrspace": std.lang.AddressSpace, derivation: Valu
18081801 .one => .single_array_ptr,
18091802 .many => .many_ptr,
18101803 },
1811 @"addrspace",
1804 as,
18121805 derivation.elem_ty,
1813 try cg.derivePtr(@"addrspace", derived.parent.*),
1806 try cg.derivePtr(as, derived.parent.*),
18141807 try cg.constInt(.usize, derived.elem_index),
18151808 ),
18161809 .offset_and_cast => |derived| {
1817 const parent_ptr_id = try cg.derivePtr(@"addrspace", derived.parent.*);
1810 const parent_ptr_id = try cg.derivePtr(as, derived.parent.*);
18181811
18191812 if (derived.byte_offset == 0) {
18201813 var depth: u32 = 0;
......@@ -1849,13 +1842,13 @@ fn derivePtr(cg: *CodeGen, @"addrspace": std.lang.AddressSpace, derivation: Valu
18491842 const zero = try cg.constInt(.u32, 0);
18501843 const ids = try cg.id_scratch.addManyAsSlice(gpa, depth);
18511844 @memset(ids, zero);
1852 return cg.accessChainId(try cg.derivedPtrType(@"addrspace", derivation), parent_ptr_id, ids);
1845 return cg.accessChainId(try cg.derivedPtrType(as, derivation), parent_ptr_id, ids);
18531846 } else {
18541847 return parent_ptr_id;
18551848 }
18561849 }
1857 if (target.os.tag == .opencl) {
1858 const result_ty_id = try cg.derivedPtrType(@"addrspace", derivation);
1850 if (!target_util.addrSpaceIsLogical(target, as)) {
1851 const result_ty_id = try cg.derivedPtrType(as, derivation);
18591852 const result_ptr_id = cg.allocId();
18601853 try cg.body.emit(gpa, .OpBitcast, .{
18611854 .id_result_type = result_ty_id,
......@@ -3820,7 +3813,7 @@ fn generateTestEntryPoint(
38203813 const anyerror_ty_id = try cg.resolveType(.anyerror, .direct);
38213814 const ptr_anyerror_ty = try cg.pt.ptrType(.{
38223815 .child = .anyerror_type,
3823 .flags = .{ .address_space = .global },
3816 .flags = .{ .address_space = .storage_buffer },
38243817 });
38253818 const ptr_anyerror_ty_id = try cg.resolveType(ptr_anyerror_ty, .direct);
38263819
......@@ -3863,7 +3856,7 @@ fn generateTestEntryPoint(
38633856 const ptr_buffer_struct_ty_id = cg.allocId();
38643857 try cg.module.emit(gpa, .OpTypePointer, .{
38653858 .id_result = ptr_buffer_struct_ty_id,
3866 .storage_class = cg.storageClass(.global),
3859 .storage_class = cg.storageClass(.storage_buffer),
38673860 .type = buffer_struct_ty_id,
38683861 });
38693862
......@@ -3872,7 +3865,7 @@ fn generateTestEntryPoint(
38723865 try cg.module.emit(gpa, .OpVariable, .{
38733866 .id_result_type = ptr_buffer_struct_ty_id,
38743867 .id_result = error_buffer_id,
3875 .storage_class = cg.storageClass(.global),
3868 .storage_class = cg.storageClass(.storage_buffer),
38763869 });
38773870 try cg.decorate(error_buffer_id, .{ .descriptor_set = .{ .descriptor_set = 0 } });
38783871 try cg.decorate(error_buffer_id, .{ .binding = .{ .binding_point = 0 } });
......@@ -5464,6 +5457,7 @@ fn accessChain(
54645457
54655458fn ptrAccessChain(
54665459 cg: *CodeGen,
5460 as: std.lang.AddressSpace,
54675461 result_ty_id: Id,
54685462 base: Id,
54695463 element: Id,
......@@ -5491,8 +5485,7 @@ fn ptrAccessChain(
54915485 });
54925486 },
54935487 .vulkan, .opengl => {
5494 assert(target.cpu.has(.spirv, .variable_pointers) or
5495 target.cpu.has(.spirv, .variable_pointers_storage_buffer));
5488 assert(!target_util.addrSpaceIsLogical(target, as));
54965489 try cg.body.emit(gpa, .OpPtrAccessChain, .{
54975490 .id_result_type = result_ty_id,
54985491 .id_result = result_id,
......@@ -5513,11 +5506,11 @@ fn ptrAdd(cg: *CodeGen, result_ty: Type, ptr_ty: Type, ptr_id: Id, offset_id: Id
55135506 const result_ty_id = try cg.ptrType(child_ty_id, cg.storageClass(as));
55145507 return switch (ptr_ty.ptrSize(zcu)) {
55155508 .one => cg.accessChainId(result_ty_id, ptr_id, &.{offset_id}),
5516 .c, .many => cg.ptrAccessChain(result_ty_id, ptr_id, offset_id, &.{}),
5509 .c, .many => cg.ptrAccessChain(as, result_ty_id, ptr_id, offset_id, &.{}),
55175510 .slice => blk: {
55185511 // TODO: This is probably incorrect. A slice should be returned here, though this is what llvm does.
55195512 const slice_ptr_id = try cg.extractField(result_ty, ptr_id, 0);
5520 break :blk cg.ptrAccessChain(result_ty_id, slice_ptr_id, offset_id, &.{});
5513 break :blk cg.ptrAccessChain(as, result_ty_id, slice_ptr_id, offset_id, &.{});
55215514 },
55225515 };
55235516}
......@@ -5770,8 +5763,8 @@ fn bitCast(
57705763 const target = zcu.getTarget();
57715764
57725765 if (src_ty.toIntern() == dst_ty.toIntern()) return src_id;
5773 if (src_ty.isPtrAtRuntime(zcu) and dst_ty.isPtrAtRuntime(zcu)) switch (target.os.tag) {
5774 .vulkan, .opengl => if (src_ty.ptrAddressSpace(zcu) != .physical_storage_buffer) {
5766 if (src_ty.isPtrAtRuntime(zcu) and dst_ty.isPtrAtRuntime(zcu)) {
5767 if (target_util.addrSpaceIsLogical(target, src_ty.ptrAddressSpace(zcu))) {
57755768 const src_child = src_ty.childType(zcu);
57765769 const dst_child = dst_ty.childType(zcu);
57775770 if (!dst_child.hasRuntimeBits(zcu)) return src_id;
......@@ -5797,9 +5790,8 @@ fn bitCast(
57975790 }
57985791 const dst_ty_id = try cg.resolveType(dst_ty, .direct);
57995792 return try cg.accessChain(dst_ty_id, src_id, indices.items);
5800 },
5801 else => {},
5802 };
5793 }
5794 }
58035795
58045796 const dst_ty_id = try cg.resolveType(dst_ty, .direct);
58055797 const result_id = blk: {
......@@ -5836,13 +5828,11 @@ fn bitCast(
58365828 }
58375829
58385830 if (src_ty.zigTypeTag(zcu) == .int and dst_ty.isPtrAtRuntime(zcu)) {
5839 if (target.os.tag != .opencl) {
5840 if (dst_ty.ptrAddressSpace(zcu) != .physical_storage_buffer) {
5841 return cg.fail(
5842 "cannot cast integer to pointer with address space '{s}'",
5843 .{@tagName(dst_ty.ptrAddressSpace(zcu))},
5844 );
5845 }
5831 if (target_util.addrSpaceIsLogical(target, dst_ty.ptrAddressSpace(zcu))) {
5832 return cg.fail(
5833 "cannot cast integer to pointer with address space '{s}'",
5834 .{@tagName(dst_ty.ptrAddressSpace(zcu))},
5835 );
58465836 }
58475837
58485838 const result_id = cg.allocId();
......@@ -5869,16 +5859,13 @@ fn bitCast(
58695859 break :blk result_id;
58705860 }
58715861
5872 switch (target.os.tag) {
5873 .vulkan, .opengl => {
5874 // Logical addressing forbids OpBitcast on pointers. Allocate
5875 // the temp with dst_ty so the load reads through a slot of the right type.
5876 const dst_ty_indirect_id = try cg.resolveType(dst_ty, .indirect);
5877 const tmp_id = try cg.alloc(dst_ty_indirect_id, null);
5878 try cg.store(dst_ty, tmp_id, src_id, .{});
5879 break :blk try cg.load(dst_ty, tmp_id, .{});
5880 },
5881 else => {},
5862 if (target_util.addrSpaceIsLogical(target, .local)) {
5863 // Logical addressing forbids OpBitcast on pointers. Allocate
5864 // the temp with dst_ty so the load reads through a slot of the right type.
5865 const dst_ty_indirect_id = try cg.resolveType(dst_ty, .indirect);
5866 const tmp_id = try cg.alloc(dst_ty_indirect_id, null);
5867 try cg.store(dst_ty, tmp_id, src_id, .{});
5868 break :blk try cg.load(dst_ty, tmp_id, .{});
58825869 }
58835870
58845871 const dst_ptr_ty_id = try cg.ptrType(dst_ty_id, .function);
......@@ -6463,7 +6450,7 @@ fn airSliceElemPtr(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
64636450 const ptr_ty_id = try cg.resolveType(ptr_ty, .direct);
64646451
64656452 const slice_ptr = try cg.extractField(ptr_ty, slice_id, 0);
6466 return try cg.ptrAccessChain(ptr_ty_id, slice_ptr, index_id, &.{});
6453 return try cg.ptrAccessChain(ptr_ty.ptrAddressSpace(zcu), ptr_ty_id, slice_ptr, index_id, &.{});
64676454}
64686455
64696456fn airSliceElemVal(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
......@@ -6479,22 +6466,22 @@ fn airSliceElemVal(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
64796466 const ptr_ty_id = try cg.resolveType(ptr_ty, .direct);
64806467
64816468 const slice_ptr = try cg.extractField(ptr_ty, slice_id, 0);
6482 const elem_ptr = try cg.ptrAccessChain(ptr_ty_id, slice_ptr, index_id, &.{});
6469 const elem_ptr = try cg.ptrAccessChain(ptr_ty.ptrAddressSpace(zcu), ptr_ty_id, slice_ptr, index_id, &.{});
64836470 return try cg.load(slice_ty.childType(zcu), elem_ptr, .{ .is_volatile = slice_ty.isVolatilePtr(zcu) });
64846471}
64856472
64866473fn ptrElemPtr(
64876474 cg: *CodeGen,
64886475 mode: enum { single_array_ptr, many_ptr },
6489 @"addrspace": std.lang.AddressSpace,
6476 as: std.lang.AddressSpace,
64906477 elem_ty: Type,
64916478 ptr_id: Id,
64926479 index_id: Id,
64936480) !Id {
64946481 // Construct new pointer type for the resulting pointer
64956482 const elem_is_block = cg.block_var_ids.contains(ptr_id);
6496 const elem_ty_id = try cg.pointeeType(@"addrspace", elem_ty, elem_is_block);
6497 const elem_ptr_ty_id = try cg.ptrType(elem_ty_id, cg.storageClass(@"addrspace"));
6483 const elem_ty_id = try cg.pointeeType(as, elem_ty, elem_is_block);
6484 const elem_ptr_ty_id = try cg.ptrType(elem_ty_id, cg.storageClass(as));
64986485 switch (mode) {
64996486 .single_array_ptr => {
65006487 // Pointer-to-array. In this case, the resulting pointer is not of the same type
......@@ -6503,7 +6490,7 @@ fn ptrElemPtr(
65036490 },
65046491 .many_ptr => {
65056492 // Resulting pointer type is the same as the ptr_ty, so use ptrAccessChain
6506 return cg.ptrAccessChain(elem_ptr_ty_id, ptr_id, index_id, &.{});
6493 return cg.ptrAccessChain(as, elem_ptr_ty_id, ptr_id, index_id, &.{});
65076494 },
65086495 }
65096496}
......@@ -6821,14 +6808,11 @@ fn airAggFieldVal(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
68216808 return try cg.load(field_ty, pl_ptr_id, .{});
68226809 }
68236810
6824 switch (zcu.getTarget().os.tag) {
6825 .vulkan, .opengl => {
6826 // Logical addressing forbids OpBitcast on pointers. Load the
6827 // payload as its type and bitcast the value instead.
6828 const payload_id = try cg.load(layout.payload_ty, pl_ptr_id, .{});
6829 return try cg.bitCast(field_ty, layout.payload_ty, payload_id);
6830 },
6831 else => {},
6811 if (target_util.addrSpaceIsLogical(zcu.getTarget(), .local)) {
6812 // Logical addressing forbids OpBitcast on pointers. Load the
6813 // payload as its type and bitcast the value instead.
6814 const payload_id = try cg.load(layout.payload_ty, pl_ptr_id, .{});
6815 return try cg.bitCast(field_ty, layout.payload_ty, payload_id);
68326816 }
68336817
68346818 const field_ty_id = try cg.resolveType(field_ty, .indirect);
......@@ -6871,13 +6855,11 @@ fn airFieldParentPtr(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
68716855 break :base_ptr_int try result.materialize(cg);
68726856 };
68736857
6874 if (target.os.tag != .opencl) {
6875 if (field_ptr_ty.ptrAddressSpace(zcu) != .physical_storage_buffer) {
6876 return cg.fail(
6877 "cannot cast integer to pointer with address space '{s}'",
6878 .{@tagName(field_ptr_ty.ptrAddressSpace(zcu))},
6879 );
6880 }
6858 if (target_util.addrSpaceIsLogical(target, field_ptr_ty.ptrAddressSpace(zcu))) {
6859 return cg.fail(
6860 "cannot cast integer to pointer with address space '{s}'",
6861 .{@tagName(field_ptr_ty.ptrAddressSpace(zcu))},
6862 );
68816863 }
68826864
68836865 const base_ptr = cg.allocId();
......@@ -6892,7 +6874,7 @@ fn airFieldParentPtr(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
68926874
68936875fn structFieldPtr(
68946876 cg: *CodeGen,
6895 @"addrspace": std.lang.AddressSpace,
6877 as: std.lang.AddressSpace,
68966878 result_ptr_ty_id: Id,
68976879 field_ty: Type,
68986880 object_ty: Type,
......@@ -6926,21 +6908,18 @@ fn structFieldPtr(
69266908 return try cg.constUndef(result_ptr_ty_id);
69276909 }
69286910
6929 const storage_class = cg.storageClass(@"addrspace");
6911 const storage_class = cg.storageClass(as);
69306912 if (field_ty.toIntern() == layout.payload_ty.toIntern()) {
69316913 if (object_ty.containerLayout(zcu) == .@"packed") return object_ptr;
69326914 return try cg.accessChain(result_ptr_ty_id, object_ptr, &.{layout.payload_index});
69336915 }
69346916
6935 switch (zcu.getTarget().os.tag) {
6936 .vulkan, .opengl => {
6937 // Logical addressing forbids OpBitcast on pointers. If the field
6938 // type is structurally identical to the payload type (dedup will
6939 // unify them) the access chain typed as the field type is valid.
6940 if (object_ty.containerLayout(zcu) == .@"packed") return object_ptr;
6941 return try cg.accessChain(result_ptr_ty_id, object_ptr, &.{layout.payload_index});
6942 },
6943 else => {},
6917 if (target_util.addrSpaceIsLogical(zcu.getTarget(), as)) {
6918 // Logical addressing forbids OpBitcast on pointers. If the field
6919 // type is structurally identical to the payload type (dedup will
6920 // unify them) the access chain typed as the field type is valid.
6921 if (object_ty.containerLayout(zcu) == .@"packed") return object_ptr;
6922 return try cg.accessChain(result_ptr_ty_id, object_ptr, &.{layout.payload_index});
69446923 }
69456924
69466925 const layout_payload_ty_id = try cg.resolveType(layout.payload_ty, .indirect);
......@@ -7039,18 +7018,13 @@ fn airAlloc(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
70397018 const ptr_ty = cg.typeOfIndex(inst);
70407019 const child_ty = ptr_ty.childType(zcu);
70417020
7042 switch (target.os.tag) {
7043 .vulkan, .opengl => {
7044 if (child_ty.zigTypeTag(zcu) == .pointer and !child_ty.isSlice(zcu)) {
7045 const as = child_ty.ptrAddressSpace(zcu);
7046 if (cg.storageClass(as) == .function) {
7047 const result_id = cg.allocId();
7048 try cg.tracked_allocas.put(cg.gpa, result_id, null);
7049 return result_id;
7050 }
7051 }
7052 },
7053 else => {},
7021 if (child_ty.zigTypeTag(zcu) == .pointer and !child_ty.isSlice(zcu)) {
7022 const as = child_ty.ptrAddressSpace(zcu);
7023 if (target_util.addrSpaceIsLogical(target, as) and cg.storageClass(as) == .function) {
7024 const result_id = cg.allocId();
7025 try cg.tracked_allocas.put(cg.gpa, result_id, null);
7026 return result_id;
7027 }
70547028 }
70557029
70567030 const child_ty_id = try cg.resolveType(child_ty, .indirect);
......@@ -8790,6 +8764,7 @@ const log = std.log.scoped(.codegen);
87908764const builtin = @import("builtin");
87918765const link = @import("../../link.zig");
87928766const codegen = @import("../../codegen.zig");
8767const target_util = @import("../../target.zig");
87938768const Zcu = @import("../../Zcu.zig");
87948769const Type = @import("../../Type.zig");
87958770const Value = @import("../../Value.zig");
src/target.zig+22-32
......@@ -635,38 +635,28 @@ pub fn addrSpaceCastIsValid(
635635 }
636636}
637637
638/// Returns whether pointer operations (arithmetic, indexing, etc.) should be blocked
639/// for the given address space on the target architecture.
640///
641/// Under SPIR-V with Vulkan
642/// (a) all physical pointers (.physical_storage_buffer, .global) always support pointer operations,
643/// (b) by default logical pointers (.constant, .input, .output, etc.) never support operations
644/// (c) some logical pointers (.storage_buffer, .shared) do support operations when
645/// the VariablePointers capability is enabled (which enables OpPtrAccessChain).
646pub fn shouldBlockPointerOps(target: *const std.Target, as: AddressSpace) bool {
647 if (target.os.tag != .vulkan and target.os.tag != .opengl) return false;
648
649 return switch (as) {
650 // TODO: Vulkan doesn't support pointers in the generic address space, we
651 // should remove this case but this requires a change in defaultAddressSpace().
652 .generic => true,
653 // For now, all global pointers are represented using StorageBuffer or CrossWorkgroup,
654 // so these are real pointers.
655 // Physical pointers always support operations
656 .global, .physical_storage_buffer => false,
657 // Logical pointers that support operations with VariablePointers capability
658 .shared => !target.cpu.features.isEnabled(@backingInt(std.Target.spirv.Feature.variable_pointers)),
659 .storage_buffer => !target.cpu.features.isEnabled(@backingInt(std.Target.spirv.Feature.variable_pointers)),
660 // Logical pointers that never support operations
661 .constant,
662 .local,
663 .private,
664 .input,
665 .output,
666 .uniform,
667 .push_constant,
668 => true,
669 else => unreachable,
638/// Returns true if the given address space memory model is logical (i.e. arithmetic pointer
639/// operations are illegal).
640pub fn addrSpaceIsLogical(target: *const std.Target, as: AddressSpace) bool {
641 const features = &target.cpu.features;
642 return switch (target.os.tag) {
643 .vulkan, .opengl => switch (as) {
644 .generic,
645 .constant,
646 .local,
647 .private,
648 .input,
649 .output,
650 .uniform,
651 .push_constant,
652 => true,
653 .shared => !features.isEnabled(@backingInt(std.Target.spirv.Feature.variable_pointers)),
654 .storage_buffer => !features.isEnabled(@backingInt(std.Target.spirv.Feature.variable_pointers)) and
655 !features.isEnabled(@backingInt(std.Target.spirv.Feature.variable_pointers_storage_buffer)),
656 .physical_storage_buffer => false,
657 else => unreachable,
658 },
659 else => false,
670660 };
671661}
672662
test/behavior/abs.zig+1
......@@ -203,6 +203,7 @@ fn testAbsUnsignedBigInt() !void {
203203test "@abs floats" {
204204 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
205205 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
206 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // Fails on lavapipe
206207
207208 try comptime testAbsFloats(f16);
208209 if (builtin.zig_backend != .stage2_riscv64) try testAbsFloats(f16);
test/behavior/bitcast.zig+2
......@@ -107,6 +107,7 @@ test "bitcast generates a temporary value" {
107107}
108108
109109test "@bitCast packed structs at runtime and comptime" {
110 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
110111 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
111112 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
112113 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
......@@ -134,6 +135,7 @@ test "@bitCast packed structs at runtime and comptime" {
134135}
135136
136137test "bitcast packed struct to integer and back" {
138 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
137139 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
138140 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
139141 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
test/behavior/cast.zig+3-1
......@@ -273,6 +273,7 @@ test "type coercion from int to float" {
273273}
274274
275275test "@intFromFloat" {
276 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
276277 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
277278 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
278279
......@@ -299,7 +300,6 @@ fn testIntFromFloats() !void {
299300
300301 try expectRoundCast(f32, -128.2, i8, -128);
301302 try expectCeilCast(f32, -128.2, i8, -128);
302 try expectTruncCast(f32, -128.2, i8, -128);
303303}
304304
305305test "rounding builtins with anytype and context propagation" {
......@@ -3077,6 +3077,7 @@ test "peer type resolution: slice of sentinel-terminated array" {
30773077
30783078test "@intFromFloat boundary cases" {
30793079 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
3080 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
30803081
30813082 const S = struct {
30823083 fn case(comptime I: type, x: f32, bump: enum { up, down }, expected: I) !void {
......@@ -3107,6 +3108,7 @@ test "@intFromFloat boundary cases" {
31073108}
31083109
31093110test "@intFromFloat vector boundary cases" {
3111 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
31103112 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
31113113 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
31123114
test/behavior/enum.zig+1
......@@ -1217,6 +1217,7 @@ const bit_field_1 = BitFieldOfEnums{
12171217};
12181218
12191219test "bit field access with enum fields" {
1220 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
12201221 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
12211222 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
12221223 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
test/behavior/floatop.zig+4
......@@ -137,6 +137,7 @@ test "cmp f64" {
137137 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
138138 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isAarch64() and builtin.os.tag == .netbsd) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/36765
139139 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isAarch64() and builtin.os.tag == .netbsd) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/36765
140 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // Fails on lavapipe
140141
141142 try testCmp(f64);
142143 try comptime testCmp(f64);
......@@ -247,6 +248,7 @@ test "vector cmp f64" {
247248 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isAarch64() and builtin.os.tag == .netbsd) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/36765
248249 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isAarch64() and builtin.os.tag == .netbsd) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/36765
249250 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .hexagon) return error.SkipZigTest;
251 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // Fails on lavapipe
250252
251253 try testCmpVector(f64);
252254 try comptime testCmpVector(f64);
......@@ -1024,6 +1026,7 @@ test "@abs f16" {
10241026 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
10251027 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
10261028 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1029 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // Fails on lavapipe
10271030
10281031 try testFabs(f16);
10291032 try comptime testFabs(f16);
......@@ -1032,6 +1035,7 @@ test "@abs f16" {
10321035test "@abs f32/f64" {
10331036 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
10341037 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1038 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // Fails on lavapipe
10351039
10361040 try testFabs(f32);
10371041 try comptime testFabs(f32);
test/behavior/math.zig+1
......@@ -2613,6 +2613,7 @@ test "float vector multiplication of comptime zero by runtime nan is nan" {
26132613 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
26142614 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
26152615 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
2616 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // Fails on lavapipe
26162617
26172618 const ct_zero: @Vector(1, f32) = .{0};
26182619 var rt_nan: @Vector(1, f32) = .{math.nan(f32)};
test/behavior/maximum_minimum.zig+1
......@@ -62,6 +62,7 @@ test "@min" {
6262 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
6363 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
6464 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
65 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // Fails on lavapipe
6566
6667 const S = struct {
6768 fn doTheTest() !void {
test/behavior/memcpy.zig+2
......@@ -182,6 +182,8 @@ test "@memcpy no sentinel source into sentinel destination" {
182182}
183183
184184test "@memcpy a global array" {
185 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
186
185187 const S = struct {
186188 var array_u8: [1]u8 = .{1};
187189 const slice_u8: []u8 = &array_u8;
test/behavior/memmove.zig+2
......@@ -172,6 +172,8 @@ comptime {
172172}
173173
174174test "@memmove a global array" {
175 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
176
175177 const S = struct {
176178 var array_u8: [1]u8 = .{1};
177179 const slice_u8: []u8 = &array_u8;
test/behavior/packed-struct.zig+10
......@@ -225,6 +225,7 @@ test "nested packed structs" {
225225}
226226
227227test "regular in irregular packed struct" {
228 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
228229 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
229230 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
230231 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
......@@ -792,6 +793,7 @@ test "nested packed struct at non-zero offset 2" {
792793}
793794
794795test "runtime init of unnamed packed struct type" {
796 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
795797 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
796798 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
797799
......@@ -885,6 +887,7 @@ test "pointer to container level packed struct field" {
885887}
886888
887889test "store undefined to packed result location" {
890 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
888891 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
889892 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
890893 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
......@@ -907,6 +910,7 @@ test "bitcast back and forth" {
907910
908911// Originally reported at https://github.com/ziglang/zig/issues/14200
909912test "field access of packed struct smaller than its abi size inside struct initialized with rls" {
913 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
910914 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
911915 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
912916
......@@ -1001,6 +1005,7 @@ test "packed struct acts as a namespace" {
10011005}
10021006
10031007test "assignment to non-byte-aligned field in packed struct" {
1008 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
10041009 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
10051010 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
10061011 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
......@@ -1039,6 +1044,7 @@ test "packed struct field pointer aligned properly" {
10391044}
10401045
10411046test "load flag from packed struct in union" {
1047 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
10421048 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
10431049 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
10441050 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
......@@ -1162,6 +1168,7 @@ test "packed struct equality" {
11621168}
11631169
11641170test "packed struct equality ignores padding bits" {
1171 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
11651172 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
11661173
11671174 const S = packed struct { b: bool };
......@@ -1172,6 +1179,7 @@ test "packed struct equality ignores padding bits" {
11721179}
11731180
11741181test "packed struct with signed field" {
1182 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
11751183 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
11761184
11771185 var s: packed struct {
......@@ -1184,6 +1192,7 @@ test "packed struct with signed field" {
11841192}
11851193
11861194test "assign packed struct initialized with RLS to packed struct literal field" {
1195 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
11871196 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
11881197 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
11891198
......@@ -1200,6 +1209,7 @@ test "assign packed struct initialized with RLS to packed struct literal field"
12001209}
12011210
12021211test "packed struct store of comparison result" {
1212 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
12031213 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
12041214 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
12051215
test/behavior/struct.zig+6
......@@ -376,6 +376,7 @@ const APackedStruct = packed struct {
376376};
377377
378378test "packed struct" {
379 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
379380 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
380381 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
381382 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
......@@ -502,6 +503,7 @@ test "packed struct fields are ordered from LSB to MSB" {
502503}
503504
504505test "implicit cast packed struct field to const ptr" {
506 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
505507 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
506508 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
507509 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
......@@ -564,6 +566,7 @@ const bit_field_1 = BitField1{
564566};
565567
566568test "bit field access" {
569 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
567570 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
568571 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
569572 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
......@@ -686,6 +689,7 @@ const FooArrayOfAligned = packed struct {
686689};
687690
688691test "pointer to packed struct member in a stack variable" {
692 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
689693 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
690694 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
691695 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
......@@ -815,6 +819,7 @@ test "non-packed struct with u128 entry in union" {
815819}
816820
817821test "packed struct field passed to generic function" {
822 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
818823 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
819824 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
820825 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
......@@ -1197,6 +1202,7 @@ test "packed struct aggregate init" {
11971202}
11981203
11991204test "packed struct field access via pointer" {
1205 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
12001206 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
12011207 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
12021208 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
test/behavior/switch.zig+2
......@@ -1671,6 +1671,8 @@ test "union field pointer capture preserves alignment in inline prong" {
16711671}
16721672
16731673test "switch on expression" {
1674 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1675
16741676 var a: []const []const u8 = &.{ "b", "b", "A", "A", "b" };
16751677 _ = &a;
16761678 var c: isize = 0;
test/cases/compile_errors/spirv_slices.zig+2-4
......@@ -19,7 +19,5 @@ export fn b() void {
1919// target=spirv32-opengl,spirv32-vulkan
2020// cpu_features=baseline+variable_pointers
2121//
22// :3:16: error: cannot construct slice from address space 'generic'
23// :3:16: note: only 'shared' and 'storage_buffer' address spaces support slicing on SPIR-V
24// :14:11: error: cannot construct slice from address space 'generic'
25// :14:11: note: only 'shared' and 'storage_buffer' address spaces support slicing on SPIR-V
22// :3:16: error: cannot construct slice from logical address space 'generic'
23// :14:11: error: cannot construct slice from logical address space 'generic'
test/cases/spirv_mergable_pointers.zig+3-3
......@@ -1,7 +1,7 @@
11export fn a() void {
2 var x: *addrspace(.global) i32 = undefined;
2 var x: *addrspace(.physical_storage_buffer) i32 = undefined;
33 _ = &x;
4 var y: *addrspace(.global) i32 = undefined;
4 var y: *addrspace(.physical_storage_buffer) i32 = undefined;
55 _ = &y;
66 var rt_cond = false;
77 _ = &rt_cond;
......@@ -13,5 +13,5 @@ export fn a() void {
1313// compile
1414// output_mode=Obj
1515// backend=selfhosted
16// target=spirv32-vulkan
16// target=spirv64-vulkan
1717// emit_bin=true