authorgravatar for robin@voetter.nlRobin Voetter <robin@voetter.nl> 2022-11-26 18:55:25+01:00
committergravatar for robin@voetter.nlRobin Voetter <robin@voetter.nl> 2023-04-09 01:51:49+02:00
logc23d668c79e25ba6a83ec01d9e58f136a5afe7cf
tree46b558b2571be81f3ab75ebb45462c448e3ab5ee
parent3c5ab4dd3d23b191b184b70dc8255b253a7ddc2c
signaturelock-open Commit is signed but in an unrecognized format.

spirv: slice operations

This commit adds support for SPIR-V code generation for the following AIR instructions: - slice_ptr - slice_len - slice_elem_ptr - slice_elem_val

1 files changed, 94 insertions(+), 3 deletions(-)

src/codegen/spirv.zig+94-3
......@@ -717,8 +717,12 @@ pub const DeclGen = struct {
717717 .bool_and => try self.airBinOpSimple(inst, .OpLogicalAnd),
718718 .bool_or => try self.airBinOpSimple(inst, .OpLogicalOr),
719719
720 .bitcast => try self.airBitcast(inst),
721 .not => try self.airNot(inst),
720 .bitcast => try self.airBitcast(inst),
721 .not => try self.airNot(inst),
722 .slice_ptr => try self.airSliceField(inst, 0),
723 .slice_len => try self.airSliceField(inst, 1),
724 .slice_elem_ptr => try self.airSliceElemPtr(inst),
725 .slice_elem_val => try self.airSliceElemVal(inst),
722726
723727 .cmp_eq => try self.airCmp(inst, .OpFOrdEqual, .OpLogicalEqual, .OpIEqual),
724728 .cmp_neq => try self.airCmp(inst, .OpFOrdNotEqual, .OpLogicalNotEqual, .OpINotEqual),
......@@ -924,7 +928,7 @@ pub const DeclGen = struct {
924928 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
925929 const operand_id = try self.resolve(ty_op.operand);
926930 const result_id = self.spv.allocId();
927 const result_type_id = try self.resolveTypeId(Type.initTag(.bool));
931 const result_type_id = try self.resolveTypeId(self.air.typeOfIndex(inst));
928932 try self.func.body.emit(self.spv.gpa, .OpBitcast, .{
929933 .id_result_type = result_type_id,
930934 .id_result = result_id,
......@@ -947,6 +951,93 @@ pub const DeclGen = struct {
947951 return result_id.toRef();
948952 }
949953
954 fn airSliceField(self: *DeclGen, inst: Air.Inst.Index, field: u32) !?IdRef {
955 if (self.liveness.isUnused(inst)) return null;
956 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
957 const result_id = self.spv.allocId();
958 try self.func.body.emit(self.spv.gpa, .OpCompositeExtract, .{
959 .id_result_type = try self.resolveTypeId(self.air.typeOfIndex(inst)),
960 .id_result = result_id,
961 .composite = try self.resolve(ty_op.operand),
962 .indexes = &.{field},
963 });
964 return result_id.toRef();
965 }
966
967 fn airSliceElemPtr(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
968 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
969 const slice_ty = self.air.typeOf(bin_op.lhs);
970 if (!slice_ty.isVolatilePtr() and self.liveness.isUnused(inst)) return null;
971
972 const slice = try self.resolve(bin_op.lhs);
973 const index = try self.resolve(bin_op.rhs);
974
975 const spv_ptr_ty = try self.resolveTypeId(self.air.typeOfIndex(inst));
976
977 const slice_ptr = blk: {
978 const result_id = self.spv.allocId();
979 try self.func.body.emit(self.spv.gpa, .OpCompositeExtract, .{
980 .id_result_type = spv_ptr_ty,
981 .id_result = result_id,
982 .composite = slice,
983 .indexes = &.{0},
984 });
985 break :blk result_id.toRef();
986 };
987
988 const result_id = self.spv.allocId();
989 try self.func.body.emit(self.spv.gpa, .OpInBoundsAccessChain, .{
990 .id_result_type = spv_ptr_ty,
991 .id_result = result_id,
992 .base = slice_ptr,
993 .indexes = &.{index},
994 });
995 return result_id.toRef();
996 }
997
998 fn airSliceElemVal(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
999 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1000 const slice_ty = self.air.typeOf(bin_op.lhs);
1001 if (!slice_ty.isVolatilePtr() and self.liveness.isUnused(inst)) return null;
1002
1003 const slice = try self.resolve(bin_op.lhs);
1004 const index = try self.resolve(bin_op.rhs);
1005
1006 const spv_elem_ty = try self.resolveTypeId(self.air.typeOfIndex(inst));
1007 var slice_buf: Type.SlicePtrFieldTypeBuffer = undefined;
1008 const spv_ptr_ty = try self.resolveTypeId(slice_ty.slicePtrFieldType(&slice_buf));
1009
1010 const slice_ptr = blk: {
1011 const result_id = self.spv.allocId();
1012 try self.func.body.emit(self.spv.gpa, .OpCompositeExtract, .{
1013 .id_result_type = spv_ptr_ty,
1014 .id_result = result_id,
1015 .composite = slice,
1016 .indexes = &.{0},
1017 });
1018 break :blk result_id.toRef();
1019 };
1020
1021 const elem_ptr = blk: {
1022 const result_id = self.spv.allocId();
1023 try self.func.body.emit(self.spv.gpa, .OpInBoundsAccessChain, .{
1024 .id_result_type = spv_ptr_ty,
1025 .id_result = result_id,
1026 .base = slice_ptr,
1027 .indexes = &.{index},
1028 });
1029 break :blk result_id.toRef();
1030 };
1031
1032 const result_id = self.spv.allocId();
1033 try self.func.body.emit(self.spv.gpa, .OpLoad, .{
1034 .id_result_type = spv_elem_ty,
1035 .id_result = result_id,
1036 .pointer = elem_ptr,
1037 });
1038 return result_id.toRef();
1039 }
1040
9501041 fn airAlloc(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
9511042 if (self.liveness.isUnused(inst)) return null;
9521043 const ty = self.air.typeOfIndex(inst);