authorgravatar for robin@voetter.nlRobin Voetter <robin@voetter.nl> 2025-03-18 22:31:57+01:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2025-03-18 22:31:57+01:00
log5105c3c7fa46969dc731b7447415436fd7572e87
treef3bdcc2b4f9193476cfc738a25b6d8869908999a
parent074dd4d083b8ddefc370425568b61c890efe905d
parentee06b2ce760d927b62726de1e2e3cb33b48d4932
signaturebadge-check Signed by PGP key B5690EEEBB952194

Merge pull request #23158 from alichraghi/ali_spirv

spirv: miscellaneous stuff #2

22 files changed, 407 insertions(+), 186 deletions(-)

lib/std/Target/spirv.zig+19-19
...@@ -10,18 +10,18 @@ pub const Feature = enum {...@@ -10,18 +10,18 @@ pub const Feature = enum {
10 v1_4,10 v1_4,
11 v1_5,11 v1_5,
12 v1_6,12 v1_6,
13 int8,
14 int16,
15 int64,13 int64,
16 float16,14 float16,
17 float64,15 float64,
18 addresses,
19 matrix,16 matrix,
20 storage_push_constant16,17 storage_push_constant16,
18 arbitrary_precision_integers,
21 kernel,19 kernel,
20 addresses,
22 generic_pointer,21 generic_pointer,
23 vector16,22 vector16,
24 shader,23 shader,
24 physical_storage_buffer,
25};25};
2626
27pub const featureSet = CpuFeature.FeatureSetFns(Feature).featureSet;27pub const featureSet = CpuFeature.FeatureSetFns(Feature).featureSet;
...@@ -69,16 +69,6 @@ pub const all_features = blk: {...@@ -69,16 +69,6 @@ pub const all_features = blk: {
69 .description = "Enable version 1.6",69 .description = "Enable version 1.6",
70 .dependencies = featureSet(&[_]Feature{.v1_5}),70 .dependencies = featureSet(&[_]Feature{.v1_5}),
71 };71 };
72 result[@intFromEnum(Feature.int8)] = .{
73 .llvm_name = null,
74 .description = "Enable Int8 capability",
75 .dependencies = featureSet(&[_]Feature{.v1_0}),
76 };
77 result[@intFromEnum(Feature.int16)] = .{
78 .llvm_name = null,
79 .description = "Enable Int16 capability",
80 .dependencies = featureSet(&[_]Feature{.v1_0}),
81 };
82 result[@intFromEnum(Feature.int64)] = .{72 result[@intFromEnum(Feature.int64)] = .{
83 .llvm_name = null,73 .llvm_name = null,
84 .description = "Enable Int64 capability",74 .description = "Enable Int64 capability",
...@@ -94,11 +84,6 @@ pub const all_features = blk: {...@@ -94,11 +84,6 @@ pub const all_features = blk: {
94 .description = "Enable Float64 capability",84 .description = "Enable Float64 capability",
95 .dependencies = featureSet(&[_]Feature{.v1_0}),85 .dependencies = featureSet(&[_]Feature{.v1_0}),
96 };86 };
97 result[@intFromEnum(Feature.addresses)] = .{
98 .llvm_name = null,
99 .description = "Enable either the Addresses capability or, SPV_KHR_physical_storage_buffer extension and the PhysicalStorageBufferAddresses capability",
100 .dependencies = featureSet(&[_]Feature{.v1_0}),
101 };
102 result[@intFromEnum(Feature.matrix)] = .{87 result[@intFromEnum(Feature.matrix)] = .{
103 .llvm_name = null,88 .llvm_name = null,
104 .description = "Enable Matrix capability",89 .description = "Enable Matrix capability",
...@@ -109,11 +94,21 @@ pub const all_features = blk: {...@@ -109,11 +94,21 @@ pub const all_features = blk: {
109 .description = "Enable SPV_KHR_16bit_storage extension and the StoragePushConstant16 capability",94 .description = "Enable SPV_KHR_16bit_storage extension and the StoragePushConstant16 capability",
110 .dependencies = featureSet(&[_]Feature{.v1_3}),95 .dependencies = featureSet(&[_]Feature{.v1_3}),
111 };96 };
97 result[@intFromEnum(Feature.arbitrary_precision_integers)] = .{
98 .llvm_name = null,
99 .description = "Enable SPV_INTEL_arbitrary_precision_integers extension and the ArbitraryPrecisionIntegersINTEL capability",
100 .dependencies = featureSet(&[_]Feature{.v1_5}),
101 };
112 result[@intFromEnum(Feature.kernel)] = .{102 result[@intFromEnum(Feature.kernel)] = .{
113 .llvm_name = null,103 .llvm_name = null,
114 .description = "Enable Kernel capability",104 .description = "Enable Kernel capability",
115 .dependencies = featureSet(&[_]Feature{.v1_0}),105 .dependencies = featureSet(&[_]Feature{.v1_0}),
116 };106 };
107 result[@intFromEnum(Feature.addresses)] = .{
108 .llvm_name = null,
109 .description = "Enable Addresses capability",
110 .dependencies = featureSet(&[_]Feature{.v1_0}),
111 };
117 result[@intFromEnum(Feature.generic_pointer)] = .{112 result[@intFromEnum(Feature.generic_pointer)] = .{
118 .llvm_name = null,113 .llvm_name = null,
119 .description = "Enable GenericPointer capability",114 .description = "Enable GenericPointer capability",
...@@ -129,6 +124,11 @@ pub const all_features = blk: {...@@ -129,6 +124,11 @@ pub const all_features = blk: {
129 .description = "Enable Shader capability",124 .description = "Enable Shader capability",
130 .dependencies = featureSet(&[_]Feature{ .v1_0, .matrix }),125 .dependencies = featureSet(&[_]Feature{ .v1_0, .matrix }),
131 };126 };
127 result[@intFromEnum(Feature.physical_storage_buffer)] = .{
128 .llvm_name = null,
129 .description = "Enable SPV_KHR_physical_storage_buffer extension and the PhysicalStorageBufferAddresses capability",
130 .dependencies = featureSet(&[_]Feature{.v1_0}),
131 };
132 const ti = @typeInfo(Feature);132 const ti = @typeInfo(Feature);
133 for (&result, 0..) |*elem, i| {133 for (&result, 0..) |*elem, i| {
134 elem.index = i;134 elem.index = i;
...@@ -147,7 +147,7 @@ pub const cpu = struct {...@@ -147,7 +147,7 @@ pub const cpu = struct {
147 pub const vulkan_v1_2: CpuModel = .{147 pub const vulkan_v1_2: CpuModel = .{
148 .name = "vulkan_v1_2",148 .name = "vulkan_v1_2",
149 .llvm_name = null,149 .llvm_name = null,
150 .features = featureSet(&[_]Feature{ .v1_5, .shader, .addresses }),150 .features = featureSet(&[_]Feature{ .v1_5, .shader, .physical_storage_buffer }),
151 };151 };
152152
153 pub const opencl_v2: CpuModel = .{153 pub const opencl_v2: CpuModel = .{
lib/std/gpu.zig+10-5
...@@ -80,7 +80,8 @@ pub fn fragmentDepth(comptime ptr: *addrspace(.output) f32) void {...@@ -80,7 +80,8 @@ pub fn fragmentDepth(comptime ptr: *addrspace(.output) f32) void {
80/// Forms the main linkage for `input` and `output` address spaces.80/// Forms the main linkage for `input` and `output` address spaces.
81/// `ptr` must be a reference to variable or struct field.81/// `ptr` must be a reference to variable or struct field.
82pub fn location(comptime ptr: anytype, comptime loc: u32) void {82pub fn location(comptime ptr: anytype, comptime loc: u32) void {
83 asm volatile ("OpDecorate %ptr Location $loc"83 asm volatile (
84 \\OpDecorate %ptr Location $loc
84 :85 :
85 : [ptr] "" (ptr),86 : [ptr] "" (ptr),
86 [loc] "c" (loc),87 [loc] "c" (loc),
...@@ -110,7 +111,8 @@ pub const Origin = enum(u32) {...@@ -110,7 +111,8 @@ pub const Origin = enum(u32) {
110/// The coordinates appear to originate in the specified `origin`.111/// The coordinates appear to originate in the specified `origin`.
111/// Only valid with the `Fragment` calling convention.112/// Only valid with the `Fragment` calling convention.
112pub fn fragmentOrigin(comptime entry_point: anytype, comptime origin: Origin) void {113pub fn fragmentOrigin(comptime entry_point: anytype, comptime origin: Origin) void {
113 asm volatile ("OpExecutionMode %entry_point $origin"114 asm volatile (
115 \\OpExecutionMode %entry_point $origin
114 :116 :
115 : [entry_point] "" (entry_point),117 : [entry_point] "" (entry_point),
116 [origin] "c" (@intFromEnum(origin)),118 [origin] "c" (@intFromEnum(origin)),
...@@ -137,7 +139,8 @@ pub const DepthMode = enum(u32) {...@@ -137,7 +139,8 @@ pub const DepthMode = enum(u32) {
137139
138/// Only valid with the `Fragment` calling convention.140/// Only valid with the `Fragment` calling convention.
139pub fn depthMode(comptime entry_point: anytype, comptime mode: DepthMode) void {141pub fn depthMode(comptime entry_point: anytype, comptime mode: DepthMode) void {
140 asm volatile ("OpExecutionMode %entry_point $mode"142 asm volatile (
143 \\OpExecutionMode %entry_point $mode
141 :144 :
142 : [entry_point] "" (entry_point),145 : [entry_point] "" (entry_point),
143 [mode] "c" (mode),146 [mode] "c" (mode),
...@@ -147,7 +150,8 @@ pub fn depthMode(comptime entry_point: anytype, comptime mode: DepthMode) void {...@@ -147,7 +150,8 @@ pub fn depthMode(comptime entry_point: anytype, comptime mode: DepthMode) void {
147/// Indicates the workgroup size in the `x`, `y`, and `z` dimensions.150/// Indicates the workgroup size in the `x`, `y`, and `z` dimensions.
148/// Only valid with the `GLCompute` or `Kernel` calling conventions.151/// Only valid with the `GLCompute` or `Kernel` calling conventions.
149pub fn workgroupSize(comptime entry_point: anytype, comptime size: @Vector(3, u32)) void {152pub fn workgroupSize(comptime entry_point: anytype, comptime size: @Vector(3, u32)) void {
150 asm volatile ("OpExecutionMode %entry_point LocalSize %x %y %z"153 asm volatile (
154 \\OpExecutionMode %entry_point LocalSize %x %y %z
151 :155 :
152 : [entry_point] "" (entry_point),156 : [entry_point] "" (entry_point),
153 [x] "c" (size[0]),157 [x] "c" (size[0]),
...@@ -159,7 +163,8 @@ pub fn workgroupSize(comptime entry_point: anytype, comptime size: @Vector(3, u3...@@ -159,7 +163,8 @@ pub fn workgroupSize(comptime entry_point: anytype, comptime size: @Vector(3, u3
159/// A hint to the client, which indicates the workgroup size in the `x`, `y`, and `z` dimensions.163/// A hint to the client, which indicates the workgroup size in the `x`, `y`, and `z` dimensions.
160/// Only valid with the `GLCompute` or `Kernel` calling conventions.164/// Only valid with the `GLCompute` or `Kernel` calling conventions.
161pub fn workgroupSizeHint(comptime entry_point: anytype, comptime size: @Vector(3, u32)) void {165pub fn workgroupSizeHint(comptime entry_point: anytype, comptime size: @Vector(3, u32)) void {
162 asm volatile ("OpExecutionMode %entry_point LocalSizeHint %x %y %z"166 asm volatile (
167 \\OpExecutionMode %entry_point LocalSizeHint %x %y %z
163 :168 :
164 : [entry_point] "" (entry_point),169 : [entry_point] "" (entry_point),
165 [x] "c" (size[0]),170 [x] "c" (size[0]),
src/Sema.zig+53-24
...@@ -3648,7 +3648,7 @@ fn indexablePtrLen(...@@ -3648,7 +3648,7 @@ fn indexablePtrLen(
3648 const object_ty = sema.typeOf(object);3648 const object_ty = sema.typeOf(object);
3649 const is_pointer_to = object_ty.isSinglePointer(zcu);3649 const is_pointer_to = object_ty.isSinglePointer(zcu);
3650 const indexable_ty = if (is_pointer_to) object_ty.childType(zcu) else object_ty;3650 const indexable_ty = if (is_pointer_to) object_ty.childType(zcu) else object_ty;
3651 try checkIndexable(sema, block, src, indexable_ty);3651 try sema.checkIndexable(block, src, indexable_ty);
3652 const field_name = try zcu.intern_pool.getOrPutString(sema.gpa, pt.tid, "len", .no_embedded_nulls);3652 const field_name = try zcu.intern_pool.getOrPutString(sema.gpa, pt.tid, "len", .no_embedded_nulls);
3653 return sema.fieldVal(block, src, object, field_name, src);3653 return sema.fieldVal(block, src, object, field_name, src);
3654}3654}
...@@ -10103,6 +10103,7 @@ fn zirIntFromPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!...@@ -10103,6 +10103,7 @@ fn zirIntFromPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
10103 }10103 }
10104 try sema.requireRuntimeBlock(block, block.nodeOffset(inst_data.src_node), ptr_src);10104 try sema.requireRuntimeBlock(block, block.nodeOffset(inst_data.src_node), ptr_src);
10105 try sema.validateRuntimeValue(block, ptr_src, operand);10105 try sema.validateRuntimeValue(block, ptr_src, operand);
10106 try sema.checkLogicalPtrOperation(block, ptr_src, ptr_ty);
10106 if (!is_vector or zcu.backendSupportsFeature(.all_vector_instructions)) {10107 if (!is_vector or zcu.backendSupportsFeature(.all_vector_instructions)) {
10107 return block.addBitCast(dest_ty, operand);10108 return block.addBitCast(dest_ty, operand);
10108 }10109 }
...@@ -16389,6 +16390,8 @@ fn analyzeArithmetic(...@@ -16389,6 +16390,8 @@ fn analyzeArithmetic(
16389 };16390 };
1639016391
16391 try sema.requireRuntimeBlock(block, src, runtime_src);16392 try sema.requireRuntimeBlock(block, src, runtime_src);
16393 try sema.checkLogicalPtrOperation(block, src, lhs_ty);
16394 try sema.checkLogicalPtrOperation(block, src, rhs_ty);
16392 const lhs_int = try block.addBitCast(.usize, lhs);16395 const lhs_int = try block.addBitCast(.usize, lhs);
16393 const rhs_int = try block.addBitCast(.usize, rhs);16396 const rhs_int = try block.addBitCast(.usize, rhs);
16394 const address = try block.addBinOp(.sub_wrap, lhs_int, rhs_int);16397 const address = try block.addBinOp(.sub_wrap, lhs_int, rhs_int);
...@@ -16620,24 +16623,7 @@ fn analyzePtrArithmetic(...@@ -16620,24 +16623,7 @@ fn analyzePtrArithmetic(
16620 };16623 };
1662116624
16622 try sema.requireRuntimeBlock(block, op_src, runtime_src);16625 try sema.requireRuntimeBlock(block, op_src, runtime_src);
1662316626 try sema.checkLogicalPtrOperation(block, op_src, ptr_ty);
16624 const target = zcu.getTarget();
16625 if (target_util.arePointersLogical(target, ptr_info.flags.address_space)) {
16626 return sema.failWithOwnedErrorMsg(block, msg: {
16627 const msg = try sema.errMsg(op_src, "illegal pointer arithmetic on pointer of type '{}'", .{ptr_ty.fmt(pt)});
16628 errdefer msg.destroy(sema.gpa);
16629
16630 const backend = target_util.zigBackend(target, zcu.comp.config.use_llvm);
16631 try sema.errNote(op_src, msg, "arithmetic cannot be performed on pointers with address space '{s}' on target {s}-{s} by compiler backend {s}", .{
16632 @tagName(ptr_info.flags.address_space),
16633 target.cpu.arch.genericName(),
16634 @tagName(target.os.tag),
16635 @tagName(backend),
16636 });
16637
16638 break :msg msg;
16639 });
16640 }
1664116627
16642 return block.addInst(.{16628 return block.addInst(.{
16643 .tag = air_tag,16629 .tag = air_tag,
...@@ -22501,6 +22487,7 @@ fn zirPtrFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!...@@ -22501,6 +22487,7 @@ fn zirPtrFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
22501 });22487 });
22502 }22488 }
22503 try sema.requireRuntimeBlock(block, src, operand_src);22489 try sema.requireRuntimeBlock(block, src, operand_src);
22490 try sema.checkLogicalPtrOperation(block, src, ptr_ty);
22504 if (!is_vector or zcu.backendSupportsFeature(.all_vector_instructions)) {22491 if (!is_vector or zcu.backendSupportsFeature(.all_vector_instructions)) {
22505 if (block.wantSafety() and (try elem_ty.hasRuntimeBitsSema(pt) or elem_ty.zigTypeTag(zcu) == .@"fn")) {22492 if (block.wantSafety() and (try elem_ty.hasRuntimeBitsSema(pt) or elem_ty.zigTypeTag(zcu) == .@"fn")) {
22506 if (!ptr_ty.isAllowzeroPtr(zcu)) {22493 if (!ptr_ty.isAllowzeroPtr(zcu)) {
...@@ -23165,8 +23152,9 @@ fn ptrCastFull(...@@ -23165,8 +23152,9 @@ fn ptrCastFull(
2316523152
23166 try sema.validateRuntimeValue(block, operand_src, operand);23153 try sema.validateRuntimeValue(block, operand_src, operand);
2316723154
23168 const need_null_check = block.wantSafety() and operand_ty.ptrAllowsZero(zcu) and !dest_ty.ptrAllowsZero(zcu);23155 const can_cast_to_int = !target_util.arePointersLogical(zcu.getTarget(), operand_ty.ptrAddressSpace(zcu));
23169 const need_align_check = block.wantSafety() and dest_align.compare(.gt, src_align);23156 const need_null_check = can_cast_to_int and block.wantSafety() and operand_ty.ptrAllowsZero(zcu) and !dest_ty.ptrAllowsZero(zcu);
23157 const need_align_check = can_cast_to_int and block.wantSafety() and dest_align.compare(.gt, src_align);
2317023158
23171 // `operand` might be a slice. If `need_operand_ptr`, we'll populate `operand_ptr` with the raw pointer.23159 // `operand` might be a slice. If `need_operand_ptr`, we'll populate `operand_ptr` with the raw pointer.
23172 const need_operand_ptr = src_info.flags.size != .slice or // we already have it23160 const need_operand_ptr = src_info.flags.size != .slice or // we already have it
...@@ -23832,6 +23820,32 @@ fn checkPtrType(...@@ -23832,6 +23820,32 @@ fn checkPtrType(
23832 return sema.fail(block, ty_src, "expected pointer type, found '{}'", .{ty.fmt(pt)});23820 return sema.fail(block, ty_src, "expected pointer type, found '{}'", .{ty.fmt(pt)});
23833}23821}
2383423822
23823fn checkLogicalPtrOperation(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void {
23824 const pt = sema.pt;
23825 const zcu = pt.zcu;
23826 if (zcu.intern_pool.indexToKey(ty.toIntern()) == .ptr_type) {
23827 const target = zcu.getTarget();
23828 const as = ty.ptrAddressSpace(zcu);
23829 if (target_util.arePointersLogical(target, as)) {
23830 return sema.failWithOwnedErrorMsg(block, msg: {
23831 const msg = try sema.errMsg(src, "illegal operation on logical pointer of type '{}'", .{ty.fmt(pt)});
23832 errdefer msg.destroy(sema.gpa);
23833 try sema.errNote(
23834 src,
23835 msg,
23836 "cannot perform arithmetic on pointers with address space '{s}' on target {s}-{s}",
23837 .{
23838 @tagName(as),
23839 target.cpu.arch.genericName(),
23840 @tagName(target.os.tag),
23841 },
23842 );
23843 break :msg msg;
23844 });
23845 }
23846 }
23847}
23848
23835fn checkVectorElemType(23849fn checkVectorElemType(
23836 sema: *Sema,23850 sema: *Sema,
23837 block: *Block,23851 block: *Block,
...@@ -28326,7 +28340,7 @@ fn elemPtr(...@@ -28326,7 +28340,7 @@ fn elemPtr(
28326 .pointer => indexable_ptr_ty.childType(zcu),28340 .pointer => indexable_ptr_ty.childType(zcu),
28327 else => return sema.fail(block, indexable_ptr_src, "expected pointer, found '{}'", .{indexable_ptr_ty.fmt(pt)}),28341 else => return sema.fail(block, indexable_ptr_src, "expected pointer, found '{}'", .{indexable_ptr_ty.fmt(pt)}),
28328 };28342 };
28329 try checkIndexable(sema, block, src, indexable_ty);28343 try sema.checkIndexable(block, src, indexable_ty);
2833028344
28331 const elem_ptr = switch (indexable_ty.zigTypeTag(zcu)) {28345 const elem_ptr = switch (indexable_ty.zigTypeTag(zcu)) {
28332 .array, .vector => try sema.elemPtrArray(block, src, indexable_ptr_src, indexable_ptr, elem_index_src, elem_index, init, oob_safety),28346 .array, .vector => try sema.elemPtrArray(block, src, indexable_ptr_src, indexable_ptr, elem_index_src, elem_index, init, oob_safety),
...@@ -28362,7 +28376,7 @@ fn elemPtrOneLayerOnly(...@@ -28362,7 +28376,7 @@ fn elemPtrOneLayerOnly(
28362 const pt = sema.pt;28376 const pt = sema.pt;
28363 const zcu = pt.zcu;28377 const zcu = pt.zcu;
2836428378
28365 try checkIndexable(sema, block, src, indexable_ty);28379 try sema.checkIndexable(block, src, indexable_ty);
2836628380
28367 switch (indexable_ty.ptrSize(zcu)) {28381 switch (indexable_ty.ptrSize(zcu)) {
28368 .slice => return sema.elemPtrSlice(block, src, indexable_src, indexable, elem_index_src, elem_index, oob_safety),28382 .slice => return sema.elemPtrSlice(block, src, indexable_src, indexable, elem_index_src, elem_index, oob_safety),
...@@ -28376,6 +28390,8 @@ fn elemPtrOneLayerOnly(...@@ -28376,6 +28390,8 @@ fn elemPtrOneLayerOnly(
28376 const elem_ptr = try ptr_val.ptrElem(index, pt);28390 const elem_ptr = try ptr_val.ptrElem(index, pt);
28377 return Air.internedToRef(elem_ptr.toIntern());28391 return Air.internedToRef(elem_ptr.toIntern());
28378 }28392 }
28393
28394 try sema.checkLogicalPtrOperation(block, src, indexable_ty);
28379 const result_ty = try indexable_ty.elemPtrType(null, pt);28395 const result_ty = try indexable_ty.elemPtrType(null, pt);
2838028396
28381 return block.addPtrElemPtr(indexable, elem_index, result_ty);28397 return block.addPtrElemPtr(indexable, elem_index, result_ty);
...@@ -28412,7 +28428,7 @@ fn elemVal(...@@ -28412,7 +28428,7 @@ fn elemVal(
28412 const pt = sema.pt;28428 const pt = sema.pt;
28413 const zcu = pt.zcu;28429 const zcu = pt.zcu;
2841428430
28415 try checkIndexable(sema, block, src, indexable_ty);28431 try sema.checkIndexable(block, src, indexable_ty);
2841628432
28417 // TODO in case of a vector of pointers, we need to detect whether the element28433 // TODO in case of a vector of pointers, we need to detect whether the element
28418 // index is a scalar or vector instead of unconditionally casting to usize.28434 // index is a scalar or vector instead of unconditionally casting to usize.
...@@ -28438,6 +28454,7 @@ fn elemVal(...@@ -28438,6 +28454,7 @@ fn elemVal(
28438 return Air.internedToRef((try pt.getCoerced(elem_val, elem_ty)).toIntern());28454 return Air.internedToRef((try pt.getCoerced(elem_val, elem_ty)).toIntern());
28439 }28455 }
2844028456
28457 try sema.checkLogicalPtrOperation(block, src, indexable_ty);
28441 return block.addBinOp(.ptr_elem_val, indexable, elem_index);28458 return block.addBinOp(.ptr_elem_val, indexable, elem_index);
28442 },28459 },
28443 .one => {28460 .one => {
...@@ -28477,6 +28494,9 @@ fn validateRuntimeElemAccess(...@@ -28477,6 +28494,9 @@ fn validateRuntimeElemAccess(
28477 parent_ty: Type,28494 parent_ty: Type,
28478 parent_src: LazySrcLoc,28495 parent_src: LazySrcLoc,
28479) CompileError!void {28496) CompileError!void {
28497 const pt = sema.pt;
28498 const zcu = pt.zcu;
28499
28480 if (try elem_ty.comptimeOnlySema(sema.pt)) {28500 if (try elem_ty.comptimeOnlySema(sema.pt)) {
28481 const msg = msg: {28501 const msg = msg: {
28482 const msg = try sema.errMsg(28502 const msg = try sema.errMsg(
...@@ -28492,6 +28512,14 @@ fn validateRuntimeElemAccess(...@@ -28492,6 +28512,14 @@ fn validateRuntimeElemAccess(
28492 };28512 };
28493 return sema.failWithOwnedErrorMsg(block, msg);28513 return sema.failWithOwnedErrorMsg(block, msg);
28494 }28514 }
28515
28516 if (zcu.intern_pool.indexToKey(parent_ty.toIntern()) == .ptr_type) {
28517 const target = zcu.getTarget();
28518 const as = parent_ty.ptrAddressSpace(zcu);
28519 if (target_util.arePointersLogical(target, as)) {
28520 return sema.fail(block, elem_index_src, "cannot access element of logical pointer '{}'", .{parent_ty.fmt(pt)});
28521 }
28522 }
28495}28523}
2849628524
28497fn tupleFieldPtr(28525fn tupleFieldPtr(
...@@ -31158,6 +31186,7 @@ fn coerceCompatiblePtrs(...@@ -31158,6 +31186,7 @@ fn coerceCompatiblePtrs(
31158 if (block.wantSafety() and inst_allows_zero and !dest_ty.ptrAllowsZero(zcu) and31186 if (block.wantSafety() and inst_allows_zero and !dest_ty.ptrAllowsZero(zcu) and
31159 (try dest_ty.elemType2(zcu).hasRuntimeBitsSema(pt) or dest_ty.elemType2(zcu).zigTypeTag(zcu) == .@"fn"))31187 (try dest_ty.elemType2(zcu).hasRuntimeBitsSema(pt) or dest_ty.elemType2(zcu).zigTypeTag(zcu) == .@"fn"))
31160 {31188 {
31189 try sema.checkLogicalPtrOperation(block, inst_src, inst_ty);
31161 const actual_ptr = if (inst_ty.isSlice(zcu))31190 const actual_ptr = if (inst_ty.isSlice(zcu))
31162 try sema.analyzeSlicePtr(block, inst_src, inst, inst_ty)31191 try sema.analyzeSlicePtr(block, inst_src, inst, inst_ty)
31163 else31192 else
src/codegen/spirv.zig+190-77
...@@ -464,7 +464,7 @@ const NavGen = struct {...@@ -464,7 +464,7 @@ const NavGen = struct {
464464
465 const zcu = self.pt.zcu;465 const zcu = self.pt.zcu;
466 const ty = Type.fromInterned(zcu.intern_pool.typeOf(val));466 const ty = Type.fromInterned(zcu.intern_pool.typeOf(val));
467 const decl_ptr_ty_id = try self.ptrType(ty, .Generic, .indirect);467 const decl_ptr_ty_id = try self.ptrType(ty, self.spvStorageClass(.generic), .indirect);
468468
469 const spv_decl_index = blk: {469 const spv_decl_index = blk: {
470 const entry = try self.object.uav_link.getOrPut(self.object.gpa, .{ val, .Function });470 const entry = try self.object.uav_link.getOrPut(self.object.gpa, .{ val, .Function });
...@@ -581,18 +581,18 @@ const NavGen = struct {...@@ -581,18 +581,18 @@ const NavGen = struct {
581 /// that size. In this case, multiple elements of the largest type should be used.581 /// that size. In this case, multiple elements of the largest type should be used.
582 /// The backing type will be chosen as the smallest supported integer larger or equal to it in number of bits.582 /// The backing type will be chosen as the smallest supported integer larger or equal to it in number of bits.
583 /// The result is valid to be used with OpTypeInt.583 /// The result is valid to be used with OpTypeInt.
584 /// TODO: The extension SPV_INTEL_arbitrary_precision_integers allows any integer size (at least up to 32 bits).
585 /// TODO: This probably needs an ABI-version as well (especially in combination with SPV_INTEL_arbitrary_precision_integers).
586 /// TODO: Should the result of this function be cached?584 /// TODO: Should the result of this function be cached?
587 fn backingIntBits(self: *NavGen, bits: u16) ?u16 {585 fn backingIntBits(self: *NavGen, bits: u16) ?u16 {
588 // The backend will never be asked to compiler a 0-bit integer, so we won't have to handle those in this function.586 // The backend will never be asked to compiler a 0-bit integer, so we won't have to handle those in this function.
589 assert(bits != 0);587 assert(bits != 0);
590588
591 // 8, 16 and 64-bit integers require the Int8, Int16 and Inr64 capabilities respectively.589 if (self.spv.hasFeature(.arbitrary_precision_integers) and bits <= 32) return bits;
590
591 // We require Int8 and Int16 capabilities and benefit Int64 when available.
592 // 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).
593 const ints = [_]struct { bits: u16, feature: ?Target.spirv.Feature }{593 const ints = [_]struct { bits: u16, feature: ?Target.spirv.Feature }{
594 .{ .bits = 8, .feature = .int8 },594 .{ .bits = 8, .feature = null },
595 .{ .bits = 16, .feature = .int16 },595 .{ .bits = 16, .feature = null },
596 .{ .bits = 32, .feature = null },596 .{ .bits = 32, .feature = null },
597 .{ .bits = 64, .feature = .int64 },597 .{ .bits = 64, .feature = .int64 },
598 };598 };
...@@ -714,6 +714,7 @@ const NavGen = struct {...@@ -714,6 +714,7 @@ const NavGen = struct {
714 const int_info = scalar_ty.intInfo(zcu);714 const int_info = scalar_ty.intInfo(zcu);
715 // Use backing bits so that negatives are sign extended715 // Use backing bits so that negatives are sign extended
716 const backing_bits = self.backingIntBits(int_info.bits).?; // Assertion failure means big int716 const backing_bits = self.backingIntBits(int_info.bits).?; // Assertion failure means big int
717 assert(backing_bits != 0); // u0 is comptime
717718
718 const signedness: Signedness = switch (@typeInfo(@TypeOf(value))) {719 const signedness: Signedness = switch (@typeInfo(@TypeOf(value))) {
719 .int => |int| int.signedness,720 .int => |int| int.signedness,
...@@ -721,35 +722,35 @@ const NavGen = struct {...@@ -721,35 +722,35 @@ const NavGen = struct {
721 else => unreachable,722 else => unreachable,
722 };723 };
723724
724 const value64: u64 = switch (signedness) {725 const final_value: spec.LiteralContextDependentNumber = blk: {
725 .signed => @bitCast(@as(i64, @intCast(value))),726 if (self.spv.hasFeature(.kernel)) {
726 .unsigned => @as(u64, @intCast(value)),727 const value64: u64 = switch (signedness) {
727 };728 .signed => @bitCast(@as(i64, @intCast(value))),
729 .unsigned => @as(u64, @intCast(value)),
730 };
728731
729 // Manually truncate the value to the right amount of bits.732 // Manually truncate the value to the right amount of bits.
730 const truncated_value = if (backing_bits == 64)733 const truncated_value = if (backing_bits == 64)
731 value64734 value64
732 else735 else
733 value64 & (@as(u64, 1) << @intCast(backing_bits)) - 1;736 value64 & (@as(u64, 1) << @intCast(backing_bits)) - 1;
734737
735 const result_ty_id = try self.resolveType(scalar_ty, .indirect);738 break :blk switch (backing_bits) {
736 const result_id = self.spv.allocId();739 1...32 => .{ .uint32 = @truncate(truncated_value) },
740 33...64 => .{ .uint64 = truncated_value },
741 else => unreachable, // TODO: Large integer constants
742 };
743 }
737744
738 const section = &self.spv.sections.types_globals_constants;745 break :blk switch (backing_bits) {
739 switch (backing_bits) {746 1...32 => if (signedness == .signed) .{ .int32 = @intCast(value) } else .{ .uint32 = @intCast(value) },
740 0 => unreachable, // u0 is comptime747 33...64 => if (signedness == .signed) .{ .int64 = value } else .{ .uint64 = value },
741 1...32 => try section.emit(self.spv.gpa, .OpConstant, .{748 else => unreachable, // TODO: Large integer constants
742 .id_result_type = result_ty_id,749 };
743 .id_result = result_id,750 };
744 .value = .{ .uint32 = @truncate(truncated_value) },751
745 }),752 const result_ty_id = try self.resolveType(scalar_ty, .indirect);
746 33...64 => try section.emit(self.spv.gpa, .OpConstant, .{753 const result_id = try self.spv.constant(result_ty_id, final_value);
747 .id_result_type = result_ty_id,
748 .id_result = result_id,
749 .value = .{ .uint64 = truncated_value },
750 }),
751 else => unreachable, // TODO: Large integer constants
752 }
753754
754 if (!ty.isVector(zcu)) return result_id;755 if (!ty.isVector(zcu)) return result_id;
755 return self.constructCompositeSplat(ty, result_id);756 return self.constructCompositeSplat(ty, result_id);
...@@ -804,8 +805,6 @@ const NavGen = struct {...@@ -804,8 +805,6 @@ const NavGen = struct {
804 return self.spv.constUndef(result_ty_id);805 return self.spv.constUndef(result_ty_id);
805 }806 }
806807
807 const section = &self.spv.sections.types_globals_constants;
808
809 const cacheable_id = cache: {808 const cacheable_id = cache: {
810 switch (ip.indexToKey(val.toIntern())) {809 switch (ip.indexToKey(val.toIntern())) {
811 .int_type,810 .int_type,
...@@ -860,13 +859,7 @@ const NavGen = struct {...@@ -860,13 +859,7 @@ const NavGen = struct {
860 80, 128 => unreachable, // TODO859 80, 128 => unreachable, // TODO
861 else => unreachable,860 else => unreachable,
862 };861 };
863 const result_id = self.spv.allocId();862 break :cache try self.spv.constant(result_ty_id, lit);
864 try section.emit(self.spv.gpa, .OpConstant, .{
865 .id_result_type = result_ty_id,
866 .id_result = result_id,
867 .value = lit,
868 });
869 break :cache result_id;
870 },863 },
871 .err => |err| {864 .err => |err| {
872 const value = try pt.getErrorValue(err.name);865 const value = try pt.getErrorValue(err.name);
...@@ -989,8 +982,17 @@ const NavGen = struct {...@@ -989,8 +982,17 @@ const NavGen = struct {
989 },982 },
990 .struct_type => {983 .struct_type => {
991 const struct_type = zcu.typeToStruct(ty).?;984 const struct_type = zcu.typeToStruct(ty).?;
985
992 if (struct_type.layout == .@"packed") {986 if (struct_type.layout == .@"packed") {
993 return self.todo("packed struct constants", .{});987 // TODO: composite int
988 // TODO: endianness
989 const bits: u16 = @intCast(ty.bitSize(zcu));
990 const bytes = std.mem.alignForward(u16, self.backingIntBits(bits).?, 8) / 8;
991 var limbs: [8]u8 = undefined;
992 @memset(&limbs, 0);
993 val.writeToPackedMemory(ty, pt, limbs[0..bytes], 0) catch unreachable;
994 const backing_ty = Type.fromInterned(struct_type.backingIntTypeUnordered(ip));
995 return try self.constInt(backing_ty, @as(u64, @bitCast(limbs)));
994 }996 }
995997
996 var types = std.ArrayList(Type).init(self.gpa);998 var types = std.ArrayList(Type).init(self.gpa);
...@@ -1022,6 +1024,11 @@ const NavGen = struct {...@@ -1022,6 +1024,11 @@ const NavGen = struct {
1022 else => unreachable,1024 else => unreachable,
1023 },1025 },
1024 .un => |un| {1026 .un => |un| {
1027 if (un.tag == .none) {
1028 assert(ty.containerLayout(zcu) == .@"packed"); // TODO
1029 const int_ty = try pt.intType(.unsigned, @intCast(ty.bitSize(zcu)));
1030 return try self.constant(int_ty, Value.fromInterned(un.val), .direct);
1031 }
1025 const active_field = ty.unionTagFieldIndex(Value.fromInterned(un.tag), zcu).?;1032 const active_field = ty.unionTagFieldIndex(Value.fromInterned(un.tag), zcu).?;
1026 const union_obj = zcu.typeToUnion(ty).?;1033 const union_obj = zcu.typeToUnion(ty).?;
1027 const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[active_field]);1034 const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[active_field]);
...@@ -1354,7 +1361,7 @@ const NavGen = struct {...@@ -1354,7 +1361,7 @@ const NavGen = struct {
1354 const union_obj = zcu.typeToUnion(ty).?;1361 const union_obj = zcu.typeToUnion(ty).?;
13551362
1356 if (union_obj.flagsUnordered(ip).layout == .@"packed") {1363 if (union_obj.flagsUnordered(ip).layout == .@"packed") {
1357 return self.todo("packed union types", .{});1364 return try self.intType(.unsigned, @intCast(ty.bitSize(zcu)));
1358 }1365 }
13591366
1360 const layout = self.unionLayout(ty);1367 const layout = self.unionLayout(ty);
...@@ -1366,7 +1373,7 @@ const NavGen = struct {...@@ -1366,7 +1373,7 @@ const NavGen = struct {
1366 var member_types: [4]IdRef = undefined;1373 var member_types: [4]IdRef = undefined;
1367 var member_names: [4][]const u8 = undefined;1374 var member_names: [4][]const u8 = undefined;
13681375
1369 const u8_ty_id = try self.resolveType(Type.u8, .direct); // TODO: What if Int8Type is not enabled?1376 const u8_ty_id = try self.resolveType(Type.u8, .direct);
13701377
1371 if (layout.tag_size != 0) {1378 if (layout.tag_size != 0) {
1372 const tag_ty_id = try self.resolveType(Type.fromInterned(union_obj.enum_tag_ty), .indirect);1379 const tag_ty_id = try self.resolveType(Type.fromInterned(union_obj.enum_tag_ty), .indirect);
...@@ -2821,6 +2828,7 @@ const NavGen = struct {...@@ -2821,6 +2828,7 @@ const NavGen = struct {
2821 /// TODO is to also write out the error as a function call parameter, and to somehow fetch2828 /// TODO is to also write out the error as a function call parameter, and to somehow fetch
2822 /// the name of an error in the text executor.2829 /// the name of an error in the text executor.
2823 fn generateTestEntryPoint(self: *NavGen, name: []const u8, spv_test_decl_index: SpvModule.Decl.Index) !void {2830 fn generateTestEntryPoint(self: *NavGen, name: []const u8, spv_test_decl_index: SpvModule.Decl.Index) !void {
2831 const zcu = self.pt.zcu;
2824 const target = self.spv.target;2832 const target = self.spv.target;
28252833
2826 const anyerror_ty_id = try self.resolveType(Type.anyerror, .direct);2834 const anyerror_ty_id = try self.resolveType(Type.anyerror, .direct);
...@@ -2950,7 +2958,7 @@ const NavGen = struct {...@@ -2950,7 +2958,7 @@ const NavGen = struct {
2950 .pointer = p_error_id,2958 .pointer = p_error_id,
2951 .object = error_id,2959 .object = error_id,
2952 .memory_access = .{2960 .memory_access = .{
2953 .Aligned = .{ .literal_integer = @sizeOf(u16) },2961 .Aligned = .{ .literal_integer = @intCast(Type.abiAlignment(.anyerror, zcu).toByteUnits().?) },
2954 },2962 },
2955 });2963 });
2956 try section.emit(self.spv.gpa, .OpReturn, {});2964 try section.emit(self.spv.gpa, .OpReturn, {});
...@@ -3223,10 +3231,13 @@ const NavGen = struct {...@@ -3223,10 +3231,13 @@ const NavGen = struct {
3223 };3231 };
32243232
3225 fn load(self: *NavGen, value_ty: Type, ptr_id: IdRef, options: MemoryOptions) !IdRef {3233 fn load(self: *NavGen, value_ty: Type, ptr_id: IdRef, options: MemoryOptions) !IdRef {
3234 const zcu = self.pt.zcu;
3235 const alignment: u32 = @intCast(value_ty.abiAlignment(zcu).toByteUnits().?);
3226 const indirect_value_ty_id = try self.resolveType(value_ty, .indirect);3236 const indirect_value_ty_id = try self.resolveType(value_ty, .indirect);
3227 const result_id = self.spv.allocId();3237 const result_id = self.spv.allocId();
3228 const access = spec.MemoryAccess.Extended{3238 const access = spec.MemoryAccess.Extended{
3229 .Volatile = options.is_volatile,3239 .Volatile = options.is_volatile,
3240 .Aligned = .{ .literal_integer = alignment },
3230 };3241 };
3231 try self.func.body.emit(self.spv.gpa, .OpLoad, .{3242 try self.func.body.emit(self.spv.gpa, .OpLoad, .{
3232 .id_result_type = indirect_value_ty_id,3243 .id_result_type = indirect_value_ty_id,
...@@ -4229,7 +4240,7 @@ const NavGen = struct {...@@ -4229,7 +4240,7 @@ const NavGen = struct {
4229 defer self.gpa.free(ids);4240 defer self.gpa.free(ids);
42304241
4231 const result_id = self.spv.allocId();4242 const result_id = self.spv.allocId();
4232 if (self.spv.hasFeature(.kernel)) {4243 if (self.spv.hasFeature(.addresses)) {
4233 try self.func.body.emit(self.spv.gpa, .OpInBoundsPtrAccessChain, .{4244 try self.func.body.emit(self.spv.gpa, .OpInBoundsPtrAccessChain, .{
4234 .id_result_type = result_ty_id,4245 .id_result_type = result_ty_id,
4235 .id_result = result_id,4246 .id_result = result_id,
...@@ -4308,6 +4319,7 @@ const NavGen = struct {...@@ -4308,6 +4319,7 @@ const NavGen = struct {
4308 ) !Temporary {4319 ) !Temporary {
4309 const pt = self.pt;4320 const pt = self.pt;
4310 const zcu = pt.zcu;4321 const zcu = pt.zcu;
4322 const ip = &zcu.intern_pool;
4311 const scalar_ty = lhs.ty.scalarType(zcu);4323 const scalar_ty = lhs.ty.scalarType(zcu);
4312 const is_vector = lhs.ty.isVector(zcu);4324 const is_vector = lhs.ty.isVector(zcu);
43134325
...@@ -4318,6 +4330,11 @@ const NavGen = struct {...@@ -4318,6 +4330,11 @@ const NavGen = struct {
4318 const ty = lhs.ty.intTagType(zcu);4330 const ty = lhs.ty.intTagType(zcu);
4319 return try self.cmp(op, lhs.pun(ty), rhs.pun(ty));4331 return try self.cmp(op, lhs.pun(ty), rhs.pun(ty));
4320 },4332 },
4333 .@"struct" => {
4334 const struct_ty = zcu.typeToPackedStruct(scalar_ty).?;
4335 const ty = Type.fromInterned(struct_ty.backingIntTypeUnordered(ip));
4336 return try self.cmp(op, lhs.pun(ty), rhs.pun(ty));
4337 },
4321 .error_set => {4338 .error_set => {
4322 assert(!is_vector);4339 assert(!is_vector);
4323 const err_int_ty = try pt.errorIntType();4340 const err_int_ty = try pt.errorIntType();
...@@ -4745,8 +4762,42 @@ const NavGen = struct {...@@ -4745,8 +4762,42 @@ const NavGen = struct {
4745 switch (result_ty.zigTypeTag(zcu)) {4762 switch (result_ty.zigTypeTag(zcu)) {
4746 .@"struct" => {4763 .@"struct" => {
4747 if (zcu.typeToPackedStruct(result_ty)) |struct_type| {4764 if (zcu.typeToPackedStruct(result_ty)) |struct_type| {
4748 _ = struct_type;4765 comptime assert(Type.packed_struct_layout_version == 2);
4749 unreachable; // TODO4766 const backing_int_ty = Type.fromInterned(struct_type.backingIntTypeUnordered(ip));
4767 var running_int_id = try self.constInt(backing_int_ty, 0);
4768 var running_bits: u16 = 0;
4769 for (struct_type.field_types.get(ip), elements) |field_ty_ip, element| {
4770 const field_ty = Type.fromInterned(field_ty_ip);
4771 if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue;
4772 const field_id = try self.resolve(element);
4773 const ty_bit_size: u16 = @intCast(field_ty.bitSize(zcu));
4774 const field_int_ty = try self.pt.intType(.unsigned, ty_bit_size);
4775 const field_int_id = blk: {
4776 if (field_ty.isPtrAtRuntime(zcu)) {
4777 assert(self.spv.hasFeature(.addresses) or
4778 (self.spv.hasFeature(.physical_storage_buffer) and field_ty.ptrAddressSpace(zcu) == .storage_buffer));
4779 break :blk try self.intFromPtr(field_id);
4780 }
4781 break :blk try self.bitCast(field_int_ty, field_ty, field_id);
4782 };
4783 const shift_rhs = try self.constInt(backing_int_ty, running_bits);
4784 const extended_int_conv = try self.buildIntConvert(backing_int_ty, .{
4785 .ty = field_int_ty,
4786 .value = .{ .singleton = field_int_id },
4787 });
4788 const shifted = try self.buildBinary(.sll, extended_int_conv, .{
4789 .ty = backing_int_ty,
4790 .value = .{ .singleton = shift_rhs },
4791 });
4792 const running_int_tmp = try self.buildBinary(
4793 .bit_or,
4794 .{ .ty = backing_int_ty, .value = .{ .singleton = running_int_id } },
4795 shifted,
4796 );
4797 running_int_id = try running_int_tmp.materialize(self);
4798 running_bits += ty_bit_size;
4799 }
4800 return running_int_id;
4750 }4801 }
47514802
4752 const types = try self.gpa.alloc(Type, elements.len);4803 const types = try self.gpa.alloc(Type, elements.len);
...@@ -5087,11 +5138,33 @@ const NavGen = struct {...@@ -5087,11 +5138,33 @@ const NavGen = struct {
5087 const union_ty = zcu.typeToUnion(ty).?;5138 const union_ty = zcu.typeToUnion(ty).?;
5088 const tag_ty = Type.fromInterned(union_ty.enum_tag_ty);5139 const tag_ty = Type.fromInterned(union_ty.enum_tag_ty);
50895140
5141 const layout = self.unionLayout(ty);
5142 const payload_ty = Type.fromInterned(union_ty.field_types.get(ip)[active_field]);
5143
5090 if (union_ty.flagsUnordered(ip).layout == .@"packed") {5144 if (union_ty.flagsUnordered(ip).layout == .@"packed") {
5091 unreachable; // TODO5145 if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) {
5092 }5146 const int_ty = try pt.intType(.unsigned, @intCast(ty.bitSize(zcu)));
5147 return self.constInt(int_ty, 0);
5148 }
50935149
5094 const layout = self.unionLayout(ty);5150 assert(payload != null);
5151 if (payload_ty.isInt(zcu)) {
5152 if (ty.bitSize(zcu) == payload_ty.bitSize(zcu)) {
5153 return self.bitCast(ty, payload_ty, payload.?);
5154 }
5155
5156 const trunc = try self.buildIntConvert(ty, .{ .ty = payload_ty, .value = .{ .singleton = payload.? } });
5157 return try trunc.materialize(self);
5158 }
5159
5160 const payload_int_ty = try pt.intType(.unsigned, @intCast(payload_ty.bitSize(zcu)));
5161 const payload_int = if (payload_ty.ip_index == .bool_type)
5162 try self.convertToIndirect(payload_ty, payload.?)
5163 else
5164 try self.bitCast(payload_int_ty, payload_ty, payload.?);
5165 const trunc = try self.buildIntConvert(ty, .{ .ty = payload_int_ty, .value = .{ .singleton = payload_int } });
5166 return try trunc.materialize(self);
5167 }
50955168
5096 const tag_int = if (layout.tag_size != 0) blk: {5169 const tag_int = if (layout.tag_size != 0) blk: {
5097 const tag_val = try pt.enumValueFieldIndex(tag_ty, active_field);5170 const tag_val = try pt.enumValueFieldIndex(tag_ty, active_field);
...@@ -5112,7 +5185,6 @@ const NavGen = struct {...@@ -5112,7 +5185,6 @@ const NavGen = struct {
5112 try self.store(tag_ty, ptr_id, tag_id, .{});5185 try self.store(tag_ty, ptr_id, tag_id, .{});
5113 }5186 }
51145187
5115 const payload_ty = Type.fromInterned(union_ty.field_types.get(ip)[active_field]);
5116 if (payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) {5188 if (payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) {
5117 const pl_ptr_ty_id = try self.ptrType(layout.payload_ty, .Function, .indirect);5189 const pl_ptr_ty_id = try self.ptrType(layout.payload_ty, .Function, .indirect);
5118 const pl_ptr_id = try self.accessChain(pl_ptr_ty_id, tmp_id, &.{layout.payload_index});5190 const pl_ptr_id = try self.accessChain(pl_ptr_ty_id, tmp_id, &.{layout.payload_index});
...@@ -5167,11 +5239,51 @@ const NavGen = struct {...@@ -5167,11 +5239,51 @@ const NavGen = struct {
51675239
5168 switch (object_ty.zigTypeTag(zcu)) {5240 switch (object_ty.zigTypeTag(zcu)) {
5169 .@"struct" => switch (object_ty.containerLayout(zcu)) {5241 .@"struct" => switch (object_ty.containerLayout(zcu)) {
5170 .@"packed" => unreachable, // TODO5242 .@"packed" => {
5243 const struct_ty = zcu.typeToPackedStruct(object_ty).?;
5244 const bit_offset = pt.structPackedFieldBitOffset(struct_ty, field_index);
5245 const bit_offset_id = try self.constInt(.u16, bit_offset);
5246 const signedness = if (field_ty.isInt(zcu)) field_ty.intInfo(zcu).signedness else .unsigned;
5247 const field_bit_size: u16 = @intCast(field_ty.bitSize(zcu));
5248 const field_int_ty = try pt.intType(signedness, field_bit_size);
5249 const shift_lhs: Temporary = .{ .ty = object_ty, .value = .{ .singleton = object_id } };
5250 const shift = try self.buildBinary(.srl, shift_lhs, .{ .ty = .u16, .value = .{ .singleton = bit_offset_id } });
5251 const mask_id = try self.constInt(object_ty, (@as(u64, 1) << @as(u6, @intCast(field_bit_size))) - 1);
5252 const masked = try self.buildBinary(.bit_and, shift, .{ .ty = object_ty, .value = .{ .singleton = mask_id } });
5253 const result_id = blk: {
5254 if (self.backingIntBits(field_bit_size).? == self.backingIntBits(@intCast(object_ty.bitSize(zcu))).?)
5255 break :blk try self.bitCast(field_int_ty, object_ty, try masked.materialize(self));
5256 const trunc = try self.buildIntConvert(field_int_ty, masked);
5257 break :blk try trunc.materialize(self);
5258 };
5259 if (field_ty.ip_index == .bool_type) return try self.convertToDirect(.bool, result_id);
5260 if (field_ty.isInt(zcu)) return result_id;
5261 return try self.bitCast(field_ty, field_int_ty, result_id);
5262 },
5171 else => return try self.extractField(field_ty, object_id, field_index),5263 else => return try self.extractField(field_ty, object_id, field_index),
5172 },5264 },
5173 .@"union" => switch (object_ty.containerLayout(zcu)) {5265 .@"union" => switch (object_ty.containerLayout(zcu)) {
5174 .@"packed" => unreachable, // TODO5266 .@"packed" => {
5267 const backing_int_ty = try pt.intType(.unsigned, @intCast(object_ty.bitSize(zcu)));
5268 const signedness = if (field_ty.isInt(zcu)) field_ty.intInfo(zcu).signedness else .unsigned;
5269 const field_bit_size: u16 = @intCast(field_ty.bitSize(zcu));
5270 const int_ty = try pt.intType(signedness, field_bit_size);
5271 const mask_id = try self.constInt(backing_int_ty, (@as(u64, 1) << @as(u6, @intCast(field_bit_size))) - 1);
5272 const masked = try self.buildBinary(
5273 .bit_and,
5274 .{ .ty = backing_int_ty, .value = .{ .singleton = object_id } },
5275 .{ .ty = backing_int_ty, .value = .{ .singleton = mask_id } },
5276 );
5277 const result_id = blk: {
5278 if (self.backingIntBits(field_bit_size).? == self.backingIntBits(@intCast(backing_int_ty.bitSize(zcu))).?)
5279 break :blk try self.bitCast(int_ty, backing_int_ty, try masked.materialize(self));
5280 const trunc = try self.buildIntConvert(int_ty, masked);
5281 break :blk try trunc.materialize(self);
5282 };
5283 if (field_ty.ip_index == .bool_type) return try self.convertToDirect(.bool, result_id);
5284 if (field_ty.isInt(zcu)) return result_id;
5285 return try self.bitCast(field_ty, int_ty, result_id);
5286 },
5175 else => {5287 else => {
5176 // Store, ptr-elem-ptr, pointer-cast, load5288 // Store, ptr-elem-ptr, pointer-cast, load
5177 const layout = self.unionLayout(object_ty);5289 const layout = self.unionLayout(object_ty);
...@@ -5252,28 +5364,28 @@ const NavGen = struct {...@@ -5252,28 +5364,28 @@ const NavGen = struct {
5252 return try self.accessChain(result_ty_id, object_ptr, &.{field_index});5364 return try self.accessChain(result_ty_id, object_ptr, &.{field_index});
5253 },5365 },
5254 },5366 },
5255 .@"union" => switch (object_ty.containerLayout(zcu)) {5367 .@"union" => {
5256 .@"packed" => return self.todo("implement field access for packed unions", .{}),5368 const layout = self.unionLayout(object_ty);
5257 else => {5369 if (!layout.has_payload) {
5258 const layout = self.unionLayout(object_ty);5370 // Asked to get a pointer to a zero-sized field. Just lower this
5259 if (!layout.has_payload) {5371 // to undefined, there is no reason to make it be a valid pointer.
5260 // Asked to get a pointer to a zero-sized field. Just lower this5372 return try self.spv.constUndef(result_ty_id);
5261 // to undefined, there is no reason to make it be a valid pointer.5373 }
5262 return try self.spv.constUndef(result_ty_id);
5263 }
52645374
5265 const storage_class = self.spvStorageClass(object_ptr_ty.ptrAddressSpace(zcu));5375 const storage_class = self.spvStorageClass(object_ptr_ty.ptrAddressSpace(zcu));
5266 const pl_ptr_ty_id = try self.ptrType(layout.payload_ty, storage_class, .indirect);5376 const pl_ptr_ty_id = try self.ptrType(layout.payload_ty, storage_class, .indirect);
5267 const pl_ptr_id = try self.accessChain(pl_ptr_ty_id, object_ptr, &.{layout.payload_index});5377 const pl_ptr_id = blk: {
5378 if (object_ty.containerLayout(zcu) == .@"packed") break :blk object_ptr;
5379 break :blk try self.accessChain(pl_ptr_ty_id, object_ptr, &.{layout.payload_index});
5380 };
52685381
5269 const active_pl_ptr_id = self.spv.allocId();5382 const active_pl_ptr_id = self.spv.allocId();
5270 try self.func.body.emit(self.spv.gpa, .OpBitcast, .{5383 try self.func.body.emit(self.spv.gpa, .OpBitcast, .{
5271 .id_result_type = result_ty_id,5384 .id_result_type = result_ty_id,
5272 .id_result = active_pl_ptr_id,5385 .id_result = active_pl_ptr_id,
5273 .operand = pl_ptr_id,5386 .operand = pl_ptr_id,
5274 });5387 });
5275 return active_pl_ptr_id;5388 return active_pl_ptr_id;
5276 },
5277 },5389 },
5278 else => unreachable,5390 else => unreachable,
5279 }5391 }
...@@ -5292,7 +5404,7 @@ const NavGen = struct {...@@ -5292,7 +5404,7 @@ const NavGen = struct {
5292 /// The final storage class of the pointer. This may be either `.Generic` or `.Function`.5404 /// The final storage class of the pointer. This may be either `.Generic` or `.Function`.
5293 /// In either case, the local is allocated in the `.Function` storage class, and optionally5405 /// In either case, the local is allocated in the `.Function` storage class, and optionally
5294 /// cast back to `.Generic`.5406 /// cast back to `.Generic`.
5295 storage_class: StorageClass = .Generic,5407 storage_class: StorageClass,
5296 };5408 };
52975409
5298 // Allocate a function-local variable, with possible initializer.5410 // Allocate a function-local variable, with possible initializer.
...@@ -5332,9 +5444,10 @@ const NavGen = struct {...@@ -5332,9 +5444,10 @@ const NavGen = struct {
5332 fn airAlloc(self: *NavGen, inst: Air.Inst.Index) !?IdRef {5444 fn airAlloc(self: *NavGen, inst: Air.Inst.Index) !?IdRef {
5333 const zcu = self.pt.zcu;5445 const zcu = self.pt.zcu;
5334 const ptr_ty = self.typeOfIndex(inst);5446 const ptr_ty = self.typeOfIndex(inst);
5335 assert(ptr_ty.ptrAddressSpace(zcu) == .generic);
5336 const child_ty = ptr_ty.childType(zcu);5447 const child_ty = ptr_ty.childType(zcu);
5337 return try self.alloc(child_ty, .{});5448 return try self.alloc(child_ty, .{
5449 .storage_class = self.spvStorageClass(ptr_ty.ptrAddressSpace(zcu)),
5450 });
5338 }5451 }
53395452
5340 fn airArg(self: *NavGen) IdRef {5453 fn airArg(self: *NavGen) IdRef {
src/codegen/spirv/Assembler.zig+45-11
...@@ -368,6 +368,40 @@ fn processTypeInstruction(self: *Assembler) !AsmValue {...@@ -368,6 +368,40 @@ fn processTypeInstruction(self: *Assembler) !AsmValue {
368 });368 });
369 break :blk result_id;369 break :blk result_id;
370 },370 },
371 .OpTypeStruct => blk: {
372 const ids = try self.gpa.alloc(IdRef, operands[1..].len);
373 defer self.gpa.free(ids);
374 for (operands[1..], ids) |op, *id| id.* = try self.resolveRefId(op.ref_id);
375 const result_id = self.spv.allocId();
376 try self.spv.structType(result_id, ids, null);
377 break :blk result_id;
378 },
379 .OpTypeImage => blk: {
380 const sampled_type = try self.resolveRefId(operands[1].ref_id);
381 const result_id = self.spv.allocId();
382 try section.emit(self.gpa, .OpTypeImage, .{
383 .id_result = result_id,
384 .sampled_type = sampled_type,
385 .dim = @enumFromInt(operands[2].value),
386 .depth = operands[3].literal32,
387 .arrayed = operands[4].literal32,
388 .ms = operands[5].literal32,
389 .sampled = operands[6].literal32,
390 .image_format = @enumFromInt(operands[7].value),
391 });
392 break :blk result_id;
393 },
394 .OpTypeSampler => blk: {
395 const result_id = self.spv.allocId();
396 try section.emit(self.gpa, .OpTypeSampler, .{ .id_result = result_id });
397 break :blk result_id;
398 },
399 .OpTypeSampledImage => blk: {
400 const image_type = try self.resolveRefId(operands[1].ref_id);
401 const result_id = self.spv.allocId();
402 try section.emit(self.gpa, .OpTypeSampledImage, .{ .id_result = result_id, .image_type = image_type });
403 break :blk result_id;
404 },
371 .OpTypeFunction => blk: {405 .OpTypeFunction => blk: {
372 const param_operands = operands[2..];406 const param_operands = operands[2..];
373 const return_type = try self.resolveRefId(operands[1].ref_id);407 const return_type = try self.resolveRefId(operands[1].ref_id);
...@@ -406,18 +440,18 @@ fn processGenericInstruction(self: *Assembler) !?AsmValue {...@@ -406,18 +440,18 @@ fn processGenericInstruction(self: *Assembler) !?AsmValue {
406 else => switch (self.inst.opcode) {440 else => switch (self.inst.opcode) {
407 .OpEntryPoint => unreachable,441 .OpEntryPoint => unreachable,
408 .OpExecutionMode, .OpExecutionModeId => &self.spv.sections.execution_modes,442 .OpExecutionMode, .OpExecutionModeId => &self.spv.sections.execution_modes,
409 .OpVariable => switch (@as(spec.StorageClass, @enumFromInt(operands[2].value))) {443 .OpVariable => section: {
410 .Function => &self.func.prologue,444 const storage_class: spec.StorageClass = @enumFromInt(operands[2].value);
411 .Input, .Output => section: {445 if (storage_class == .Function) break :section &self.func.prologue;
412 maybe_spv_decl_index = try self.spv.allocDecl(.global);446 maybe_spv_decl_index = try self.spv.allocDecl(.global);
413 try self.func.decl_deps.put(self.spv.gpa, maybe_spv_decl_index.?, {});447 if (self.spv.version.minor < 4 and storage_class != .Input and storage_class != .Output) {
414 // TODO: In theory this can be non-empty if there is an initializer which depends on another global...448 // Before version 1.4, the interface’s storage classes are limited to the Input and Output
415 try self.spv.declareDeclDeps(maybe_spv_decl_index.?, &.{});
416 break :section &self.spv.sections.types_globals_constants;449 break :section &self.spv.sections.types_globals_constants;
417 },450 }
418 // These don't need to be marked in the dependency system.451 try self.func.decl_deps.put(self.spv.gpa, maybe_spv_decl_index.?, {});
419 // Probably we should add them anyway, then filter out PushConstant globals.452 // TODO: In theory this can be non-empty if there is an initializer which depends on another global...
420 else => &self.spv.sections.types_globals_constants,453 try self.spv.declareDeclDeps(maybe_spv_decl_index.?, &.{});
454 break :section &self.spv.sections.types_globals_constants;
421 },455 },
422 // Default case - to be worked out further.456 // Default case - to be worked out further.
423 else => &self.func.body,457 else => &self.func.body,
src/codegen/spirv/Module.zig+22-7
...@@ -333,8 +333,6 @@ pub fn finalize(self: *Module, a: Allocator) ![]Word {...@@ -333,8 +333,6 @@ pub fn finalize(self: *Module, a: Allocator) ![]Word {
333 // Versions333 // Versions
334 .v1_0, .v1_1, .v1_2, .v1_3, .v1_4, .v1_5, .v1_6 => {},334 .v1_0, .v1_1, .v1_2, .v1_3, .v1_4, .v1_5, .v1_6 => {},
335 // Features with no dependencies335 // Features with no dependencies
336 .int8 => try self.addCapability(.Int8),
337 .int16 => try self.addCapability(.Int16),
338 .int64 => try self.addCapability(.Int64),336 .int64 => try self.addCapability(.Int64),
339 .float16 => try self.addCapability(.Float16),337 .float16 => try self.addCapability(.Float16),
340 .float64 => try self.addCapability(.Float64),338 .float64 => try self.addCapability(.Float64),
...@@ -343,21 +341,27 @@ pub fn finalize(self: *Module, a: Allocator) ![]Word {...@@ -343,21 +341,27 @@ pub fn finalize(self: *Module, a: Allocator) ![]Word {
343 try self.addExtension("SPV_KHR_16bit_storage");341 try self.addExtension("SPV_KHR_16bit_storage");
344 try self.addCapability(.StoragePushConstant16);342 try self.addCapability(.StoragePushConstant16);
345 },343 },
346 .addresses => if (self.hasFeature(.shader)) {344 .arbitrary_precision_integers => {
347 try self.addExtension("SPV_KHR_physical_storage_buffer");345 try self.addExtension("SPV_INTEL_arbitrary_precision_integers");
348 try self.addCapability(.PhysicalStorageBufferAddresses);346 try self.addCapability(.ArbitraryPrecisionIntegersINTEL);
349 } else {
350 try self.addCapability(.Addresses);
351 },347 },
348 .addresses => try self.addCapability(.Addresses),
352 // Kernel349 // Kernel
353 .kernel => try self.addCapability(.Kernel),350 .kernel => try self.addCapability(.Kernel),
354 .generic_pointer => try self.addCapability(.GenericPointer),351 .generic_pointer => try self.addCapability(.GenericPointer),
355 .vector16 => try self.addCapability(.Vector16),352 .vector16 => try self.addCapability(.Vector16),
356 // Shader353 // Shader
357 .shader => try self.addCapability(.Shader),354 .shader => try self.addCapability(.Shader),
355 .physical_storage_buffer => {
356 try self.addExtension("SPV_KHR_physical_storage_buffer");
357 try self.addCapability(.PhysicalStorageBufferAddresses);
358 },
358 }359 }
359 }360 }
360 }361 }
362 // These are well supported
363 try self.addCapability(.Int8);
364 try self.addCapability(.Int16);
361365
362 // Emit memory model366 // Emit memory model
363 const addressing_model: spec.AddressingModel = blk: {367 const addressing_model: spec.AddressingModel = blk: {
...@@ -610,6 +614,17 @@ pub fn functionType(self: *Module, return_ty_id: IdRef, param_type_ids: []const...@@ -610,6 +614,17 @@ pub fn functionType(self: *Module, return_ty_id: IdRef, param_type_ids: []const
610 return result_id;614 return result_id;
611}615}
612616
617pub fn constant(self: *Module, result_ty_id: IdRef, value: spec.LiteralContextDependentNumber) !IdRef {
618 const result_id = self.allocId();
619 const section = &self.sections.types_globals_constants;
620 try section.emit(self.gpa, .OpConstant, .{
621 .id_result_type = result_ty_id,
622 .id_result = result_id,
623 .value = value,
624 });
625 return result_id;
626}
627
613pub fn constBool(self: *Module, value: bool) !IdRef {628pub fn constBool(self: *Module, value: bool) !IdRef {
614 if (self.cache.bool_const[@intFromBool(value)]) |b| return b;629 if (self.cache.bool_const[@intFromBool(value)]) |b| return b;
615630
test/behavior.zig+2
...@@ -140,6 +140,8 @@ test {...@@ -140,6 +140,8 @@ test {
140140
141// This bug only repros in the root file141// This bug only repros in the root file
142test "deference @embedFile() of a file full of zero bytes" {142test "deference @embedFile() of a file full of zero bytes" {
143 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
144
143 const contents = @embedFile("behavior/zero.bin").*;145 const contents = @embedFile("behavior/zero.bin").*;
144 try @import("std").testing.expect(contents.len == 456);146 try @import("std").testing.expect(contents.len == 456);
145 for (contents) |byte| try @import("std").testing.expect(byte == 0);147 for (contents) |byte| try @import("std").testing.expect(byte == 0);
test/behavior/bitcast.zig-2
...@@ -165,7 +165,6 @@ test "@bitCast packed structs at runtime and comptime" {...@@ -165,7 +165,6 @@ test "@bitCast packed structs at runtime and comptime" {
165 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;165 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
166 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;166 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
167 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO167 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
168 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
169168
170 const Full = packed struct {169 const Full = packed struct {
171 number: u16,170 number: u16,
...@@ -226,7 +225,6 @@ test "bitcast packed struct to integer and back" {...@@ -226,7 +225,6 @@ test "bitcast packed struct to integer and back" {
226 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;225 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
227 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;226 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
228 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO227 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
229 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
230228
231 const LevelUpMove = packed struct {229 const LevelUpMove = packed struct {
232 move_id: u9,230 move_id: u9,
test/behavior/cast_int.zig-4
...@@ -22,7 +22,6 @@ test "coerce i8 to i32 and @intCast back" {...@@ -22,7 +22,6 @@ test "coerce i8 to i32 and @intCast back" {
22 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO22 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
23 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO23 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
24 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO24 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
25 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
2625
27 var x: i8 = -5;26 var x: i8 = -5;
28 var y: i32 = -5;27 var y: i32 = -5;
...@@ -36,8 +35,6 @@ test "coerce i8 to i32 and @intCast back" {...@@ -36,8 +35,6 @@ test "coerce i8 to i32 and @intCast back" {
36}35}
3736
38test "coerce non byte-sized integers accross 32bits boundary" {37test "coerce non byte-sized integers accross 32bits boundary" {
39 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
40
41 {38 {
42 var v: u21 = 6417;39 var v: u21 = 6417;
43 _ = &v;40 _ = &v;
...@@ -217,7 +214,6 @@ test "load non byte-sized value in union" {...@@ -217,7 +214,6 @@ test "load non byte-sized value in union" {
217 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;214 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
218 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;215 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
219 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;216 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
220 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
221 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;217 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
222 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;218 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
223219
test/behavior/export_keyword.zig-1
...@@ -25,7 +25,6 @@ const PackedUnion = packed union {...@@ -25,7 +25,6 @@ const PackedUnion = packed union {
2525
26test "packed struct, enum, union parameters in extern function" {26test "packed struct, enum, union parameters in extern function" {
27 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO27 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
28 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
2928
30 testPackedStuff(&(PackedStruct{29 testPackedStuff(&(PackedStruct{
31 .a = 1,30 .a = 1,
test/behavior/floatop.zig+3
...@@ -133,6 +133,7 @@ test "cmp f16" {...@@ -133,6 +133,7 @@ test "cmp f16" {
133}133}
134134
135test "cmp f32" {135test "cmp f32" {
136 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
136 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO137 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
137 if (builtin.cpu.arch.isArm() and builtin.target.abi.float() == .soft) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/21234138 if (builtin.cpu.arch.isArm() and builtin.target.abi.float() == .soft) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/21234
138 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;139 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
...@@ -142,6 +143,7 @@ test "cmp f32" {...@@ -142,6 +143,7 @@ test "cmp f32" {
142}143}
143144
144test "cmp f64" {145test "cmp f64" {
146 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
145 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO147 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
146 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;148 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
147 if (builtin.cpu.arch.isArm() and builtin.target.abi.float() == .soft) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/21234149 if (builtin.cpu.arch.isArm() and builtin.target.abi.float() == .soft) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/21234
...@@ -245,6 +247,7 @@ test "vector cmp f16" {...@@ -245,6 +247,7 @@ test "vector cmp f16" {
245}247}
246248
247test "vector cmp f32" {249test "vector cmp f32" {
250 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
248 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO251 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
249 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO252 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
250 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;253 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
test/behavior/globals.zig+4
...@@ -69,6 +69,8 @@ test "global loads can affect liveness" {...@@ -69,6 +69,8 @@ test "global loads can affect liveness" {
69}69}
7070
71test "global const can be self-referential" {71test "global const can be self-referential" {
72 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
73
72 const S = struct {74 const S = struct {
73 self: *const @This(),75 self: *const @This(),
74 x: u32,76 x: u32,
...@@ -113,6 +115,8 @@ test "global var can be self-referential" {...@@ -113,6 +115,8 @@ test "global var can be self-referential" {
113}115}
114116
115test "global const can be indirectly self-referential" {117test "global const can be indirectly self-referential" {
118 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
119
116 const S = struct {120 const S = struct {
117 other: *const @This(),121 other: *const @This(),
118 x: u32,122 x: u32,
test/behavior/packed-struct.zig-14
...@@ -123,7 +123,6 @@ test "correct sizeOf and offsets in packed structs" {...@@ -123,7 +123,6 @@ test "correct sizeOf and offsets in packed structs" {
123 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO123 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
124 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO124 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
125 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO125 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
126 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
127126
128 const PStruct = packed struct {127 const PStruct = packed struct {
129 bool_a: bool,128 bool_a: bool,
...@@ -191,7 +190,6 @@ test "nested packed structs" {...@@ -191,7 +190,6 @@ test "nested packed structs" {
191 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO190 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
192 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO191 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
193 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO192 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
194 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
195193
196 const S1 = packed struct { a: u8, b: u8, c: u8 };194 const S1 = packed struct { a: u8, b: u8, c: u8 };
197195
...@@ -257,7 +255,6 @@ test "nested packed struct unaligned" {...@@ -257,7 +255,6 @@ test "nested packed struct unaligned" {
257 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;255 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
258 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;256 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
259 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO257 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
260 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
261 if (native_endian != .little) return error.SkipZigTest; // Byte aligned packed struct field pointers have not been implemented yet258 if (native_endian != .little) return error.SkipZigTest; // Byte aligned packed struct field pointers have not been implemented yet
262259
263 const S1 = packed struct {260 const S1 = packed struct {
...@@ -895,7 +892,6 @@ test "packed struct passed to callconv(.c) function" {...@@ -895,7 +892,6 @@ test "packed struct passed to callconv(.c) function" {
895 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;892 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
896 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;893 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
897 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO894 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
898 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
899 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;895 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
900896
901 const S = struct {897 const S = struct {
...@@ -944,7 +940,6 @@ test "packed struct initialized in bitcast" {...@@ -944,7 +940,6 @@ test "packed struct initialized in bitcast" {
944 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO940 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
945 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO941 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
946 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO942 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
947 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
948 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;943 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
949944
950 const T = packed struct { val: u8 };945 const T = packed struct { val: u8 };
...@@ -982,7 +977,6 @@ test "pointer to container level packed struct field" {...@@ -982,7 +977,6 @@ test "pointer to container level packed struct field" {
982test "store undefined to packed result location" {977test "store undefined to packed result location" {
983 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;978 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
984 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;979 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
985 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
986 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;980 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
987981
988 var x: u4 = 0;982 var x: u4 = 0;
...@@ -992,8 +986,6 @@ test "store undefined to packed result location" {...@@ -992,8 +986,6 @@ test "store undefined to packed result location" {
992}986}
993987
994test "bitcast back and forth" {988test "bitcast back and forth" {
995 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
996
997 // Originally reported at https://github.com/ziglang/zig/issues/9914989 // Originally reported at https://github.com/ziglang/zig/issues/9914
998 const S = packed struct { one: u6, two: u1 };990 const S = packed struct { one: u6, two: u1 };
999 const s = S{ .one = 0b110101, .two = 0b1 };991 const s = S{ .one = 0b110101, .two = 0b1 };
...@@ -1290,8 +1282,6 @@ test "2-byte packed struct argument in C calling convention" {...@@ -1290,8 +1282,6 @@ test "2-byte packed struct argument in C calling convention" {
1290}1282}
12911283
1292test "packed struct contains optional pointer" {1284test "packed struct contains optional pointer" {
1293 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1294
1295 const foo: packed struct {1285 const foo: packed struct {
1296 a: ?*@This() = null,1286 a: ?*@This() = null,
1297 } = .{};1287 } = .{};
...@@ -1299,8 +1289,6 @@ test "packed struct contains optional pointer" {...@@ -1299,8 +1289,6 @@ test "packed struct contains optional pointer" {
1299}1289}
13001290
1301test "packed struct equality" {1291test "packed struct equality" {
1302 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1303
1304 const Foo = packed struct {1292 const Foo = packed struct {
1305 a: u4,1293 a: u4,
1306 b: u4,1294 b: u4,
...@@ -1321,8 +1309,6 @@ test "packed struct equality" {...@@ -1321,8 +1309,6 @@ test "packed struct equality" {
1321}1309}
13221310
1323test "packed struct with signed field" {1311test "packed struct with signed field" {
1324 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1325
1326 var s: packed struct {1312 var s: packed struct {
1327 a: i2,1313 a: i2,
1328 b: u6,1314 b: u6,
test/behavior/packed-union.zig-3
...@@ -137,7 +137,6 @@ test "packed union initialized with a runtime value" {...@@ -137,7 +137,6 @@ test "packed union initialized with a runtime value" {
137 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO137 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
138 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO138 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
139 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO139 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
140 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
141 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;140 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
142141
143 const Fields = packed struct {142 const Fields = packed struct {
...@@ -174,8 +173,6 @@ test "assigning to non-active field at comptime" {...@@ -174,8 +173,6 @@ test "assigning to non-active field at comptime" {
174}173}
175174
176test "comptime packed union of pointers" {175test "comptime packed union of pointers" {
177 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
178
179 const U = packed union {176 const U = packed union {
180 a: *const u32,177 a: *const u32,
181 b: *const [1]u32,178 b: *const [1]u32,
test/behavior/packed_struct_explicit_backing_int.zig-1
...@@ -9,7 +9,6 @@ test "packed struct explicit backing integer" {...@@ -9,7 +9,6 @@ test "packed struct explicit backing integer" {
9 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO9 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
10 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO10 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
11 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO11 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
12 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1312
14 const S1 = packed struct { a: u8, b: u8, c: u8 };13 const S1 = packed struct { a: u8, b: u8, c: u8 };
1514
test/behavior/ptrcast.zig-2
...@@ -287,8 +287,6 @@ test "@ptrCast undefined value at comptime" {...@@ -287,8 +287,6 @@ test "@ptrCast undefined value at comptime" {
287}287}
288288
289test "comptime @ptrCast with packed struct leaves value unmodified" {289test "comptime @ptrCast with packed struct leaves value unmodified" {
290 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
291
292 const S = packed struct { three: u3 };290 const S = packed struct { three: u3 };
293 const st: S = .{ .three = 6 };291 const st: S = .{ .three = 6 };
294 try expect(st.three == 6);292 try expect(st.three == 6);
test/behavior/ptrfromint.zig+2
...@@ -3,6 +3,8 @@ const builtin = @import("builtin");...@@ -3,6 +3,8 @@ const builtin = @import("builtin");
3const expectEqual = std.testing.expectEqual;3const expectEqual = std.testing.expectEqual;
44
5test "casting integer address to function pointer" {5test "casting integer address to function pointer" {
6 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
7
6 addressToFunction();8 addressToFunction();
7 comptime addressToFunction();9 comptime addressToFunction();
8}10}
test/behavior/sizeof_and_typeof.zig+2
...@@ -233,6 +233,8 @@ test "@sizeOf comparison against zero" {...@@ -233,6 +233,8 @@ test "@sizeOf comparison against zero" {
233}233}
234234
235test "hardcoded address in typeof expression" {235test "hardcoded address in typeof expression" {
236 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
237
236 const S = struct {238 const S = struct {
237 fn func() @TypeOf(@as(*[]u8, @ptrFromInt(0x10)).*[0]) {239 fn func() @TypeOf(@as(*[]u8, @ptrFromInt(0x10)).*[0]) {
238 return 0;240 return 0;
test/behavior/struct.zig-3
...@@ -1023,7 +1023,6 @@ test "packed struct with undefined initializers" {...@@ -1023,7 +1023,6 @@ test "packed struct with undefined initializers" {
1023 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;1023 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1024 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1024 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1025 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1025 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1026 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
10271026
1028 const S = struct {1027 const S = struct {
1029 const P = packed struct {1028 const P = packed struct {
...@@ -1221,7 +1220,6 @@ test "packed struct aggregate init" {...@@ -1221,7 +1220,6 @@ test "packed struct aggregate init" {
1221 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1220 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1222 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1221 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1223 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1222 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1224 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1225 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1223 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
12261224
1227 const S = struct {1225 const S = struct {
...@@ -1971,7 +1969,6 @@ test "struct field default value is a call" {...@@ -1971,7 +1969,6 @@ test "struct field default value is a call" {
1971 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1969 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1972 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1970 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1973 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1971 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1974 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
19751972
1976 const Z = packed struct {1973 const Z = packed struct {
1977 a: u32,1974 a: u32,
test/behavior/union.zig+2-12
...@@ -1372,14 +1372,13 @@ test "packed union in packed struct" {...@@ -1372,14 +1372,13 @@ test "packed union in packed struct" {
1372 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1372 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1373 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1373 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1374 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1374 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1375 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
13761375
1377 const S = packed struct {1376 const S = packed struct {
1378 nested: packed union {1377 nested: packed union {
1379 val: usize,1378 val: u16,
1380 foo: u32,1379 foo: u32,
1381 },1380 },
1382 bar: u32,1381 bar: u16,
13831382
1384 fn unpack(self: @This()) usize {1383 fn unpack(self: @This()) usize {
1385 return self.nested.foo;1384 return self.nested.foo;
...@@ -1460,7 +1459,6 @@ test "packed union with zero-bit field" {...@@ -1460,7 +1459,6 @@ test "packed union with zero-bit field" {
1460 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1459 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1461 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1460 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1462 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1461 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1463 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
14641462
1465 const S = packed struct {1463 const S = packed struct {
1466 nested: packed union {1464 nested: packed union {
...@@ -1479,7 +1477,6 @@ test "packed union with zero-bit field" {...@@ -1479,7 +1477,6 @@ test "packed union with zero-bit field" {
1479test "reinterpreting enum value inside packed union" {1477test "reinterpreting enum value inside packed union" {
1480 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1478 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1481 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1479 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1482 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
14831480
1484 const U = packed union {1481 const U = packed union {
1485 tag: enum(u8) { a, b },1482 tag: enum(u8) { a, b },
...@@ -1527,7 +1524,6 @@ test "defined-layout union field pointer has correct alignment" {...@@ -1527,7 +1524,6 @@ test "defined-layout union field pointer has correct alignment" {
1527 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1524 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1528 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1525 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1529 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1526 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1530 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
15311527
1532 const S = struct {1528 const S = struct {
1533 fn doTheTest(comptime U: type) !void {1529 fn doTheTest(comptime U: type) !void {
...@@ -1901,8 +1897,6 @@ test "inner struct initializer uses union layout" {...@@ -1901,8 +1897,6 @@ test "inner struct initializer uses union layout" {
1901}1897}
19021898
1903test "inner struct initializer uses packed union layout" {1899test "inner struct initializer uses packed union layout" {
1904 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1905
1906 const namespace = struct {1900 const namespace = struct {
1907 const U = packed union {1901 const U = packed union {
1908 a: packed struct {1902 a: packed struct {
...@@ -1946,8 +1940,6 @@ test "extern union initialized via reintepreted struct field initializer" {...@@ -1946,8 +1940,6 @@ test "extern union initialized via reintepreted struct field initializer" {
1946}1940}
19471941
1948test "packed union initialized via reintepreted struct field initializer" {1942test "packed union initialized via reintepreted struct field initializer" {
1949 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1950
1951 const bytes = [_]u8{ 0xaa, 0xbb, 0xcc, 0xdd };1943 const bytes = [_]u8{ 0xaa, 0xbb, 0xcc, 0xdd };
19521944
1953 const U = packed union {1945 const U = packed union {
...@@ -1988,8 +1980,6 @@ test "store of comptime reinterpreted memory to extern union" {...@@ -1988,8 +1980,6 @@ test "store of comptime reinterpreted memory to extern union" {
1988}1980}
19891981
1990test "store of comptime reinterpreted memory to packed union" {1982test "store of comptime reinterpreted memory to packed union" {
1991 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1992
1993 const bytes = [_]u8{ 0xaa, 0xbb, 0xcc, 0xdd };1983 const bytes = [_]u8{ 0xaa, 0xbb, 0xcc, 0xdd };
19941984
1995 const U = packed union {1985 const U = packed union {
test/cases/compile_errors/illegal_operation_on_logical_ptr.zig created+52
...@@ -0,0 +1,52 @@
1export fn elemPtr() void {
2 var ptr: [*]u8 = undefined;
3 ptr[0] = 0;
4}
5
6export fn elemVal() void {
7 var ptr: [*]u8 = undefined;
8 var val = ptr[0];
9 _ = &ptr;
10 _ = &val;
11}
12
13export fn intFromPtr() void {
14 var value: u8 = 0;
15 _ = @intFromPtr(&value);
16}
17
18export fn ptrFromInt() void {
19 var v: u32 = 0x1234;
20 var ptr: *u8 = @ptrFromInt(v);
21 _ = &v;
22 _ = &ptr;
23}
24
25export fn ptrPtrArithmetic() void {
26 var value0: u8 = 0;
27 var value1: u8 = 0;
28 _ = &value0 - &value1;
29}
30
31export fn ptrIntArithmetic() void {
32 var ptr0: [*]u8 = undefined;
33 _ = &ptr0;
34 _ = ptr0 - 10;
35}
36
37// error
38// backend=stage2
39// target=spirv64-vulkan
40//
41// :3:8: error: illegal operation on logical pointer of type '[*]u8'
42// :3:8: note: cannot perform arithmetic on pointers with address space 'generic' on target spirv-vulkan
43// :8:18: error: illegal operation on logical pointer of type '[*]u8'
44// :8:18: note: cannot perform arithmetic on pointers with address space 'generic' on target spirv-vulkan
45// :15:21: error: illegal operation on logical pointer of type '*u8'
46// :15:21: note: cannot perform arithmetic on pointers with address space 'generic' on target spirv-vulkan
47// :20:20: error: illegal operation on logical pointer of type '*u8'
48// :20:20: note: cannot perform arithmetic on pointers with address space 'generic' on target spirv-vulkan
49// :28:17: error: illegal operation on logical pointer of type '*u8'
50// :28:17: note: cannot perform arithmetic on pointers with address space 'generic' on target spirv-vulkan
51// :34:14: error: illegal operation on logical pointer of type '[*]u8'
52// :34:14: note: cannot perform arithmetic on pointers with address space 'generic' on target spirv-vulkan
test/tests.zig+1-1
...@@ -143,7 +143,7 @@ const test_targets = blk: {...@@ -143,7 +143,7 @@ const test_targets = blk: {
143 .{143 .{
144 .target = std.Target.Query.parse(.{144 .target = std.Target.Query.parse(.{
145 .arch_os_abi = "spirv64-vulkan",145 .arch_os_abi = "spirv64-vulkan",
146 .cpu_features = "vulkan_v1_2+int8+int16+int64+float16+float64",146 .cpu_features = "vulkan_v1_2+int64+float16+float64",
147 }) catch unreachable,147 }) catch unreachable,
148 .use_llvm = false,148 .use_llvm = false,
149 .use_lld = false,149 .use_lld = false,