authorgravatar for robin@voetter.nlRobin Voetter <robin@voetter.nl> 2023-10-21 16:20:00+02:00
committergravatar for robin@voetter.nlRobin Voetter <robin@voetter.nl> 2023-10-21 17:46:53+02:00
log6e955af8c84e1f9f75fef7f1a5820ab1b5bcff94
treedb4f8afbfa19a95ce9a5c034227dc12540b2dd10
parent1deec09f03d07aefcff1f886085c929c93669b5d
signaturebadge-check Signed by SSH key SHA256:CQ99aPxq+RueiL9u7z0FEki5Fm7V6T8q4PrEGmINrA4

spirv: make constructStruct also use self.ptrType

This completes the migration from spv.ptrType to self.ptrType. Unfortunately this requires us to pass a list of types to constructStruct, which also requires some extra allocations here and there.

1 files changed, 66 insertions(+), 47 deletions(-)

src/codegen/spirv.zig+66-47
...@@ -581,45 +581,30 @@ const DeclGen = struct {...@@ -581,45 +581,30 @@ const DeclGen = struct {
581 }581 }
582582
583 /// Construct a struct at runtime.583 /// Construct a struct at runtime.
584 /// result_ty_ref must be a struct type.584 /// ty must be a struct type.
585 /// Constituents should be in `indirect` representation (as the elements of a struct should be).585 /// Constituents should be in `indirect` representation (as the elements of a struct should be).
586 /// Result is in `direct` representation.586 /// Result is in `direct` representation.
587 fn constructStruct(self: *DeclGen, result_ty_ref: CacheRef, constituents: []const IdRef) !IdRef {587 fn constructStruct(self: *DeclGen, ty: Type, types: []const Type, constituents: []const IdRef) !IdRef {
588 assert(types.len == constituents.len);
588 // The Khronos LLVM-SPIRV translator crashes because it cannot construct structs which'589 // The Khronos LLVM-SPIRV translator crashes because it cannot construct structs which'
589 // operands are not constant.590 // operands are not constant.
590 // See https://github.com/KhronosGroup/SPIRV-LLVM-Translator/issues/1349591 // See https://github.com/KhronosGroup/SPIRV-LLVM-Translator/issues/1349
591 // For now, just initialize the struct by setting the fields manually...592 // For now, just initialize the struct by setting the fields manually...
592 // TODO: Make this OpCompositeConstruct when we can593 // TODO: Make this OpCompositeConstruct when we can
593 const ptr_ty_ref = try self.spv.ptrType(result_ty_ref, .Function);594 const ptr_composite_id = try self.alloc(ty, .{ .storage_class = .Function });
594 const ptr_composite_id = self.spv.allocId();595 for (constituents, types, 0..) |constitent_id, member_ty, index| {
595 try self.func.prologue.emit(self.spv.gpa, .OpVariable, .{596 const ptr_member_ty_ref = try self.ptrType(member_ty, .Function);
596 .id_result_type = self.typeId(ptr_ty_ref),
597 .id_result = ptr_composite_id,
598 .storage_class = .Function,
599 });
600
601 const spv_composite_ty = self.spv.cache.lookup(result_ty_ref).struct_type;
602 const member_types = spv_composite_ty.member_types;
603
604 for (constituents, member_types, 0..) |constitent_id, member_ty_ref, index| {
605 const ptr_member_ty_ref = try self.spv.ptrType(member_ty_ref, .Function);
606 const ptr_id = try self.accessChain(ptr_member_ty_ref, ptr_composite_id, &.{@as(u32, @intCast(index))});597 const ptr_id = try self.accessChain(ptr_member_ty_ref, ptr_composite_id, &.{@as(u32, @intCast(index))});
607 try self.func.body.emit(self.spv.gpa, .OpStore, .{598 try self.func.body.emit(self.spv.gpa, .OpStore, .{
608 .pointer = ptr_id,599 .pointer = ptr_id,
609 .object = constitent_id,600 .object = constitent_id,
610 });601 });
611 }602 }
612 const result_id = self.spv.allocId();603 return try self.load(ty, ptr_composite_id, .{});
613 try self.func.body.emit(self.spv.gpa, .OpLoad, .{
614 .id_result_type = self.typeId(result_ty_ref),
615 .id_result = result_id,
616 .pointer = ptr_composite_id,
617 });
618 return result_id;
619 }604 }
620605
621 /// Construct an array at runtime.606 /// Construct an array at runtime.
622 /// result_ty_ref must be an array type.607 /// ty must be an array type.
623 /// Constituents should be in `indirect` representation (as the elements of an array should be).608 /// Constituents should be in `indirect` representation (as the elements of an array should be).
624 /// Result is in `direct` representation.609 /// Result is in `direct` representation.
625 fn constructArray(self: *DeclGen, ty: Type, constituents: []const IdRef) !IdRef {610 fn constructArray(self: *DeclGen, ty: Type, constituents: []const IdRef) !IdRef {
...@@ -750,15 +735,18 @@ const DeclGen = struct {...@@ -750,15 +735,18 @@ const DeclGen = struct {
750 }.toValue();735 }.toValue();
751736
752 var constituents: [2]IdRef = undefined;737 var constituents: [2]IdRef = undefined;
738 var types: [2]Type = undefined;
753 if (eu_layout.error_first) {739 if (eu_layout.error_first) {
754 constituents[0] = try self.constant(err_ty, err_val, .indirect);740 constituents[0] = try self.constant(err_ty, err_val, .indirect);
755 constituents[1] = try self.constant(payload_ty, payload_val, .indirect);741 constituents[1] = try self.constant(payload_ty, payload_val, .indirect);
742 types = .{ err_ty, payload_ty };
756 } else {743 } else {
757 constituents[0] = try self.constant(payload_ty, payload_val, .indirect);744 constituents[0] = try self.constant(payload_ty, payload_val, .indirect);
758 constituents[1] = try self.constant(err_ty, err_val, .indirect);745 constituents[1] = try self.constant(err_ty, err_val, .indirect);
746 types = .{ payload_ty, err_ty };
759 }747 }
760748
761 return try self.constructStruct(result_ty_ref, &constituents);749 return try self.constructStruct(ty, &types, &constituents);
762 },750 },
763 .enum_tag => {751 .enum_tag => {
764 const int_val = try val.intFromEnum(ty, mod);752 const int_val = try val.intFromEnum(ty, mod);
...@@ -776,7 +764,11 @@ const DeclGen = struct {...@@ -776,7 +764,11 @@ const DeclGen = struct {
776 }764 }
777765
778 const len_id = try self.constant(Type.usize, ptr.len.toValue(), .indirect);766 const len_id = try self.constant(Type.usize, ptr.len.toValue(), .indirect);
779 return try self.constructStruct(result_ty_ref, &.{ ptr_id, len_id });767 return try self.constructStruct(
768 ty,
769 &.{ ptr_ty, Type.usize },
770 &.{ ptr_id, len_id },
771 );
780 },772 },
781 .opt => {773 .opt => {
782 const payload_ty = ty.optionalChild(mod);774 const payload_ty = ty.optionalChild(mod);
...@@ -803,7 +795,11 @@ const DeclGen = struct {...@@ -803,7 +795,11 @@ const DeclGen = struct {
803 else795 else
804 try self.spv.constUndef(try self.resolveType(payload_ty, .indirect));796 try self.spv.constUndef(try self.resolveType(payload_ty, .indirect));
805797
806 return try self.constructStruct(result_ty_ref, &.{ payload_id, has_pl_id });798 return try self.constructStruct(
799 ty,
800 &.{ payload_ty, Type.bool },
801 &.{ payload_id, has_pl_id },
802 );
807 },803 },
808 .aggregate => |aggregate| switch (ip.indexToKey(ty.ip_index)) {804 .aggregate => |aggregate| switch (ip.indexToKey(ty.ip_index)) {
809 inline .array_type, .vector_type => |array_type, tag| {805 inline .array_type, .vector_type => |array_type, tag| {
...@@ -849,6 +845,9 @@ const DeclGen = struct {...@@ -849,6 +845,9 @@ const DeclGen = struct {
849 return self.todo("packed struct constants", .{});845 return self.todo("packed struct constants", .{});
850 }846 }
851847
848 var types = std.ArrayList(Type).init(self.gpa);
849 defer types.deinit();
850
852 var constituents = std.ArrayList(IdRef).init(self.gpa);851 var constituents = std.ArrayList(IdRef).init(self.gpa);
853 defer constituents.deinit();852 defer constituents.deinit();
854853
...@@ -864,10 +863,11 @@ const DeclGen = struct {...@@ -864,10 +863,11 @@ const DeclGen = struct {
864 const field_val = try val.fieldValue(mod, field_index);863 const field_val = try val.fieldValue(mod, field_index);
865 const field_id = try self.constant(field_ty, field_val, .indirect);864 const field_id = try self.constant(field_ty, field_val, .indirect);
866865
866 try types.append(field_ty);
867 try constituents.append(field_id);867 try constituents.append(field_id);
868 }868 }
869869
870 return try self.constructStruct(result_ty_ref, constituents.items);870 return try self.constructStruct(ty, types.items, constituents.items);
871 },871 },
872 .anon_struct_type => unreachable, // TODO872 .anon_struct_type => unreachable, // TODO
873 else => unreachable,873 else => unreachable,
...@@ -2449,11 +2449,11 @@ const DeclGen = struct {...@@ -2449,11 +2449,11 @@ const DeclGen = struct {
2449 // Construct the struct that Zig wants as result.2449 // Construct the struct that Zig wants as result.
2450 // The value should already be the correct type.2450 // The value should already be the correct type.
2451 const ov_id = try self.intFromBool(ov_ty_ref, overflowed_id);2451 const ov_id = try self.intFromBool(ov_ty_ref, overflowed_id);
2452 const result_ty_ref = try self.resolveType(result_ty, .direct);2452 return try self.constructStruct(
2453 return try self.constructStruct(result_ty_ref, &.{2453 result_ty,
2454 value_id,2454 &.{ operand_ty, ov_ty },
2455 ov_id,2455 &.{ value_id, ov_id },
2456 });2456 );
2457 }2457 }
24582458
2459 fn airShuffle(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {2459 fn airShuffle(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
...@@ -3032,7 +3032,6 @@ const DeclGen = struct {...@@ -3032,7 +3032,6 @@ const DeclGen = struct {
3032 const elem_ptr_ty = slice_ty.slicePtrFieldType(mod);3032 const elem_ptr_ty = slice_ty.slicePtrFieldType(mod);
30333033
3034 const elem_ptr_ty_ref = try self.resolveType(elem_ptr_ty, .direct);3034 const elem_ptr_ty_ref = try self.resolveType(elem_ptr_ty, .direct);
3035 const slice_ty_ref = try self.resolveType(slice_ty, .direct);
3036 const size_ty_ref = try self.sizeType();3035 const size_ty_ref = try self.sizeType();
30373036
3038 const array_ptr_id = try self.resolve(ty_op.operand);3037 const array_ptr_id = try self.resolve(ty_op.operand);
...@@ -3045,7 +3044,11 @@ const DeclGen = struct {...@@ -3045,7 +3044,11 @@ const DeclGen = struct {
3045 // Convert the pointer-to-array to a pointer to the first element.3044 // Convert the pointer-to-array to a pointer to the first element.
3046 try self.accessChain(elem_ptr_ty_ref, array_ptr_id, &.{0});3045 try self.accessChain(elem_ptr_ty_ref, array_ptr_id, &.{0});
30473046
3048 return try self.constructStruct(slice_ty_ref, &.{ elem_ptr_id, len_id });3047 return try self.constructStruct(
3048 slice_ty,
3049 &.{ elem_ptr_ty, Type.usize },
3050 &.{ elem_ptr_id, len_id },
3051 );
3049 }3052 }
30503053
3051 fn airSlice(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {3054 fn airSlice(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
...@@ -3055,13 +3058,16 @@ const DeclGen = struct {...@@ -3055,13 +3058,16 @@ const DeclGen = struct {
3055 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;3058 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
3056 const ptr_id = try self.resolve(bin_op.lhs);3059 const ptr_id = try self.resolve(bin_op.lhs);
3057 const len_id = try self.resolve(bin_op.rhs);3060 const len_id = try self.resolve(bin_op.rhs);
3061 const ptr_ty = self.typeOf(bin_op.lhs);
3058 const slice_ty = self.typeOfIndex(inst);3062 const slice_ty = self.typeOfIndex(inst);
3059 const slice_ty_ref = try self.resolveType(slice_ty, .direct);
30603063
3061 return try self.constructStruct(slice_ty_ref, &.{3064 // Note: Types should not need to be converted to direct, these types
3062 ptr_id, // Note: Type should not need to be converted to direct.3065 // dont need to be converted.
3063 len_id, // Note: Type should not need to be converted to direct.3066 return try self.constructStruct(
3064 });3067 slice_ty,
3068 &.{ ptr_ty, Type.usize },
3069 &.{ ptr_id, len_id },
3070 );
3065 }3071 }
30663072
3067 fn airAggregateInit(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {3073 fn airAggregateInit(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
...@@ -3071,7 +3077,6 @@ const DeclGen = struct {...@@ -3071,7 +3077,6 @@ const DeclGen = struct {
3071 const ip = &mod.intern_pool;3077 const ip = &mod.intern_pool;
3072 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;3078 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
3073 const result_ty = self.typeOfIndex(inst);3079 const result_ty = self.typeOfIndex(inst);
3074 const result_ty_ref = try self.resolveType(result_ty, .direct);
3075 const len: usize = @intCast(result_ty.arrayLen(mod));3080 const len: usize = @intCast(result_ty.arrayLen(mod));
3076 const elements: []const Air.Inst.Ref = @ptrCast(self.air.extra[ty_pl.payload..][0..len]);3081 const elements: []const Air.Inst.Ref = @ptrCast(self.air.extra[ty_pl.payload..][0..len]);
30773082
...@@ -3083,6 +3088,8 @@ const DeclGen = struct {...@@ -3083,6 +3088,8 @@ const DeclGen = struct {
3083 unreachable; // TODO3088 unreachable; // TODO
3084 }3089 }
30853090
3091 const types = try self.gpa.alloc(Type, elements.len);
3092 defer self.gpa.free(types);
3086 const constituents = try self.gpa.alloc(IdRef, elements.len);3093 const constituents = try self.gpa.alloc(IdRef, elements.len);
3087 defer self.gpa.free(constituents);3094 defer self.gpa.free(constituents);
3088 var index: usize = 0;3095 var index: usize = 0;
...@@ -3094,6 +3101,7 @@ const DeclGen = struct {...@@ -3094,6 +3101,7 @@ const DeclGen = struct {
3094 assert(field_ty.toType().hasRuntimeBits(mod));3101 assert(field_ty.toType().hasRuntimeBits(mod));
30953102
3096 const id = try self.resolve(element);3103 const id = try self.resolve(element);
3104 types[index] = field_ty.toType();
3097 constituents[index] = try self.convertToIndirect(field_ty.toType(), id);3105 constituents[index] = try self.convertToIndirect(field_ty.toType(), id);
3098 index += 1;3106 index += 1;
3099 }3107 }
...@@ -3107,6 +3115,7 @@ const DeclGen = struct {...@@ -3107,6 +3115,7 @@ const DeclGen = struct {
3107 assert(field_ty.hasRuntimeBitsIgnoreComptime(mod));3115 assert(field_ty.hasRuntimeBitsIgnoreComptime(mod));
31083116
3109 const id = try self.resolve(element);3117 const id = try self.resolve(element);
3118 types[index] = field_ty;
3110 constituents[index] = try self.convertToIndirect(field_ty, id);3119 constituents[index] = try self.convertToIndirect(field_ty, id);
3111 index += 1;3120 index += 1;
3112 }3121 }
...@@ -3114,7 +3123,11 @@ const DeclGen = struct {...@@ -3114,7 +3123,11 @@ const DeclGen = struct {
3114 else => unreachable,3123 else => unreachable,
3115 }3124 }
31163125
3117 return try self.constructStruct(result_ty_ref, constituents[0..index]);3126 return try self.constructStruct(
3127 result_ty,
3128 types[0..index],
3129 constituents[0..index],
3130 );
3118 },3131 },
3119 .Array => {3132 .Array => {
3120 const array_info = result_ty.arrayInfo(mod);3133 const array_info = result_ty.arrayInfo(mod);
...@@ -3912,8 +3925,11 @@ const DeclGen = struct {...@@ -3912,8 +3925,11 @@ const DeclGen = struct {
3912 members[eu_layout.errorFieldIndex()] = operand_id;3925 members[eu_layout.errorFieldIndex()] = operand_id;
3913 members[eu_layout.payloadFieldIndex()] = try self.spv.constUndef(payload_ty_ref);3926 members[eu_layout.payloadFieldIndex()] = try self.spv.constUndef(payload_ty_ref);
39143927
3915 const err_union_ty_ref = try self.resolveType(err_union_ty, .direct);3928 var types: [2]Type = undefined;
3916 return try self.constructStruct(err_union_ty_ref, &members);3929 types[eu_layout.errorFieldIndex()] = Type.anyerror;
3930 types[eu_layout.payloadFieldIndex()] = payload_ty;
3931
3932 return try self.constructStruct(err_union_ty, &types, &members);
3917 }3933 }
39183934
3919 fn airWrapErrUnionPayload(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {3935 fn airWrapErrUnionPayload(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
...@@ -3934,8 +3950,11 @@ const DeclGen = struct {...@@ -3934,8 +3950,11 @@ const DeclGen = struct {
3934 members[eu_layout.errorFieldIndex()] = try self.constInt(err_ty_ref, 0);3950 members[eu_layout.errorFieldIndex()] = try self.constInt(err_ty_ref, 0);
3935 members[eu_layout.payloadFieldIndex()] = try self.convertToIndirect(payload_ty, operand_id);3951 members[eu_layout.payloadFieldIndex()] = try self.convertToIndirect(payload_ty, operand_id);
39363952
3937 const err_union_ty_ref = try self.resolveType(err_union_ty, .direct);3953 var types: [2]Type = undefined;
3938 return try self.constructStruct(err_union_ty_ref, &members);3954 types[eu_layout.errorFieldIndex()] = Type.anyerror;
3955 types[eu_layout.payloadFieldIndex()] = payload_ty;
3956
3957 return try self.constructStruct(err_union_ty, &types, &members);
3939 }3958 }
39403959
3941 fn airIsNull(self: *DeclGen, inst: Air.Inst.Index, pred: enum { is_null, is_non_null }) !?IdRef {3960 fn airIsNull(self: *DeclGen, inst: Air.Inst.Index, pred: enum { is_null, is_non_null }) !?IdRef {
...@@ -4067,10 +4086,10 @@ const DeclGen = struct {...@@ -4067,10 +4086,10 @@ const DeclGen = struct {
4067 return operand_id;4086 return operand_id;
4068 }4087 }
40694088
4070 const optional_ty_ref = try self.resolveType(optional_ty, .direct);
4071 const payload_id = try self.convertToIndirect(payload_ty, operand_id);4089 const payload_id = try self.convertToIndirect(payload_ty, operand_id);
4072 const members = [_]IdRef{ payload_id, try self.constBool(true, .indirect) };4090 const members = [_]IdRef{ payload_id, try self.constBool(true, .indirect) };
4073 return try self.constructStruct(optional_ty_ref, &members);4091 const types = [_]Type{ payload_ty, Type.bool };
4092 return try self.constructStruct(optional_ty, &types, &members);
4074 }4093 }
40754094
4076 fn airSwitchBr(self: *DeclGen, inst: Air.Inst.Index) !void {4095 fn airSwitchBr(self: *DeclGen, inst: Air.Inst.Index) !void {