authorgravatar for me@brianferri.devBrian Ferri <me@brianferri.dev> 2026-10-04 11:50:49+02:00
committergravatar for alichraghi@proton.meAli Chraghi <alichraghi@proton.me> 2026-10-04 11:50:49+02:00
log25cafe0b345635dfaa533557f7185e76d5f405ef
tree2921cc7901f0aa0b973c4cd8cdf15aabd7f3cac3
parentca725632483559fc50df605cb885444005dcadb5

spirv: fix vector casts, packed field pointers and debug names of comptime-known values (#37040)

I'm writing a small numeric library whose kernels run on the CPU, on CUDA and on Vulkan through the self-hosted SPIR-V backend, and I was making them generic over the float type. `f64` needs its own `exp` and `log` on the GPU, so I wrote them as polynomial series, and the `f64` Vulkan module stopped validating. This fixes the three backend bugs underneath that, and a crash I ran into after merging master. The series take floats apart with `@bitCast` on vectors. Between vectors of the same length this reaches the Vulkan/OpenGL fallback in `bitCast`, which stores the source into a function variable of the destination type: ```zig export fn main() callconv(.{ .spirv_kernel = .{ .x = 1, .y = 1, .z = 1 } }) void { var x: @Vector(2, f32) = .{ 1, 2 }; _ = &x; const bits: @Vector(2, i32) = @bitCast(x); _ = bits; } ``` ``` $ zig build-exe -fno-llvm -target spirv64-vulkan -mcpu vulkan_v1_2 bitcast.zig -femit-bin=bitcast.spv $ spirv-val --target-env vulkan1.2 bitcast.spv error: line 45: OpStore Pointer <id> '36[%36]'s type does not match Object <id> '29[%29]'s type. ``` An elementwise vector bitcast is now a scalar `bitCast` per lane, the way `buildConvert` and friends already unroll vectors. Going through the scalar path also normalizes lanes of strange integers: a single `OpBitcast` on the whole vector validates for `@Vector(n, u3)` to `@Vector(n, i3)`, but leaves lanes that don't compare equal to the negative values they should hold. The series also convert between integer and float lanes. A vector of one lane, or of more than four without `vector16`, is an array in SPIR-V, and `airFloatFromInt` and `airIntFromFloat` emitted a single `OpConvert*` with that array as its result type: ```zig export fn main() callconv(.{ .spirv_kernel = .{ .x = 1, .y = 1, .z = 1 } }) void { var x: @Vector(1, i32) = .{1}; _ = &x; const y: @Vector(1, f32) = @floatFromInt(x); _ = y; } ``` ``` $ spirv-val --target-env vulkan1.2 convert.spv error: line 40: Expected float scalar or vector type as Result Type: ConvertSToF %y = OpConvertSToF %_arr_f32_u32_1 %26 ``` `@floatCast` and `@intCast` already go through `buildConvert`, which unrolls the vector; these two now do as well, with `buildConvert` picking the int/float conversion opcodes. The coefficients sit in a comptime array that the series take as a comptime slice, and that alone fails to compile, although nothing reads the slice at runtime: ```zig const weights = [_]f32{ 1, 2, 3 }; inline fn first(comptime w: []const f32) f32 { return w[0]; } export fn main() callconv(.{ .spirv_kernel = .{ .x = 1, .y = 1, .z = 1 } }) void { var x: f32 = first(&weights); _ = &x; } ``` ``` $ zig build-exe -fno-llvm -target spirv64-vulkan -mcpu vulkan_v1_2 dbgvar.zig -femit-bin=dbgvar.spv dbgvar.zig:7:8: error: TODO (SPIR-V): pointer to constant 'dbgvar.weights' ``` It appears `airDbgVar` lowers the operand only to attach an `OpName` to it, and a pointer to a non-extern constant is still a TODO. A comptime-known value has no runtime variable of its own to name, so `airDbgVar` now leaves interned operands alone. The same thing held back 58 of the behavior tests skipped on SPIR-V, and the test commit un-skips them. After merging master, four of those tests crashed the compiler in `structFieldPtr`, which has `unreachable` for packed containers since ebb8683ef1 ([#36996](https://codeberg.org/ziglang/zig/pulls/36996)): ```zig const Flags = packed struct { a: bool, b: bool }; export fn main() callconv(.{ .spirv_kernel = .{ .x = 1, .y = 1, .z = 1 } }) void { var flags: Flags = .{ .a = true, .b = false }; const b = &flags.b; b.* = true; } ``` ``` thread 3961624 panic: reached unreachable code src/codegen/spirv/CodeGen.zig:6906:27: 0x4767157 in structFieldPtr (main.zig) .@"packed" => unreachable, ``` My reading is that the `unreachable` holds for the pointer derivations it was written for, since `constantPtr` now turns packed pointers into pointers to their host integer first, but `airStructFieldPtr` and `airStructFieldPtrIndex` still pass packed structs through. A pointer to a packed field is a bit-pointer into the struct's own host integer, so it is the struct pointer: that is what the old code computed, and what the C backend now does with `.begin`. Packed unions get back the TODO error they had before. I may be missing a plan for packed field pointers here, and I'm happy to change it if so. The commit also un-skips three packed tests that crash on master the same way. I suppose nothing caught this because those tests are skipped on SPIR-V and the `spirv64-vulkan` behavior target is commented out in `test/tests.zig`. I ran the behavior tests through `tools/unskip_spirv_tests.zig` and [zig-spirv-test-executor](https://github.com/Snektron/zig-spirv-test-executor) on a Radeon 680M, and the new and un-skipped tests on an RTX 4060 as well. Every fix has tests that fail on master and pass with it; the vector ones compare lane by lane, since `expectEqual` on vectors doesn't compile for SPIR-V yet. Running each behavior file whole, nothing that passes on master fails. Five more skips already pass on master without these changes, so I left them out, but I can add them. The new vector tests copy the aarch64, arm, sparc64 and riscv64 skips of the tests around them, which I couldn't check. Reviewed-on: https://codeberg.org/ziglang/zig/pulls/37040 Reviewed-by: Ali Cheraghi <alichraghi@noreply.codeberg.org>

20 files changed, 119 insertions(+), 137 deletions(-)

src/codegen/spirv/CodeGen.zig+40-43
...@@ -3423,8 +3423,8 @@ fn vectorization(cg: *CodeGen, args: anytype) Vectorization {...@@ -3423,8 +3423,8 @@ fn vectorization(cg: *CodeGen, args: anytype) Vectorization {
3423 return v;3423 return v;
3424}3424}
34253425
3426/// This function builds an OpSConvert of OpUConvert depending on the3426/// This function builds the conversion between two numeric types: OpFConvert, OpSConvert or
3427/// signedness of the types.3427/// OpUConvert within floats or integers, and OpConvert{S,U}ToF or OpConvertFTo{S,U} across them.
3428fn buildConvert(cg: *CodeGen, dst_ty: Type, src: Temporary) !Temporary {3428fn buildConvert(cg: *CodeGen, dst_ty: Type, src: Temporary) !Temporary {
3429 const zcu = cg.zcu;3429 const zcu = cg.zcu;
34303430
...@@ -3453,8 +3453,16 @@ fn buildConvert(cg: *CodeGen, dst_ty: Type, src: Temporary) !Temporary {...@@ -3453,8 +3453,16 @@ fn buildConvert(cg: *CodeGen, dst_ty: Type, src: Temporary) !Temporary {
3453 const op_result_ty_id = try cg.resolveType(op_result_ty, .direct);3453 const op_result_ty_id = try cg.resolveType(op_result_ty, .direct);
34543454
3455 const opcode: Opcode = blk: {3455 const opcode: Opcode = blk: {
3456 if (dst_ty.scalarType(zcu).isAnyFloat()) break :blk .OpFConvert;3456 if (dst_scalar.isAnyFloat()) {
3457 if (dst_ty.scalarType(zcu).isSignedInt(zcu)) break :blk .OpSConvert;3457 if (src_scalar.isAnyFloat()) break :blk .OpFConvert;
3458 if (src_scalar.isSignedInt(zcu)) break :blk .OpConvertSToF;
3459 break :blk .OpConvertUToF;
3460 }
3461 if (src_scalar.isAnyFloat()) {
3462 if (dst_scalar.isSignedInt(zcu)) break :blk .OpConvertFToS;
3463 break :blk .OpConvertFToU;
3464 }
3465 if (dst_scalar.isSignedInt(zcu)) break :blk .OpSConvert;
3458 break :blk .OpUConvert;3466 break :blk .OpUConvert;
3459 };3467 };
34603468
...@@ -5801,6 +5809,23 @@ fn bitCast(...@@ -5801,6 +5809,23 @@ fn bitCast(
5801 // TODO: Some more cases are missing here5809 // TODO: Some more cases are missing here
5802 // See fn bitCast in llvm.zig5810 // See fn bitCast in llvm.zig
58035811
5812 // An elementwise vector bitcast is a scalar bitcast per lane, which also normalizes lanes
5813 // of strange integers.
5814 if (src_ty.isVector(zcu) and dst_ty.isVector(zcu) and
5815 src_ty.vectorLen(zcu) == dst_ty.vectorLen(zcu) and
5816 src_ty.childType(zcu).isNumeric(zcu) and dst_ty.childType(zcu).isNumeric(zcu))
5817 {
5818 const src_elem_ty = src_ty.childType(zcu);
5819 const dst_elem_ty = dst_ty.childType(zcu);
5820 const scratch_top = cg.id_scratch.items.len;
5821 defer cg.id_scratch.shrinkRetainingCapacity(scratch_top);
5822 for (0..src_ty.vectorLen(zcu)) |i| {
5823 const src_lane_id = try cg.extractVectorComponent(src_elem_ty, src_id, @intCast(i));
5824 try cg.id_scratch.append(gpa, try cg.bitCast(dst_elem_ty, src_elem_ty, src_lane_id));
5825 }
5826 break :blk try cg.constructComposite(dst_ty_id, cg.id_scratch.items[scratch_top..]);
5827 }
5828
5804 if (src_ty.zigTypeTag(zcu) == .int and dst_ty.isPtrAtRuntime(zcu)) {5829 if (src_ty.zigTypeTag(zcu) == .int and dst_ty.isPtrAtRuntime(zcu)) {
5805 if (target.os.tag != .opencl) {5830 if (target.os.tag != .opencl) {
5806 if (dst_ty.ptrAddressSpace(zcu) != .physical_storage_buffer) {5831 if (dst_ty.ptrAddressSpace(zcu) != .physical_storage_buffer) {
...@@ -6139,50 +6164,19 @@ fn intFromPtr(cg: *CodeGen, operand_id: Id) !Id {...@@ -6139,50 +6164,19 @@ fn intFromPtr(cg: *CodeGen, operand_id: Id) !Id {
6139}6164}
61406165
6141fn airFloatFromInt(cg: *CodeGen, inst: Air.Inst.Index) !?Id {6166fn airFloatFromInt(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
6142 const gpa = cg.gpa;
6143 const ty_op = cg.air.instructions.items(.data)[@backingInt(inst)].ty_op;6167 const ty_op = cg.air.instructions.items(.data)[@backingInt(inst)].ty_op;
6144 const operand_ty = cg.typeOf(ty_op.operand);6168 const operand = try cg.temporary(ty_op.operand);
6145 const operand_id = try cg.resolve(ty_op.operand);
6146 const result_ty = cg.typeOfIndex(inst);6169 const result_ty = cg.typeOfIndex(inst);
6147 const operand_info = cg.arithmeticTypeInfo(operand_ty);6170 const result = try cg.buildConvert(result_ty, operand);
6148 const result_id = cg.allocId();6171 return try result.materialize(cg);
6149 const result_ty_id = try cg.resolveType(result_ty, .direct);
6150 switch (operand_info.signedness) {
6151 .signed => try cg.body.emit(gpa, .OpConvertSToF, .{
6152 .id_result_type = result_ty_id,
6153 .id_result = result_id,
6154 .signed_value = operand_id,
6155 }),
6156 .unsigned => try cg.body.emit(gpa, .OpConvertUToF, .{
6157 .id_result_type = result_ty_id,
6158 .id_result = result_id,
6159 .unsigned_value = operand_id,
6160 }),
6161 }
6162 return result_id;
6163}6172}
61646173
6165fn airIntFromFloat(cg: *CodeGen, inst: Air.Inst.Index) !?Id {6174fn airIntFromFloat(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
6166 const gpa = cg.gpa;
6167 const ty_op = cg.air.instructions.items(.data)[@backingInt(inst)].ty_op;6175 const ty_op = cg.air.instructions.items(.data)[@backingInt(inst)].ty_op;
6168 const operand_id = try cg.resolve(ty_op.operand);6176 const operand = try cg.temporary(ty_op.operand);
6169 const result_ty = cg.typeOfIndex(inst);6177 const result_ty = cg.typeOfIndex(inst);
6170 const result_info = cg.arithmeticTypeInfo(result_ty);6178 const result = try cg.buildConvert(result_ty, operand);
6171 const result_ty_id = try cg.resolveType(result_ty, .direct);6179 return try result.materialize(cg);
6172 const result_id = cg.allocId();
6173 switch (result_info.signedness) {
6174 .signed => try cg.body.emit(gpa, .OpConvertFToS, .{
6175 .id_result_type = result_ty_id,
6176 .id_result = result_id,
6177 .float_value = operand_id,
6178 }),
6179 .unsigned => try cg.body.emit(gpa, .OpConvertFToU, .{
6180 .id_result_type = result_ty_id,
6181 .id_result = result_id,
6182 .float_value = operand_id,
6183 }),
6184 }
6185 return result_id;
6186}6180}
61876181
6188fn airFloatCast(cg: *CodeGen, inst: Air.Inst.Index) !?Id {6182fn airFloatCast(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
...@@ -6903,14 +6897,14 @@ fn structFieldPtr(...@@ -6903,14 +6897,14 @@ fn structFieldPtr(
6903 return cg.accessChain(result_ptr_ty_id, object_ptr, &.{field_index});6897 return cg.accessChain(result_ptr_ty_id, object_ptr, &.{field_index});
6904 },6898 },
6905 .@"struct" => switch (object_ty.containerLayout(zcu)) {6899 .@"struct" => switch (object_ty.containerLayout(zcu)) {
6906 .@"packed" => unreachable,6900 .@"packed" => return cg.todo("implement field access for packed structs", .{}),
6907 .auto, .@"extern" => {6901 .auto, .@"extern" => {
6908 const member_index = cg.memberIndex(object_ty, field_index);6902 const member_index = cg.memberIndex(object_ty, field_index);
6909 return try cg.accessChain(result_ptr_ty_id, object_ptr, &.{member_index});6903 return try cg.accessChain(result_ptr_ty_id, object_ptr, &.{member_index});
6910 },6904 },
6911 },6905 },
6912 .@"union" => switch (object_ty.containerLayout(zcu)) {6906 .@"union" => switch (object_ty.containerLayout(zcu)) {
6913 .@"packed" => unreachable,6907 .@"packed" => return cg.todo("implement field access for packed unions", .{}),
6914 .auto => {6908 .auto => {
6915 if (!field_ty.hasRuntimeBits(zcu)) return try cg.constUndef(result_ptr_ty_id);6909 if (!field_ty.hasRuntimeBits(zcu)) return try cg.constUndef(result_ptr_ty_id);
6916 return try cg.accessChain(result_ptr_ty_id, object_ptr, &.{field_index});6910 return try cg.accessChain(result_ptr_ty_id, object_ptr, &.{field_index});
...@@ -8483,6 +8477,9 @@ fn airDbgInlineBlock(cg: *CodeGen, inst: Air.Inst.Index) !?Id {...@@ -8483,6 +8477,9 @@ fn airDbgInlineBlock(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
84838477
8484fn airDbgVar(cg: *CodeGen, inst: Air.Inst.Index) !void {8478fn airDbgVar(cg: *CodeGen, inst: Air.Inst.Index) !void {
8485 const pl_op = cg.air.instructions.items(.data)[@backingInt(inst)].pl_op;8479 const pl_op = cg.air.instructions.items(.data)[@backingInt(inst)].pl_op;
8480 // A comptime-known value has no runtime variable of its own to name, and lowering it only to
8481 // name it can fail, as for a slice of a global constant.
8482 if (pl_op.operand.toInterned() != null) return;
8486 const target_id = switch (try cg.resolvePtr(pl_op.operand)) {8483 const target_id = switch (try cg.resolvePtr(pl_op.operand)) {
8487 .tracked => return,8484 .tracked => return,
8488 .id => |id| id,8485 .id => |id| id,
test/behavior/align.zig-2
...@@ -639,8 +639,6 @@ test "function pointer @intFromPtr/@ptrFromInt roundtrip" {...@@ -639,8 +639,6 @@ test "function pointer @intFromPtr/@ptrFromInt roundtrip" {
639}639}
640640
641test "function pointer align mask" {641test "function pointer align mask" {
642 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
643
644 const int = if (builtin.cpu.arch.isArm() or builtin.cpu.arch.isMIPS()) 0x20202021 else 0x20202020;642 const int = if (builtin.cpu.arch.isArm() or builtin.cpu.arch.isMIPS()) 0x20202021 else 0x20202020;
645 const unaligned: *const fn () callconv(.c) void = @ptrFromInt(int);643 const unaligned: *const fn () callconv(.c) void = @ptrFromInt(int);
646 const aligned: *align(16) const fn () callconv(.c) void = @alignCast(unaligned);644 const aligned: *align(16) const fn () callconv(.c) void = @alignCast(unaligned);
test/behavior/array.zig-8
...@@ -836,8 +836,6 @@ test "pointer to sentinel-terminated array initialized through reference to anon...@@ -836,8 +836,6 @@ test "pointer to sentinel-terminated array initialized through reference to anon
836}836}
837837
838test "tuple initialized through reference to anonymous array init provides result types" {838test "tuple initialized through reference to anonymous array init provides result types" {
839 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
840
841 const Tuple = struct { u64, *const u32 };839 const Tuple = struct { u64, *const u32 };
842 const foo: *const Tuple = &.{840 const foo: *const Tuple = &.{
843 @intCast(12345),841 @intCast(12345),
...@@ -978,15 +976,11 @@ test "runtime index of array of zero-bit values" {...@@ -978,15 +976,11 @@ test "runtime index of array of zero-bit values" {
978}976}
979977
980test "initialize slice with reference to empty array initializer" {978test "initialize slice with reference to empty array initializer" {
981 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
982
983 const a: []const u8 = &.{};979 const a: []const u8 = &.{};
984 comptime assert(a.len == 0);980 comptime assert(a.len == 0);
985}981}
986982
987test "initialize many-pointer with reference to empty array initializer" {983test "initialize many-pointer with reference to empty array initializer" {
988 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
989
990 const a: [*]const u8 = &.{};984 const a: [*]const u8 = &.{};
991 _ = a; // nothing meaningful to test; points to zero bits985 _ = a; // nothing meaningful to test; points to zero bits
992}986}
...@@ -1012,8 +1006,6 @@ test "pass pointer to empty array initializer to anytype parameter" {...@@ -1012,8 +1006,6 @@ test "pass pointer to empty array initializer to anytype parameter" {
1012}1006}
10131007
1014test "initialize pointer to anyopaque with reference to empty array initializer" {1008test "initialize pointer to anyopaque with reference to empty array initializer" {
1015 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1016
1017 const ptr: *const anyopaque = &.{};1009 const ptr: *const anyopaque = &.{};
1018 // The above acts like an untyped initializer, since the `.{}` has no result type.1010 // The above acts like an untyped initializer, since the `.{}` has no result type.
1019 // So, `ptr` points in memory to an empty tuple (`@TypeOf(.{})`).1011 // So, `ptr` points in memory to an empty tuple (`@TypeOf(.{})`).
test/behavior/basic.zig-8
...@@ -297,7 +297,6 @@ const global_a: i32 = 1234;...@@ -297,7 +297,6 @@ const global_a: i32 = 1234;
297const global_b: *const i32 = &global_a;297const global_b: *const i32 = &global_a;
298const global_c: *const f32 = @as(*const f32, @ptrCast(global_b));298const global_c: *const f32 = @as(*const f32, @ptrCast(global_b));
299test "compile time global reinterpret" {299test "compile time global reinterpret" {
300 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
301 const d = @as(*const i32, @ptrCast(global_c));300 const d = @as(*const i32, @ptrCast(global_c));
302 try expect(d.* == 1234);301 try expect(d.* == 1234);
303}302}
...@@ -637,7 +636,6 @@ fn emptyFn() void {}...@@ -637,7 +636,6 @@ fn emptyFn() void {}
637636
638const addr1 = @as(*const u8, @ptrCast(&emptyFn));637const addr1 = @as(*const u8, @ptrCast(&emptyFn));
639test "comptime cast fn to ptr" {638test "comptime cast fn to ptr" {
640 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
641 const addr2 = @as(*const u8, @ptrCast(&emptyFn));639 const addr2 = @as(*const u8, @ptrCast(&emptyFn));
642 comptime assert(addr1 == addr2);640 comptime assert(addr1 == addr2);
643}641}
...@@ -915,7 +913,6 @@ test "labeled block with runtime branch forwards its result location type to bre...@@ -915,7 +913,6 @@ test "labeled block with runtime branch forwards its result location type to bre
915913
916test "try in labeled block doesn't cast to wrong type" {914test "try in labeled block doesn't cast to wrong type" {
917 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO915 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
918 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
919916
920 const S = struct {917 const S = struct {
921 a: u32,918 a: u32,
...@@ -1001,8 +998,6 @@ test "generic function uses return type of other generic function" {...@@ -1001,8 +998,6 @@ test "generic function uses return type of other generic function" {
1001}998}
1002999
1003test "const alloc with comptime-known initializer is made comptime-known" {1000test "const alloc with comptime-known initializer is made comptime-known" {
1004 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1005
1006 const S = struct {1001 const S = struct {
1007 a: bool,1002 a: bool,
1008 b: [2]u8,1003 b: [2]u8,
...@@ -1276,7 +1271,6 @@ test "@Int returned from block" {...@@ -1276,7 +1271,6 @@ test "@Int returned from block" {
1276}1271}
12771272
1278test "comptime variable initialized with addresses of literals" {1273test "comptime variable initialized with addresses of literals" {
1279 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1280 comptime var st = .{1274 comptime var st = .{
1281 .foo = &1,1275 .foo = &1,
1282 .bar = &2,1276 .bar = &2,
...@@ -1326,8 +1320,6 @@ test "proper value is returned from labeled block" {...@@ -1326,8 +1320,6 @@ test "proper value is returned from labeled block" {
1326}1320}
13271321
1328test "const inferred array of slices" {1322test "const inferred array of slices" {
1329 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1330
1331 const T = struct { v: bool };1323 const T = struct { v: bool };
13321324
1333 const decls = [_][]const T{1325 const decls = [_][]const T{
test/behavior/bitcast.zig+30
...@@ -311,6 +311,36 @@ test "bitcast vector to integer and back" {...@@ -311,6 +311,36 @@ test "bitcast vector to integer and back" {
311 try expect(int_again == 0b1111_1111_1111_1101);311 try expect(int_again == 0b1111_1111_1111_1101);
312}312}
313313
314test "bitcast vector elementwise" {
315 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
316 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
317 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
318 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
319
320 const S = struct {
321 fn doTheTest(comptime len: comptime_int) !void {
322 var floats: @Vector(len, f32) = std.simd.iota(f32, len) + @as(@Vector(len, f32), @splat(0.5));
323 _ = &floats;
324 const bits: @Vector(len, i32) = @bitCast(floats);
325 inline for (0..len) |i| try expect(bits[i] == @as(i32, @bitCast(@as(f32, @floatFromInt(i)) + 0.5)));
326 const floats_again: @Vector(len, f32) = @bitCast(bits);
327 inline for (0..len) |i| try expect(floats_again[i] == @as(f32, @floatFromInt(i)) + 0.5);
328
329 var unsigned: @Vector(len, u3) = std.simd.iota(u3, len);
330 _ = &unsigned;
331 const signed: @Vector(len, i3) = @bitCast(unsigned);
332 inline for (0..len) |i| try expect(signed[i] == @as(i3, @bitCast(@as(u3, i))));
333 const unsigned_again: @Vector(len, u3) = @bitCast(signed);
334 inline for (0..len) |i| try expect(unsigned_again[i] == i);
335 }
336 };
337
338 inline for (.{ 1, 2, 3, 4, 8 }) |len| {
339 try S.doTheTest(len);
340 try comptime S.doTheTest(len);
341 }
342}
343
314fn bitCastWrapper16(x: f16) u16 {344fn bitCastWrapper16(x: f16) u16 {
315 return @as(u16, @bitCast(x));345 return @as(u16, @bitCast(x));
316}346}
test/behavior/cast.zig+30-13
...@@ -9,8 +9,6 @@ const maxInt = std.math.maxInt;...@@ -9,8 +9,6 @@ const maxInt = std.math.maxInt;
9const native_endian = builtin.target.cpu.arch.endian();9const native_endian = builtin.target.cpu.arch.endian();
1010
11test "int to ptr cast" {11test "int to ptr cast" {
12 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
13
14 const x = @as(usize, 13);12 const x = @as(usize, 13);
15 const y = @as(*u8, @ptrFromInt(x));13 const y = @as(*u8, @ptrFromInt(x));
16 const z = @intFromPtr(y);14 const z = @intFromPtr(y);
...@@ -18,8 +16,6 @@ test "int to ptr cast" {...@@ -18,8 +16,6 @@ test "int to ptr cast" {
18}16}
1917
20test "integer literal to pointer cast" {18test "integer literal to pointer cast" {
21 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
22
23 const vga_mem = @as(*u16, @ptrFromInt(0xB8000));19 const vga_mem = @as(*u16, @ptrFromInt(0xB8000));
24 try expect(@intFromPtr(vga_mem) == 0xB8000);20 try expect(@intFromPtr(vga_mem) == 0xB8000);
25}21}
...@@ -71,8 +67,6 @@ test "implicit cast comptime_int to comptime_float" {...@@ -71,8 +67,6 @@ test "implicit cast comptime_int to comptime_float" {
71}67}
7268
73test "comptime_int @floatFromInt" {69test "comptime_int @floatFromInt" {
74 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
75
76 {70 {
77 const result = @as(f16, @floatFromInt(1234));71 const result = @as(f16, @floatFromInt(1234));
78 try expect(@TypeOf(result) == f16);72 try expect(@TypeOf(result) == f16);
...@@ -538,8 +532,6 @@ test "return u8 coercing into ?u32 return type" {...@@ -538,8 +532,6 @@ test "return u8 coercing into ?u32 return type" {
538}532}
539533
540test "cast from ?[*]T to ??[*]T" {534test "cast from ?[*]T to ??[*]T" {
541 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
542
543 const a: ??[*]u8 = @as(?[*]u8, null);535 const a: ??[*]u8 = @as(?[*]u8, null);
544 try expect(a != null and a.? == null);536 try expect(a != null and a.? == null);
545}537}
...@@ -1423,7 +1415,6 @@ test "comptime float casts" {...@@ -1423,7 +1415,6 @@ test "comptime float casts" {
1423}1415}
14241416
1425test "pointer reinterpret const float to int" {1417test "pointer reinterpret const float to int" {
1426 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1427 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1418 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
14281419
1429 // The hex representation is 0x3fe3333333333303.1420 // The hex representation is 0x3fe3333333333303.
...@@ -1843,8 +1834,6 @@ test "coerce between pointers of compatible differently-named floats" {...@@ -1843,8 +1834,6 @@ test "coerce between pointers of compatible differently-named floats" {
1843}1834}
18441835
1845test "peer type resolution of const and non-const pointer to array" {1836test "peer type resolution of const and non-const pointer to array" {
1846 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1847
1848 const a = @as(*[1024]u8, @ptrFromInt(42));1837 const a = @as(*[1024]u8, @ptrFromInt(42));
1849 const b = @as(*const [1024]u8, @ptrFromInt(42));1838 const b = @as(*const [1024]u8, @ptrFromInt(42));
1850 try std.testing.expect(@TypeOf(a, b) == *const [1024]u8);1839 try std.testing.expect(@TypeOf(a, b) == *const [1024]u8);
...@@ -1909,8 +1898,6 @@ test "optional pointer coerced to optional allowzero pointer" {...@@ -1909,8 +1898,6 @@ test "optional pointer coerced to optional allowzero pointer" {
1909}1898}
19101899
1911test "optional slice coerced to allowzero many pointer" {1900test "optional slice coerced to allowzero many pointer" {
1912 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1913
1914 const a: ?[]const u32 = null;1901 const a: ?[]const u32 = null;
1915 const b: [*]allowzero const u8 = @ptrCast(a);1902 const b: [*]allowzero const u8 = @ptrCast(a);
1916 const c = @intFromPtr(b);1903 const c = @intFromPtr(b);
...@@ -2932,6 +2919,36 @@ test "@intFromFloat on vector" {...@@ -2932,6 +2919,36 @@ test "@intFromFloat on vector" {
2932 try comptime S.doTheTest();2919 try comptime S.doTheTest();
2933}2920}
29342921
2922test "@floatFromInt and @intFromFloat on vectors of any length" {
2923 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
2924 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2925 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
2926 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
2927
2928 const S = struct {
2929 fn doTheTest(comptime len: comptime_int) !void {
2930 var signed: @Vector(len, i32) = std.simd.iota(i32, len) - @as(@Vector(len, i32), @splat(4));
2931 _ = &signed;
2932 const from_signed: @Vector(len, f32) = @floatFromInt(signed);
2933 inline for (0..len) |i| try expect(from_signed[i] == @as(f32, @floatFromInt(@as(i32, i) - 4)));
2934 const to_signed: @Vector(len, i32) = @intFromFloat(from_signed);
2935 inline for (0..len) |i| try expect(to_signed[i] == @as(i32, i) - 4);
2936
2937 var unsigned: @Vector(len, u32) = std.simd.iota(u32, len) * @as(@Vector(len, u32), @splat(3));
2938 _ = &unsigned;
2939 const from_unsigned: @Vector(len, f32) = @floatFromInt(unsigned);
2940 inline for (0..len) |i| try expect(from_unsigned[i] == @as(f32, @floatFromInt(i * 3)));
2941 const to_unsigned: @Vector(len, u32) = @intFromFloat(from_unsigned);
2942 inline for (0..len) |i| try expect(to_unsigned[i] == i * 3);
2943 }
2944 };
2945
2946 inline for (.{ 1, 2, 3, 4, 8 }) |len| {
2947 try S.doTheTest(len);
2948 try comptime S.doTheTest(len);
2949 }
2950}
2951
2935test "@intFromBool on vector" {2952test "@intFromBool on vector" {
2936 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;2953 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
2937 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;2954 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
test/behavior/comptime_memory.zig-10
...@@ -407,8 +407,6 @@ test "mutate entire slice at comptime" {...@@ -407,8 +407,6 @@ test "mutate entire slice at comptime" {
407}407}
408408
409test "dereference undefined pointer to zero-bit type" {409test "dereference undefined pointer to zero-bit type" {
410 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
411
412 const p0: *void = undefined;410 const p0: *void = undefined;
413 try testing.expectEqual({}, p0.*);411 try testing.expectEqual({}, p0.*);
414412
...@@ -424,16 +422,12 @@ test "type pun extern struct" {...@@ -424,16 +422,12 @@ test "type pun extern struct" {
424}422}
425423
426test "type pun @ptrFromInt" {424test "type pun @ptrFromInt" {
427 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
428
429 const p: *u8 = @ptrFromInt(42);425 const p: *u8 = @ptrFromInt(42);
430 // note that expectEqual hides the bug426 // note that expectEqual hides the bug
431 try testing.expect(@as(*const [*]u8, @ptrCast(&p)).* == @as([*]u8, @ptrFromInt(42)));427 try testing.expect(@as(*const [*]u8, @ptrCast(&p)).* == @as([*]u8, @ptrFromInt(42)));
432}428}
433429
434test "type pun null pointer-like optional" {430test "type pun null pointer-like optional" {
435 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
436
437 const p: ?*u8 = null;431 const p: ?*u8 = null;
438 // note that expectEqual hides the bug432 // note that expectEqual hides the bug
439 try testing.expect(@as(*const ?*i8, @ptrCast(&p)).* == null);433 try testing.expect(@as(*const ?*i8, @ptrCast(&p)).* == null);
...@@ -557,8 +551,6 @@ test "comptime store of packed struct with void field into array" {...@@ -557,8 +551,6 @@ test "comptime store of packed struct with void field into array" {
557}551}
558552
559test "comptime store of reinterpreted zero-bit type" {553test "comptime store of reinterpreted zero-bit type" {
560 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
561
562 const S = struct {554 const S = struct {
563 fn doTheTest(comptime T: type) void {555 fn doTheTest(comptime T: type) void {
564 comptime var buf: T = undefined;556 comptime var buf: T = undefined;
...@@ -590,8 +582,6 @@ test "comptime store to extern struct reinterpreted as byte array" {...@@ -590,8 +582,6 @@ test "comptime store to extern struct reinterpreted as byte array" {
590}582}
591583
592test "reinterpret sentinel-terminated array as packed struct" {584test "reinterpret sentinel-terminated array as packed struct" {
593 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
594
595 const S = packed struct(u16) { lo: u8, hi: u8 };585 const S = packed struct(u16) { lo: u8, hi: u8 };
596 const data: [2:0]u8 = .{ 0x12, 0x34 };586 const data: [2:0]u8 = .{ 0x12, 0x34 };
597 const ptr: *align(1) const S = @ptrCast(&data);587 const ptr: *align(1) const S = @ptrCast(&data);
test/behavior/error.zig-2
...@@ -555,7 +555,6 @@ test "return result loc as peer result loc in inferred error set function" {...@@ -555,7 +555,6 @@ test "return result loc as peer result loc in inferred error set function" {
555}555}
556556
557test "error payload type is correctly resolved" {557test "error payload type is correctly resolved" {
558 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
559 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO558 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
560 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO559 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
561560
...@@ -1108,7 +1107,6 @@ test "'if' ignores error via local while 'else' ignores error directly" {...@@ -1108,7 +1107,6 @@ test "'if' ignores error via local while 'else' ignores error directly" {
1108}1107}
11091108
1110test "@errorCast into own inferred error set" {1109test "@errorCast into own inferred error set" {
1111 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1112 const static = struct {1110 const static = struct {
1113 fn foo(b: bool) !void {1111 fn foo(b: bool) !void {
1114 if (b) {1112 if (b) {
test/behavior/eval.zig-6
...@@ -876,16 +876,12 @@ test "comptime pointer load through elem_ptr" {...@@ -876,16 +876,12 @@ test "comptime pointer load through elem_ptr" {
876}876}
877877
878test "debug variable type resolved through indirect zero-bit types" {878test "debug variable type resolved through indirect zero-bit types" {
879 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
880
881 const T = struct { key: []void };879 const T = struct { key: []void };
882 const slice: []const T = &[_]T{};880 const slice: []const T = &[_]T{};
883 _ = slice;881 _ = slice;
884}882}
885883
886test "const local with comptime init through array init" {884test "const local with comptime init through array init" {
887 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
888
889 const E1 = enum {885 const E1 = enum {
890 A,886 A,
891 pub fn a() void {}887 pub fn a() void {}
...@@ -1163,8 +1159,6 @@ test "repeated value is correctly expanded" {...@@ -1163,8 +1159,6 @@ test "repeated value is correctly expanded" {
1163}1159}
11641160
1165test "value in if block is comptime-known" {1161test "value in if block is comptime-known" {
1166 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1167
1168 const first = blk: {1162 const first = blk: {
1169 const s = if (false) "a" else "b";1163 const s = if (false) "a" else "b";
1170 break :blk "foo" ++ s;1164 break :blk "foo" ++ s;
test/behavior/floatop.zig-2
...@@ -349,7 +349,6 @@ fn testDifferentSizedFloatComparisons() !void {...@@ -349,7 +349,6 @@ fn testDifferentSizedFloatComparisons() !void {
349test "negative f128 intFromFloat at compile-time" {349test "negative f128 intFromFloat at compile-time" {
350 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO350 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
351 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO351 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
352 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
353352
354 const a: f128 = -2;353 const a: f128 = -2;
355 var b: i64 = @intFromFloat(a);354 var b: i64 = @intFromFloat(a);
...@@ -1550,7 +1549,6 @@ test "comptime fixed-width float zero divided by zero produces NaN" {...@@ -1550,7 +1549,6 @@ test "comptime fixed-width float zero divided by zero produces NaN" {
1550test "comptime fixed-width float non-zero divided by zero produces signed Inf" {1549test "comptime fixed-width float non-zero divided by zero produces signed Inf" {
1551 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1550 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1552 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1551 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1553 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
15541552
1555 inline for (.{ f16, f32, f64, f80, f128 }) |F| {1553 inline for (.{ f16, f32, f64, f80, f128 }) |F| {
1556 const pos = @as(F, 1) / @as(F, 0);1554 const pos = @as(F, 1) / @as(F, 0);
test/behavior/for.zig-3
...@@ -453,7 +453,6 @@ test "inline for with counter as the comptime-known" {...@@ -453,7 +453,6 @@ test "inline for with counter as the comptime-known" {
453test "inline for on tuple pointer" {453test "inline for on tuple pointer" {
454 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO454 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
455 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO455 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
456 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
457456
458 const S = struct { u32, u32, u32 };457 const S = struct { u32, u32, u32 };
459 var s: S = .{ 100, 200, 300 };458 var s: S = .{ 100, 200, 300 };
...@@ -522,8 +521,6 @@ test "return from inline for" {...@@ -522,8 +521,6 @@ test "return from inline for" {
522}521}
523522
524test "for loop 0 length range" {523test "for loop 0 length range" {
525 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
526
527 const map: []const u8 = &.{};524 const map: []const u8 = &.{};
528 for (map, 0..map.len) |i, j| {525 for (map, 0..map.len) |i, j| {
529 _ = i;526 _ = i;
test/behavior/math.zig-1
...@@ -2506,7 +2506,6 @@ test "runtime comparison to NaN is comptime-known" {...@@ -2506,7 +2506,6 @@ test "runtime comparison to NaN is comptime-known" {
2506test "runtime int comparison to inf is comptime-known" {2506test "runtime int comparison to inf is comptime-known" {
2507 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO2507 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2508 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO2508 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
2509 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
2510 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;2509 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
25112510
2512 const S = struct {2511 const S = struct {
test/behavior/pointers.zig-14
...@@ -266,8 +266,6 @@ test "implicit cast error unions with non-optional to optional pointer" {...@@ -266,8 +266,6 @@ test "implicit cast error unions with non-optional to optional pointer" {
266}266}
267267
268test "compare equality of optional and non-optional pointer" {268test "compare equality of optional and non-optional pointer" {
269 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
270
271 const a = @as(*const usize, @ptrFromInt(0x12345678));269 const a = @as(*const usize, @ptrFromInt(0x12345678));
272 const b = @as(?*usize, @ptrFromInt(0x12345678));270 const b = @as(?*usize, @ptrFromInt(0x12345678));
273 try expect(a == b);271 try expect(a == b);
...@@ -453,8 +451,6 @@ test "pointer sentinel with +inf" {...@@ -453,8 +451,6 @@ test "pointer sentinel with +inf" {
453}451}
454452
455test "pointer to array at fixed address" {453test "pointer to array at fixed address" {
456 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
457
458 const array = @as(*volatile [2]u32, @ptrFromInt(0x10));454 const array = @as(*volatile [2]u32, @ptrFromInt(0x10));
459 // Silly check just to reference `array`455 // Silly check just to reference `array`
460 try expect(@intFromPtr(&array[0]) == 0x10);456 try expect(@intFromPtr(&array[0]) == 0x10);
...@@ -496,8 +492,6 @@ test "pointer-integer arithmetic affects the alignment" {...@@ -496,8 +492,6 @@ test "pointer-integer arithmetic affects the alignment" {
496}492}
497493
498test "@intFromPtr on null optional at comptime" {494test "@intFromPtr on null optional at comptime" {
499 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
500
501 {495 {
502 const pointer = @as(?*u8, @ptrFromInt(0x000));496 const pointer = @as(?*u8, @ptrFromInt(0x000));
503 const x = @intFromPtr(pointer);497 const x = @intFromPtr(pointer);
...@@ -642,8 +636,6 @@ test "result type preserved through multiple references" {...@@ -642,8 +636,6 @@ test "result type preserved through multiple references" {
642}636}
643637
644test "result type found through optional pointer" {638test "result type found through optional pointer" {
645 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
646
647 const ptr1: ?*const u32 = &@intCast(123);639 const ptr1: ?*const u32 = &@intCast(123);
648 const ptr2: ?[]const u8 = &.{ @intCast(123), @truncate(0xABCD) };640 const ptr2: ?[]const u8 = &.{ @intCast(123), @truncate(0xABCD) };
649 try expect(ptr1.?.* == 123);641 try expect(ptr1.?.* == 123);
...@@ -710,8 +702,6 @@ test "pointer-to-array constness for zero-size elements, const" {...@@ -710,8 +702,6 @@ test "pointer-to-array constness for zero-size elements, const" {
710}702}
711703
712test "cast pointers with zero sized elements" {704test "cast pointers with zero sized elements" {
713 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
714
715 const a: *void = undefined;705 const a: *void = undefined;
716 const b: *[1]void = a;706 const b: *[1]void = a;
717 _ = b;707 _ = b;
...@@ -721,8 +711,6 @@ test "cast pointers with zero sized elements" {...@@ -721,8 +711,6 @@ test "cast pointers with zero sized elements" {
721}711}
722712
723test "comptime pointer equality through distinct fields with well-defined layout" {713test "comptime pointer equality through distinct fields with well-defined layout" {
724 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
725
726 const A = extern struct {714 const A = extern struct {
727 x: u32,715 x: u32,
728 z: u16,716 z: u16,
...@@ -785,8 +773,6 @@ test "pointers to elements of many-ptr to zero-bit type" {...@@ -785,8 +773,6 @@ test "pointers to elements of many-ptr to zero-bit type" {
785}773}
786774
787test "comptime C pointer to optional pointer" {775test "comptime C pointer to optional pointer" {
788 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
789
790 const opt: ?*u8 = @ptrFromInt(0x1000);776 const opt: ?*u8 = @ptrFromInt(0x1000);
791 const outer_ptr: [*c]const ?*u8 = &opt;777 const outer_ptr: [*c]const ?*u8 = &opt;
792 const inner_ptr = &outer_ptr.*.?;778 const inner_ptr = &outer_ptr.*.?;
test/behavior/ptrcast.zig-9
...@@ -24,7 +24,6 @@ fn testReinterpretBytesAsInteger() !void {...@@ -24,7 +24,6 @@ fn testReinterpretBytesAsInteger() !void {
24test "reinterpret an array over multiple elements, with no well-defined layout" {24test "reinterpret an array over multiple elements, with no well-defined layout" {
25 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO25 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
26 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO26 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
27 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
2827
29 try testReinterpretWithOffsetAndNoWellDefinedLayout();28 try testReinterpretWithOffsetAndNoWellDefinedLayout();
30 try comptime testReinterpretWithOffsetAndNoWellDefinedLayout();29 try comptime testReinterpretWithOffsetAndNoWellDefinedLayout();
...@@ -282,8 +281,6 @@ test "@ptrCast undefined value at comptime" {...@@ -282,8 +281,6 @@ test "@ptrCast undefined value at comptime" {
282}281}
283282
284test "comptime @ptrCast with packed struct leaves value unmodified" {283test "comptime @ptrCast with packed struct leaves value unmodified" {
285 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
286
287 const S = packed struct { three: u3 };284 const S = packed struct { three: u3 };
288 const st: S = .{ .three = 6 };285 const st: S = .{ .three = 6 };
289 try expect(st.three == 6);286 try expect(st.three == 6);
...@@ -293,8 +290,6 @@ test "comptime @ptrCast with packed struct leaves value unmodified" {...@@ -293,8 +290,6 @@ test "comptime @ptrCast with packed struct leaves value unmodified" {
293}290}
294291
295test "@ptrCast restructures comptime-only array" {292test "@ptrCast restructures comptime-only array" {
296 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
297
298 {293 {
299 const a3a2: [3][2]comptime_int = .{294 const a3a2: [3][2]comptime_int = .{
300 .{ 1, 2 },295 .{ 1, 2 },
...@@ -561,8 +556,6 @@ test "@ptrCast single-item pointer to slice of bytes" {...@@ -561,8 +556,6 @@ test "@ptrCast single-item pointer to slice of bytes" {
561}556}
562557
563test "@ptrCast array pointer removing sentinel" {558test "@ptrCast array pointer removing sentinel" {
564 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
565
566 const in: *const [4:0]u8 = &.{ 1, 2, 3, 4 };559 const in: *const [4:0]u8 = &.{ 1, 2, 3, 4 };
567 const out: []const i8 = @ptrCast(in);560 const out: []const i8 = @ptrCast(in);
568 comptime assert(out.len == 4);561 comptime assert(out.len == 4);
...@@ -573,8 +566,6 @@ test "@ptrCast array pointer removing sentinel" {...@@ -573,8 +566,6 @@ test "@ptrCast array pointer removing sentinel" {
573}566}
574567
575test "@ptrcast larger type to smaller one" {568test "@ptrcast larger type to smaller one" {
576 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
577
578 const T = packed struct { x: u17 };569 const T = packed struct { x: u17 };
579 const a: u32 = 0;570 const a: u32 = 0;
580 const b: *const T = @ptrCast(&a);571 const b: *const T = @ptrCast(&a);
test/behavior/ptrfromint.zig-1
...@@ -44,7 +44,6 @@ test "@ptrFromInt creates null pointer" {...@@ -44,7 +44,6 @@ test "@ptrFromInt creates null pointer" {
44test "@ptrFromInt creates allowzero zero pointer" {44test "@ptrFromInt creates allowzero zero pointer" {
45 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;45 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
46 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO46 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
47 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
4847
49 const ptr = @as(*allowzero u32, @ptrFromInt(0));48 const ptr = @as(*allowzero u32, @ptrFromInt(0));
50 try expectEqual(@as(usize, 0), @intFromPtr(ptr));49 try expectEqual(@as(usize, 0), @intFromPtr(ptr));
test/behavior/slice.zig+19-2
...@@ -385,8 +385,6 @@ test "obtaining a null terminated slice" {...@@ -385,8 +385,6 @@ test "obtaining a null terminated slice" {
385}385}
386386
387test "empty array to slice" {387test "empty array to slice" {
388 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
389
390 const S = struct {388 const S = struct {
391 fn doTheTest() !void {389 fn doTheTest() !void {
392 const empty: []align(16) u8 = &[_]u8{};390 const empty: []align(16) u8 = &[_]u8{};
...@@ -403,6 +401,25 @@ test "empty array to slice" {...@@ -403,6 +401,25 @@ test "empty array to slice" {
403 try comptime S.doTheTest();401 try comptime S.doTheTest();
404}402}
405403
404test "comptime-known slice of a global constant" {
405 const S = struct {
406 const weights = [_]f32{ 1, 2, 3 };
407
408 inline fn first(comptime w: []const f32) f32 {
409 return w[0];
410 }
411 };
412
413 var from_param: f32 = S.first(&S.weights);
414 _ = &from_param;
415 try expect(from_param == 1);
416
417 const w: []const f32 = &S.weights;
418 var from_local: f32 = w[1];
419 _ = &from_local;
420 try expect(from_local == 2);
421}
422
406test "@ptrCast slice to pointer" {423test "@ptrCast slice to pointer" {
407 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO424 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
408 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;425 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
test/behavior/struct.zig-3
...@@ -1631,8 +1631,6 @@ test "struct init with no result pointer sets field result types" {...@@ -1631,8 +1631,6 @@ test "struct init with no result pointer sets field result types" {
1631}1631}
16321632
1633test "runtime side-effects in comptime-known struct init" {1633test "runtime side-effects in comptime-known struct init" {
1634 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1635
1636 var side_effects: u4 = 0;1634 var side_effects: u4 = 0;
1637 const S = struct { a: u4, b: u4, c: u4, d: u4 };1635 const S = struct { a: u4, b: u4, c: u4, d: u4 };
1638 const init = S{1636 const init = S{
...@@ -2275,7 +2273,6 @@ test "struct contains underaligned field with overaligned pointer to itself" {...@@ -2275,7 +2273,6 @@ test "struct contains underaligned field with overaligned pointer to itself" {
2275}2273}
22762274
2277test "struct contains pointer to function accepting that struct" {2275test "struct contains pointer to function accepting that struct" {
2278 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
2279 const S = struct {2276 const S = struct {
2280 const FnPtr = ?*const fn (@This()) void;2277 const FnPtr = ?*const fn (@This()) void;
2281 fn_ptr: FnPtr,2278 fn_ptr: FnPtr,
test/behavior/type.zig-2
...@@ -406,8 +406,6 @@ test "matching captures causes opaque equivalence" {...@@ -406,8 +406,6 @@ test "matching captures causes opaque equivalence" {
406}406}
407407
408test "reify enum where fields refers to part of array" {408test "reify enum where fields refers to part of array" {
409 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
410
411 const field_names: [3][]const u8 = .{ "foo", "bar", undefined };409 const field_names: [3][]const u8 = .{ "foo", "bar", undefined };
412 const field_values: [3]u8 = .{ undefined, 0, 1 };410 const field_values: [3]u8 = .{ undefined, 0, 1 };
413 const E = @Enum(u8, .exhaustive, field_names[0..2], field_values[1..3]);411 const E = @Enum(u8, .exhaustive, field_names[0..2], field_values[1..3]);
test/behavior/type_info.zig-4
...@@ -310,8 +310,6 @@ const TestStruct = struct {...@@ -310,8 +310,6 @@ const TestStruct = struct {
310};310};
311311
312test "type info: packed struct info" {312test "type info: packed struct info" {
313 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
314
315 try testPackedStruct();313 try testPackedStruct();
316 try comptime testPackedStruct();314 try comptime testPackedStruct();
317}315}
...@@ -596,8 +594,6 @@ test "value from struct @typeInfo default_value_ptr can be loaded at comptime" {...@@ -596,8 +594,6 @@ test "value from struct @typeInfo default_value_ptr can be loaded at comptime" {
596}594}
597595
598test "type info of tuple of string literal default value" {596test "type info of tuple of string literal default value" {
599 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
600
601 const struct_info = @typeInfo(@TypeOf(.{"hi"})).@"struct";597 const struct_info = @typeInfo(@TypeOf(.{"hi"})).@"struct";
602 const struct_field_attrs = struct_info.field_attrs[0];598 const struct_field_attrs = struct_info.field_attrs[0];
603 const struct_field_type = struct_info.field_types[0];599 const struct_field_type = struct_info.field_types[0];
test/behavior/union.zig-4
...@@ -1109,8 +1109,6 @@ test "union with a large struct field" {...@@ -1109,8 +1109,6 @@ test "union with a large struct field" {
1109}1109}
11101110
1111test "comptime equality of extern unions with same tag" {1111test "comptime equality of extern unions with same tag" {
1112 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1113
1114 const S = struct {1112 const S = struct {
1115 const U = extern union {1113 const U = extern union {
1116 a: i32,1114 a: i32,
...@@ -1845,8 +1843,6 @@ test "inner struct initializer uses packed union layout" {...@@ -1845,8 +1843,6 @@ test "inner struct initializer uses packed union layout" {
1845}1843}
18461844
1847test "extern union initialized via reintepreted struct field initializer" {1845test "extern union initialized via reintepreted struct field initializer" {
1848 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1849
1850 const bytes = [_]u8{ 0xaa, 0xbb, 0xcc, 0xdd };1846 const bytes = [_]u8{ 0xaa, 0xbb, 0xcc, 0xdd };
18511847
1852 const U = extern union {1848 const U = extern union {