Skip to content

Commit 3bffa58

Browse files
committed
Revert "spirv: merge construct(Struct/Vector/Array) into constructComposite"
This reverts commit eb2d61d.
1 parent 294f518 commit 3bffa58

File tree

2 files changed

+130
-30
lines changed

2 files changed

+130
-30
lines changed

src/codegen/spirv.zig

+129-29
Original file line numberDiff line numberDiff line change
@@ -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,19 +3662,28 @@ 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 {
35953673
const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
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,14 +3729,19 @@ 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
}
36493736
},
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
Original file line numberDiff line numberDiff line change
@@ -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

0 commit comments

Comments
 (0)