authorgravatar for robin@voetter.nlRobin Voetter <robin@voetter.nl> 2023-05-19 14:17:58+02:00
committergravatar for robin@voetter.nlRobin Voetter <robin@voetter.nl> 2023-05-20 17:30:23+02:00
log65157d30ab90de01da583dd97ee2409d8ad8aeb0
tree0c9767c8c174bfd55fd0d9c5525d4ddef1ec7ceb
parent77b8bf2b82ffa71fc8ecf85f6780130f27dbeaf3
signaturelock-open Commit is signed but in an unrecognized format.

spirv: ptr_elem_val

Implements the ptr_elem_val air tag. Implementation is unified with ptr_elem_ptr.

21 files changed, 36 insertions(+), 41 deletions(-)

src/codegen/spirv.zig+36-12
...@@ -1765,6 +1765,7 @@ pub const DeclGen = struct {...@@ -1765,6 +1765,7 @@ pub const DeclGen = struct {
1765 .slice_elem_ptr => try self.airSliceElemPtr(inst),1765 .slice_elem_ptr => try self.airSliceElemPtr(inst),
1766 .slice_elem_val => try self.airSliceElemVal(inst),1766 .slice_elem_val => try self.airSliceElemVal(inst),
1767 .ptr_elem_ptr => try self.airPtrElemPtr(inst),1767 .ptr_elem_ptr => try self.airPtrElemPtr(inst),
1768 .ptr_elem_val => try self.airPtrElemVal(inst),
17681769
1769 .struct_field_val => try self.airStructFieldVal(inst),1770 .struct_field_val => try self.airStructFieldVal(inst),
17701771
...@@ -2482,29 +2483,52 @@ pub const DeclGen = struct {...@@ -2482,29 +2483,52 @@ pub const DeclGen = struct {
2482 return try self.load(slice_ty, elem_ptr);2483 return try self.load(slice_ty, elem_ptr);
2483 }2484 }
24842485
2486 fn ptrElemPtr(self: *DeclGen, ptr_ty: Type, ptr_id: IdRef, index_id: IdRef) !IdRef {
2487 // Construct new pointer type for the resulting pointer
2488 const elem_ty = ptr_ty.elemType2(); // use elemType() so that we get T for *[N]T.
2489 const elem_ty_ref = try self.resolveType(elem_ty, .direct);
2490 const elem_ptr_ty_ref = try self.spv.ptrType(elem_ty_ref, spvStorageClass(ptr_ty.ptrAddressSpace()), 0);
2491 if (ptr_ty.isSinglePointer()) {
2492 // Pointer-to-array. In this case, the resulting pointer is not of the same type
2493 // as the ptr_ty (we want a *T, not a *[N]T), and hence we need to use accessChain.
2494 return try self.accessChain(elem_ptr_ty_ref, ptr_id, &.{index_id});
2495 } else {
2496 // Resulting pointer type is the same as the ptr_ty, so use ptrAccessChain
2497 return try self.ptrAccessChain(elem_ptr_ty_ref, ptr_id, index_id, &.{});
2498 }
2499 }
2500
2485 fn airPtrElemPtr(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {2501 fn airPtrElemPtr(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
2486 if (self.liveness.isUnused(inst)) return null;2502 if (self.liveness.isUnused(inst)) return null;
24872503
2488 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;2504 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
2489 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;2505 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
2490 const ptr_ty = self.air.typeOf(bin_op.lhs);2506 const ptr_ty = self.air.typeOf(bin_op.lhs);
2491 const result_ty = self.air.typeOfIndex(inst);
2492 const elem_ty = ptr_ty.childType();2507 const elem_ty = ptr_ty.childType();
2493 // TODO: Make this return a null ptr or something2508 // TODO: Make this return a null ptr or something
2494 if (!elem_ty.hasRuntimeBitsIgnoreComptime()) return null;2509 if (!elem_ty.hasRuntimeBitsIgnoreComptime()) return null;
24952510
2496 const result_ty_ref = try self.resolveType(result_ty, .direct);2511 const ptr_id = try self.resolve(bin_op.lhs);
2497 const base_ptr = try self.resolve(bin_op.lhs);2512 const index_id = try self.resolve(bin_op.rhs);
2498 const rhs = try self.resolve(bin_op.rhs);2513 return try self.ptrElemPtr(ptr_ty, ptr_id, index_id);
2514 }
24992515
2500 if (ptr_ty.isSinglePointer()) {2516 fn airPtrElemVal(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
2501 // Pointer-to-array. In this case, the resulting pointer is not of the same type2517 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
2502 // as the ptr_ty, and hence we need to use accessChain.2518 const ptr_ty = self.air.typeOf(bin_op.lhs);
2503 return try self.accessChain(result_ty_ref, base_ptr, &.{rhs});2519 const ptr_id = try self.resolve(bin_op.lhs);
2504 } else {2520 const index_id = try self.resolve(bin_op.rhs);
2505 // Resulting pointer type is the same as the ptr_ty, so use ptrAccessChain2521
2506 return try self.ptrAccessChain(result_ty_ref, base_ptr, rhs, &.{});2522 const elem_ptr_id = try self.ptrElemPtr(ptr_ty, ptr_id, index_id);
2507 }2523
2524 // If we have a pointer-to-array, construct an element pointer to use with load()
2525 // If we pass ptr_ty directly, it will attempt to load the entire array rather than
2526 // just an element.
2527 var elem_ptr_info = ptr_ty.ptrInfo();
2528 elem_ptr_info.data.size = .One;
2529 const elem_ptr_ty = Type.initPayload(&elem_ptr_info.base);
2530
2531 return try self.load(elem_ptr_ty, elem_ptr_id);
2508 }2532 }
25092533
2510 fn airStructFieldVal(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {2534 fn airStructFieldVal(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
test/behavior/align.zig-2
...@@ -215,8 +215,6 @@ test "alignment and size of structs with 128-bit fields" {...@@ -215,8 +215,6 @@ test "alignment and size of structs with 128-bit fields" {
215}215}
216216
217test "@ptrCast preserves alignment of bigger source" {217test "@ptrCast preserves alignment of bigger source" {
218 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
219
220 var x: u32 align(16) = 1234;218 var x: u32 align(16) = 1234;
221 const ptr = @ptrCast(*u8, &x);219 const ptr = @ptrCast(*u8, &x);
222 try expect(@TypeOf(ptr) == *align(16) u8);220 try expect(@TypeOf(ptr) == *align(16) u8);
test/behavior/call.zig-2
...@@ -385,8 +385,6 @@ test "generic function with generic function parameter" {...@@ -385,8 +385,6 @@ test "generic function with generic function parameter" {
385}385}
386386
387test "recursive inline call with comptime known argument" {387test "recursive inline call with comptime known argument" {
388 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
389
390 const S = struct {388 const S = struct {
391 inline fn foo(x: i32) i32 {389 inline fn foo(x: i32) i32 {
392 if (x <= 0) {390 if (x <= 0) {
test/behavior/cast.zig-1
...@@ -322,7 +322,6 @@ test "peer result null and comptime_int" {...@@ -322,7 +322,6 @@ test "peer result null and comptime_int" {
322test "*const ?[*]const T to [*c]const [*c]const T" {322test "*const ?[*]const T to [*c]const [*c]const T" {
323 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;323 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
324 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO324 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
325 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
326325
327 var array = [_]u8{ 'o', 'k' };326 var array = [_]u8{ 'o', 'k' };
328 const opt_array_ptr: ?[*]const u8 = &array;327 const opt_array_ptr: ?[*]const u8 = &array;
test/behavior/error.zig-1
...@@ -22,7 +22,6 @@ test "error values" {...@@ -22,7 +22,6 @@ test "error values" {
22}22}
2323
24test "redefinition of error values allowed" {24test "redefinition of error values allowed" {
25 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
26 shouldBeNotEqual(error.AnError, error.SecondError);25 shouldBeNotEqual(error.AnError, error.SecondError);
27}26}
28fn shouldBeNotEqual(a: anyerror, b: anyerror) void {27fn shouldBeNotEqual(a: anyerror, b: anyerror) void {
test/behavior/eval.zig-2
...@@ -47,8 +47,6 @@ test "inline variable gets result of const if" {...@@ -47,8 +47,6 @@ test "inline variable gets result of const if" {
47}47}
4848
49test "static function evaluation" {49test "static function evaluation" {
50 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
51
52 try expect(statically_added_number == 3);50 try expect(statically_added_number == 3);
53}51}
54const statically_added_number = staticAdd(1, 2);52const statically_added_number = staticAdd(1, 2);
test/behavior/floatop.zig-1
...@@ -620,7 +620,6 @@ test "@floor" {...@@ -620,7 +620,6 @@ test "@floor" {
620 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO620 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
621 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO621 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
622 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO622 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
623 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
624623
625 comptime try testFloor();624 comptime try testFloor();
626 try testFloor();625 try testFloor();
test/behavior/fn.zig-2
...@@ -12,8 +12,6 @@ fn testParamsAdd(a: i32, b: i32) i32 {...@@ -12,8 +12,6 @@ fn testParamsAdd(a: i32, b: i32) i32 {
12}12}
1313
14test "local variables" {14test "local variables" {
15 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
16
17 testLocVars(2);15 testLocVars(2);
18}16}
19fn testLocVars(b: i32) void {17fn testLocVars(b: i32) void {
test/behavior/for.zig-2
...@@ -39,8 +39,6 @@ fn testBreakOuter() !void {...@@ -39,8 +39,6 @@ fn testBreakOuter() !void {
39}39}
4040
41test "continue outer for loop" {41test "continue outer for loop" {
42 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
43
44 try testContinueOuter();42 try testContinueOuter();
45 comptime try testContinueOuter();43 comptime try testContinueOuter();
46}44}
test/behavior/generics.zig-1
...@@ -19,7 +19,6 @@ fn checkSize(comptime T: type) usize {...@@ -19,7 +19,6 @@ fn checkSize(comptime T: type) usize {
19test "simple generic fn" {19test "simple generic fn" {
20 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;20 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
21 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO21 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
22 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
2322
24 try expect(max(i32, 3, -1) == 3);23 try expect(max(i32, 3, -1) == 3);
25 try expect(max(u8, 1, 100) == 100);24 try expect(max(u8, 1, 100) == 100);
test/behavior/optional.zig-1
...@@ -421,7 +421,6 @@ test "optional of noreturn used with orelse" {...@@ -421,7 +421,6 @@ test "optional of noreturn used with orelse" {
421}421}
422422
423test "orelse on C pointer" {423test "orelse on C pointer" {
424 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
425424
426 // TODO https://github.com/ziglang/zig/issues/6597425 // TODO https://github.com/ziglang/zig/issues/6597
427 const foo: [*c]const u8 = "hey";426 const foo: [*c]const u8 = "hey";
test/behavior/packed-struct.zig-1
...@@ -93,7 +93,6 @@ test "flags in packed structs" {...@@ -93,7 +93,6 @@ test "flags in packed structs" {
9393
94test "consistent size of packed structs" {94test "consistent size of packed structs" {
95 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO95 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
96 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
9796
98 const TxData1 = packed struct { data: u8, _23: u23, full: bool = false };97 const TxData1 = packed struct { data: u8, _23: u23, full: bool = false };
99 const TxData2 = packed struct { data: u9, _22: u22, full: bool = false };98 const TxData2 = packed struct { data: u9, _22: u22, full: bool = false };
test/behavior/pointers.zig-2
...@@ -19,7 +19,6 @@ fn testDerefPtr() !void {...@@ -19,7 +19,6 @@ fn testDerefPtr() !void {
19test "pointer arithmetic" {19test "pointer arithmetic" {
20 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;20 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
21 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO21 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
22 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
2322
24 var ptr: [*]const u8 = "abcd";23 var ptr: [*]const u8 = "abcd";
2524
...@@ -300,7 +299,6 @@ test "null terminated pointer" {...@@ -300,7 +299,6 @@ test "null terminated pointer" {
300test "allow any sentinel" {299test "allow any sentinel" {
301 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;300 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
302 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO301 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
303 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
304302
305 const S = struct {303 const S = struct {
306 fn doTheTest() !void {304 fn doTheTest() !void {
test/behavior/sizeof_and_typeof.zig-1
...@@ -154,7 +154,6 @@ test "@TypeOf() has no runtime side effects" {...@@ -154,7 +154,6 @@ test "@TypeOf() has no runtime side effects" {
154154
155test "branching logic inside @TypeOf" {155test "branching logic inside @TypeOf" {
156 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;156 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
157 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
158157
159 const S = struct {158 const S = struct {
160 var data: i32 = 0;159 var data: i32 = 0;
test/behavior/slice.zig-1
...@@ -672,7 +672,6 @@ test "array mult of slice gives ptr to array" {...@@ -672,7 +672,6 @@ test "array mult of slice gives ptr to array" {
672672
673test "slice bounds in comptime concatenation" {673test "slice bounds in comptime concatenation" {
674 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO674 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
675 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
676675
677 const bs = comptime blk: {676 const bs = comptime blk: {
678 const b = "........1........";677 const b = "........1........";
test/behavior/struct.zig-2
...@@ -121,8 +121,6 @@ test "struct byval assign" {...@@ -121,8 +121,6 @@ test "struct byval assign" {
121}121}
122122
123test "call struct static method" {123test "call struct static method" {
124 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
125
126 const result = StructWithNoFields.add(3, 4);124 const result = StructWithNoFields.add(3, 4);
127 try expect(result == 7);125 try expect(result == 7);
128}126}
test/behavior/switch.zig-2
...@@ -348,8 +348,6 @@ fn returnsFalse() bool {...@@ -348,8 +348,6 @@ fn returnsFalse() bool {
348 }348 }
349}349}
350test "switch on const enum with var" {350test "switch on const enum with var" {
351 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
352
353 try expect(!returnsFalse());351 try expect(!returnsFalse());
354}352}
355353
test/behavior/threadlocal.zig-1
...@@ -46,7 +46,6 @@ test "reference a global threadlocal variable" {...@@ -46,7 +46,6 @@ test "reference a global threadlocal variable" {
46 else => return error.SkipZigTest,46 else => return error.SkipZigTest,
47 }; // TODO47 }; // TODO
48 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO48 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
49 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
5049
51 _ = nrfx_uart_rx(&g_uart0);50 _ = nrfx_uart_rx(&g_uart0);
52}51}
test/behavior/type_info.zig-1
...@@ -512,7 +512,6 @@ test "type info for async frames" {...@@ -512,7 +512,6 @@ test "type info for async frames" {
512512
513test "Declarations are returned in declaration order" {513test "Declarations are returned in declaration order" {
514 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO514 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
515 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
516515
517 const S = struct {516 const S = struct {
518 const a = 1;517 const a = 1;
test/behavior/var_args.zig-1
...@@ -30,7 +30,6 @@ test "send void arg to var args" {...@@ -30,7 +30,6 @@ test "send void arg to var args" {
30test "pass args directly" {30test "pass args directly" {
31 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO31 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
32 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO32 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
33 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
3433
35 try expect(addSomeStuff(.{ @as(i32, 1), @as(i32, 2), @as(i32, 3), @as(i32, 4) }) == 10);34 try expect(addSomeStuff(.{ @as(i32, 1), @as(i32, 2), @as(i32, 3), @as(i32, 4) }) == 10);
36 try expect(addSomeStuff(.{@as(i32, 1234)}) == 1234);35 try expect(addSomeStuff(.{@as(i32, 1234)}) == 1234);
test/behavior/while.zig-2
...@@ -38,8 +38,6 @@ fn staticWhileLoop2() i32 {...@@ -38,8 +38,6 @@ fn staticWhileLoop2() i32 {
38}38}
3939
40test "while with continue expression" {40test "while with continue expression" {
41 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
42
43 var sum: i32 = 0;41 var sum: i32 = 0;
44 {42 {
45 var i: i32 = 0;43 var i: i32 = 0;