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 {...@@ -768,18 +768,75 @@ const DeclGen = struct {
768 };768 };
769 }769 }
770770
771 /// Construct a composite value at runtime. If the parameters are in direct771 /// Construct a struct at runtime.
772 /// representation, then the result is also in direct representation. Otherwise,772 /// ty must be a struct type.
773 /// if the parameters are in indirect representation, then the result is too.773 /// Constituents should be in `indirect` representation (as the elements of a struct should be).
774 fn constructComposite(self: *DeclGen, ty: Type, constituents: []const IdRef) !IdRef {774 /// Result is in `direct` representation.
775 const constituents_id = self.spv.allocId();775 fn constructStruct(self: *DeclGen, ty: Type, types: []const Type, constituents: []const IdRef) !IdRef {
776 const type_id = try self.resolveType(ty, .direct);776 assert(types.len == constituents.len);
777 try self.func.body.emit(self.spv.gpa, .OpCompositeConstruct, .{777 // The Khronos LLVM-SPIRV translator crashes because it cannot construct structs which'
778 .id_result_type = self.typeId(type_id),778 // operands are not constant.
779 .id_result = constituents_id,779 // See https://github.com/KhronosGroup/SPIRV-LLVM-Translator/issues/1349
780 .constituents = constituents,780 // For now, just initialize the struct by setting the fields manually...
781 });781 // TODO: Make this OpCompositeConstruct when we can
782 return constituents_id;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, .{});
783 }840 }
784841
785 /// This function generates a load for a constant in direct (ie, non-memory) representation.842 /// This function generates a load for a constant in direct (ie, non-memory) representation.
...@@ -887,15 +944,18 @@ const DeclGen = struct {...@@ -887,15 +944,18 @@ const DeclGen = struct {
887 });944 });
888945
889 var constituents: [2]IdRef = undefined;946 var constituents: [2]IdRef = undefined;
947 var types: [2]Type = undefined;
890 if (eu_layout.error_first) {948 if (eu_layout.error_first) {
891 constituents[0] = try self.constant(err_ty, err_val, .indirect);949 constituents[0] = try self.constant(err_ty, err_val, .indirect);
892 constituents[1] = try self.constant(payload_ty, payload_val, .indirect);950 constituents[1] = try self.constant(payload_ty, payload_val, .indirect);
951 types = .{ err_ty, payload_ty };
893 } else {952 } else {
894 constituents[0] = try self.constant(payload_ty, payload_val, .indirect);953 constituents[0] = try self.constant(payload_ty, payload_val, .indirect);
895 constituents[1] = try self.constant(err_ty, err_val, .indirect);954 constituents[1] = try self.constant(err_ty, err_val, .indirect);
955 types = .{ payload_ty, err_ty };
896 }956 }
897957
898 return try self.constructComposite(ty, &constituents);958 return try self.constructStruct(ty, &types, &constituents);
899 },959 },
900 .enum_tag => {960 .enum_tag => {
901 const int_val = try val.intFromEnum(ty, mod);961 const int_val = try val.intFromEnum(ty, mod);
...@@ -907,7 +967,11 @@ const DeclGen = struct {...@@ -907,7 +967,11 @@ const DeclGen = struct {
907 const ptr_ty = ty.slicePtrFieldType(mod);967 const ptr_ty = ty.slicePtrFieldType(mod);
908 const ptr_id = try self.constantPtr(ptr_ty, Value.fromInterned(slice.ptr));968 const ptr_id = try self.constantPtr(ptr_ty, Value.fromInterned(slice.ptr));
909 const len_id = try self.constant(Type.usize, Value.fromInterned(slice.len), .indirect);969 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 );
911 },975 },
912 .opt => {976 .opt => {
913 const payload_ty = ty.optionalChild(mod);977 const payload_ty = ty.optionalChild(mod);
...@@ -934,7 +998,11 @@ const DeclGen = struct {...@@ -934,7 +998,11 @@ const DeclGen = struct {
934 else998 else
935 try self.spv.constUndef(try self.resolveType(payload_ty, .indirect));999 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 );
938 },1006 },
939 .aggregate => |aggregate| switch (ip.indexToKey(ty.ip_index)) {1007 .aggregate => |aggregate| switch (ip.indexToKey(ty.ip_index)) {
940 inline .array_type, .vector_type => |array_type, tag| {1008 inline .array_type, .vector_type => |array_type, tag| {
...@@ -971,9 +1039,9 @@ const DeclGen = struct {...@@ -971,9 +1039,9 @@ const DeclGen = struct {
971 const sentinel = Value.fromInterned(array_type.sentinel);1039 const sentinel = Value.fromInterned(array_type.sentinel);
972 constituents[constituents.len - 1] = try self.constant(elem_ty, sentinel, .indirect);1040 constituents[constituents.len - 1] = try self.constant(elem_ty, sentinel, .indirect);
973 }1041 }
974 return self.constructComposite(ty, constituents);1042 return self.constructArray(ty, constituents);
975 },1043 },
976 inline .vector_type => return self.constructComposite(ty, constituents),1044 inline .vector_type => return self.constructVector(ty, constituents),
977 else => unreachable,1045 else => unreachable,
978 }1046 }
979 },1047 },
...@@ -983,6 +1051,9 @@ const DeclGen = struct {...@@ -983,6 +1051,9 @@ const DeclGen = struct {
983 return self.todo("packed struct constants", .{});1051 return self.todo("packed struct constants", .{});
984 }1052 }
9851053
1054 var types = std.ArrayList(Type).init(self.gpa);
1055 defer types.deinit();
1056
986 var constituents = std.ArrayList(IdRef).init(self.gpa);1057 var constituents = std.ArrayList(IdRef).init(self.gpa);
987 defer constituents.deinit();1058 defer constituents.deinit();
9881059
...@@ -998,10 +1069,11 @@ const DeclGen = struct {...@@ -998,10 +1069,11 @@ const DeclGen = struct {
998 const field_val = try val.fieldValue(mod, field_index);1069 const field_val = try val.fieldValue(mod, field_index);
999 const field_id = try self.constant(field_ty, field_val, .indirect);1070 const field_id = try self.constant(field_ty, field_val, .indirect);
10001071
1072 try types.append(field_ty);
1001 try constituents.append(field_id);1073 try constituents.append(field_id);
1002 }1074 }
10031075
1004 return try self.constructComposite(ty, constituents.items);1076 return try self.constructStruct(ty, types.items, constituents.items);
1005 },1077 },
1006 .anon_struct_type => unreachable, // TODO1078 .anon_struct_type => unreachable, // TODO
1007 else => unreachable,1079 else => unreachable,
...@@ -1841,7 +1913,7 @@ const DeclGen = struct {...@@ -1841,7 +1913,7 @@ const DeclGen = struct {
1841 for (wip.results) |*result| {1913 for (wip.results) |*result| {
1842 result.* = try wip.dg.convertToIndirect(wip.ty, result.*);1914 result.* = try wip.dg.convertToIndirect(wip.ty, result.*);
1843 }1915 }
1844 return try wip.dg.constructComposite(wip.result_ty, wip.results);1916 return try wip.dg.constructArray(wip.result_ty, wip.results);
1845 } else {1917 } else {
1846 return wip.results[0];1918 return wip.results[0];
1847 }1919 }
...@@ -2792,8 +2864,9 @@ const DeclGen = struct {...@@ -2792,8 +2864,9 @@ const DeclGen = struct {
2792 ov_id.* = try self.intFromBool(wip_ov.ty_ref, overflowed_id);2864 ov_id.* = try self.intFromBool(wip_ov.ty_ref, overflowed_id);
2793 }2865 }
27942866
2795 return try self.constructComposite(2867 return try self.constructStruct(
2796 result_ty,2868 result_ty,
2869 &.{ operand_ty, ov_ty },
2797 &.{ try wip_result.finalize(), try wip_ov.finalize() },2870 &.{ try wip_result.finalize(), try wip_ov.finalize() },
2798 );2871 );
2799 }2872 }
...@@ -2885,8 +2958,9 @@ const DeclGen = struct {...@@ -2885,8 +2958,9 @@ const DeclGen = struct {
2885 ov_id.* = try self.intFromBool(wip_ov.ty_ref, overflowed_id);2958 ov_id.* = try self.intFromBool(wip_ov.ty_ref, overflowed_id);
2886 }2959 }
28872960
2888 return try self.constructComposite(2961 return try self.constructStruct(
2889 result_ty,2962 result_ty,
2963 &.{ operand_ty, ov_ty },
2890 &.{ try wip_result.finalize(), try wip_ov.finalize() },2964 &.{ try wip_result.finalize(), try wip_ov.finalize() },
2891 );2965 );
2892 }2966 }
...@@ -3588,7 +3662,11 @@ const DeclGen = struct {...@@ -3588,7 +3662,11 @@ const DeclGen = struct {
3588 // Convert the pointer-to-array to a pointer to the first element.3662 // Convert the pointer-to-array to a pointer to the first element.
3589 try self.accessChain(elem_ptr_ty_ref, array_ptr_id, &.{0});3663 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 );
3592 }3670 }
35933671
3594 fn airSlice(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {3672 fn airSlice(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
...@@ -3596,11 +3674,16 @@ const DeclGen = struct {...@@ -3596,11 +3674,16 @@ const DeclGen = struct {
3596 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;3674 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
3597 const ptr_id = try self.resolve(bin_op.lhs);3675 const ptr_id = try self.resolve(bin_op.lhs);
3598 const len_id = try self.resolve(bin_op.rhs);3676 const len_id = try self.resolve(bin_op.rhs);
3677 const ptr_ty = self.typeOf(bin_op.lhs);
3599 const slice_ty = self.typeOfIndex(inst);3678 const slice_ty = self.typeOfIndex(inst);
36003679
3601 // Note: Types should not need to be converted to direct, these types3680 // Note: Types should not need to be converted to direct, these types
3602 // dont need to be converted.3681 // 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 );
3604 }3687 }
36053688
3606 fn airAggregateInit(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {3689 fn airAggregateInit(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
...@@ -3618,6 +3701,8 @@ const DeclGen = struct {...@@ -3618,6 +3701,8 @@ const DeclGen = struct {
3618 unreachable; // TODO3701 unreachable; // TODO
3619 }3702 }
36203703
3704 const types = try self.gpa.alloc(Type, elements.len);
3705 defer self.gpa.free(types);
3621 const constituents = try self.gpa.alloc(IdRef, elements.len);3706 const constituents = try self.gpa.alloc(IdRef, elements.len);
3622 defer self.gpa.free(constituents);3707 defer self.gpa.free(constituents);
3623 var index: usize = 0;3708 var index: usize = 0;
...@@ -3629,6 +3714,7 @@ const DeclGen = struct {...@@ -3629,6 +3714,7 @@ const DeclGen = struct {
3629 assert(Type.fromInterned(field_ty).hasRuntimeBits(mod));3714 assert(Type.fromInterned(field_ty).hasRuntimeBits(mod));
36303715
3631 const id = try self.resolve(element);3716 const id = try self.resolve(element);
3717 types[index] = Type.fromInterned(field_ty);
3632 constituents[index] = try self.convertToIndirect(Type.fromInterned(field_ty), id);3718 constituents[index] = try self.convertToIndirect(Type.fromInterned(field_ty), id);
3633 index += 1;3719 index += 1;
3634 }3720 }
...@@ -3643,6 +3729,7 @@ const DeclGen = struct {...@@ -3643,6 +3729,7 @@ const DeclGen = struct {
3643 assert(field_ty.hasRuntimeBitsIgnoreComptime(mod));3729 assert(field_ty.hasRuntimeBitsIgnoreComptime(mod));
36443730
3645 const id = try self.resolve(element);3731 const id = try self.resolve(element);
3732 types[index] = field_ty;
3646 constituents[index] = try self.convertToIndirect(field_ty, id);3733 constituents[index] = try self.convertToIndirect(field_ty, id);
3647 index += 1;3734 index += 1;
3648 }3735 }
...@@ -3650,7 +3737,11 @@ const DeclGen = struct {...@@ -3650,7 +3737,11 @@ const DeclGen = struct {
3650 else => unreachable,3737 else => unreachable,
3651 }3738 }
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 );
3654 },3745 },
3655 .Vector => {3746 .Vector => {
3656 const n_elems = result_ty.vectorLen(mod);3747 const n_elems = result_ty.vectorLen(mod);
...@@ -3662,7 +3753,7 @@ const DeclGen = struct {...@@ -3662,7 +3753,7 @@ const DeclGen = struct {
3662 elem_ids[i] = try self.convertToIndirect(result_ty.childType(mod), id);3753 elem_ids[i] = try self.convertToIndirect(result_ty.childType(mod), id);
3663 }3754 }
36643755
3665 return try self.constructComposite(result_ty, elem_ids);3756 return try self.constructVector(result_ty, elem_ids);
3666 },3757 },
3667 .Array => {3758 .Array => {
3668 const array_info = result_ty.arrayInfo(mod);3759 const array_info = result_ty.arrayInfo(mod);
...@@ -3679,7 +3770,7 @@ const DeclGen = struct {...@@ -3679,7 +3770,7 @@ const DeclGen = struct {
3679 elem_ids[n_elems - 1] = try self.constant(array_info.elem_type, sentinel_val, .indirect);3770 elem_ids[n_elems - 1] = try self.constant(array_info.elem_type, sentinel_val, .indirect);
3680 }3771 }
36813772
3682 return try self.constructComposite(result_ty, elem_ids);3773 return try self.constructArray(result_ty, elem_ids);
3683 },3774 },
3684 else => unreachable,3775 else => unreachable,
3685 }3776 }
...@@ -4792,7 +4883,11 @@ const DeclGen = struct {...@@ -4792,7 +4883,11 @@ const DeclGen = struct {
4792 members[eu_layout.errorFieldIndex()] = operand_id;4883 members[eu_layout.errorFieldIndex()] = operand_id;
4793 members[eu_layout.payloadFieldIndex()] = try self.spv.constUndef(payload_ty_ref);4884 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);
4796 }4891 }
47974892
4798 fn airWrapErrUnionPayload(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {4893 fn airWrapErrUnionPayload(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
...@@ -4811,7 +4906,11 @@ const DeclGen = struct {...@@ -4811,7 +4906,11 @@ const DeclGen = struct {
4811 members[eu_layout.errorFieldIndex()] = try self.constInt(err_ty_ref, 0);4906 members[eu_layout.errorFieldIndex()] = try self.constInt(err_ty_ref, 0);
4812 members[eu_layout.payloadFieldIndex()] = try self.convertToIndirect(payload_ty, operand_id);4907 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);
4815 }4914 }
48164915
4817 fn airIsNull(self: *DeclGen, inst: Air.Inst.Index, is_pointer: bool, pred: enum { is_null, is_non_null }) !?IdRef {4916 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 {...@@ -4978,7 +5077,8 @@ const DeclGen = struct {
49785077
4979 const payload_id = try self.convertToIndirect(payload_ty, operand_id);5078 const payload_id = try self.convertToIndirect(payload_ty, operand_id);
4980 const members = [_]IdRef{ payload_id, try self.constBool(true, .indirect) };5079 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);
4982 }5082 }
49835083
4984 fn airSwitchBr(self: *DeclGen, inst: Air.Inst.Index) !void {5084 fn airSwitchBr(self: *DeclGen, inst: Air.Inst.Index) !void {
src/link/SpirV.zig+1-1
...@@ -163,7 +163,7 @@ pub fn updateExports(...@@ -163,7 +163,7 @@ pub fn updateExports(
163 .Vertex => spec.ExecutionModel.Vertex,163 .Vertex => spec.ExecutionModel.Vertex,
164 .Fragment => spec.ExecutionModel.Fragment,164 .Fragment => spec.ExecutionModel.Fragment,
165 .Kernel => spec.ExecutionModel.Kernel,165 .Kernel => spec.ExecutionModel.Kernel,
166 else => return,166 else => unreachable,
167 };167 };
168 const is_vulkan = target.os.tag == .vulkan;168 const is_vulkan = target.os.tag == .vulkan;
169169