diff options
| author | Robin Voetter <robin@voetter.nl> | 2023-09-18 20:28:31 +0200 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2023-09-23 12:36:56 -0700 |
| commit | 5d844faf7c5c30555664b4161e5f9a903daaf562 (patch) | |
| tree | 788856661b2789bafbd1049b863dd596cc611b72 /src/codegen/spirv.zig | |
| parent | 26c279cca2e9b9d93c2d8744ba45c49076ff4a32 (diff) | |
| download | zig-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.zig | 35 |
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; |
