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.
This commit is contained in:
Robin Voetter
2023-09-18 20:28:31 +02:00
committed by Andrew Kelley
parent 26c279cca2
commit 5d844faf7c
2 changed files with 35 additions and 11 deletions

View File

@@ -1694,6 +1694,7 @@ pub const DeclGen = struct {
.slice_elem_val => try self.airSliceElemVal(inst),
.ptr_elem_ptr => try self.airPtrElemPtr(inst),
.ptr_elem_val => try self.airPtrElemVal(inst),
.array_elem_val => try self.airArrayElemVal(inst),
.set_union_tag => return try self.airSetUnionTag(inst),
.get_union_tag => try self.airGetUnionTag(inst),
@@ -2567,6 +2568,40 @@ pub const DeclGen = struct {
return try self.ptrElemPtr(ptr_ty, ptr_id, index_id);
}
fn airArrayElemVal(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
if (self.liveness.isUnused(inst)) return null;
const mod = self.module;
const bin_op = self.air.instructions.items(.data)[inst].bin_op;
const array_ty = self.typeOf(bin_op.lhs);
const array_ty_ref = try self.resolveType(array_ty, .direct);
const elem_ty = array_ty.childType(mod);
const elem_ty_ref = try self.resolveType(elem_ty, .indirect);
const array_id = try self.resolve(bin_op.lhs);
const index_id = try self.resolve(bin_op.rhs);
// SPIR-V doesn't have an array indexing function for some damn reason.
// For now, just generate a temporary and use that.
// TODO: This backend probably also should use isByRef from llvm...
const array_ptr_ty_ref = try self.spv.ptrType(array_ty_ref, .Function);
const elem_ptr_ty_ref = try self.spv.ptrType(elem_ty_ref, .Function);
const tmp_id = self.spv.allocId();
try self.func.prologue.emit(self.spv.gpa, .OpVariable, .{
.id_result_type = self.typeId(array_ptr_ty_ref),
.id_result = tmp_id,
.storage_class = .Function,
});
try self.func.body.emit(self.spv.gpa, .OpStore, .{
.pointer = tmp_id,
.object = array_id,
});
const elem_ptr_id = try self.accessChainId(elem_ptr_ty_ref, tmp_id, &.{index_id});
return try self.load(elem_ty, elem_ptr_id, false);
}
fn airPtrElemVal(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
if (self.liveness.isUnused(inst)) return null;

View File

@@ -21,7 +21,6 @@ test "arrays" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
var array: [5]u32 = undefined;
@@ -141,7 +140,6 @@ test "array literal with specified size" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
var array = [2]u8{ 1, 2 };
try expect(array[0] == 1);
@@ -201,7 +199,6 @@ test "nested arrays of strings" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
const array_of_strings = [_][]const u8{ "hello", "this", "is", "my", "thing" };
for (array_of_strings, 0..) |s, i| {
@@ -288,7 +285,6 @@ test "anonymous list literal syntax" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
const S = struct {
fn doTheTest() !void {
@@ -479,7 +475,6 @@ test "anonymous literal in array" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
const S = struct {
const Foo = struct {
@@ -504,7 +499,6 @@ test "anonymous literal in array" {
test "access the null element of a null terminated array" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
const S = struct {
fn doTheTest() !void {
@@ -522,7 +516,6 @@ test "type deduction for array subscript expression" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
const S = struct {
fn doTheTest() !void {
@@ -620,7 +613,6 @@ test "type coercion of pointer to anon struct literal to pointer to array" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
const S = struct {
const U = union {
@@ -703,7 +695,6 @@ test "array of array agregate init" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
var a = [1]u32{11} ** 10;
var b = [1][10]u32{a} ** 2;
@@ -763,8 +754,6 @@ test "slicing array of zero-sized values" {
}
test "array init with no result pointer sets field result types" {
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
const S = struct {
// A function parameter has a result type, but no result pointer.
fn f(arr: [1]u32) u32 {