authorgravatar for robin@voetter.nlRobin Voetter <robin@voetter.nl> 2023-09-18 20:28:31+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-09-23 12:36:56-07:00
log5d844faf7c5c30555664b4161e5f9a903daaf562
tree788856661b2789bafbd1049b863dd596cc611b72
parent26c279cca2e9b9d93c2d8744ba45c49076ff4a32

spirv: air array_elem_val using hack

SPIR-V doesn't support true element indexing, so we probably need to switch over to isByRef like in llvm for this to work properly. Currently a temporary is used, which at least seems to work.

2 files changed, 35 insertions(+), 11 deletions(-)

src/codegen/spirv.zig+35
...@@ -1694,6 +1694,7 @@ pub const DeclGen = struct {...@@ -1694,6 +1694,7 @@ pub const DeclGen = struct {
1694 .slice_elem_val => try self.airSliceElemVal(inst),1694 .slice_elem_val => try self.airSliceElemVal(inst),
1695 .ptr_elem_ptr => try self.airPtrElemPtr(inst),1695 .ptr_elem_ptr => try self.airPtrElemPtr(inst),
1696 .ptr_elem_val => try self.airPtrElemVal(inst),1696 .ptr_elem_val => try self.airPtrElemVal(inst),
1697 .array_elem_val => try self.airArrayElemVal(inst),
16971698
1698 .set_union_tag => return try self.airSetUnionTag(inst),1699 .set_union_tag => return try self.airSetUnionTag(inst),
1699 .get_union_tag => try self.airGetUnionTag(inst),1700 .get_union_tag => try self.airGetUnionTag(inst),
...@@ -2567,6 +2568,40 @@ pub const DeclGen = struct {...@@ -2567,6 +2568,40 @@ pub const DeclGen = struct {
2567 return try self.ptrElemPtr(ptr_ty, ptr_id, index_id);2568 return try self.ptrElemPtr(ptr_ty, ptr_id, index_id);
2568 }2569 }
25692570
2571 fn airArrayElemVal(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
2572 if (self.liveness.isUnused(inst)) return null;
2573
2574 const mod = self.module;
2575 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
2576 const array_ty = self.typeOf(bin_op.lhs);
2577 const array_ty_ref = try self.resolveType(array_ty, .direct);
2578 const elem_ty = array_ty.childType(mod);
2579 const elem_ty_ref = try self.resolveType(elem_ty, .indirect);
2580 const array_id = try self.resolve(bin_op.lhs);
2581 const index_id = try self.resolve(bin_op.rhs);
2582
2583 // SPIR-V doesn't have an array indexing function for some damn reason.
2584 // For now, just generate a temporary and use that.
2585 // TODO: This backend probably also should use isByRef from llvm...
2586
2587 const array_ptr_ty_ref = try self.spv.ptrType(array_ty_ref, .Function);
2588 const elem_ptr_ty_ref = try self.spv.ptrType(elem_ty_ref, .Function);
2589
2590 const tmp_id = self.spv.allocId();
2591 try self.func.prologue.emit(self.spv.gpa, .OpVariable, .{
2592 .id_result_type = self.typeId(array_ptr_ty_ref),
2593 .id_result = tmp_id,
2594 .storage_class = .Function,
2595 });
2596 try self.func.body.emit(self.spv.gpa, .OpStore, .{
2597 .pointer = tmp_id,
2598 .object = array_id,
2599 });
2600
2601 const elem_ptr_id = try self.accessChainId(elem_ptr_ty_ref, tmp_id, &.{index_id});
2602 return try self.load(elem_ty, elem_ptr_id, false);
2603 }
2604
2570 fn airPtrElemVal(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {2605 fn airPtrElemVal(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
2571 if (self.liveness.isUnused(inst)) return null;2606 if (self.liveness.isUnused(inst)) return null;
25722607
test/behavior/array.zig-11
...@@ -21,7 +21,6 @@ test "arrays" {...@@ -21,7 +21,6 @@ test "arrays" {
21 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;21 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
22 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;22 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
23 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO23 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
24 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
2524
26 var array: [5]u32 = undefined;25 var array: [5]u32 = undefined;
2726
...@@ -141,7 +140,6 @@ test "array literal with specified size" {...@@ -141,7 +140,6 @@ test "array literal with specified size" {
141 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;140 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
142 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;141 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
143 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO142 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
144 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
145143
146 var array = [2]u8{ 1, 2 };144 var array = [2]u8{ 1, 2 };
147 try expect(array[0] == 1);145 try expect(array[0] == 1);
...@@ -201,7 +199,6 @@ test "nested arrays of strings" {...@@ -201,7 +199,6 @@ test "nested arrays of strings" {
201 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;199 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
202 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;200 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
203 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO201 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
204 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
205202
206 const array_of_strings = [_][]const u8{ "hello", "this", "is", "my", "thing" };203 const array_of_strings = [_][]const u8{ "hello", "this", "is", "my", "thing" };
207 for (array_of_strings, 0..) |s, i| {204 for (array_of_strings, 0..) |s, i| {
...@@ -288,7 +285,6 @@ test "anonymous list literal syntax" {...@@ -288,7 +285,6 @@ test "anonymous list literal syntax" {
288 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;285 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
289 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;286 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
290 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO287 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
291 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
292288
293 const S = struct {289 const S = struct {
294 fn doTheTest() !void {290 fn doTheTest() !void {
...@@ -479,7 +475,6 @@ test "anonymous literal in array" {...@@ -479,7 +475,6 @@ test "anonymous literal in array" {
479 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;475 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
480 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO476 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
481 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO477 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
482 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
483478
484 const S = struct {479 const S = struct {
485 const Foo = struct {480 const Foo = struct {
...@@ -504,7 +499,6 @@ test "anonymous literal in array" {...@@ -504,7 +499,6 @@ test "anonymous literal in array" {
504test "access the null element of a null terminated array" {499test "access the null element of a null terminated array" {
505 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;500 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
506 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO501 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
507 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
508502
509 const S = struct {503 const S = struct {
510 fn doTheTest() !void {504 fn doTheTest() !void {
...@@ -522,7 +516,6 @@ test "type deduction for array subscript expression" {...@@ -522,7 +516,6 @@ test "type deduction for array subscript expression" {
522 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;516 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
523 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO517 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
524 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO518 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
525 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
526519
527 const S = struct {520 const S = struct {
528 fn doTheTest() !void {521 fn doTheTest() !void {
...@@ -620,7 +613,6 @@ test "type coercion of pointer to anon struct literal to pointer to array" {...@@ -620,7 +613,6 @@ test "type coercion of pointer to anon struct literal to pointer to array" {
620 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO613 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
621 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO614 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
622 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO615 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
623 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
624616
625 const S = struct {617 const S = struct {
626 const U = union {618 const U = union {
...@@ -703,7 +695,6 @@ test "array of array agregate init" {...@@ -703,7 +695,6 @@ test "array of array agregate init" {
703 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO695 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
704 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO696 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
705 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO697 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
706 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
707698
708 var a = [1]u32{11} ** 10;699 var a = [1]u32{11} ** 10;
709 var b = [1][10]u32{a} ** 2;700 var b = [1][10]u32{a} ** 2;
...@@ -763,8 +754,6 @@ test "slicing array of zero-sized values" {...@@ -763,8 +754,6 @@ test "slicing array of zero-sized values" {
763}754}
764755
765test "array init with no result pointer sets field result types" {756test "array init with no result pointer sets field result types" {
766 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
767
768 const S = struct {757 const S = struct {
769 // A function parameter has a result type, but no result pointer.758 // A function parameter has a result type, but no result pointer.
770 fn f(arr: [1]u32) u32 {759 fn f(arr: [1]u32) u32 {