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 {
581581 }
582582
583583 /// Construct a struct at runtime.
584 /// result_ty_ref must be a struct type.
584 /// ty must be a struct type.
585585 /// Constituents should be in `indirect` representation (as the elements of a struct should be).
586586 /// 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);
588589 // The Khronos LLVM-SPIRV translator crashes because it cannot construct structs which'
589590 // operands are not constant.
590591 // See https://github.com/KhronosGroup/SPIRV-LLVM-Translator/issues/1349
591592 // For now, just initialize the struct by setting the fields manually...
592593 // 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 = self.spv.allocId();
595 try self.func.prologue.emit(self.spv.gpa, .OpVariable, .{
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);
594 const ptr_composite_id = try self.alloc(ty, .{ .storage_class = .Function });
595 for (constituents, types, 0..) |constitent_id, member_ty, index| {
596 const ptr_member_ty_ref = try self.ptrType(member_ty, .Function);
606597 const ptr_id = try self.accessChain(ptr_member_ty_ref, ptr_composite_id, &.{@as(u32, @intCast(index))});
607598 try self.func.body.emit(self.spv.gpa, .OpStore, .{
608599 .pointer = ptr_id,
609600 .object = constitent_id,
610601 });
611602 }
612 const result_id = self.spv.allocId();
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;
603 return try self.load(ty, ptr_composite_id, .{});
619604 }
620605
621606 /// Construct an array at runtime.
622 /// result_ty_ref must be an array type.
607 /// ty must be an array type.
623608 /// Constituents should be in `indirect` representation (as the elements of an array should be).
624609 /// Result is in `direct` representation.
625610 fn constructArray(self: *DeclGen, ty: Type, constituents: []const IdRef) !IdRef {
......@@ -750,15 +735,18 @@ const DeclGen = struct {
750735 }.toValue();
751736
752737 var constituents: [2]IdRef = undefined;
738 var types: [2]Type = undefined;
753739 if (eu_layout.error_first) {
754740 constituents[0] = try self.constant(err_ty, err_val, .indirect);
755741 constituents[1] = try self.constant(payload_ty, payload_val, .indirect);
742 types = .{ err_ty, payload_ty };
756743 } else {
757744 constituents[0] = try self.constant(payload_ty, payload_val, .indirect);
758745 constituents[1] = try self.constant(err_ty, err_val, .indirect);
746 types = .{ payload_ty, err_ty };
759747 }
760748
761 return try self.constructStruct(result_ty_ref, &constituents);
749 return try self.constructStruct(ty, &types, &constituents);
762750 },
763751 .enum_tag => {
764752 const int_val = try val.intFromEnum(ty, mod);
......@@ -776,7 +764,11 @@ const DeclGen = struct {
776764 }
777765
778766 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 );
780772 },
781773 .opt => {
782774 const payload_ty = ty.optionalChild(mod);
......@@ -803,7 +795,11 @@ const DeclGen = struct {
803795 else
804796 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 );
807803 },
808804 .aggregate => |aggregate| switch (ip.indexToKey(ty.ip_index)) {
809805 inline .array_type, .vector_type => |array_type, tag| {
......@@ -849,6 +845,9 @@ const DeclGen = struct {
849845 return self.todo("packed struct constants", .{});
850846 }
851847
848 var types = std.ArrayList(Type).init(self.gpa);
849 defer types.deinit();
850
852851 var constituents = std.ArrayList(IdRef).init(self.gpa);
853852 defer constituents.deinit();
854853
......@@ -864,10 +863,11 @@ const DeclGen = struct {
864863 const field_val = try val.fieldValue(mod, field_index);
865864 const field_id = try self.constant(field_ty, field_val, .indirect);
866865
866 try types.append(field_ty);
867867 try constituents.append(field_id);
868868 }
869869
870 return try self.constructStruct(result_ty_ref, constituents.items);
870 return try self.constructStruct(ty, types.items, constituents.items);
871871 },
872872 .anon_struct_type => unreachable, // TODO
873873 else => unreachable,
......@@ -2449,11 +2449,11 @@ const DeclGen = struct {
24492449 // Construct the struct that Zig wants as result.
24502450 // The value should already be the correct type.
24512451 const ov_id = try self.intFromBool(ov_ty_ref, overflowed_id);
2452 const result_ty_ref = try self.resolveType(result_ty, .direct);
2453 return try self.constructStruct(result_ty_ref, &.{
2454 value_id,
2455 ov_id,
2456 });
2452 return try self.constructStruct(
2453 result_ty,
2454 &.{ operand_ty, ov_ty },
2455 &.{ value_id, ov_id },
2456 );
24572457 }
24582458
24592459 fn airShuffle(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
......@@ -3032,7 +3032,6 @@ const DeclGen = struct {
30323032 const elem_ptr_ty = slice_ty.slicePtrFieldType(mod);
30333033
30343034 const elem_ptr_ty_ref = try self.resolveType(elem_ptr_ty, .direct);
3035 const slice_ty_ref = try self.resolveType(slice_ty, .direct);
30363035 const size_ty_ref = try self.sizeType();
30373036
30383037 const array_ptr_id = try self.resolve(ty_op.operand);
......@@ -3045,7 +3044,11 @@ const DeclGen = struct {
30453044 // Convert the pointer-to-array to a pointer to the first element.
30463045 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 );
30493052 }
30503053
30513054 fn airSlice(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
......@@ -3055,13 +3058,16 @@ const DeclGen = struct {
30553058 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
30563059 const ptr_id = try self.resolve(bin_op.lhs);
30573060 const len_id = try self.resolve(bin_op.rhs);
3061 const ptr_ty = self.typeOf(bin_op.lhs);
30583062 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, &.{
3062 ptr_id, // Note: Type should not need to be converted to direct.
3063 len_id, // Note: Type should not need to be converted to direct.
3064 });
3064 // Note: Types should not need to be converted to direct, these types
3065 // dont need to be converted.
3066 return try self.constructStruct(
3067 slice_ty,
3068 &.{ ptr_ty, Type.usize },
3069 &.{ ptr_id, len_id },
3070 );
30653071 }
30663072
30673073 fn airAggregateInit(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
......@@ -3071,7 +3077,6 @@ const DeclGen = struct {
30713077 const ip = &mod.intern_pool;
30723078 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
30733079 const result_ty = self.typeOfIndex(inst);
3074 const result_ty_ref = try self.resolveType(result_ty, .direct);
30753080 const len: usize = @intCast(result_ty.arrayLen(mod));
30763081 const elements: []const Air.Inst.Ref = @ptrCast(self.air.extra[ty_pl.payload..][0..len]);
30773082
......@@ -3083,6 +3088,8 @@ const DeclGen = struct {
30833088 unreachable; // TODO
30843089 }
30853090
3091 const types = try self.gpa.alloc(Type, elements.len);
3092 defer self.gpa.free(types);
30863093 const constituents = try self.gpa.alloc(IdRef, elements.len);
30873094 defer self.gpa.free(constituents);
30883095 var index: usize = 0;
......@@ -3094,6 +3101,7 @@ const DeclGen = struct {
30943101 assert(field_ty.toType().hasRuntimeBits(mod));
30953102
30963103 const id = try self.resolve(element);
3104 types[index] = field_ty.toType();
30973105 constituents[index] = try self.convertToIndirect(field_ty.toType(), id);
30983106 index += 1;
30993107 }
......@@ -3107,6 +3115,7 @@ const DeclGen = struct {
31073115 assert(field_ty.hasRuntimeBitsIgnoreComptime(mod));
31083116
31093117 const id = try self.resolve(element);
3118 types[index] = field_ty;
31103119 constituents[index] = try self.convertToIndirect(field_ty, id);
31113120 index += 1;
31123121 }
......@@ -3114,7 +3123,11 @@ const DeclGen = struct {
31143123 else => unreachable,
31153124 }
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 );
31183131 },
31193132 .Array => {
31203133 const array_info = result_ty.arrayInfo(mod);
......@@ -3912,8 +3925,11 @@ const DeclGen = struct {
39123925 members[eu_layout.errorFieldIndex()] = operand_id;
39133926 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);
3916 return try self.constructStruct(err_union_ty_ref, &members);
3928 var types: [2]Type = undefined;
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);
39173933 }
39183934
39193935 fn airWrapErrUnionPayload(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
......@@ -3934,8 +3950,11 @@ const DeclGen = struct {
39343950 members[eu_layout.errorFieldIndex()] = try self.constInt(err_ty_ref, 0);
39353951 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);
3938 return try self.constructStruct(err_union_ty_ref, &members);
3953 var types: [2]Type = undefined;
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);
39393958 }
39403959
39413960 fn airIsNull(self: *DeclGen, inst: Air.Inst.Index, pred: enum { is_null, is_non_null }) !?IdRef {
......@@ -4067,10 +4086,10 @@ const DeclGen = struct {
40674086 return operand_id;
40684087 }
40694088
4070 const optional_ty_ref = try self.resolveType(optional_ty, .direct);
40714089 const payload_id = try self.convertToIndirect(payload_ty, operand_id);
40724090 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);
40744093 }
40754094
40764095 fn airSwitchBr(self: *DeclGen, inst: Air.Inst.Index) !void {