authorgravatar for robin@voetter.nlRobin Voetter <robin@voetter.nl> 2024-03-02 13:23:38+01:00
committergravatar for robin@voetter.nlRobin Voetter <robin@voetter.nl> 2024-03-17 14:17:26+01:00
log3bffa58012bbe298c1f99f27e55d6f088d5d2078
tree25f5e9dee5aa092d12e8c5a6c300e87d63bd76db
parent294f51814f491ae4a09348d9e7221ae3e550c16f
signaturebadge-check Signed by SSH key SHA256:ZS52FNyUv2WUXvO4njmVaFVO46RHojFuOrxRc4LuKzg

Revert "spirv: merge `construct(Struct/Vector/Array)` into `constructComposite`"

This reverts commit eb2d61d02e503f01070c05e2e1fc87e827124d94.

2 files changed, 130 insertions(+), 30 deletions(-)

src/codegen/spirv.zig+129-29
......@@ -768,18 +768,75 @@ const DeclGen = struct {
768768 };
769769 }
770770
771 /// Construct a composite value at runtime. If the parameters are in direct
772 /// representation, then the result is also in direct representation. Otherwise,
773 /// if the parameters are in indirect representation, then the result is too.
774 fn constructComposite(self: *DeclGen, ty: Type, constituents: []const IdRef) !IdRef {
775 const constituents_id = self.spv.allocId();
776 const type_id = try self.resolveType(ty, .direct);
777 try self.func.body.emit(self.spv.gpa, .OpCompositeConstruct, .{
778 .id_result_type = self.typeId(type_id),
779 .id_result = constituents_id,
780 .constituents = constituents,
781 });
782 return constituents_id;
771 /// Construct a struct at runtime.
772 /// ty must be a struct type.
773 /// Constituents should be in `indirect` representation (as the elements of a struct should be).
774 /// Result is in `direct` representation.
775 fn constructStruct(self: *DeclGen, ty: Type, types: []const Type, constituents: []const IdRef) !IdRef {
776 assert(types.len == constituents.len);
777 // The Khronos LLVM-SPIRV translator crashes because it cannot construct structs which'
778 // operands are not constant.
779 // See https://github.com/KhronosGroup/SPIRV-LLVM-Translator/issues/1349
780 // For now, just initialize the struct by setting the fields manually...
781 // TODO: Make this OpCompositeConstruct when we can
782 const ptr_composite_id = try self.alloc(ty, .{ .storage_class = .Function });
783 for (constituents, types, 0..) |constitent_id, member_ty, index| {
784 const ptr_member_ty_ref = try self.ptrType(member_ty, .Function);
785 const ptr_id = try self.accessChain(ptr_member_ty_ref, ptr_composite_id, &.{@as(u32, @intCast(index))});
786 try self.func.body.emit(self.spv.gpa, .OpStore, .{
787 .pointer = ptr_id,
788 .object = constitent_id,
789 });
790 }
791 return try self.load(ty, ptr_composite_id, .{});
792 }
793
794 /// Construct a vector at runtime.
795 /// ty must be an vector type.
796 /// Constituents should be in `indirect` representation (as the elements of an vector should be).
797 /// Result is in `direct` representation.
798 fn constructVector(self: *DeclGen, ty: Type, constituents: []const IdRef) !IdRef {
799 // The Khronos LLVM-SPIRV translator crashes because it cannot construct structs which'
800 // operands are not constant.
801 // See https://github.com/KhronosGroup/SPIRV-LLVM-Translator/issues/1349
802 // For now, just initialize the struct by setting the fields manually...
803 // TODO: Make this OpCompositeConstruct when we can
804 const mod = self.module;
805 const ptr_composite_id = try self.alloc(ty, .{ .storage_class = .Function });
806 const ptr_elem_ty_ref = try self.ptrType(ty.elemType2(mod), .Function);
807 for (constituents, 0..) |constitent_id, index| {
808 const ptr_id = try self.accessChain(ptr_elem_ty_ref, ptr_composite_id, &.{@as(u32, @intCast(index))});
809 try self.func.body.emit(self.spv.gpa, .OpStore, .{
810 .pointer = ptr_id,
811 .object = constitent_id,
812 });
813 }
814
815 return try self.load(ty, ptr_composite_id, .{});
816 }
817
818 /// Construct an array at runtime.
819 /// ty must be an array type.
820 /// Constituents should be in `indirect` representation (as the elements of an array should be).
821 /// Result is in `direct` representation.
822 fn constructArray(self: *DeclGen, ty: Type, constituents: []const IdRef) !IdRef {
823 // The Khronos LLVM-SPIRV translator crashes because it cannot construct structs which'
824 // operands are not constant.
825 // See https://github.com/KhronosGroup/SPIRV-LLVM-Translator/issues/1349
826 // For now, just initialize the struct by setting the fields manually...
827 // TODO: Make this OpCompositeConstruct when we can
828 const mod = self.module;
829 const ptr_composite_id = try self.alloc(ty, .{ .storage_class = .Function });
830 const ptr_elem_ty_ref = try self.ptrType(ty.elemType2(mod), .Function);
831 for (constituents, 0..) |constitent_id, index| {
832 const ptr_id = try self.accessChain(ptr_elem_ty_ref, ptr_composite_id, &.{@as(u32, @intCast(index))});
833 try self.func.body.emit(self.spv.gpa, .OpStore, .{
834 .pointer = ptr_id,
835 .object = constitent_id,
836 });
837 }
838
839 return try self.load(ty, ptr_composite_id, .{});
783840 }
784841
785842 /// This function generates a load for a constant in direct (ie, non-memory) representation.
......@@ -887,15 +944,18 @@ const DeclGen = struct {
887944 });
888945
889946 var constituents: [2]IdRef = undefined;
947 var types: [2]Type = undefined;
890948 if (eu_layout.error_first) {
891949 constituents[0] = try self.constant(err_ty, err_val, .indirect);
892950 constituents[1] = try self.constant(payload_ty, payload_val, .indirect);
951 types = .{ err_ty, payload_ty };
893952 } else {
894953 constituents[0] = try self.constant(payload_ty, payload_val, .indirect);
895954 constituents[1] = try self.constant(err_ty, err_val, .indirect);
955 types = .{ payload_ty, err_ty };
896956 }
897957
898 return try self.constructComposite(ty, &constituents);
958 return try self.constructStruct(ty, &types, &constituents);
899959 },
900960 .enum_tag => {
901961 const int_val = try val.intFromEnum(ty, mod);
......@@ -907,7 +967,11 @@ const DeclGen = struct {
907967 const ptr_ty = ty.slicePtrFieldType(mod);
908968 const ptr_id = try self.constantPtr(ptr_ty, Value.fromInterned(slice.ptr));
909969 const len_id = try self.constant(Type.usize, Value.fromInterned(slice.len), .indirect);
910 return self.constructComposite(ty, &.{ ptr_id, len_id });
970 return self.constructStruct(
971 ty,
972 &.{ ptr_ty, Type.usize },
973 &.{ ptr_id, len_id },
974 );
911975 },
912976 .opt => {
913977 const payload_ty = ty.optionalChild(mod);
......@@ -934,7 +998,11 @@ const DeclGen = struct {
934998 else
935999 try self.spv.constUndef(try self.resolveType(payload_ty, .indirect));
9361000
937 return try self.constructComposite(ty, &.{ payload_id, has_pl_id });
1001 return try self.constructStruct(
1002 ty,
1003 &.{ payload_ty, Type.bool },
1004 &.{ payload_id, has_pl_id },
1005 );
9381006 },
9391007 .aggregate => |aggregate| switch (ip.indexToKey(ty.ip_index)) {
9401008 inline .array_type, .vector_type => |array_type, tag| {
......@@ -971,9 +1039,9 @@ const DeclGen = struct {
9711039 const sentinel = Value.fromInterned(array_type.sentinel);
9721040 constituents[constituents.len - 1] = try self.constant(elem_ty, sentinel, .indirect);
9731041 }
974 return self.constructComposite(ty, constituents);
1042 return self.constructArray(ty, constituents);
9751043 },
976 inline .vector_type => return self.constructComposite(ty, constituents),
1044 inline .vector_type => return self.constructVector(ty, constituents),
9771045 else => unreachable,
9781046 }
9791047 },
......@@ -983,6 +1051,9 @@ const DeclGen = struct {
9831051 return self.todo("packed struct constants", .{});
9841052 }
9851053
1054 var types = std.ArrayList(Type).init(self.gpa);
1055 defer types.deinit();
1056
9861057 var constituents = std.ArrayList(IdRef).init(self.gpa);
9871058 defer constituents.deinit();
9881059
......@@ -998,10 +1069,11 @@ const DeclGen = struct {
9981069 const field_val = try val.fieldValue(mod, field_index);
9991070 const field_id = try self.constant(field_ty, field_val, .indirect);
10001071
1072 try types.append(field_ty);
10011073 try constituents.append(field_id);
10021074 }
10031075
1004 return try self.constructComposite(ty, constituents.items);
1076 return try self.constructStruct(ty, types.items, constituents.items);
10051077 },
10061078 .anon_struct_type => unreachable, // TODO
10071079 else => unreachable,
......@@ -1841,7 +1913,7 @@ const DeclGen = struct {
18411913 for (wip.results) |*result| {
18421914 result.* = try wip.dg.convertToIndirect(wip.ty, result.*);
18431915 }
1844 return try wip.dg.constructComposite(wip.result_ty, wip.results);
1916 return try wip.dg.constructArray(wip.result_ty, wip.results);
18451917 } else {
18461918 return wip.results[0];
18471919 }
......@@ -2792,8 +2864,9 @@ const DeclGen = struct {
27922864 ov_id.* = try self.intFromBool(wip_ov.ty_ref, overflowed_id);
27932865 }
27942866
2795 return try self.constructComposite(
2867 return try self.constructStruct(
27962868 result_ty,
2869 &.{ operand_ty, ov_ty },
27972870 &.{ try wip_result.finalize(), try wip_ov.finalize() },
27982871 );
27992872 }
......@@ -2885,8 +2958,9 @@ const DeclGen = struct {
28852958 ov_id.* = try self.intFromBool(wip_ov.ty_ref, overflowed_id);
28862959 }
28872960
2888 return try self.constructComposite(
2961 return try self.constructStruct(
28892962 result_ty,
2963 &.{ operand_ty, ov_ty },
28902964 &.{ try wip_result.finalize(), try wip_ov.finalize() },
28912965 );
28922966 }
......@@ -3588,7 +3662,11 @@ const DeclGen = struct {
35883662 // Convert the pointer-to-array to a pointer to the first element.
35893663 try self.accessChain(elem_ptr_ty_ref, array_ptr_id, &.{0});
35903664
3591 return try self.constructComposite(slice_ty, &.{ elem_ptr_id, len_id });
3665 return try self.constructStruct(
3666 slice_ty,
3667 &.{ elem_ptr_ty, Type.usize },
3668 &.{ elem_ptr_id, len_id },
3669 );
35923670 }
35933671
35943672 fn airSlice(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
......@@ -3596,11 +3674,16 @@ const DeclGen = struct {
35963674 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
35973675 const ptr_id = try self.resolve(bin_op.lhs);
35983676 const len_id = try self.resolve(bin_op.rhs);
3677 const ptr_ty = self.typeOf(bin_op.lhs);
35993678 const slice_ty = self.typeOfIndex(inst);
36003679
36013680 // Note: Types should not need to be converted to direct, these types
36023681 // dont need to be converted.
3603 return try self.constructComposite(slice_ty, &.{ ptr_id, len_id });
3682 return try self.constructStruct(
3683 slice_ty,
3684 &.{ ptr_ty, Type.usize },
3685 &.{ ptr_id, len_id },
3686 );
36043687 }
36053688
36063689 fn airAggregateInit(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
......@@ -3618,6 +3701,8 @@ const DeclGen = struct {
36183701 unreachable; // TODO
36193702 }
36203703
3704 const types = try self.gpa.alloc(Type, elements.len);
3705 defer self.gpa.free(types);
36213706 const constituents = try self.gpa.alloc(IdRef, elements.len);
36223707 defer self.gpa.free(constituents);
36233708 var index: usize = 0;
......@@ -3629,6 +3714,7 @@ const DeclGen = struct {
36293714 assert(Type.fromInterned(field_ty).hasRuntimeBits(mod));
36303715
36313716 const id = try self.resolve(element);
3717 types[index] = Type.fromInterned(field_ty);
36323718 constituents[index] = try self.convertToIndirect(Type.fromInterned(field_ty), id);
36333719 index += 1;
36343720 }
......@@ -3643,6 +3729,7 @@ const DeclGen = struct {
36433729 assert(field_ty.hasRuntimeBitsIgnoreComptime(mod));
36443730
36453731 const id = try self.resolve(element);
3732 types[index] = field_ty;
36463733 constituents[index] = try self.convertToIndirect(field_ty, id);
36473734 index += 1;
36483735 }
......@@ -3650,7 +3737,11 @@ const DeclGen = struct {
36503737 else => unreachable,
36513738 }
36523739
3653 return try self.constructComposite(result_ty, constituents[0..index]);
3740 return try self.constructStruct(
3741 result_ty,
3742 types[0..index],
3743 constituents[0..index],
3744 );
36543745 },
36553746 .Vector => {
36563747 const n_elems = result_ty.vectorLen(mod);
......@@ -3662,7 +3753,7 @@ const DeclGen = struct {
36623753 elem_ids[i] = try self.convertToIndirect(result_ty.childType(mod), id);
36633754 }
36643755
3665 return try self.constructComposite(result_ty, elem_ids);
3756 return try self.constructVector(result_ty, elem_ids);
36663757 },
36673758 .Array => {
36683759 const array_info = result_ty.arrayInfo(mod);
......@@ -3679,7 +3770,7 @@ const DeclGen = struct {
36793770 elem_ids[n_elems - 1] = try self.constant(array_info.elem_type, sentinel_val, .indirect);
36803771 }
36813772
3682 return try self.constructComposite(result_ty, elem_ids);
3773 return try self.constructArray(result_ty, elem_ids);
36833774 },
36843775 else => unreachable,
36853776 }
......@@ -4792,7 +4883,11 @@ const DeclGen = struct {
47924883 members[eu_layout.errorFieldIndex()] = operand_id;
47934884 members[eu_layout.payloadFieldIndex()] = try self.spv.constUndef(payload_ty_ref);
47944885
4795 return try self.constructComposite(err_union_ty, &members);
4886 var types: [2]Type = undefined;
4887 types[eu_layout.errorFieldIndex()] = Type.anyerror;
4888 types[eu_layout.payloadFieldIndex()] = payload_ty;
4889
4890 return try self.constructStruct(err_union_ty, &types, &members);
47964891 }
47974892
47984893 fn airWrapErrUnionPayload(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
......@@ -4811,7 +4906,11 @@ const DeclGen = struct {
48114906 members[eu_layout.errorFieldIndex()] = try self.constInt(err_ty_ref, 0);
48124907 members[eu_layout.payloadFieldIndex()] = try self.convertToIndirect(payload_ty, operand_id);
48134908
4814 return try self.constructComposite(err_union_ty, &members);
4909 var types: [2]Type = undefined;
4910 types[eu_layout.errorFieldIndex()] = Type.anyerror;
4911 types[eu_layout.payloadFieldIndex()] = payload_ty;
4912
4913 return try self.constructStruct(err_union_ty, &types, &members);
48154914 }
48164915
48174916 fn airIsNull(self: *DeclGen, inst: Air.Inst.Index, is_pointer: bool, pred: enum { is_null, is_non_null }) !?IdRef {
......@@ -4978,7 +5077,8 @@ const DeclGen = struct {
49785077
49795078 const payload_id = try self.convertToIndirect(payload_ty, operand_id);
49805079 const members = [_]IdRef{ payload_id, try self.constBool(true, .indirect) };
4981 return try self.constructComposite(optional_ty, &members);
5080 const types = [_]Type{ payload_ty, Type.bool };
5081 return try self.constructStruct(optional_ty, &types, &members);
49825082 }
49835083
49845084 fn airSwitchBr(self: *DeclGen, inst: Air.Inst.Index) !void {
src/link/SpirV.zig+1-1
......@@ -163,7 +163,7 @@ pub fn updateExports(
163163 .Vertex => spec.ExecutionModel.Vertex,
164164 .Fragment => spec.ExecutionModel.Fragment,
165165 .Kernel => spec.ExecutionModel.Kernel,
166 else => return,
166 else => unreachable,
167167 };
168168 const is_vulkan = target.os.tag == .vulkan;
169169