aboutsummaryrefslogtreecommitdiff
path: root/src/codegen/spirv.zig
diff options
context:
space:
mode:
authorRobin Voetter <robin@voetter.nl>2023-09-18 20:28:31 +0200
committerAndrew Kelley <andrew@ziglang.org>2023-09-23 12:36:56 -0700
commit5d844faf7c5c30555664b4161e5f9a903daaf562 (patch)
tree788856661b2789bafbd1049b863dd596cc611b72 /src/codegen/spirv.zig
parent26c279cca2e9b9d93c2d8744ba45c49076ff4a32 (diff)
downloadzig-5d844faf7c5c30555664b4161e5f9a903daaf562.tar.gz
zig-5d844faf7c5c30555664b4161e5f9a903daaf562.zip
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.
Diffstat (limited to 'src/codegen/spirv.zig')
-rw-r--r--src/codegen/spirv.zig35
1 files changed, 35 insertions, 0 deletions
diff --git a/src/codegen/spirv.zig b/src/codegen/spirv.zig
index e05c8142db..e4ce3e5f3f 100644
--- a/src/codegen/spirv.zig
+++ b/src/codegen/spirv.zig
@@ -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;