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 {
16941694 .slice_elem_val => try self.airSliceElemVal(inst),
16951695 .ptr_elem_ptr => try self.airPtrElemPtr(inst),
16961696 .ptr_elem_val => try self.airPtrElemVal(inst),
1697 .array_elem_val => try self.airArrayElemVal(inst),
16971698
16981699 .set_union_tag => return try self.airSetUnionTag(inst),
16991700 .get_union_tag => try self.airGetUnionTag(inst),
......@@ -2567,6 +2568,40 @@ pub const DeclGen = struct {
25672568 return try self.ptrElemPtr(ptr_ty, ptr_id, index_id);
25682569 }
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
25702605 fn airPtrElemVal(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
25712606 if (self.liveness.isUnused(inst)) return null;
25722607
test/behavior/array.zig-11
......@@ -21,7 +21,6 @@ test "arrays" {
2121 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
2222 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
2323 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
24 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
2524
2625 var array: [5]u32 = undefined;
2726
......@@ -141,7 +140,6 @@ test "array literal with specified size" {
141140 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
142141 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
143142 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
144 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
145143
146144 var array = [2]u8{ 1, 2 };
147145 try expect(array[0] == 1);
......@@ -201,7 +199,6 @@ test "nested arrays of strings" {
201199 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
202200 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
203201 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
204 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
205202
206203 const array_of_strings = [_][]const u8{ "hello", "this", "is", "my", "thing" };
207204 for (array_of_strings, 0..) |s, i| {
......@@ -288,7 +285,6 @@ test "anonymous list literal syntax" {
288285 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
289286 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
290287 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
291 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
292288
293289 const S = struct {
294290 fn doTheTest() !void {
......@@ -479,7 +475,6 @@ test "anonymous literal in array" {
479475 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
480476 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
481477 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
482 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
483478
484479 const S = struct {
485480 const Foo = struct {
......@@ -504,7 +499,6 @@ test "anonymous literal in array" {
504499test "access the null element of a null terminated array" {
505500 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
506501 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
507 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
508502
509503 const S = struct {
510504 fn doTheTest() !void {
......@@ -522,7 +516,6 @@ test "type deduction for array subscript expression" {
522516 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
523517 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
524518 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
525 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
526519
527520 const S = struct {
528521 fn doTheTest() !void {
......@@ -620,7 +613,6 @@ test "type coercion of pointer to anon struct literal to pointer to array" {
620613 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
621614 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
622615 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
623 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
624616
625617 const S = struct {
626618 const U = union {
......@@ -703,7 +695,6 @@ test "array of array agregate init" {
703695 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
704696 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
705697 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
706 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
707698
708699 var a = [1]u32{11} ** 10;
709700 var b = [1][10]u32{a} ** 2;
......@@ -763,8 +754,6 @@ test "slicing array of zero-sized values" {
763754}
764755
765756test "array init with no result pointer sets field result types" {
766 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
767
768757 const S = struct {
769758 // A function parameter has a result type, but no result pointer.
770759 fn f(arr: [1]u32) u32 {