authorgravatar for robin@voetter.nlRobin Voetter <robin@voetter.nl> 2024-04-05 00:30:06+02:00
committergravatar for robin@voetter.nlRobin Voetter <robin@voetter.nl> 2024-04-06 13:37:39+02:00
log97a67762ba1fcc363656a59af10a3031332cbd62
tree7e333b5d505b6886dae97ca1f1a734690c588712
parent188922a5448417d1939023b1eab7f70fa1953dde
signaturebadge-check Signed by SSH key SHA256:ZS52FNyUv2WUXvO4njmVaFVO46RHojFuOrxRc4LuKzg

spirv: remove cache usage for types


4 files changed, 555 insertions(+), 496 deletions(-)

src/codegen/spirv.zig+417-433
...@@ -22,8 +22,6 @@ const IdResultType = spec.IdResultType;...@@ -22,8 +22,6 @@ const IdResultType = spec.IdResultType;
22const StorageClass = spec.StorageClass;22const StorageClass = spec.StorageClass;
2323
24const SpvModule = @import("spirv/Module.zig");24const SpvModule = @import("spirv/Module.zig");
25const CacheRef = SpvModule.CacheRef;
26const CacheString = SpvModule.CacheString;
2725
28const SpvSection = @import("spirv/Section.zig");26const SpvSection = @import("spirv/Section.zig");
29const SpvAssembler = @import("spirv/Assembler.zig");27const SpvAssembler = @import("spirv/Assembler.zig");
...@@ -32,16 +30,11 @@ const InstMap = std.AutoHashMapUnmanaged(Air.Inst.Index, IdRef);...@@ -32,16 +30,11 @@ const InstMap = std.AutoHashMapUnmanaged(Air.Inst.Index, IdRef);
3230
33pub const zig_call_abi_ver = 3;31pub const zig_call_abi_ver = 3;
3432
35/// We want to store some extra facts about types as mapped from Zig to SPIR-V.
36/// This structure is used to keep that extra information, as well as
37/// the cached reference to the type.
38const SpvTypeInfo = struct {
39 ty_ref: CacheRef,
40};
41
42const TypeMap = std.AutoHashMapUnmanaged(InternPool.Index, SpvTypeInfo);
43
44const InternMap = std.AutoHashMapUnmanaged(struct { InternPool.Index, DeclGen.Repr }, IdResult);33const InternMap = std.AutoHashMapUnmanaged(struct { InternPool.Index, DeclGen.Repr }, IdResult);
34const PtrTypeMap = std.AutoHashMapUnmanaged(
35 struct { InternPool.Index, StorageClass },
36 struct { ty_id: IdRef, fwd_emitted: bool },
37);
4538
46const ControlFlow = union(enum) {39const ControlFlow = union(enum) {
47 const Structured = struct {40 const Structured = struct {
...@@ -164,17 +157,17 @@ pub const Object = struct {...@@ -164,17 +157,17 @@ pub const Object = struct {
164 /// A map of Zig InternPool indices for anonymous decls to SPIR-V decl indices.157 /// A map of Zig InternPool indices for anonymous decls to SPIR-V decl indices.
165 anon_decl_link: std.AutoHashMapUnmanaged(struct { InternPool.Index, StorageClass }, SpvModule.Decl.Index) = .{},158 anon_decl_link: std.AutoHashMapUnmanaged(struct { InternPool.Index, StorageClass }, SpvModule.Decl.Index) = .{},
166159
167 /// A map that maps AIR intern pool indices to SPIR-V cache references (which160 /// A map that maps AIR intern pool indices to SPIR-V result-ids.
168 /// is basically the same thing except for SPIR-V).
169 /// This map is typically only used for structures that are deemed heavy enough
170 /// that it is worth to store them here. The SPIR-V module also interns types,
171 /// and so the main purpose of this map is to avoid recomputation and to
172 /// cache extra information about the type rather than to aid in validity
173 /// of the SPIR-V module.
174 type_map: TypeMap = .{},
175
176 intern_map: InternMap = .{},161 intern_map: InternMap = .{},
177162
163 /// This map serves a dual purpose:
164 /// - It keeps track of pointers that are currently being emitted, so that we can tell
165 /// if they are recursive and need an OpTypeForwardPointer.
166 /// - It caches pointers by child-type. This is required because sometimes we rely on
167 /// ID-equality for pointers, and pointers constructed via `ptrType()` aren't interned
168 /// via the usual `intern_map` mechanism.
169 ptr_types: PtrTypeMap = .{},
170
178 pub fn init(gpa: Allocator) Object {171 pub fn init(gpa: Allocator) Object {
179 return .{172 return .{
180 .gpa = gpa,173 .gpa = gpa,
...@@ -186,8 +179,8 @@ pub const Object = struct {...@@ -186,8 +179,8 @@ pub const Object = struct {
186 self.spv.deinit();179 self.spv.deinit();
187 self.decl_link.deinit(self.gpa);180 self.decl_link.deinit(self.gpa);
188 self.anon_decl_link.deinit(self.gpa);181 self.anon_decl_link.deinit(self.gpa);
189 self.type_map.deinit(self.gpa);
190 self.intern_map.deinit(self.gpa);182 self.intern_map.deinit(self.gpa);
183 self.ptr_types.deinit(self.gpa);
191 }184 }
192185
193 fn genDecl(186 fn genDecl(
...@@ -209,8 +202,8 @@ pub const Object = struct {...@@ -209,8 +202,8 @@ pub const Object = struct {
209 .decl_index = decl_index,202 .decl_index = decl_index,
210 .air = air,203 .air = air,
211 .liveness = liveness,204 .liveness = liveness,
212 .type_map = &self.type_map,
213 .intern_map = &self.intern_map,205 .intern_map = &self.intern_map,
206 .ptr_types = &self.ptr_types,
214 .control_flow = switch (structured_cfg) {207 .control_flow = switch (structured_cfg) {
215 true => .{ .structured = .{} },208 true => .{ .structured = .{} },
216 false => .{ .unstructured = .{} },209 false => .{ .unstructured = .{} },
...@@ -315,15 +308,12 @@ const DeclGen = struct {...@@ -315,15 +308,12 @@ const DeclGen = struct {
315 /// A map keeping track of which instruction generated which result-id.308 /// A map keeping track of which instruction generated which result-id.
316 inst_results: InstMap = .{},309 inst_results: InstMap = .{},
317310
318 /// A map that maps AIR intern pool indices to SPIR-V cache references.311 /// A map that maps AIR intern pool indices to SPIR-V result-ids.
319 /// See Object.type_map312 /// See `Object.intern_map`.
320 type_map: *TypeMap,
321
322 intern_map: *InternMap,313 intern_map: *InternMap,
323314
324 /// Child types of pointers that are currently in progress of being resolved. If a pointer315 /// Module's pointer types, see `Object.ptr_types`.
325 /// is already in this map, its recursive.316 ptr_types: *PtrTypeMap,
326 wip_pointers: std.AutoHashMapUnmanaged(struct { InternPool.Index, StorageClass }, CacheRef) = .{},
327317
328 /// This field keeps track of the current state wrt structured or unstructured control flow.318 /// This field keeps track of the current state wrt structured or unstructured control flow.
329 control_flow: ControlFlow,319 control_flow: ControlFlow,
...@@ -410,7 +400,6 @@ const DeclGen = struct {...@@ -410,7 +400,6 @@ const DeclGen = struct {
410 pub fn deinit(self: *DeclGen) void {400 pub fn deinit(self: *DeclGen) void {
411 self.args.deinit(self.gpa);401 self.args.deinit(self.gpa);
412 self.inst_results.deinit(self.gpa);402 self.inst_results.deinit(self.gpa);
413 self.wip_pointers.deinit(self.gpa);
414 self.control_flow.deinit(self.gpa);403 self.control_flow.deinit(self.gpa);
415 self.func.deinit(self.gpa);404 self.func.deinit(self.gpa);
416 }405 }
...@@ -460,7 +449,7 @@ const DeclGen = struct {...@@ -460,7 +449,7 @@ const DeclGen = struct {
460449
461 const mod = self.module;450 const mod = self.module;
462 const ty = Type.fromInterned(mod.intern_pool.typeOf(val));451 const ty = Type.fromInterned(mod.intern_pool.typeOf(val));
463 const decl_ptr_ty_ref = try self.ptrType(ty, .Generic);452 const decl_ptr_ty_id = try self.ptrType(ty, .Generic);
464453
465 const spv_decl_index = blk: {454 const spv_decl_index = blk: {
466 const entry = try self.object.anon_decl_link.getOrPut(self.object.gpa, .{ val, .Function });455 const entry = try self.object.anon_decl_link.getOrPut(self.object.gpa, .{ val, .Function });
...@@ -468,7 +457,7 @@ const DeclGen = struct {...@@ -468,7 +457,7 @@ const DeclGen = struct {
468 try self.addFunctionDep(entry.value_ptr.*, .Function);457 try self.addFunctionDep(entry.value_ptr.*, .Function);
469458
470 const result_id = self.spv.declPtr(entry.value_ptr.*).result_id;459 const result_id = self.spv.declPtr(entry.value_ptr.*).result_id;
471 return try self.castToGeneric(self.typeId(decl_ptr_ty_ref), result_id);460 return try self.castToGeneric(decl_ptr_ty_id, result_id);
472 }461 }
473462
474 const spv_decl_index = try self.spv.allocDecl(.invocation_global);463 const spv_decl_index = try self.spv.allocDecl(.invocation_global);
...@@ -496,19 +485,14 @@ const DeclGen = struct {...@@ -496,19 +485,14 @@ const DeclGen = struct {
496 self.func = .{};485 self.func = .{};
497 defer self.func.deinit(self.gpa);486 defer self.func.deinit(self.gpa);
498487
499 const void_ty_ref = try self.resolveType(Type.void, .direct);488 const initializer_proto_ty_id = try self.functionType(Type.void, &.{});
500 const initializer_proto_ty_ref = try self.spv.resolve(.{ .function_type = .{
501 .return_type = void_ty_ref,
502 .parameters = &.{},
503 } });
504489
505 const initializer_id = self.spv.allocId();490 const initializer_id = self.spv.allocId();
506
507 try self.func.prologue.emit(self.spv.gpa, .OpFunction, .{491 try self.func.prologue.emit(self.spv.gpa, .OpFunction, .{
508 .id_result_type = self.typeId(void_ty_ref),492 .id_result_type = try self.resolveType(Type.void, .direct),
509 .id_result = initializer_id,493 .id_result = initializer_id,
510 .function_control = .{},494 .function_control = .{},
511 .function_type = self.typeId(initializer_proto_ty_ref),495 .function_type = initializer_proto_ty_id,
512 });496 });
513 const root_block_id = self.spv.allocId();497 const root_block_id = self.spv.allocId();
514 try self.func.prologue.emit(self.spv.gpa, .OpLabel, .{498 try self.func.prologue.emit(self.spv.gpa, .OpLabel, .{
...@@ -528,9 +512,9 @@ const DeclGen = struct {...@@ -528,9 +512,9 @@ const DeclGen = struct {
528512
529 try self.spv.debugNameFmt(initializer_id, "initializer of __anon_{d}", .{@intFromEnum(val)});513 try self.spv.debugNameFmt(initializer_id, "initializer of __anon_{d}", .{@intFromEnum(val)});
530514
531 const fn_decl_ptr_ty_ref = try self.ptrType(ty, .Function);515 const fn_decl_ptr_ty_id = try self.ptrType(ty, .Function);
532 try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpExtInst, .{516 try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpExtInst, .{
533 .id_result_type = self.typeId(fn_decl_ptr_ty_ref),517 .id_result_type = fn_decl_ptr_ty_id,
534 .id_result = result_id,518 .id_result = result_id,
535 .set = try self.spv.importInstructionSet(.zig),519 .set = try self.spv.importInstructionSet(.zig),
536 .instruction = .{ .inst = 0 }, // TODO: Put this definition somewhere...520 .instruction = .{ .inst = 0 }, // TODO: Put this definition somewhere...
...@@ -538,7 +522,7 @@ const DeclGen = struct {...@@ -538,7 +522,7 @@ const DeclGen = struct {
538 });522 });
539 }523 }
540524
541 return try self.castToGeneric(self.typeId(decl_ptr_ty_ref), result_id);525 return try self.castToGeneric(decl_ptr_ty_id, result_id);
542 }526 }
543527
544 fn addFunctionDep(self: *DeclGen, decl_index: SpvModule.Decl.Index, storage_class: StorageClass) !void {528 fn addFunctionDep(self: *DeclGen, decl_index: SpvModule.Decl.Index, storage_class: StorageClass) !void {
...@@ -712,7 +696,7 @@ const DeclGen = struct {...@@ -712,7 +696,7 @@ const DeclGen = struct {
712 return try self.constInt(Type.u1, @intFromBool(value), .indirect);696 return try self.constInt(Type.u1, @intFromBool(value), .indirect);
713 },697 },
714 .direct => {698 .direct => {
715 const result_ty_id = try self.resolveType2(Type.bool, .direct);699 const result_ty_id = try self.resolveType(Type.bool, .direct);
716 const result_id = self.spv.allocId();700 const result_id = self.spv.allocId();
717 const operands = .{701 const operands = .{
718 .id_result_type = result_ty_id,702 .id_result_type = result_ty_id,
...@@ -751,7 +735,7 @@ const DeclGen = struct {...@@ -751,7 +735,7 @@ const DeclGen = struct {
751 else735 else
752 bits & (@as(u64, 1) << @intCast(backing_bits)) - 1;736 bits & (@as(u64, 1) << @intCast(backing_bits)) - 1;
753737
754 const result_ty_id = try self.resolveType2(scalar_ty, repr);738 const result_ty_id = try self.resolveType(scalar_ty, repr);
755 const result_id = self.spv.allocId();739 const result_id = self.spv.allocId();
756740
757 const section = &self.spv.sections.types_globals_constants;741 const section = &self.spv.sections.types_globals_constants;
...@@ -779,7 +763,7 @@ const DeclGen = struct {...@@ -779,7 +763,7 @@ const DeclGen = struct {
779 defer self.gpa.free(ids);763 defer self.gpa.free(ids);
780 @memset(ids, result_id);764 @memset(ids, result_id);
781765
782 const vec_ty_id = try self.resolveType2(ty, repr);766 const vec_ty_id = try self.resolveType(ty, repr);
783 const vec_result_id = self.spv.allocId();767 const vec_result_id = self.spv.allocId();
784 try self.func.body.emit(self.spv.gpa, .OpCompositeConstruct, .{768 try self.func.body.emit(self.spv.gpa, .OpCompositeConstruct, .{
785 .id_result_type = vec_ty_id,769 .id_result_type = vec_ty_id,
...@@ -802,8 +786,8 @@ const DeclGen = struct {...@@ -802,8 +786,8 @@ const DeclGen = struct {
802 // TODO: Make this OpCompositeConstruct when we can786 // TODO: Make this OpCompositeConstruct when we can
803 const ptr_composite_id = try self.alloc(ty, .{ .storage_class = .Function });787 const ptr_composite_id = try self.alloc(ty, .{ .storage_class = .Function });
804 for (constituents, types, 0..) |constitent_id, member_ty, index| {788 for (constituents, types, 0..) |constitent_id, member_ty, index| {
805 const ptr_member_ty_ref = try self.ptrType(member_ty, .Function);789 const ptr_member_ty_id = try self.ptrType(member_ty, .Function);
806 const ptr_id = try self.accessChain(ptr_member_ty_ref, ptr_composite_id, &.{@as(u32, @intCast(index))});790 const ptr_id = try self.accessChain(ptr_member_ty_id, ptr_composite_id, &.{@as(u32, @intCast(index))});
807 try self.func.body.emit(self.spv.gpa, .OpStore, .{791 try self.func.body.emit(self.spv.gpa, .OpStore, .{
808 .pointer = ptr_id,792 .pointer = ptr_id,
809 .object = constitent_id,793 .object = constitent_id,
...@@ -824,9 +808,9 @@ const DeclGen = struct {...@@ -824,9 +808,9 @@ const DeclGen = struct {
824 // TODO: Make this OpCompositeConstruct when we can808 // TODO: Make this OpCompositeConstruct when we can
825 const mod = self.module;809 const mod = self.module;
826 const ptr_composite_id = try self.alloc(ty, .{ .storage_class = .Function });810 const ptr_composite_id = try self.alloc(ty, .{ .storage_class = .Function });
827 const ptr_elem_ty_ref = try self.ptrType(ty.elemType2(mod), .Function);811 const ptr_elem_ty_id = try self.ptrType(ty.elemType2(mod), .Function);
828 for (constituents, 0..) |constitent_id, index| {812 for (constituents, 0..) |constitent_id, index| {
829 const ptr_id = try self.accessChain(ptr_elem_ty_ref, ptr_composite_id, &.{@as(u32, @intCast(index))});813 const ptr_id = try self.accessChain(ptr_elem_ty_id, ptr_composite_id, &.{@as(u32, @intCast(index))});
830 try self.func.body.emit(self.spv.gpa, .OpStore, .{814 try self.func.body.emit(self.spv.gpa, .OpStore, .{
831 .pointer = ptr_id,815 .pointer = ptr_id,
832 .object = constitent_id,816 .object = constitent_id,
...@@ -848,9 +832,9 @@ const DeclGen = struct {...@@ -848,9 +832,9 @@ const DeclGen = struct {
848 // TODO: Make this OpCompositeConstruct when we can832 // TODO: Make this OpCompositeConstruct when we can
849 const mod = self.module;833 const mod = self.module;
850 const ptr_composite_id = try self.alloc(ty, .{ .storage_class = .Function });834 const ptr_composite_id = try self.alloc(ty, .{ .storage_class = .Function });
851 const ptr_elem_ty_ref = try self.ptrType(ty.elemType2(mod), .Function);835 const ptr_elem_ty_id = try self.ptrType(ty.elemType2(mod), .Function);
852 for (constituents, 0..) |constitent_id, index| {836 for (constituents, 0..) |constitent_id, index| {
853 const ptr_id = try self.accessChain(ptr_elem_ty_ref, ptr_composite_id, &.{@as(u32, @intCast(index))});837 const ptr_id = try self.accessChain(ptr_elem_ty_id, ptr_composite_id, &.{@as(u32, @intCast(index))});
854 try self.func.body.emit(self.spv.gpa, .OpStore, .{838 try self.func.body.emit(self.spv.gpa, .OpStore, .{
855 .pointer = ptr_id,839 .pointer = ptr_id,
856 .object = constitent_id,840 .object = constitent_id,
...@@ -876,8 +860,7 @@ const DeclGen = struct {...@@ -876,8 +860,7 @@ const DeclGen = struct {
876860
877 const mod = self.module;861 const mod = self.module;
878 const target = self.getTarget();862 const target = self.getTarget();
879 const result_ty_ref = try self.resolveType(ty, repr);863 const result_ty_id = try self.resolveType(ty, repr);
880 const result_ty_id = self.typeId(result_ty_ref);
881 const ip = &mod.intern_pool;864 const ip = &mod.intern_pool;
882865
883 log.debug("lowering constant: ty = {}, val = {}", .{ ty.fmt(mod), val.fmtValue(mod) });866 log.debug("lowering constant: ty = {}, val = {}", .{ ty.fmt(mod), val.fmtValue(mod) });
...@@ -1033,7 +1016,7 @@ const DeclGen = struct {...@@ -1033,7 +1016,7 @@ const DeclGen = struct {
1033 const payload_id = if (maybe_payload_val) |payload_val|1016 const payload_id = if (maybe_payload_val) |payload_val|
1034 try self.constant(payload_ty, payload_val, .indirect)1017 try self.constant(payload_ty, payload_val, .indirect)
1035 else1018 else
1036 try self.spv.constUndef(try self.resolveType2(payload_ty, .indirect));1019 try self.spv.constUndef(try self.resolveType(payload_ty, .indirect));
10371020
1038 return try self.constructStruct(1021 return try self.constructStruct(
1039 ty,1022 ty,
...@@ -1134,8 +1117,9 @@ const DeclGen = struct {...@@ -1134,8 +1117,9 @@ const DeclGen = struct {
1134 }1117 }
11351118
1136 fn constantPtr(self: *DeclGen, ptr_ty: Type, ptr_val: Value) Error!IdRef {1119 fn constantPtr(self: *DeclGen, ptr_ty: Type, ptr_val: Value) Error!IdRef {
1137 const result_ty_id = try self.resolveType2(ptr_ty, .direct);1120 // TODO: Caching??
1138 const result_ty_ref = try self.resolveType(ptr_ty, .direct);1121
1122 const result_ty_id = try self.resolveType(ptr_ty, .direct);
1139 const mod = self.module;1123 const mod = self.module;
11401124
1141 if (ptr_val.isUndef(mod)) return self.spv.constUndef(result_ty_id);1125 if (ptr_val.isUndef(mod)) return self.spv.constUndef(result_ty_id);
...@@ -1149,7 +1133,7 @@ const DeclGen = struct {...@@ -1149,7 +1133,7 @@ const DeclGen = struct {
1149 // that is not implemented by Mesa yet. Therefore, just generate it1133 // that is not implemented by Mesa yet. Therefore, just generate it
1150 // as a runtime operation.1134 // as a runtime operation.
1151 try self.func.body.emit(self.spv.gpa, .OpConvertUToPtr, .{1135 try self.func.body.emit(self.spv.gpa, .OpConvertUToPtr, .{
1152 .id_result_type = self.typeId(result_ty_ref),1136 .id_result_type = result_ty_id,
1153 .id_result = ptr_id,1137 .id_result = ptr_id,
1154 .integer_value = try self.constant(Type.usize, Value.fromInterned(int), .direct),1138 .integer_value = try self.constant(Type.usize, Value.fromInterned(int), .direct),
1155 });1139 });
...@@ -1167,16 +1151,17 @@ const DeclGen = struct {...@@ -1167,16 +1151,17 @@ const DeclGen = struct {
11671151
1168 // TODO: Can we consolidate this in ptrElemPtr?1152 // TODO: Can we consolidate this in ptrElemPtr?
1169 const elem_ty = parent_ptr_ty.elemType2(mod); // use elemType() so that we get T for *[N]T.1153 const elem_ty = parent_ptr_ty.elemType2(mod); // use elemType() so that we get T for *[N]T.
1170 const elem_ptr_ty_ref = try self.ptrType(elem_ty, self.spvStorageClass(parent_ptr_ty.ptrAddressSpace(mod)));1154 const elem_ptr_ty_id = try self.ptrType(elem_ty, self.spvStorageClass(parent_ptr_ty.ptrAddressSpace(mod)));
11711155
1172 if (elem_ptr_ty_ref == result_ty_ref) {1156 // TODO: Can we remove this ID comparison?
1157 if (elem_ptr_ty_id == result_ty_id) {
1173 return elem_ptr_id;1158 return elem_ptr_id;
1174 }1159 }
1175 // This may happen when we have pointer-to-array and the result is1160 // This may happen when we have pointer-to-array and the result is
1176 // another pointer-to-array instead of a pointer-to-element.1161 // another pointer-to-array instead of a pointer-to-element.
1177 const result_id = self.spv.allocId();1162 const result_id = self.spv.allocId();
1178 try self.func.body.emit(self.spv.gpa, .OpBitcast, .{1163 try self.func.body.emit(self.spv.gpa, .OpBitcast, .{
1179 .id_result_type = self.typeId(result_ty_ref),1164 .id_result_type = result_ty_id,
1180 .id_result = result_id,1165 .id_result = result_id,
1181 .operand = elem_ptr_id,1166 .operand = elem_ptr_id,
1182 });1167 });
...@@ -1200,7 +1185,7 @@ const DeclGen = struct {...@@ -1200,7 +1185,7 @@ const DeclGen = struct {
12001185
1201 const mod = self.module;1186 const mod = self.module;
1202 const ip = &mod.intern_pool;1187 const ip = &mod.intern_pool;
1203 const ty_ref = try self.resolveType(ty, .direct);1188 const ty_id = try self.resolveType(ty, .direct);
1204 const decl_val = anon_decl.val;1189 const decl_val = anon_decl.val;
1205 const decl_ty = Type.fromInterned(ip.typeOf(decl_val));1190 const decl_ty = Type.fromInterned(ip.typeOf(decl_val));
12061191
...@@ -1215,7 +1200,7 @@ const DeclGen = struct {...@@ -1215,7 +1200,7 @@ const DeclGen = struct {
1215 // const is_fn_body = decl_ty.zigTypeTag(mod) == .Fn;1200 // const is_fn_body = decl_ty.zigTypeTag(mod) == .Fn;
1216 if (!decl_ty.isFnOrHasRuntimeBitsIgnoreComptime(mod)) {1201 if (!decl_ty.isFnOrHasRuntimeBitsIgnoreComptime(mod)) {
1217 // Pointer to nothing - return undefoined1202 // Pointer to nothing - return undefoined
1218 return self.spv.constUndef(self.typeId(ty_ref));1203 return self.spv.constUndef(ty_id);
1219 }1204 }
12201205
1221 if (decl_ty.zigTypeTag(mod) == .Fn) {1206 if (decl_ty.zigTypeTag(mod) == .Fn) {
...@@ -1224,14 +1209,14 @@ const DeclGen = struct {...@@ -1224,14 +1209,14 @@ const DeclGen = struct {
12241209
1225 // Anon decl refs are always generic.1210 // Anon decl refs are always generic.
1226 assert(ty.ptrAddressSpace(mod) == .generic);1211 assert(ty.ptrAddressSpace(mod) == .generic);
1227 const decl_ptr_ty_ref = try self.ptrType(decl_ty, .Generic);1212 const decl_ptr_ty_id = try self.ptrType(decl_ty, .Generic);
1228 const ptr_id = try self.resolveAnonDecl(decl_val);1213 const ptr_id = try self.resolveAnonDecl(decl_val);
12291214
1230 if (decl_ptr_ty_ref != ty_ref) {1215 if (decl_ptr_ty_id != ty_id) {
1231 // Differing pointer types, insert a cast.1216 // Differing pointer types, insert a cast.
1232 const casted_ptr_id = self.spv.allocId();1217 const casted_ptr_id = self.spv.allocId();
1233 try self.func.body.emit(self.spv.gpa, .OpBitcast, .{1218 try self.func.body.emit(self.spv.gpa, .OpBitcast, .{
1234 .id_result_type = self.typeId(ty_ref),1219 .id_result_type = ty_id,
1235 .id_result = casted_ptr_id,1220 .id_result = casted_ptr_id,
1236 .operand = ptr_id,1221 .operand = ptr_id,
1237 });1222 });
...@@ -1243,8 +1228,7 @@ const DeclGen = struct {...@@ -1243,8 +1228,7 @@ const DeclGen = struct {
12431228
1244 fn constantDeclRef(self: *DeclGen, ty: Type, decl_index: InternPool.DeclIndex) !IdRef {1229 fn constantDeclRef(self: *DeclGen, ty: Type, decl_index: InternPool.DeclIndex) !IdRef {
1245 const mod = self.module;1230 const mod = self.module;
1246 const ty_ref = try self.resolveType(ty, .direct);1231 const ty_id = try self.resolveType(ty, .direct);
1247 const ty_id = self.typeId(ty_ref);
1248 const decl = mod.declPtr(decl_index);1232 const decl = mod.declPtr(decl_index);
12491233
1250 switch (mod.intern_pool.indexToKey(decl.val.ip_index)) {1234 switch (mod.intern_pool.indexToKey(decl.val.ip_index)) {
...@@ -1273,14 +1257,14 @@ const DeclGen = struct {...@@ -1273,14 +1257,14 @@ const DeclGen = struct {
1273 const final_storage_class = self.spvStorageClass(decl.@"addrspace");1257 const final_storage_class = self.spvStorageClass(decl.@"addrspace");
1274 try self.addFunctionDep(spv_decl_index, final_storage_class);1258 try self.addFunctionDep(spv_decl_index, final_storage_class);
12751259
1276 const decl_ptr_ty_ref = try self.ptrType(decl.typeOf(mod), final_storage_class);1260 const decl_ptr_ty_id = try self.ptrType(decl.typeOf(mod), final_storage_class);
12771261
1278 const ptr_id = switch (final_storage_class) {1262 const ptr_id = switch (final_storage_class) {
1279 .Generic => try self.castToGeneric(self.typeId(decl_ptr_ty_ref), decl_id),1263 .Generic => try self.castToGeneric(decl_ptr_ty_id, decl_id),
1280 else => decl_id,1264 else => decl_id,
1281 };1265 };
12821266
1283 if (decl_ptr_ty_ref != ty_ref) {1267 if (decl_ptr_ty_id != ty_id) {
1284 // Differing pointer types, insert a cast.1268 // Differing pointer types, insert a cast.
1285 const casted_ptr_id = self.spv.allocId();1269 const casted_ptr_id = self.spv.allocId();
1286 try self.func.body.emit(self.spv.gpa, .OpBitcast, .{1270 try self.func.body.emit(self.spv.gpa, .OpBitcast, .{
...@@ -1295,36 +1279,18 @@ const DeclGen = struct {...@@ -1295,36 +1279,18 @@ const DeclGen = struct {
1295 }1279 }
12961280
1297 // Turn a Zig type's name into a cache reference.1281 // Turn a Zig type's name into a cache reference.
1298 fn resolveTypeName(self: *DeclGen, ty: Type) !CacheString {1282 fn resolveTypeName(self: *DeclGen, ty: Type) ![]const u8 {
1299 var name = std.ArrayList(u8).init(self.gpa);1283 var name = std.ArrayList(u8).init(self.gpa);
1300 defer name.deinit();1284 defer name.deinit();
1301 try ty.print(name.writer(), self.module);1285 try ty.print(name.writer(), self.module);
1302 return try self.spv.resolveString(name.items);1286 return try name.toOwnedSlice();
1303 }
1304
1305 /// Turn a Zig type into a SPIR-V Type, and return its type result-id.
1306 fn resolveTypeId(self: *DeclGen, ty: Type) !IdResultType {
1307 const type_ref = try self.resolveType(ty, .direct);
1308 return self.spv.resultId(type_ref);
1309 }
1310
1311 /// Turn a Zig type into a SPIR-V Type result-id.
1312 /// This function represents the "new interface", where types handled only
1313 /// with Type and IdResult, and CacheRef is not used. Prefer this for now.
1314 fn resolveType2(self: *DeclGen, ty: Type, repr: Repr) !IdResult {
1315 const type_ref = try self.resolveType(ty, repr);
1316 return self.typeId(type_ref);
1317 }
1318
1319 fn typeId(self: *DeclGen, ty_ref: CacheRef) IdRef {
1320 return self.spv.resultId(ty_ref);
1321 }1287 }
13221288
1323 /// Create an integer type suitable for storing at least 'bits' bits.1289 /// Create an integer type suitable for storing at least 'bits' bits.
1324 /// The integer type that is returned by this function is the type that is used to perform1290 /// The integer type that is returned by this function is the type that is used to perform
1325 /// actual operations (as well as store) a Zig type of a particular number of bits. To create1291 /// actual operations (as well as store) a Zig type of a particular number of bits. To create
1326 /// a type with an exact size, use SpvModule.intType.1292 /// a type with an exact size, use SpvModule.intType.
1327 fn intType(self: *DeclGen, signedness: std.builtin.Signedness, bits: u16) !CacheRef {1293 fn intType(self: *DeclGen, signedness: std.builtin.Signedness, bits: u16) !IdRef {
1328 const backing_bits = self.backingIntBits(bits) orelse {1294 const backing_bits = self.backingIntBits(bits) orelse {
1329 // TODO: Integers too big for any native type are represented as "composite integers":1295 // TODO: Integers too big for any native type are represented as "composite integers":
1330 // An array of largestSupportedIntBits.1296 // An array of largestSupportedIntBits.
...@@ -1339,31 +1305,69 @@ const DeclGen = struct {...@@ -1339,31 +1305,69 @@ const DeclGen = struct {
1339 return self.spv.intType(.unsigned, backing_bits);1305 return self.spv.intType(.unsigned, backing_bits);
1340 }1306 }
13411307
1342 fn ptrType(self: *DeclGen, child_ty: Type, storage_class: StorageClass) !CacheRef {1308 fn arrayType(self: *DeclGen, len: u32, child_ty: IdRef) !IdRef {
1309 // TODO: Cache??
1310 const len_id = try self.constInt(Type.u32, len, .direct);
1311 const result_id = self.spv.allocId();
1312
1313 try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpTypeArray, .{
1314 .id_result = result_id,
1315 .element_type = child_ty,
1316 .length = len_id,
1317 });
1318 return result_id;
1319 }
1320
1321 fn ptrType(self: *DeclGen, child_ty: Type, storage_class: StorageClass) !IdRef {
1343 const key = .{ child_ty.toIntern(), storage_class };1322 const key = .{ child_ty.toIntern(), storage_class };
1344 const entry = try self.wip_pointers.getOrPut(self.gpa, key);1323 const entry = try self.ptr_types.getOrPut(self.gpa, key);
1345 if (entry.found_existing) {1324 if (entry.found_existing) {
1346 const fwd_ref = entry.value_ptr.*;1325 const fwd_id = entry.value_ptr.ty_id;
1347 try self.spv.cache.recursive_ptrs.put(self.spv.gpa, fwd_ref, {});1326 if (!entry.value_ptr.fwd_emitted) {
1348 return fwd_ref;1327 try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpTypeForwardPointer, .{
1328 .pointer_type = fwd_id,
1329 .storage_class = storage_class,
1330 });
1331 entry.value_ptr.fwd_emitted = true;
1332 }
1333 return fwd_id;
1349 }1334 }
13501335
1351 const fwd_ref = try self.spv.resolve(.{ .fwd_ptr_type = .{1336 const result_id = self.spv.allocId();
1352 .zig_child_type = child_ty.toIntern(),1337 entry.value_ptr.* = .{
1353 .storage_class = storage_class,1338 .ty_id = result_id,
1354 } });1339 .fwd_emitted = false,
1355 entry.value_ptr.* = fwd_ref;1340 };
13561341
1357 const child_ty_ref = try self.resolveType(child_ty, .indirect);1342 const child_ty_id = try self.resolveType(child_ty, .indirect);
1358 _ = try self.spv.resolve(.{ .ptr_type = .{1343
1344 try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpTypePointer, .{
1345 .id_result = result_id,
1359 .storage_class = storage_class,1346 .storage_class = storage_class,
1360 .child_type = child_ty_ref,1347 .type = child_ty_id,
1361 .fwd = fwd_ref,1348 });
1362 } });1349
1350 return result_id;
1351 }
1352
1353 fn functionType(self: *DeclGen, return_ty: Type, param_types: []const Type) !IdRef {
1354 // TODO: Cache??
13631355
1364 assert(self.wip_pointers.remove(key));1356 const param_ids = try self.gpa.alloc(IdRef, param_types.len);
1357 defer self.gpa.free(param_ids);
1358
1359 for (param_types, param_ids) |param_ty, *param_id| {
1360 param_id.* = try self.resolveType(param_ty, .direct);
1361 }
13651362
1366 return fwd_ref;1363 const ty_id = self.spv.allocId();
1364 try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpTypeFunction, .{
1365 .id_result = ty_id,
1366 .return_type = try self.resolveFnReturnType(return_ty),
1367 .id_ref_2 = param_ids,
1368 });
1369
1370 return ty_id;
1367 }1371 }
13681372
1369 /// Generate a union type. Union types are always generated with the1373 /// Generate a union type. Union types are always generated with the
...@@ -1384,7 +1388,7 @@ const DeclGen = struct {...@@ -1384,7 +1388,7 @@ const DeclGen = struct {
1384 /// padding: [padding_size]u8,1388 /// padding: [padding_size]u8,
1385 /// }1389 /// }
1386 /// If any of the fields' size is 0, it will be omitted.1390 /// If any of the fields' size is 0, it will be omitted.
1387 fn resolveUnionType(self: *DeclGen, ty: Type) !CacheRef {1391 fn resolveUnionType(self: *DeclGen, ty: Type) !IdRef {
1388 const mod = self.module;1392 const mod = self.module;
1389 const ip = &mod.intern_pool;1393 const ip = &mod.intern_pool;
1390 const union_obj = mod.typeToUnion(ty).?;1394 const union_obj = mod.typeToUnion(ty).?;
...@@ -1399,48 +1403,43 @@ const DeclGen = struct {...@@ -1399,48 +1403,43 @@ const DeclGen = struct {
1399 return try self.resolveType(Type.fromInterned(union_obj.enum_tag_ty), .indirect);1403 return try self.resolveType(Type.fromInterned(union_obj.enum_tag_ty), .indirect);
1400 }1404 }
14011405
1402 if (self.type_map.get(ty.toIntern())) |info| return info.ty_ref;1406 var member_types: [4]IdRef = undefined;
14031407 var member_names: [4][]const u8 = undefined;
1404 var member_types: [4]CacheRef = undefined;
1405 var member_names: [4]CacheString = undefined;
14061408
1407 const u8_ty_ref = try self.resolveType(Type.u8, .direct); // TODO: What if Int8Type is not enabled?1409 const u8_ty_id = try self.resolveType(Type.u8, .direct); // TODO: What if Int8Type is not enabled?
14081410
1409 if (layout.tag_size != 0) {1411 if (layout.tag_size != 0) {
1410 const tag_ty_ref = try self.resolveType(Type.fromInterned(union_obj.enum_tag_ty), .indirect);1412 const tag_ty_id = try self.resolveType(Type.fromInterned(union_obj.enum_tag_ty), .indirect);
1411 member_types[layout.tag_index] = tag_ty_ref;1413 member_types[layout.tag_index] = tag_ty_id;
1412 member_names[layout.tag_index] = try self.spv.resolveString("(tag)");1414 member_names[layout.tag_index] = "(tag)";
1413 }1415 }
14141416
1415 if (layout.payload_size != 0) {1417 if (layout.payload_size != 0) {
1416 const payload_ty_ref = try self.resolveType(layout.payload_ty, .indirect);1418 const payload_ty_id = try self.resolveType(layout.payload_ty, .indirect);
1417 member_types[layout.payload_index] = payload_ty_ref;1419 member_types[layout.payload_index] = payload_ty_id;
1418 member_names[layout.payload_index] = try self.spv.resolveString("(payload)");1420 member_names[layout.payload_index] = "(payload)";
1419 }1421 }
14201422
1421 if (layout.payload_padding_size != 0) {1423 if (layout.payload_padding_size != 0) {
1422 const payload_padding_ty_ref = try self.spv.arrayType(@intCast(layout.payload_padding_size), u8_ty_ref);1424 const payload_padding_ty_id = try self.arrayType(@intCast(layout.payload_padding_size), u8_ty_id);
1423 member_types[layout.payload_padding_index] = payload_padding_ty_ref;1425 member_types[layout.payload_padding_index] = payload_padding_ty_id;
1424 member_names[layout.payload_padding_index] = try self.spv.resolveString("(payload padding)");1426 member_names[layout.payload_padding_index] = "(payload padding)";
1425 }1427 }
14261428
1427 if (layout.padding_size != 0) {1429 if (layout.padding_size != 0) {
1428 const padding_ty_ref = try self.spv.arrayType(@intCast(layout.padding_size), u8_ty_ref);1430 const padding_ty_id = try self.arrayType(@intCast(layout.padding_size), u8_ty_id);
1429 member_types[layout.padding_index] = padding_ty_ref;1431 member_types[layout.padding_index] = padding_ty_id;
1430 member_names[layout.padding_index] = try self.spv.resolveString("(padding)");1432 member_names[layout.padding_index] = "(padding)";
1431 }1433 }
14321434
1433 const ty_ref = try self.spv.resolve(.{ .struct_type = .{1435 const result_id = try self.spv.structType(member_types[0..layout.total_fields], member_names[0..layout.total_fields]);
1434 .name = try self.resolveTypeName(ty),1436 const type_name = try self.resolveTypeName(ty);
1435 .member_types = member_types[0..layout.total_fields],1437 defer self.gpa.free(type_name);
1436 .member_names = member_names[0..layout.total_fields],1438 try self.spv.debugName(result_id, type_name);
1437 } });1439 return result_id;
1438
1439 try self.type_map.put(self.gpa, ty.toIntern(), .{ .ty_ref = ty_ref });
1440 return ty_ref;
1441 }1440 }
14421441
1443 fn resolveFnReturnType(self: *DeclGen, ret_ty: Type) !CacheRef {1442 fn resolveFnReturnType(self: *DeclGen, ret_ty: Type) !IdRef {
1444 const mod = self.module;1443 const mod = self.module;
1445 if (!ret_ty.hasRuntimeBitsIgnoreComptime(mod)) {1444 if (!ret_ty.hasRuntimeBitsIgnoreComptime(mod)) {
1446 // If the return type is an error set or an error union, then we make this1445 // If the return type is an error set or an error union, then we make this
...@@ -1457,25 +1456,45 @@ const DeclGen = struct {...@@ -1457,25 +1456,45 @@ const DeclGen = struct {
1457 }1456 }
14581457
1459 /// Turn a Zig type into a SPIR-V Type, and return a reference to it.1458 /// Turn a Zig type into a SPIR-V Type, and return a reference to it.
1460 fn resolveType(self: *DeclGen, ty: Type, repr: Repr) Error!CacheRef {1459 fn resolveType(self: *DeclGen, ty: Type, repr: Repr) Error!IdRef {
1460 if (self.intern_map.get(.{ ty.toIntern(), repr })) |id| {
1461 return id;
1462 }
1463
1464 const id = try self.resolveTypeInner(ty, repr);
1465 try self.intern_map.put(self.gpa, .{ ty.toIntern(), repr }, id);
1466 return id;
1467 }
1468
1469 fn resolveTypeInner(self: *DeclGen, ty: Type, repr: Repr) Error!IdRef {
1461 const mod = self.module;1470 const mod = self.module;
1462 const ip = &mod.intern_pool;1471 const ip = &mod.intern_pool;
1463 log.debug("resolveType: ty = {}", .{ty.fmt(mod)});1472 log.debug("resolveType: ty = {}", .{ty.fmt(mod)});
1464 const target = self.getTarget();1473 const target = self.getTarget();
1474
1475 const section = &self.spv.sections.types_globals_constants;
1476
1465 switch (ty.zigTypeTag(mod)) {1477 switch (ty.zigTypeTag(mod)) {
1466 .NoReturn => {1478 .NoReturn => {
1467 assert(repr == .direct);1479 assert(repr == .direct);
1468 return try self.spv.resolve(.void_type);1480 return try self.spv.voidType();
1469 },1481 },
1470 .Void => switch (repr) {1482 .Void => switch (repr) {
1471 .direct => return try self.spv.resolve(.void_type),1483 .direct => {
1484 return try self.spv.voidType();
1485 },
1472 // Pointers to void1486 // Pointers to void
1473 .indirect => return try self.spv.resolve(.{ .opaque_type = .{1487 .indirect => {
1474 .name = try self.spv.resolveString("void"),1488 const result_id = self.spv.allocId();
1475 } }),1489 try section.emit(self.spv.gpa, .OpTypeOpaque, .{
1490 .id_result = result_id,
1491 .literal_string = "void",
1492 });
1493 return result_id;
1494 },
1476 },1495 },
1477 .Bool => switch (repr) {1496 .Bool => switch (repr) {
1478 .direct => return try self.spv.resolve(.bool_type),1497 .direct => return try self.spv.boolType(),
1479 .indirect => return try self.resolveType(Type.u1, .indirect),1498 .indirect => return try self.resolveType(Type.u1, .indirect),
1480 },1499 },
1481 .Int => {1500 .Int => {
...@@ -1484,15 +1503,18 @@ const DeclGen = struct {...@@ -1484,15 +1503,18 @@ const DeclGen = struct {
1484 // Some times, the backend will be asked to generate a pointer to i0. OpTypeInt1503 // Some times, the backend will be asked to generate a pointer to i0. OpTypeInt
1485 // with 0 bits is invalid, so return an opaque type in this case.1504 // with 0 bits is invalid, so return an opaque type in this case.
1486 assert(repr == .indirect);1505 assert(repr == .indirect);
1487 return try self.spv.resolve(.{ .opaque_type = .{1506 const result_id = self.spv.allocId();
1488 .name = try self.spv.resolveString("u0"),1507 try section.emit(self.spv.gpa, .OpTypeOpaque, .{
1489 } });1508 .id_result = result_id,
1509 .literal_string = "u0",
1510 });
1511 return result_id;
1490 }1512 }
1491 return try self.intType(int_info.signedness, int_info.bits);1513 return try self.intType(int_info.signedness, int_info.bits);
1492 },1514 },
1493 .Enum => {1515 .Enum => {
1494 const tag_ty = ty.intTagType(mod);1516 const tag_ty = ty.intTagType(mod);
1495 return self.resolveType(tag_ty, repr);1517 return try self.resolveType(tag_ty, repr);
1496 },1518 },
1497 .Float => {1519 .Float => {
1498 // We can (and want) not really emulate floating points with other floating point types like with the integer types,1520 // We can (and want) not really emulate floating points with other floating point types like with the integer types,
...@@ -1510,27 +1532,29 @@ const DeclGen = struct {...@@ -1510,27 +1532,29 @@ const DeclGen = struct {
1510 return self.fail("Floating point width of {} bits is not supported for the current SPIR-V feature set", .{bits});1532 return self.fail("Floating point width of {} bits is not supported for the current SPIR-V feature set", .{bits});
1511 }1533 }
15121534
1513 return try self.spv.resolve(.{ .float_type = .{ .bits = bits } });1535 return try self.spv.floatType(bits);
1514 },1536 },
1515 .Array => {1537 .Array => {
1516 if (self.type_map.get(ty.toIntern())) |info| return info.ty_ref;
1517
1518 const elem_ty = ty.childType(mod);1538 const elem_ty = ty.childType(mod);
1519 const elem_ty_ref = try self.resolveType(elem_ty, .indirect);1539 const elem_ty_id = try self.resolveType(elem_ty, .indirect);
1520 const total_len = std.math.cast(u32, ty.arrayLenIncludingSentinel(mod)) orelse {1540 const total_len = std.math.cast(u32, ty.arrayLenIncludingSentinel(mod)) orelse {
1521 return self.fail("array type of {} elements is too large", .{ty.arrayLenIncludingSentinel(mod)});1541 return self.fail("array type of {} elements is too large", .{ty.arrayLenIncludingSentinel(mod)});
1522 };1542 };
1523 const ty_ref = if (!elem_ty.hasRuntimeBitsIgnoreComptime(mod)) blk: {1543
1544 if (!elem_ty.hasRuntimeBitsIgnoreComptime(mod)) {
1524 // The size of the array would be 0, but that is not allowed in SPIR-V.1545 // The size of the array would be 0, but that is not allowed in SPIR-V.
1525 // This path can be reached when the backend is asked to generate a pointer to1546 // This path can be reached when the backend is asked to generate a pointer to
1526 // an array of some zero-bit type. This should always be an indirect path.1547 // an array of some zero-bit type. This should always be an indirect path.
1527 assert(repr == .indirect);1548 assert(repr == .indirect);
15281549
1529 // We cannot use the child type here, so just use an opaque type.1550 // We cannot use the child type here, so just use an opaque type.
1530 break :blk try self.spv.resolve(.{ .opaque_type = .{1551 const result_id = self.spv.allocId();
1531 .name = try self.spv.resolveString("zero-sized array"),1552 try section.emit(self.spv.gpa, .OpTypeOpaque, .{
1532 } });1553 .id_result = result_id,
1533 } else if (total_len == 0) blk: {1554 .literal_string = "zero-sized array",
1555 });
1556 return result_id;
1557 } else if (total_len == 0) {
1534 // The size of the array would be 0, but that is not allowed in SPIR-V.1558 // The size of the array would be 0, but that is not allowed in SPIR-V.
1535 // This path can be reached for example when there is a slicing of a pointer1559 // This path can be reached for example when there is a slicing of a pointer
1536 // that produces a zero-length array. In all cases where this type can be generated,1560 // that produces a zero-length array. In all cases where this type can be generated,
...@@ -1540,16 +1564,13 @@ const DeclGen = struct {...@@ -1540,16 +1564,13 @@ const DeclGen = struct {
1540 // In this case, we have an array of a non-zero sized type. In this case,1564 // In this case, we have an array of a non-zero sized type. In this case,
1541 // generate an array of 1 element instead, so that ptr_elem_ptr instructions1565 // generate an array of 1 element instead, so that ptr_elem_ptr instructions
1542 // can be lowered to ptrAccessChain instead of manually performing the math.1566 // can be lowered to ptrAccessChain instead of manually performing the math.
1543 break :blk try self.spv.arrayType(1, elem_ty_ref);1567 return try self.arrayType(1, elem_ty_id);
1544 } else try self.spv.arrayType(total_len, elem_ty_ref);1568 } else {
15451569 return try self.arrayType(total_len, elem_ty_id);
1546 try self.type_map.put(self.gpa, ty.toIntern(), .{ .ty_ref = ty_ref });1570 }
1547 return ty_ref;
1548 },1571 },
1549 .Fn => switch (repr) {1572 .Fn => switch (repr) {
1550 .direct => {1573 .direct => {
1551 if (self.type_map.get(ty.toIntern())) |info| return info.ty_ref;
1552
1553 const fn_info = mod.typeToFunc(ty).?;1574 const fn_info = mod.typeToFunc(ty).?;
15541575
1555 comptime assert(zig_call_abi_ver == 3);1576 comptime assert(zig_call_abi_ver == 3);
...@@ -1562,25 +1583,28 @@ const DeclGen = struct {...@@ -1562,25 +1583,28 @@ const DeclGen = struct {
1562 if (fn_info.is_var_args)1583 if (fn_info.is_var_args)
1563 return self.fail("VarArgs functions are unsupported for SPIR-V", .{});1584 return self.fail("VarArgs functions are unsupported for SPIR-V", .{});
15641585
1565 const param_ty_refs = try self.gpa.alloc(CacheRef, fn_info.param_types.len);1586 // Note: Logic is different from functionType().
1566 defer self.gpa.free(param_ty_refs);1587 const param_ty_ids = try self.gpa.alloc(IdRef, fn_info.param_types.len);
1588 defer self.gpa.free(param_ty_ids);
1567 var param_index: usize = 0;1589 var param_index: usize = 0;
1568 for (fn_info.param_types.get(ip)) |param_ty_index| {1590 for (fn_info.param_types.get(ip)) |param_ty_index| {
1569 const param_ty = Type.fromInterned(param_ty_index);1591 const param_ty = Type.fromInterned(param_ty_index);
1570 if (!param_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;1592 if (!param_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
15711593
1572 param_ty_refs[param_index] = try self.resolveType(param_ty, .direct);1594 param_ty_ids[param_index] = try self.resolveType(param_ty, .direct);
1573 param_index += 1;1595 param_index += 1;
1574 }1596 }
1575 const return_ty_ref = try self.resolveFnReturnType(Type.fromInterned(fn_info.return_type));
15761597
1577 const ty_ref = try self.spv.resolve(.{ .function_type = .{1598 const return_ty_id = try self.resolveFnReturnType(Type.fromInterned(fn_info.return_type));
1578 .return_type = return_ty_ref,1599
1579 .parameters = param_ty_refs[0..param_index],1600 const result_id = self.spv.allocId();
1580 } });1601 try section.emit(self.spv.gpa, .OpTypeFunction, .{
1602 .id_result = result_id,
1603 .return_type = return_ty_id,
1604 .id_ref_2 = param_ty_ids[0..param_index],
1605 });
15811606
1582 try self.type_map.put(self.gpa, ty.toIntern(), .{ .ty_ref = ty_ref });1607 return result_id;
1583 return ty_ref;
1584 },1608 },
1585 .indirect => {1609 .indirect => {
1586 // TODO: Represent function pointers properly.1610 // TODO: Represent function pointers properly.
...@@ -1591,46 +1615,35 @@ const DeclGen = struct {...@@ -1591,46 +1615,35 @@ const DeclGen = struct {
1591 .Pointer => {1615 .Pointer => {
1592 const ptr_info = ty.ptrInfo(mod);1616 const ptr_info = ty.ptrInfo(mod);
15931617
1594 // Note: Don't cache this pointer type, it would mess up the recursive pointer functionality
1595 // in ptrType()!
1596
1597 const storage_class = self.spvStorageClass(ptr_info.flags.address_space);1618 const storage_class = self.spvStorageClass(ptr_info.flags.address_space);
1598 const ptr_ty_ref = try self.ptrType(Type.fromInterned(ptr_info.child), storage_class);1619 const ptr_ty_id = try self.ptrType(Type.fromInterned(ptr_info.child), storage_class);
15991620
1600 if (ptr_info.flags.size != .Slice) {1621 if (ptr_info.flags.size != .Slice) {
1601 return ptr_ty_ref;1622 return ptr_ty_id;
1602 }1623 }
16031624
1604 const size_ty_ref = try self.resolveType(Type.usize, .direct);1625 const size_ty_id = try self.resolveType(Type.usize, .direct);
1605 return self.spv.resolve(.{ .struct_type = .{1626 return self.spv.structType(
1606 .member_types = &.{ ptr_ty_ref, size_ty_ref },1627 &.{ ptr_ty_id, size_ty_id },
1607 .member_names = &.{1628 &.{ "ptr", "len" },
1608 try self.spv.resolveString("ptr"),1629 );
1609 try self.spv.resolveString("len"),
1610 },
1611 } });
1612 },1630 },
1613 .Vector => {1631 .Vector => {
1614 if (self.type_map.get(ty.toIntern())) |info| return info.ty_ref;
1615
1616 const elem_ty = ty.childType(mod);1632 const elem_ty = ty.childType(mod);
1617 const elem_ty_ref = try self.resolveType(elem_ty, .indirect);1633 // TODO: Make `.direct`.
1634 const elem_ty_id = try self.resolveType(elem_ty, .indirect);
1618 const len = ty.vectorLen(mod);1635 const len = ty.vectorLen(mod);
16191636
1620 const ty_ref = if (self.isVector(ty))1637 if (self.isVector(ty)) {
1621 try self.spv.vectorType(len, elem_ty_ref)1638 return try self.spv.vectorType(len, elem_ty_id);
1622 else1639 } else {
1623 try self.spv.arrayType(len, elem_ty_ref);1640 return try self.arrayType(len, elem_ty_id);
16241641 }
1625 try self.type_map.put(self.gpa, ty.toIntern(), .{ .ty_ref = ty_ref });
1626 return ty_ref;
1627 },1642 },
1628 .Struct => {1643 .Struct => {
1629 if (self.type_map.get(ty.toIntern())) |info| return info.ty_ref;
1630
1631 const struct_type = switch (ip.indexToKey(ty.toIntern())) {1644 const struct_type = switch (ip.indexToKey(ty.toIntern())) {
1632 .anon_struct_type => |tuple| {1645 .anon_struct_type => |tuple| {
1633 const member_types = try self.gpa.alloc(CacheRef, tuple.values.len);1646 const member_types = try self.gpa.alloc(IdRef, tuple.values.len);
1634 defer self.gpa.free(member_types);1647 defer self.gpa.free(member_types);
16351648
1636 var member_index: usize = 0;1649 var member_index: usize = 0;
...@@ -1641,13 +1654,11 @@ const DeclGen = struct {...@@ -1641,13 +1654,11 @@ const DeclGen = struct {
1641 member_index += 1;1654 member_index += 1;
1642 }1655 }
16431656
1644 const ty_ref = try self.spv.resolve(.{ .struct_type = .{1657 const result_id = try self.spv.structType(member_types[0..member_index], null);
1645 .name = try self.resolveTypeName(ty),1658 const type_name = try self.resolveTypeName(ty);
1646 .member_types = member_types[0..member_index],1659 defer self.gpa.free(type_name);
1647 } });1660 try self.spv.debugName(result_id, type_name);
16481661 return result_id;
1649 try self.type_map.put(self.gpa, ty.toIntern(), .{ .ty_ref = ty_ref });
1650 return ty_ref;
1651 },1662 },
1652 .struct_type => ip.loadStructType(ty.toIntern()),1663 .struct_type => ip.loadStructType(ty.toIntern()),
1653 else => unreachable,1664 else => unreachable,
...@@ -1657,10 +1668,10 @@ const DeclGen = struct {...@@ -1657,10 +1668,10 @@ const DeclGen = struct {
1657 return try self.resolveType(Type.fromInterned(struct_type.backingIntType(ip).*), .direct);1668 return try self.resolveType(Type.fromInterned(struct_type.backingIntType(ip).*), .direct);
1658 }1669 }
16591670
1660 var member_types = std.ArrayList(CacheRef).init(self.gpa);1671 var member_types = std.ArrayList(IdRef).init(self.gpa);
1661 defer member_types.deinit();1672 defer member_types.deinit();
16621673
1663 var member_names = std.ArrayList(CacheString).init(self.gpa);1674 var member_names = std.ArrayList([]const u8).init(self.gpa);
1664 defer member_names.deinit();1675 defer member_names.deinit();
16651676
1666 var it = struct_type.iterateRuntimeOrder(ip);1677 var it = struct_type.iterateRuntimeOrder(ip);
...@@ -1674,17 +1685,14 @@ const DeclGen = struct {...@@ -1674,17 +1685,14 @@ const DeclGen = struct {
1674 const field_name = struct_type.fieldName(ip, field_index).unwrap() orelse1685 const field_name = struct_type.fieldName(ip, field_index).unwrap() orelse
1675 try ip.getOrPutStringFmt(mod.gpa, "{d}", .{field_index});1686 try ip.getOrPutStringFmt(mod.gpa, "{d}", .{field_index});
1676 try member_types.append(try self.resolveType(field_ty, .indirect));1687 try member_types.append(try self.resolveType(field_ty, .indirect));
1677 try member_names.append(try self.spv.resolveString(ip.stringToSlice(field_name)));1688 try member_names.append(ip.stringToSlice(field_name));
1678 }1689 }
16791690
1680 const ty_ref = try self.spv.resolve(.{ .struct_type = .{1691 const result_id = try self.spv.structType(member_types.items, member_names.items);
1681 .name = try self.resolveTypeName(ty),1692 const type_name = try self.resolveTypeName(ty);
1682 .member_types = member_types.items,1693 defer self.gpa.free(type_name);
1683 .member_names = member_names.items,1694 try self.spv.debugName(result_id, type_name);
1684 } });1695 return result_id;
1685
1686 try self.type_map.put(self.gpa, ty.toIntern(), .{ .ty_ref = ty_ref });
1687 return ty_ref;
1688 },1696 },
1689 .Optional => {1697 .Optional => {
1690 const payload_ty = ty.optionalChild(mod);1698 const payload_ty = ty.optionalChild(mod);
...@@ -1695,77 +1703,58 @@ const DeclGen = struct {...@@ -1695,77 +1703,58 @@ const DeclGen = struct {
1695 return try self.resolveType(Type.bool, .indirect);1703 return try self.resolveType(Type.bool, .indirect);
1696 }1704 }
16971705
1698 const payload_ty_ref = try self.resolveType(payload_ty, .indirect);1706 const payload_ty_id = try self.resolveType(payload_ty, .indirect);
1699 if (ty.optionalReprIsPayload(mod)) {1707 if (ty.optionalReprIsPayload(mod)) {
1700 // Optional is actually a pointer or a slice.1708 // Optional is actually a pointer or a slice.
1701 return payload_ty_ref;1709 return payload_ty_id;
1702 }1710 }
17031711
1704 if (self.type_map.get(ty.toIntern())) |info| return info.ty_ref;1712 const bool_ty_id = try self.resolveType(Type.bool, .indirect);
1705
1706 const bool_ty_ref = try self.resolveType(Type.bool, .indirect);
1707
1708 const ty_ref = try self.spv.resolve(.{ .struct_type = .{
1709 .member_types = &.{ payload_ty_ref, bool_ty_ref },
1710 .member_names = &.{
1711 try self.spv.resolveString("payload"),
1712 try self.spv.resolveString("valid"),
1713 },
1714 } });
17151713
1716 try self.type_map.put(self.gpa, ty.toIntern(), .{ .ty_ref = ty_ref });1714 return try self.spv.structType(
1717 return ty_ref;1715 &.{ payload_ty_id, bool_ty_id },
1716 &.{ "payload", "valid" },
1717 );
1718 },1718 },
1719 .Union => return try self.resolveUnionType(ty),1719 .Union => return try self.resolveUnionType(ty),
1720 .ErrorSet => return try self.resolveType(Type.u16, repr),1720 .ErrorSet => return try self.resolveType(Type.u16, repr),
1721 .ErrorUnion => {1721 .ErrorUnion => {
1722 const payload_ty = ty.errorUnionPayload(mod);1722 const payload_ty = ty.errorUnionPayload(mod);
1723 const error_ty_ref = try self.resolveType(Type.anyerror, .indirect);1723 const error_ty_id = try self.resolveType(Type.anyerror, .indirect);
17241724
1725 const eu_layout = self.errorUnionLayout(payload_ty);1725 const eu_layout = self.errorUnionLayout(payload_ty);
1726 if (!eu_layout.payload_has_bits) {1726 if (!eu_layout.payload_has_bits) {
1727 return error_ty_ref;1727 return error_ty_id;
1728 }1728 }
17291729
1730 if (self.type_map.get(ty.toIntern())) |info| return info.ty_ref;1730 const payload_ty_id = try self.resolveType(payload_ty, .indirect);
1731
1732 const payload_ty_ref = try self.resolveType(payload_ty, .indirect);
17331731
1734 var member_types: [2]CacheRef = undefined;1732 var member_types: [2]IdRef = undefined;
1735 var member_names: [2]CacheString = undefined;1733 var member_names: [2][]const u8 = undefined;
1736 if (eu_layout.error_first) {1734 if (eu_layout.error_first) {
1737 // Put the error first1735 // Put the error first
1738 member_types = .{ error_ty_ref, payload_ty_ref };1736 member_types = .{ error_ty_id, payload_ty_id };
1739 member_names = .{1737 member_names = .{ "error", "payload" };
1740 try self.spv.resolveString("error"),
1741 try self.spv.resolveString("payload"),
1742 };
1743 // TODO: ABI padding?1738 // TODO: ABI padding?
1744 } else {1739 } else {
1745 // Put the payload first.1740 // Put the payload first.
1746 member_types = .{ payload_ty_ref, error_ty_ref };1741 member_types = .{ payload_ty_id, error_ty_id };
1747 member_names = .{1742 member_names = .{ "payload", "error" };
1748 try self.spv.resolveString("payload"),
1749 try self.spv.resolveString("error"),
1750 };
1751 // TODO: ABI padding?1743 // TODO: ABI padding?
1752 }1744 }
17531745
1754 const ty_ref = try self.spv.resolve(.{ .struct_type = .{1746 return try self.spv.structType(&member_types, &member_names);
1755 .name = try self.resolveTypeName(ty),
1756 .member_types = &member_types,
1757 .member_names = &member_names,
1758 } });
1759
1760 try self.type_map.put(self.gpa, ty.toIntern(), .{ .ty_ref = ty_ref });
1761 return ty_ref;
1762 },1747 },
1763 .Opaque => {1748 .Opaque => {
1764 return try self.spv.resolve(.{1749 const type_name = try self.resolveTypeName(ty);
1765 .opaque_type = .{1750 defer self.gpa.free(type_name);
1766 .name = .none, // TODO1751
1767 },1752 const result_id = self.spv.allocId();
1753 try section.emit(self.spv.gpa, .OpTypeOpaque, .{
1754 .id_result = result_id,
1755 .literal_string = type_name,
1768 });1756 });
1757 return result_id;
1769 },1758 },
17701759
1771 .Null,1760 .Null,
...@@ -1773,9 +1762,10 @@ const DeclGen = struct {...@@ -1773,9 +1762,10 @@ const DeclGen = struct {
1773 .EnumLiteral,1762 .EnumLiteral,
1774 .ComptimeFloat,1763 .ComptimeFloat,
1775 .ComptimeInt,1764 .ComptimeInt,
1765 .Type,
1776 => unreachable, // Must be comptime.1766 => unreachable, // Must be comptime.
17771767
1778 else => |tag| return self.todo("Implement zig type '{}'", .{tag}),1768 .Frame, .AnyFrame => unreachable, // TODO
1779 }1769 }
1780 }1770 }
17811771
...@@ -1924,7 +1914,6 @@ const DeclGen = struct {...@@ -1924,7 +1914,6 @@ const DeclGen = struct {
1924 result_ty: Type,1914 result_ty: Type,
1925 ty: Type,1915 ty: Type,
1926 /// Always in direct representation.1916 /// Always in direct representation.
1927 ty_ref: CacheRef,
1928 ty_id: IdRef,1917 ty_id: IdRef,
1929 /// True if the input is an array type.1918 /// True if the input is an array type.
1930 is_array: bool,1919 is_array: bool,
...@@ -1984,14 +1973,13 @@ const DeclGen = struct {...@@ -1984,14 +1973,13 @@ const DeclGen = struct {
1984 @memset(results, undefined);1973 @memset(results, undefined);
19851974
1986 const ty = if (is_array) result_ty.scalarType(mod) else result_ty;1975 const ty = if (is_array) result_ty.scalarType(mod) else result_ty;
1987 const ty_ref = try self.resolveType(ty, .direct);1976 const ty_id = try self.resolveType(ty, .direct);
19881977
1989 return .{1978 return .{
1990 .dg = self,1979 .dg = self,
1991 .result_ty = result_ty,1980 .result_ty = result_ty,
1992 .ty = ty,1981 .ty = ty,
1993 .ty_ref = ty_ref,1982 .ty_id = ty_id,
1994 .ty_id = self.typeId(ty_ref),
1995 .is_array = is_array,1983 .is_array = is_array,
1996 .results = results,1984 .results = results,
1997 };1985 };
...@@ -2018,16 +2006,13 @@ const DeclGen = struct {...@@ -2018,16 +2006,13 @@ const DeclGen = struct {
2018 /// TODO is to also write out the error as a function call parameter, and to somehow fetch2006 /// TODO is to also write out the error as a function call parameter, and to somehow fetch
2019 /// the name of an error in the text executor.2007 /// the name of an error in the text executor.
2020 fn generateTestEntryPoint(self: *DeclGen, name: []const u8, spv_test_decl_index: SpvModule.Decl.Index) !void {2008 fn generateTestEntryPoint(self: *DeclGen, name: []const u8, spv_test_decl_index: SpvModule.Decl.Index) !void {
2021 const anyerror_ty_ref = try self.resolveType(Type.anyerror, .direct);2009 const anyerror_ty_id = try self.resolveType(Type.anyerror, .direct);
2022 const ptr_anyerror_ty_ref = try self.ptrType(Type.anyerror, .CrossWorkgroup);2010 const ptr_anyerror_ty = try self.module.ptrType(.{
2023 const void_ty_ref = try self.resolveType(Type.void, .direct);2011 .child = Type.anyerror.toIntern(),
20242012 .flags = .{ .address_space = .global },
2025 const kernel_proto_ty_ref = try self.spv.resolve(.{
2026 .function_type = .{
2027 .return_type = void_ty_ref,
2028 .parameters = &.{ptr_anyerror_ty_ref},
2029 },
2030 });2013 });
2014 const ptr_anyerror_ty_id = try self.resolveType(ptr_anyerror_ty, .direct);
2015 const kernel_proto_ty_id = try self.functionType(Type.void, &.{ptr_anyerror_ty});
20312016
2032 const test_id = self.spv.declPtr(spv_test_decl_index).result_id;2017 const test_id = self.spv.declPtr(spv_test_decl_index).result_id;
20332018
...@@ -2039,20 +2024,20 @@ const DeclGen = struct {...@@ -2039,20 +2024,20 @@ const DeclGen = struct {
20392024
2040 const section = &self.spv.sections.functions;2025 const section = &self.spv.sections.functions;
2041 try section.emit(self.spv.gpa, .OpFunction, .{2026 try section.emit(self.spv.gpa, .OpFunction, .{
2042 .id_result_type = self.typeId(void_ty_ref),2027 .id_result_type = try self.resolveType(Type.void, .direct),
2043 .id_result = kernel_id,2028 .id_result = kernel_id,
2044 .function_control = .{},2029 .function_control = .{},
2045 .function_type = self.typeId(kernel_proto_ty_ref),2030 .function_type = kernel_proto_ty_id,
2046 });2031 });
2047 try section.emit(self.spv.gpa, .OpFunctionParameter, .{2032 try section.emit(self.spv.gpa, .OpFunctionParameter, .{
2048 .id_result_type = self.typeId(ptr_anyerror_ty_ref),2033 .id_result_type = ptr_anyerror_ty_id,
2049 .id_result = p_error_id,2034 .id_result = p_error_id,
2050 });2035 });
2051 try section.emit(self.spv.gpa, .OpLabel, .{2036 try section.emit(self.spv.gpa, .OpLabel, .{
2052 .id_result = self.spv.allocId(),2037 .id_result = self.spv.allocId(),
2053 });2038 });
2054 try section.emit(self.spv.gpa, .OpFunctionCall, .{2039 try section.emit(self.spv.gpa, .OpFunctionCall, .{
2055 .id_result_type = self.typeId(anyerror_ty_ref),2040 .id_result_type = anyerror_ty_id,
2056 .id_result = error_id,2041 .id_result = error_id,
2057 .function = test_id,2042 .function = test_id,
2058 });2043 });
...@@ -2084,17 +2069,17 @@ const DeclGen = struct {...@@ -2084,17 +2069,17 @@ const DeclGen = struct {
2084 .func => {2069 .func => {
2085 assert(decl.typeOf(mod).zigTypeTag(mod) == .Fn);2070 assert(decl.typeOf(mod).zigTypeTag(mod) == .Fn);
2086 const fn_info = mod.typeToFunc(decl.typeOf(mod)).?;2071 const fn_info = mod.typeToFunc(decl.typeOf(mod)).?;
2087 const return_ty_ref = try self.resolveFnReturnType(Type.fromInterned(fn_info.return_type));2072 const return_ty_id = try self.resolveFnReturnType(Type.fromInterned(fn_info.return_type));
20882073
2089 const prototype_ty_ref = try self.resolveType(decl.typeOf(mod), .direct);2074 const prototype_ty_id = try self.resolveType(decl.typeOf(mod), .direct);
2090 try self.func.prologue.emit(self.spv.gpa, .OpFunction, .{2075 try self.func.prologue.emit(self.spv.gpa, .OpFunction, .{
2091 .id_result_type = self.typeId(return_ty_ref),2076 .id_result_type = return_ty_id,
2092 .id_result = result_id,2077 .id_result = result_id,
2093 .function_control = switch (fn_info.cc) {2078 .function_control = switch (fn_info.cc) {
2094 .Inline => .{ .Inline = true },2079 .Inline => .{ .Inline = true },
2095 else => .{},2080 else => .{},
2096 },2081 },
2097 .function_type = self.typeId(prototype_ty_ref),2082 .function_type = prototype_ty_id,
2098 });2083 });
20992084
2100 comptime assert(zig_call_abi_ver == 3);2085 comptime assert(zig_call_abi_ver == 3);
...@@ -2103,7 +2088,7 @@ const DeclGen = struct {...@@ -2103,7 +2088,7 @@ const DeclGen = struct {
2103 const param_ty = Type.fromInterned(param_ty_index);2088 const param_ty = Type.fromInterned(param_ty_index);
2104 if (!param_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;2089 if (!param_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
21052090
2106 const param_type_id = try self.resolveTypeId(param_ty);2091 const param_type_id = try self.resolveType(param_ty, .direct);
2107 const arg_result_id = self.spv.allocId();2092 const arg_result_id = self.spv.allocId();
2108 try self.func.prologue.emit(self.spv.gpa, .OpFunctionParameter, .{2093 try self.func.prologue.emit(self.spv.gpa, .OpFunctionParameter, .{
2109 .id_result_type = param_type_id,2094 .id_result_type = param_type_id,
...@@ -2159,10 +2144,10 @@ const DeclGen = struct {...@@ -2159,10 +2144,10 @@ const DeclGen = struct {
2159 const final_storage_class = self.spvStorageClass(decl.@"addrspace");2144 const final_storage_class = self.spvStorageClass(decl.@"addrspace");
2160 assert(final_storage_class != .Generic); // These should be instance globals2145 assert(final_storage_class != .Generic); // These should be instance globals
21612146
2162 const ptr_ty_ref = try self.ptrType(decl.typeOf(mod), final_storage_class);2147 const ptr_ty_id = try self.ptrType(decl.typeOf(mod), final_storage_class);
21632148
2164 try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpVariable, .{2149 try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpVariable, .{
2165 .id_result_type = self.typeId(ptr_ty_ref),2150 .id_result_type = ptr_ty_id,
2166 .id_result = result_id,2151 .id_result = result_id,
2167 .storage_class = final_storage_class,2152 .storage_class = final_storage_class,
2168 });2153 });
...@@ -2182,22 +2167,18 @@ const DeclGen = struct {...@@ -2182,22 +2167,18 @@ const DeclGen = struct {
21822167
2183 try self.spv.declareDeclDeps(spv_decl_index, &.{});2168 try self.spv.declareDeclDeps(spv_decl_index, &.{});
21842169
2185 const ptr_ty_ref = try self.ptrType(decl.typeOf(mod), .Function);2170 const ptr_ty_id = try self.ptrType(decl.typeOf(mod), .Function);
21862171
2187 if (maybe_init_val) |init_val| {2172 if (maybe_init_val) |init_val| {
2188 // TODO: Combine with resolveAnonDecl?2173 // TODO: Combine with resolveAnonDecl?
2189 const void_ty_ref = try self.resolveType(Type.void, .direct);2174 const initializer_proto_ty_id = try self.functionType(Type.void, &.{});
2190 const initializer_proto_ty_ref = try self.spv.resolve(.{ .function_type = .{
2191 .return_type = void_ty_ref,
2192 .parameters = &.{},
2193 } });
21942175
2195 const initializer_id = self.spv.allocId();2176 const initializer_id = self.spv.allocId();
2196 try self.func.prologue.emit(self.spv.gpa, .OpFunction, .{2177 try self.func.prologue.emit(self.spv.gpa, .OpFunction, .{
2197 .id_result_type = self.typeId(void_ty_ref),2178 .id_result_type = try self.resolveType(Type.void, .direct),
2198 .id_result = initializer_id,2179 .id_result = initializer_id,
2199 .function_control = .{},2180 .function_control = .{},
2200 .function_type = self.typeId(initializer_proto_ty_ref),2181 .function_type = initializer_proto_ty_id,
2201 });2182 });
22022183
2203 const root_block_id = self.spv.allocId();2184 const root_block_id = self.spv.allocId();
...@@ -2220,7 +2201,7 @@ const DeclGen = struct {...@@ -2220,7 +2201,7 @@ const DeclGen = struct {
2220 try self.spv.debugNameFmt(initializer_id, "initializer of {s}", .{fqn});2201 try self.spv.debugNameFmt(initializer_id, "initializer of {s}", .{fqn});
22212202
2222 try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpExtInst, .{2203 try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpExtInst, .{
2223 .id_result_type = self.typeId(ptr_ty_ref),2204 .id_result_type = ptr_ty_id,
2224 .id_result = result_id,2205 .id_result = result_id,
2225 .set = try self.spv.importInstructionSet(.zig),2206 .set = try self.spv.importInstructionSet(.zig),
2226 .instruction = .{ .inst = 0 }, // TODO: Put this definition somewhere...2207 .instruction = .{ .inst = 0 }, // TODO: Put this definition somewhere...
...@@ -2228,7 +2209,7 @@ const DeclGen = struct {...@@ -2228,7 +2209,7 @@ const DeclGen = struct {
2228 });2209 });
2229 } else {2210 } else {
2230 try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpExtInst, .{2211 try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpExtInst, .{
2231 .id_result_type = self.typeId(ptr_ty_ref),2212 .id_result_type = ptr_ty_id,
2232 .id_result = result_id,2213 .id_result = result_id,
2233 .set = try self.spv.importInstructionSet(.zig),2214 .set = try self.spv.importInstructionSet(.zig),
2234 .instruction = .{ .inst = 0 }, // TODO: Put this definition somewhere...2215 .instruction = .{ .inst = 0 }, // TODO: Put this definition somewhere...
...@@ -2244,7 +2225,7 @@ const DeclGen = struct {...@@ -2244,7 +2225,7 @@ const DeclGen = struct {
2244 const one_id = try self.constInt(ty, 1, .direct);2225 const one_id = try self.constInt(ty, 1, .direct);
2245 const result_id = self.spv.allocId();2226 const result_id = self.spv.allocId();
2246 try self.func.body.emit(self.spv.gpa, .OpSelect, .{2227 try self.func.body.emit(self.spv.gpa, .OpSelect, .{
2247 .id_result_type = try self.resolveType2(ty, .direct),2228 .id_result_type = try self.resolveType(ty, .direct),
2248 .id_result = result_id,2229 .id_result = result_id,
2249 .condition = condition_id,2230 .condition = condition_id,
2250 .object_1 = one_id,2231 .object_1 = one_id,
...@@ -2261,7 +2242,7 @@ const DeclGen = struct {...@@ -2261,7 +2242,7 @@ const DeclGen = struct {
2261 .Bool => blk: {2242 .Bool => blk: {
2262 const result_id = self.spv.allocId();2243 const result_id = self.spv.allocId();
2263 try self.func.body.emit(self.spv.gpa, .OpINotEqual, .{2244 try self.func.body.emit(self.spv.gpa, .OpINotEqual, .{
2264 .id_result_type = try self.resolveType2(Type.bool, .direct),2245 .id_result_type = try self.resolveType(Type.bool, .direct),
2265 .id_result = result_id,2246 .id_result = result_id,
2266 .operand_1 = operand_id,2247 .operand_1 = operand_id,
2267 .operand_2 = try self.constBool(false, .indirect),2248 .operand_2 = try self.constBool(false, .indirect),
...@@ -2283,11 +2264,11 @@ const DeclGen = struct {...@@ -2283,11 +2264,11 @@ const DeclGen = struct {
2283 }2264 }
22842265
2285 fn extractField(self: *DeclGen, result_ty: Type, object: IdRef, field: u32) !IdRef {2266 fn extractField(self: *DeclGen, result_ty: Type, object: IdRef, field: u32) !IdRef {
2286 const result_ty_ref = try self.resolveType(result_ty, .indirect);2267 const result_ty_id = try self.resolveType(result_ty, .indirect);
2287 const result_id = self.spv.allocId();2268 const result_id = self.spv.allocId();
2288 const indexes = [_]u32{field};2269 const indexes = [_]u32{field};
2289 try self.func.body.emit(self.spv.gpa, .OpCompositeExtract, .{2270 try self.func.body.emit(self.spv.gpa, .OpCompositeExtract, .{
2290 .id_result_type = self.typeId(result_ty_ref),2271 .id_result_type = result_ty_id,
2291 .id_result = result_id,2272 .id_result = result_id,
2292 .composite = object,2273 .composite = object,
2293 .indexes = &indexes,2274 .indexes = &indexes,
...@@ -2301,13 +2282,13 @@ const DeclGen = struct {...@@ -2301,13 +2282,13 @@ const DeclGen = struct {
2301 };2282 };
23022283
2303 fn load(self: *DeclGen, value_ty: Type, ptr_id: IdRef, options: MemoryOptions) !IdRef {2284 fn load(self: *DeclGen, value_ty: Type, ptr_id: IdRef, options: MemoryOptions) !IdRef {
2304 const indirect_value_ty_ref = try self.resolveType(value_ty, .indirect);2285 const indirect_value_ty_id = try self.resolveType(value_ty, .indirect);
2305 const result_id = self.spv.allocId();2286 const result_id = self.spv.allocId();
2306 const access = spec.MemoryAccess.Extended{2287 const access = spec.MemoryAccess.Extended{
2307 .Volatile = options.is_volatile,2288 .Volatile = options.is_volatile,
2308 };2289 };
2309 try self.func.body.emit(self.spv.gpa, .OpLoad, .{2290 try self.func.body.emit(self.spv.gpa, .OpLoad, .{
2310 .id_result_type = self.typeId(indirect_value_ty_ref),2291 .id_result_type = indirect_value_ty_id,
2311 .id_result = result_id,2292 .id_result = result_id,
2312 .pointer = ptr_id,2293 .pointer = ptr_id,
2313 .memory_access = access,2294 .memory_access = access,
...@@ -2519,7 +2500,8 @@ const DeclGen = struct {...@@ -2519,7 +2500,8 @@ const DeclGen = struct {
25192500
2520 const result_ty = self.typeOfIndex(inst);2501 const result_ty = self.typeOfIndex(inst);
2521 const shift_ty = self.typeOf(bin_op.rhs);2502 const shift_ty = self.typeOf(bin_op.rhs);
2522 const shift_ty_ref = try self.resolveType(shift_ty, .direct);2503 const scalar_result_ty_id = try self.resolveType(result_ty.scalarType(mod), .direct);
2504 const scalar_shift_ty_id = try self.resolveType(shift_ty.scalarType(mod), .direct);
25232505
2524 const info = self.arithmeticTypeInfo(result_ty);2506 const info = self.arithmeticTypeInfo(result_ty);
2525 switch (info.class) {2507 switch (info.class) {
...@@ -2536,7 +2518,7 @@ const DeclGen = struct {...@@ -2536,7 +2518,7 @@ const DeclGen = struct {
25362518
2537 // Sometimes Zig doesn't make both of the arguments the same types here. SPIR-V expects that,2519 // Sometimes Zig doesn't make both of the arguments the same types here. SPIR-V expects that,
2538 // so just manually upcast it if required.2520 // so just manually upcast it if required.
2539 const shift_id = if (shift_ty_ref != wip.ty_ref) blk: {2521 const shift_id = if (scalar_shift_ty_id != scalar_result_ty_id) blk: {
2540 const shift_id = self.spv.allocId();2522 const shift_id = self.spv.allocId();
2541 try self.func.body.emit(self.spv.gpa, .OpUConvert, .{2523 try self.func.body.emit(self.spv.gpa, .OpUConvert, .{
2542 .id_result_type = wip.ty_id,2524 .id_result_type = wip.ty_id,
...@@ -2663,7 +2645,7 @@ const DeclGen = struct {...@@ -2663,7 +2645,7 @@ const DeclGen = struct {
2663 const result_id = self.spv.allocId();2645 const result_id = self.spv.allocId();
2664 const mask_id = try self.constInt(ty, mask_value, .direct);2646 const mask_id = try self.constInt(ty, mask_value, .direct);
2665 try self.func.body.emit(self.spv.gpa, .OpBitwiseAnd, .{2647 try self.func.body.emit(self.spv.gpa, .OpBitwiseAnd, .{
2666 .id_result_type = try self.resolveType2(ty, .direct),2648 .id_result_type = try self.resolveType(ty, .direct),
2667 .id_result = result_id,2649 .id_result = result_id,
2668 .operand_1 = value_id,2650 .operand_1 = value_id,
2669 .operand_2 = mask_id,2651 .operand_2 = mask_id,
...@@ -2675,14 +2657,14 @@ const DeclGen = struct {...@@ -2675,14 +2657,14 @@ const DeclGen = struct {
2675 const shift_amt_id = try self.constInt(ty, info.backing_bits - info.bits, .direct);2657 const shift_amt_id = try self.constInt(ty, info.backing_bits - info.bits, .direct);
2676 const left_id = self.spv.allocId();2658 const left_id = self.spv.allocId();
2677 try self.func.body.emit(self.spv.gpa, .OpShiftLeftLogical, .{2659 try self.func.body.emit(self.spv.gpa, .OpShiftLeftLogical, .{
2678 .id_result_type = try self.resolveType2(ty, .direct),2660 .id_result_type = try self.resolveType(ty, .direct),
2679 .id_result = left_id,2661 .id_result = left_id,
2680 .base = value_id,2662 .base = value_id,
2681 .shift = shift_amt_id,2663 .shift = shift_amt_id,
2682 });2664 });
2683 const right_id = self.spv.allocId();2665 const right_id = self.spv.allocId();
2684 try self.func.body.emit(self.spv.gpa, .OpShiftRightArithmetic, .{2666 try self.func.body.emit(self.spv.gpa, .OpShiftRightArithmetic, .{
2685 .id_result_type = try self.resolveType2(ty, .direct),2667 .id_result_type = try self.resolveType(ty, .direct),
2686 .id_result = right_id,2668 .id_result = right_id,
2687 .base = left_id,2669 .base = left_id,
2688 .shift = shift_amt_id,2670 .shift = shift_amt_id,
...@@ -2698,7 +2680,7 @@ const DeclGen = struct {...@@ -2698,7 +2680,7 @@ const DeclGen = struct {
2698 const lhs_id = try self.resolve(bin_op.lhs);2680 const lhs_id = try self.resolve(bin_op.lhs);
2699 const rhs_id = try self.resolve(bin_op.rhs);2681 const rhs_id = try self.resolve(bin_op.rhs);
2700 const ty = self.typeOfIndex(inst);2682 const ty = self.typeOfIndex(inst);
2701 const ty_id = try self.resolveType2(ty, .direct);2683 const ty_id = try self.resolveType(ty, .direct);
2702 const info = self.arithmeticTypeInfo(ty);2684 const info = self.arithmeticTypeInfo(ty);
2703 switch (info.class) {2685 switch (info.class) {
2704 .composite_integer => unreachable, // TODO2686 .composite_integer => unreachable, // TODO
...@@ -2759,7 +2741,7 @@ const DeclGen = struct {...@@ -2759,7 +2741,7 @@ const DeclGen = struct {
27592741
2760 fn floor(self: *DeclGen, ty: Type, operand_id: IdRef) !IdRef {2742 fn floor(self: *DeclGen, ty: Type, operand_id: IdRef) !IdRef {
2761 const target = self.getTarget();2743 const target = self.getTarget();
2762 const ty_ref = try self.resolveType(ty, .direct);2744 const ty_id = try self.resolveType(ty, .direct);
2763 const ext_inst: Word = switch (target.os.tag) {2745 const ext_inst: Word = switch (target.os.tag) {
2764 .opencl => 25,2746 .opencl => 25,
2765 .vulkan => 8,2747 .vulkan => 8,
...@@ -2773,7 +2755,7 @@ const DeclGen = struct {...@@ -2773,7 +2755,7 @@ const DeclGen = struct {
27732755
2774 const result_id = self.spv.allocId();2756 const result_id = self.spv.allocId();
2775 try self.func.body.emit(self.spv.gpa, .OpExtInst, .{2757 try self.func.body.emit(self.spv.gpa, .OpExtInst, .{
2776 .id_result_type = self.typeId(ty_ref),2758 .id_result_type = ty_id,
2777 .id_result = result_id,2759 .id_result = result_id,
2778 .set = set_id,2760 .set = set_id,
2779 .instruction = .{ .inst = ext_inst },2761 .instruction = .{ .inst = ext_inst },
...@@ -2928,11 +2910,12 @@ const DeclGen = struct {...@@ -2928,11 +2910,12 @@ const DeclGen = struct {
2928 const operand_ty = self.typeOf(extra.lhs);2910 const operand_ty = self.typeOf(extra.lhs);
2929 const ov_ty = result_ty.structFieldType(1, self.module);2911 const ov_ty = result_ty.structFieldType(1, self.module);
29302912
2931 const bool_ty_ref = try self.resolveType(Type.bool, .direct);2913 const bool_ty_id = try self.resolveType(Type.bool, .direct);
2932 const cmp_ty_ref = if (self.isVector(operand_ty))2914 const cmp_ty_id = if (self.isVector(operand_ty))
2933 try self.spv.vectorType(operand_ty.vectorLen(mod), bool_ty_ref)2915 // TODO: Resolving a vector type with .direct should return a SPIR-V vector
2916 try self.spv.vectorType(operand_ty.vectorLen(mod), try self.resolveType(Type.bool, .direct))
2934 else2917 else
2935 bool_ty_ref;2918 bool_ty_id;
29362919
2937 const info = self.arithmeticTypeInfo(operand_ty);2920 const info = self.arithmeticTypeInfo(operand_ty);
2938 switch (info.class) {2921 switch (info.class) {
...@@ -2968,7 +2951,7 @@ const DeclGen = struct {...@@ -2968,7 +2951,7 @@ const DeclGen = struct {
2968 // For subtraction the conditions need to be swapped.2951 // For subtraction the conditions need to be swapped.
2969 const overflowed_id = self.spv.allocId();2952 const overflowed_id = self.spv.allocId();
2970 try self.func.body.emit(self.spv.gpa, ucmp, .{2953 try self.func.body.emit(self.spv.gpa, ucmp, .{
2971 .id_result_type = self.typeId(cmp_ty_ref),2954 .id_result_type = cmp_ty_id,
2972 .id_result = overflowed_id,2955 .id_result = overflowed_id,
2973 .operand_1 = result_id.*,2956 .operand_1 = result_id.*,
2974 .operand_2 = lhs_elem_id,2957 .operand_2 = lhs_elem_id,
...@@ -2996,7 +2979,7 @@ const DeclGen = struct {...@@ -2996,7 +2979,7 @@ const DeclGen = struct {
2996 const rhs_lt_zero_id = self.spv.allocId();2979 const rhs_lt_zero_id = self.spv.allocId();
2997 const zero_id = try self.constInt(wip_result.ty, 0, .direct);2980 const zero_id = try self.constInt(wip_result.ty, 0, .direct);
2998 try self.func.body.emit(self.spv.gpa, .OpSLessThan, .{2981 try self.func.body.emit(self.spv.gpa, .OpSLessThan, .{
2999 .id_result_type = self.typeId(cmp_ty_ref),2982 .id_result_type = cmp_ty_id,
3000 .id_result = rhs_lt_zero_id,2983 .id_result = rhs_lt_zero_id,
3001 .operand_1 = rhs_elem_id,2984 .operand_1 = rhs_elem_id,
3002 .operand_2 = zero_id,2985 .operand_2 = zero_id,
...@@ -3004,7 +2987,7 @@ const DeclGen = struct {...@@ -3004,7 +2987,7 @@ const DeclGen = struct {
30042987
3005 const value_gt_lhs_id = self.spv.allocId();2988 const value_gt_lhs_id = self.spv.allocId();
3006 try self.func.body.emit(self.spv.gpa, scmp, .{2989 try self.func.body.emit(self.spv.gpa, scmp, .{
3007 .id_result_type = self.typeId(cmp_ty_ref),2990 .id_result_type = cmp_ty_id,
3008 .id_result = value_gt_lhs_id,2991 .id_result = value_gt_lhs_id,
3009 .operand_1 = lhs_elem_id,2992 .operand_1 = lhs_elem_id,
3010 .operand_2 = result_id.*,2993 .operand_2 = result_id.*,
...@@ -3012,7 +2995,7 @@ const DeclGen = struct {...@@ -3012,7 +2995,7 @@ const DeclGen = struct {
30122995
3013 const overflowed_id = self.spv.allocId();2996 const overflowed_id = self.spv.allocId();
3014 try self.func.body.emit(self.spv.gpa, .OpLogicalEqual, .{2997 try self.func.body.emit(self.spv.gpa, .OpLogicalEqual, .{
3015 .id_result_type = self.typeId(cmp_ty_ref),2998 .id_result_type = cmp_ty_id,
3016 .id_result = overflowed_id,2999 .id_result = overflowed_id,
3017 .operand_1 = rhs_lt_zero_id,3000 .operand_1 = rhs_lt_zero_id,
3018 .operand_2 = value_gt_lhs_id,3001 .operand_2 = value_gt_lhs_id,
...@@ -3096,15 +3079,17 @@ const DeclGen = struct {...@@ -3096,15 +3079,17 @@ const DeclGen = struct {
3096 const result_ty = self.typeOfIndex(inst);3079 const result_ty = self.typeOfIndex(inst);
3097 const operand_ty = self.typeOf(extra.lhs);3080 const operand_ty = self.typeOf(extra.lhs);
3098 const shift_ty = self.typeOf(extra.rhs);3081 const shift_ty = self.typeOf(extra.rhs);
3099 const shift_ty_ref = try self.resolveType(shift_ty, .direct);3082 const scalar_shift_ty_id = try self.resolveType(shift_ty.scalarType(mod), .direct);
3083 const scalar_operand_ty_id = try self.resolveType(operand_ty.scalarType(mod), .direct);
31003084
3101 const ov_ty = result_ty.structFieldType(1, self.module);3085 const ov_ty = result_ty.structFieldType(1, self.module);
31023086
3103 const bool_ty_ref = try self.resolveType(Type.bool, .direct);3087 const bool_ty_id = try self.resolveType(Type.bool, .direct);
3104 const cmp_ty_ref = if (self.isVector(operand_ty))3088 const cmp_ty_id = if (self.isVector(operand_ty))
3105 try self.spv.vectorType(operand_ty.vectorLen(mod), bool_ty_ref)3089 // TODO: Resolving a vector type with .direct should return a SPIR-V vector
3090 try self.spv.vectorType(operand_ty.vectorLen(mod), try self.resolveType(Type.bool, .direct))
3106 else3091 else
3107 bool_ty_ref;3092 bool_ty_id;
31083093
3109 const info = self.arithmeticTypeInfo(operand_ty);3094 const info = self.arithmeticTypeInfo(operand_ty);
3110 switch (info.class) {3095 switch (info.class) {
...@@ -3123,7 +3108,7 @@ const DeclGen = struct {...@@ -3123,7 +3108,7 @@ const DeclGen = struct {
31233108
3124 // Sometimes Zig doesn't make both of the arguments the same types here. SPIR-V expects that,3109 // Sometimes Zig doesn't make both of the arguments the same types here. SPIR-V expects that,
3125 // so just manually upcast it if required.3110 // so just manually upcast it if required.
3126 const shift_id = if (shift_ty_ref != wip_result.ty_ref) blk: {3111 const shift_id = if (scalar_shift_ty_id != scalar_operand_ty_id) blk: {
3127 const shift_id = self.spv.allocId();3112 const shift_id = self.spv.allocId();
3128 try self.func.body.emit(self.spv.gpa, .OpUConvert, .{3113 try self.func.body.emit(self.spv.gpa, .OpUConvert, .{
3129 .id_result_type = wip_result.ty_id,3114 .id_result_type = wip_result.ty_id,
...@@ -3164,7 +3149,7 @@ const DeclGen = struct {...@@ -3164,7 +3149,7 @@ const DeclGen = struct {
31643149
3165 const overflowed_id = self.spv.allocId();3150 const overflowed_id = self.spv.allocId();
3166 try self.func.body.emit(self.spv.gpa, .OpINotEqual, .{3151 try self.func.body.emit(self.spv.gpa, .OpINotEqual, .{
3167 .id_result_type = self.typeId(cmp_ty_ref),3152 .id_result_type = cmp_ty_id,
3168 .id_result = overflowed_id,3153 .id_result = overflowed_id,
3169 .operand_1 = lhs_elem_id,3154 .operand_1 = lhs_elem_id,
3170 .operand_2 = right_shift_id,3155 .operand_2 = right_shift_id,
...@@ -3235,8 +3220,7 @@ const DeclGen = struct {...@@ -3235,8 +3220,7 @@ const DeclGen = struct {
3235 defer wip.deinit();3220 defer wip.deinit();
32363221
3237 const elem_ty = if (wip.is_array) operand_ty.scalarType(mod) else operand_ty;3222 const elem_ty = if (wip.is_array) operand_ty.scalarType(mod) else operand_ty;
3238 const elem_ty_ref = try self.resolveType(elem_ty, .direct);3223 const elem_ty_id = try self.resolveType(elem_ty, .direct);
3239 const elem_ty_id = self.typeId(elem_ty_ref);
32403224
3241 for (wip.results, 0..) |*result_id, i| {3225 for (wip.results, 0..) |*result_id, i| {
3242 const elem = try wip.elementAt(operand_ty, operand, i);3226 const elem = try wip.elementAt(operand_ty, operand, i);
...@@ -3261,6 +3245,8 @@ const DeclGen = struct {...@@ -3261,6 +3245,8 @@ const DeclGen = struct {
3261 .id_ref_4 = &.{elem},3245 .id_ref_4 = &.{elem},
3262 });3246 });
32633247
3248 // TODO: Comparison should be removed..
3249 // Its valid because SpvModule caches numeric types
3264 if (wip.ty_id == elem_ty_id) {3250 if (wip.ty_id == elem_ty_id) {
3265 result_id.* = tmp;3251 result_id.* = tmp;
3266 continue;3252 continue;
...@@ -3307,8 +3293,7 @@ const DeclGen = struct {...@@ -3307,8 +3293,7 @@ const DeclGen = struct {
3307 const operand = try self.resolve(reduce.operand);3293 const operand = try self.resolve(reduce.operand);
3308 const operand_ty = self.typeOf(reduce.operand);3294 const operand_ty = self.typeOf(reduce.operand);
3309 const scalar_ty = operand_ty.scalarType(mod);3295 const scalar_ty = operand_ty.scalarType(mod);
3310 const scalar_ty_ref = try self.resolveType(scalar_ty, .direct);3296 const scalar_ty_id = try self.resolveType(scalar_ty, .direct);
3311 const scalar_ty_id = self.typeId(scalar_ty_ref);
33123297
3313 const info = self.arithmeticTypeInfo(operand_ty);3298 const info = self.arithmeticTypeInfo(operand_ty);
33143299
...@@ -3408,13 +3393,13 @@ const DeclGen = struct {...@@ -3408,13 +3393,13 @@ const DeclGen = struct {
34083393
3409 fn accessChainId(3394 fn accessChainId(
3410 self: *DeclGen,3395 self: *DeclGen,
3411 result_ty_ref: CacheRef,3396 result_ty_id: IdRef,
3412 base: IdRef,3397 base: IdRef,
3413 indices: []const IdRef,3398 indices: []const IdRef,
3414 ) !IdRef {3399 ) !IdRef {
3415 const result_id = self.spv.allocId();3400 const result_id = self.spv.allocId();
3416 try self.func.body.emit(self.spv.gpa, .OpInBoundsAccessChain, .{3401 try self.func.body.emit(self.spv.gpa, .OpInBoundsAccessChain, .{
3417 .id_result_type = self.typeId(result_ty_ref),3402 .id_result_type = result_ty_id,
3418 .id_result = result_id,3403 .id_result = result_id,
3419 .base = base,3404 .base = base,
3420 .indexes = indices,3405 .indexes = indices,
...@@ -3428,18 +3413,18 @@ const DeclGen = struct {...@@ -3428,18 +3413,18 @@ const DeclGen = struct {
3428 /// is the latter and PtrAccessChain is the former.3413 /// is the latter and PtrAccessChain is the former.
3429 fn accessChain(3414 fn accessChain(
3430 self: *DeclGen,3415 self: *DeclGen,
3431 result_ty_ref: CacheRef,3416 result_ty_id: IdRef,
3432 base: IdRef,3417 base: IdRef,
3433 indices: []const u32,3418 indices: []const u32,
3434 ) !IdRef {3419 ) !IdRef {
3435 const ids = try self.indicesToIds(indices);3420 const ids = try self.indicesToIds(indices);
3436 defer self.gpa.free(ids);3421 defer self.gpa.free(ids);
3437 return try self.accessChainId(result_ty_ref, base, ids);3422 return try self.accessChainId(result_ty_id, base, ids);
3438 }3423 }
34393424
3440 fn ptrAccessChain(3425 fn ptrAccessChain(
3441 self: *DeclGen,3426 self: *DeclGen,
3442 result_ty_ref: CacheRef,3427 result_ty_id: IdRef,
3443 base: IdRef,3428 base: IdRef,
3444 element: IdRef,3429 element: IdRef,
3445 indices: []const u32,3430 indices: []const u32,
...@@ -3449,7 +3434,7 @@ const DeclGen = struct {...@@ -3449,7 +3434,7 @@ const DeclGen = struct {
34493434
3450 const result_id = self.spv.allocId();3435 const result_id = self.spv.allocId();
3451 try self.func.body.emit(self.spv.gpa, .OpInBoundsPtrAccessChain, .{3436 try self.func.body.emit(self.spv.gpa, .OpInBoundsPtrAccessChain, .{
3452 .id_result_type = self.typeId(result_ty_ref),3437 .id_result_type = result_ty_id,
3453 .id_result = result_id,3438 .id_result = result_id,
3454 .base = base,3439 .base = base,
3455 .element = element,3440 .element = element,
...@@ -3460,21 +3445,21 @@ const DeclGen = struct {...@@ -3460,21 +3445,21 @@ const DeclGen = struct {
34603445
3461 fn ptrAdd(self: *DeclGen, result_ty: Type, ptr_ty: Type, ptr_id: IdRef, offset_id: IdRef) !IdRef {3446 fn ptrAdd(self: *DeclGen, result_ty: Type, ptr_ty: Type, ptr_id: IdRef, offset_id: IdRef) !IdRef {
3462 const mod = self.module;3447 const mod = self.module;
3463 const result_ty_ref = try self.resolveType(result_ty, .direct);3448 const result_ty_id = try self.resolveType(result_ty, .direct);
34643449
3465 switch (ptr_ty.ptrSize(mod)) {3450 switch (ptr_ty.ptrSize(mod)) {
3466 .One => {3451 .One => {
3467 // Pointer to array3452 // Pointer to array
3468 // TODO: Is this correct?3453 // TODO: Is this correct?
3469 return try self.accessChainId(result_ty_ref, ptr_id, &.{offset_id});3454 return try self.accessChainId(result_ty_id, ptr_id, &.{offset_id});
3470 },3455 },
3471 .C, .Many => {3456 .C, .Many => {
3472 return try self.ptrAccessChain(result_ty_ref, ptr_id, offset_id, &.{});3457 return try self.ptrAccessChain(result_ty_id, ptr_id, offset_id, &.{});
3473 },3458 },
3474 .Slice => {3459 .Slice => {
3475 // TODO: This is probably incorrect. A slice should be returned here, though this is what llvm does.3460 // TODO: This is probably incorrect. A slice should be returned here, though this is what llvm does.
3476 const slice_ptr_id = try self.extractField(result_ty, ptr_id, 0);3461 const slice_ptr_id = try self.extractField(result_ty, ptr_id, 0);
3477 return try self.ptrAccessChain(result_ty_ref, slice_ptr_id, offset_id, &.{});3462 return try self.ptrAccessChain(result_ty_id, slice_ptr_id, offset_id, &.{});
3478 },3463 },
3479 }3464 }
3480 }3465 }
...@@ -3497,12 +3482,12 @@ const DeclGen = struct {...@@ -3497,12 +3482,12 @@ const DeclGen = struct {
3497 const ptr_ty = self.typeOf(bin_op.lhs);3482 const ptr_ty = self.typeOf(bin_op.lhs);
3498 const offset_id = try self.resolve(bin_op.rhs);3483 const offset_id = try self.resolve(bin_op.rhs);
3499 const offset_ty = self.typeOf(bin_op.rhs);3484 const offset_ty = self.typeOf(bin_op.rhs);
3500 const offset_ty_ref = try self.resolveType(offset_ty, .direct);3485 const offset_ty_id = try self.resolveType(offset_ty, .direct);
3501 const result_ty = self.typeOfIndex(inst);3486 const result_ty = self.typeOfIndex(inst);
35023487
3503 const negative_offset_id = self.spv.allocId();3488 const negative_offset_id = self.spv.allocId();
3504 try self.func.body.emit(self.spv.gpa, .OpSNegate, .{3489 try self.func.body.emit(self.spv.gpa, .OpSNegate, .{
3505 .id_result_type = self.typeId(offset_ty_ref),3490 .id_result_type = offset_ty_id,
3506 .id_result = negative_offset_id,3491 .id_result = negative_offset_id,
3507 .operand = offset_id,3492 .operand = offset_id,
3508 });3493 });
...@@ -3520,7 +3505,7 @@ const DeclGen = struct {...@@ -3520,7 +3505,7 @@ const DeclGen = struct {
3520 const mod = self.module;3505 const mod = self.module;
3521 var cmp_lhs_id = lhs_id;3506 var cmp_lhs_id = lhs_id;
3522 var cmp_rhs_id = rhs_id;3507 var cmp_rhs_id = rhs_id;
3523 const bool_ty_ref = try self.resolveType(Type.bool, .direct);3508 const bool_ty_id = try self.resolveType(Type.bool, .direct);
3524 const op_ty = switch (ty.zigTypeTag(mod)) {3509 const op_ty = switch (ty.zigTypeTag(mod)) {
3525 .Int, .Bool, .Float => ty,3510 .Int, .Bool, .Float => ty,
3526 .Enum => ty.intTagType(mod),3511 .Enum => ty.intTagType(mod),
...@@ -3532,7 +3517,7 @@ const DeclGen = struct {...@@ -3532,7 +3517,7 @@ const DeclGen = struct {
3532 cmp_lhs_id = self.spv.allocId();3517 cmp_lhs_id = self.spv.allocId();
3533 cmp_rhs_id = self.spv.allocId();3518 cmp_rhs_id = self.spv.allocId();
35343519
3535 const usize_ty_id = try self.resolveType2(Type.usize, .direct);3520 const usize_ty_id = try self.resolveType(Type.usize, .direct);
35363521
3537 try self.func.body.emit(self.spv.gpa, .OpConvertPtrToU, .{3522 try self.func.body.emit(self.spv.gpa, .OpConvertPtrToU, .{
3538 .id_result_type = usize_ty_id,3523 .id_result_type = usize_ty_id,
...@@ -3594,20 +3579,20 @@ const DeclGen = struct {...@@ -3594,20 +3579,20 @@ const DeclGen = struct {
3594 const pl_eq_id = try self.cmp(op, Type.bool, payload_ty, lhs_pl_id, rhs_pl_id);3579 const pl_eq_id = try self.cmp(op, Type.bool, payload_ty, lhs_pl_id, rhs_pl_id);
3595 const lhs_not_valid_id = self.spv.allocId();3580 const lhs_not_valid_id = self.spv.allocId();
3596 try self.func.body.emit(self.spv.gpa, .OpLogicalNot, .{3581 try self.func.body.emit(self.spv.gpa, .OpLogicalNot, .{
3597 .id_result_type = self.typeId(bool_ty_ref),3582 .id_result_type = bool_ty_id,
3598 .id_result = lhs_not_valid_id,3583 .id_result = lhs_not_valid_id,
3599 .operand = lhs_valid_id,3584 .operand = lhs_valid_id,
3600 });3585 });
3601 const impl_id = self.spv.allocId();3586 const impl_id = self.spv.allocId();
3602 try self.func.body.emit(self.spv.gpa, .OpLogicalOr, .{3587 try self.func.body.emit(self.spv.gpa, .OpLogicalOr, .{
3603 .id_result_type = self.typeId(bool_ty_ref),3588 .id_result_type = bool_ty_id,
3604 .id_result = impl_id,3589 .id_result = impl_id,
3605 .operand_1 = lhs_not_valid_id,3590 .operand_1 = lhs_not_valid_id,
3606 .operand_2 = pl_eq_id,3591 .operand_2 = pl_eq_id,
3607 });3592 });
3608 const result_id = self.spv.allocId();3593 const result_id = self.spv.allocId();
3609 try self.func.body.emit(self.spv.gpa, .OpLogicalAnd, .{3594 try self.func.body.emit(self.spv.gpa, .OpLogicalAnd, .{
3610 .id_result_type = self.typeId(bool_ty_ref),3595 .id_result_type = bool_ty_id,
3611 .id_result = result_id,3596 .id_result = result_id,
3612 .operand_1 = valid_eq_id,3597 .operand_1 = valid_eq_id,
3613 .operand_2 = impl_id,3598 .operand_2 = impl_id,
...@@ -3620,14 +3605,14 @@ const DeclGen = struct {...@@ -3620,14 +3605,14 @@ const DeclGen = struct {
36203605
3621 const impl_id = self.spv.allocId();3606 const impl_id = self.spv.allocId();
3622 try self.func.body.emit(self.spv.gpa, .OpLogicalAnd, .{3607 try self.func.body.emit(self.spv.gpa, .OpLogicalAnd, .{
3623 .id_result_type = self.typeId(bool_ty_ref),3608 .id_result_type = bool_ty_id,
3624 .id_result = impl_id,3609 .id_result = impl_id,
3625 .operand_1 = lhs_valid_id,3610 .operand_1 = lhs_valid_id,
3626 .operand_2 = pl_neq_id,3611 .operand_2 = pl_neq_id,
3627 });3612 });
3628 const result_id = self.spv.allocId();3613 const result_id = self.spv.allocId();
3629 try self.func.body.emit(self.spv.gpa, .OpLogicalOr, .{3614 try self.func.body.emit(self.spv.gpa, .OpLogicalOr, .{
3630 .id_result_type = self.typeId(bool_ty_ref),3615 .id_result_type = bool_ty_id,
3631 .id_result = result_id,3616 .id_result = result_id,
3632 .operand_1 = valid_neq_id,3617 .operand_1 = valid_neq_id,
3633 .operand_2 = impl_id,3618 .operand_2 = impl_id,
...@@ -3695,7 +3680,7 @@ const DeclGen = struct {...@@ -3695,7 +3680,7 @@ const DeclGen = struct {
36953680
3696 const result_id = self.spv.allocId();3681 const result_id = self.spv.allocId();
3697 try self.func.body.emitRaw(self.spv.gpa, opcode, 4);3682 try self.func.body.emitRaw(self.spv.gpa, opcode, 4);
3698 self.func.body.writeOperand(spec.IdResultType, self.typeId(bool_ty_ref));3683 self.func.body.writeOperand(spec.IdResultType, bool_ty_id);
3699 self.func.body.writeOperand(spec.IdResult, result_id);3684 self.func.body.writeOperand(spec.IdResult, result_id);
3700 self.func.body.writeOperand(spec.IdResultType, cmp_lhs_id);3685 self.func.body.writeOperand(spec.IdResultType, cmp_lhs_id);
3701 self.func.body.writeOperand(spec.IdResultType, cmp_rhs_id);3686 self.func.body.writeOperand(spec.IdResultType, cmp_rhs_id);
...@@ -3728,6 +3713,7 @@ const DeclGen = struct {...@@ -3728,6 +3713,7 @@ const DeclGen = struct {
3728 return try self.cmp(op, result_ty, ty, lhs_id, rhs_id);3713 return try self.cmp(op, result_ty, ty, lhs_id, rhs_id);
3729 }3714 }
37303715
3716 /// Bitcast one type to another. Note: both types, input, output are expected in **direct** representation.
3731 fn bitCast(3717 fn bitCast(
3732 self: *DeclGen,3718 self: *DeclGen,
3733 dst_ty: Type,3719 dst_ty: Type,
...@@ -3735,13 +3721,11 @@ const DeclGen = struct {...@@ -3735,13 +3721,11 @@ const DeclGen = struct {
3735 src_id: IdRef,3721 src_id: IdRef,
3736 ) !IdRef {3722 ) !IdRef {
3737 const mod = self.module;3723 const mod = self.module;
3738 const src_ty_ref = try self.resolveType(src_ty, .direct);3724 const src_ty_id = try self.resolveType(src_ty, .direct);
3739 const dst_ty_ref = try self.resolveType(dst_ty, .direct);3725 const dst_ty_id = try self.resolveType(dst_ty, .direct);
3740 const src_key = self.spv.cache.lookup(src_ty_ref);
3741 const dst_key = self.spv.cache.lookup(dst_ty_ref);
37423726
3743 const result_id = blk: {3727 const result_id = blk: {
3744 if (src_ty_ref == dst_ty_ref) {3728 if (src_ty_id == dst_ty_id) {
3745 break :blk src_id;3729 break :blk src_id;
3746 }3730 }
37473731
...@@ -3751,7 +3735,7 @@ const DeclGen = struct {...@@ -3751,7 +3735,7 @@ const DeclGen = struct {
3751 if (src_ty.zigTypeTag(mod) == .Int and dst_ty.isPtrAtRuntime(mod)) {3735 if (src_ty.zigTypeTag(mod) == .Int and dst_ty.isPtrAtRuntime(mod)) {
3752 const result_id = self.spv.allocId();3736 const result_id = self.spv.allocId();
3753 try self.func.body.emit(self.spv.gpa, .OpConvertUToPtr, .{3737 try self.func.body.emit(self.spv.gpa, .OpConvertUToPtr, .{
3754 .id_result_type = self.typeId(dst_ty_ref),3738 .id_result_type = dst_ty_id,
3755 .id_result = result_id,3739 .id_result = result_id,
3756 .integer_value = src_id,3740 .integer_value = src_id,
3757 });3741 });
...@@ -3761,10 +3745,11 @@ const DeclGen = struct {...@@ -3761,10 +3745,11 @@ const DeclGen = struct {
3761 // We can only use OpBitcast for specific conversions: between numerical types, and3745 // We can only use OpBitcast for specific conversions: between numerical types, and
3762 // between pointers. If the resolved spir-v types fall into this category then emit OpBitcast,3746 // between pointers. If the resolved spir-v types fall into this category then emit OpBitcast,
3763 // otherwise use a temporary and perform a pointer cast.3747 // otherwise use a temporary and perform a pointer cast.
3764 if ((src_key.isNumericalType() and dst_key.isNumericalType()) or (src_key == .ptr_type and dst_key == .ptr_type)) {3748 const can_bitcast = (src_ty.isNumeric(mod) and dst_ty.isNumeric(mod)) or (src_ty.isPtrAtRuntime(mod) and dst_ty.isPtrAtRuntime(mod));
3749 if (can_bitcast) {
3765 const result_id = self.spv.allocId();3750 const result_id = self.spv.allocId();
3766 try self.func.body.emit(self.spv.gpa, .OpBitcast, .{3751 try self.func.body.emit(self.spv.gpa, .OpBitcast, .{
3767 .id_result_type = self.typeId(dst_ty_ref),3752 .id_result_type = dst_ty_id,
3768 .id_result = result_id,3753 .id_result = result_id,
3769 .operand = src_id,3754 .operand = src_id,
3770 });3755 });
...@@ -3772,13 +3757,13 @@ const DeclGen = struct {...@@ -3772,13 +3757,13 @@ const DeclGen = struct {
3772 break :blk result_id;3757 break :blk result_id;
3773 }3758 }
37743759
3775 const dst_ptr_ty_ref = try self.ptrType(dst_ty, .Function);3760 const dst_ptr_ty_id = try self.ptrType(dst_ty, .Function);
37763761
3777 const tmp_id = try self.alloc(src_ty, .{ .storage_class = .Function });3762 const tmp_id = try self.alloc(src_ty, .{ .storage_class = .Function });
3778 try self.store(src_ty, tmp_id, src_id, .{});3763 try self.store(src_ty, tmp_id, src_id, .{});
3779 const casted_ptr_id = self.spv.allocId();3764 const casted_ptr_id = self.spv.allocId();
3780 try self.func.body.emit(self.spv.gpa, .OpBitcast, .{3765 try self.func.body.emit(self.spv.gpa, .OpBitcast, .{
3781 .id_result_type = self.typeId(dst_ptr_ty_ref),3766 .id_result_type = dst_ptr_ty_id,
3782 .id_result = casted_ptr_id,3767 .id_result = casted_ptr_id,
3783 .operand = tmp_id,3768 .operand = tmp_id,
3784 });3769 });
...@@ -3850,7 +3835,7 @@ const DeclGen = struct {...@@ -3850,7 +3835,7 @@ const DeclGen = struct {
3850 }3835 }
38513836
3852 fn intFromPtr(self: *DeclGen, operand_id: IdRef) !IdRef {3837 fn intFromPtr(self: *DeclGen, operand_id: IdRef) !IdRef {
3853 const result_type_id = try self.resolveTypeId(Type.usize);3838 const result_type_id = try self.resolveType(Type.usize, .direct);
3854 const result_id = self.spv.allocId();3839 const result_id = self.spv.allocId();
3855 try self.func.body.emit(self.spv.gpa, .OpConvertPtrToU, .{3840 try self.func.body.emit(self.spv.gpa, .OpConvertPtrToU, .{
3856 .id_result_type = result_type_id,3841 .id_result_type = result_type_id,
...@@ -3871,21 +3856,21 @@ const DeclGen = struct {...@@ -3871,21 +3856,21 @@ const DeclGen = struct {
3871 const operand_ty = self.typeOf(ty_op.operand);3856 const operand_ty = self.typeOf(ty_op.operand);
3872 const operand_id = try self.resolve(ty_op.operand);3857 const operand_id = try self.resolve(ty_op.operand);
3873 const result_ty = self.typeOfIndex(inst);3858 const result_ty = self.typeOfIndex(inst);
3874 const result_ty_ref = try self.resolveType(result_ty, .direct);3859 return try self.floatFromInt(result_ty, operand_ty, operand_id);
3875 return try self.floatFromInt(result_ty_ref, operand_ty, operand_id);
3876 }3860 }
38773861
3878 fn floatFromInt(self: *DeclGen, result_ty_ref: CacheRef, operand_ty: Type, operand_id: IdRef) !IdRef {3862 fn floatFromInt(self: *DeclGen, result_ty: Type, operand_ty: Type, operand_id: IdRef) !IdRef {
3879 const operand_info = self.arithmeticTypeInfo(operand_ty);3863 const operand_info = self.arithmeticTypeInfo(operand_ty);
3880 const result_id = self.spv.allocId();3864 const result_id = self.spv.allocId();
3865 const result_ty_id = try self.resolveType(result_ty, .direct);
3881 switch (operand_info.signedness) {3866 switch (operand_info.signedness) {
3882 .signed => try self.func.body.emit(self.spv.gpa, .OpConvertSToF, .{3867 .signed => try self.func.body.emit(self.spv.gpa, .OpConvertSToF, .{
3883 .id_result_type = self.typeId(result_ty_ref),3868 .id_result_type = result_ty_id,
3884 .id_result = result_id,3869 .id_result = result_id,
3885 .signed_value = operand_id,3870 .signed_value = operand_id,
3886 }),3871 }),
3887 .unsigned => try self.func.body.emit(self.spv.gpa, .OpConvertUToF, .{3872 .unsigned => try self.func.body.emit(self.spv.gpa, .OpConvertUToF, .{
3888 .id_result_type = self.typeId(result_ty_ref),3873 .id_result_type = result_ty_id,
3889 .id_result = result_id,3874 .id_result = result_id,
3890 .unsigned_value = operand_id,3875 .unsigned_value = operand_id,
3891 }),3876 }),
...@@ -3902,16 +3887,16 @@ const DeclGen = struct {...@@ -3902,16 +3887,16 @@ const DeclGen = struct {
39023887
3903 fn intFromFloat(self: *DeclGen, result_ty: Type, operand_id: IdRef) !IdRef {3888 fn intFromFloat(self: *DeclGen, result_ty: Type, operand_id: IdRef) !IdRef {
3904 const result_info = self.arithmeticTypeInfo(result_ty);3889 const result_info = self.arithmeticTypeInfo(result_ty);
3905 const result_ty_ref = try self.resolveType(result_ty, .direct);3890 const result_ty_id = try self.resolveType(result_ty, .direct);
3906 const result_id = self.spv.allocId();3891 const result_id = self.spv.allocId();
3907 switch (result_info.signedness) {3892 switch (result_info.signedness) {
3908 .signed => try self.func.body.emit(self.spv.gpa, .OpConvertFToS, .{3893 .signed => try self.func.body.emit(self.spv.gpa, .OpConvertFToS, .{
3909 .id_result_type = self.typeId(result_ty_ref),3894 .id_result_type = result_ty_id,
3910 .id_result = result_id,3895 .id_result = result_id,
3911 .float_value = operand_id,3896 .float_value = operand_id,
3912 }),3897 }),
3913 .unsigned => try self.func.body.emit(self.spv.gpa, .OpConvertFToU, .{3898 .unsigned => try self.func.body.emit(self.spv.gpa, .OpConvertFToU, .{
3914 .id_result_type = self.typeId(result_ty_ref),3899 .id_result_type = result_ty_id,
3915 .id_result = result_id,3900 .id_result = result_id,
3916 .float_value = operand_id,3901 .float_value = operand_id,
3917 }),3902 }),
...@@ -3937,7 +3922,7 @@ const DeclGen = struct {...@@ -3937,7 +3922,7 @@ const DeclGen = struct {
3937 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;3922 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
3938 const operand_id = try self.resolve(ty_op.operand);3923 const operand_id = try self.resolve(ty_op.operand);
3939 const dest_ty = self.typeOfIndex(inst);3924 const dest_ty = self.typeOfIndex(inst);
3940 const dest_ty_id = try self.resolveTypeId(dest_ty);3925 const dest_ty_id = try self.resolveType(dest_ty, .direct);
39413926
3942 const result_id = self.spv.allocId();3927 const result_id = self.spv.allocId();
3943 try self.func.body.emit(self.spv.gpa, .OpFConvert, .{3928 try self.func.body.emit(self.spv.gpa, .OpFConvert, .{
...@@ -3987,7 +3972,7 @@ const DeclGen = struct {...@@ -3987,7 +3972,7 @@ const DeclGen = struct {
3987 const slice_ty = self.typeOfIndex(inst);3972 const slice_ty = self.typeOfIndex(inst);
3988 const elem_ptr_ty = slice_ty.slicePtrFieldType(mod);3973 const elem_ptr_ty = slice_ty.slicePtrFieldType(mod);
39893974
3990 const elem_ptr_ty_ref = try self.resolveType(elem_ptr_ty, .direct);3975 const elem_ptr_ty_id = try self.resolveType(elem_ptr_ty, .direct);
39913976
3992 const array_ptr_id = try self.resolve(ty_op.operand);3977 const array_ptr_id = try self.resolve(ty_op.operand);
3993 const len_id = try self.constInt(Type.usize, array_ty.arrayLen(mod), .direct);3978 const len_id = try self.constInt(Type.usize, array_ty.arrayLen(mod), .direct);
...@@ -3997,7 +3982,7 @@ const DeclGen = struct {...@@ -3997,7 +3982,7 @@ const DeclGen = struct {
3997 try self.bitCast(elem_ptr_ty, array_ptr_ty, array_ptr_id)3982 try self.bitCast(elem_ptr_ty, array_ptr_ty, array_ptr_id)
3998 else3983 else
3999 // Convert the pointer-to-array to a pointer to the first element.3984 // Convert the pointer-to-array to a pointer to the first element.
4000 try self.accessChain(elem_ptr_ty_ref, array_ptr_id, &.{0});3985 try self.accessChain(elem_ptr_ty_id, array_ptr_id, &.{0});
40013986
4002 return try self.constructStruct(3987 return try self.constructStruct(
4003 slice_ty,3988 slice_ty,
...@@ -4171,10 +4156,10 @@ const DeclGen = struct {...@@ -4171,10 +4156,10 @@ const DeclGen = struct {
4171 const index_id = try self.resolve(bin_op.rhs);4156 const index_id = try self.resolve(bin_op.rhs);
41724157
4173 const ptr_ty = self.typeOfIndex(inst);4158 const ptr_ty = self.typeOfIndex(inst);
4174 const ptr_ty_ref = try self.resolveType(ptr_ty, .direct);4159 const ptr_ty_id = try self.resolveType(ptr_ty, .direct);
41754160
4176 const slice_ptr = try self.extractField(ptr_ty, slice_id, 0);4161 const slice_ptr = try self.extractField(ptr_ty, slice_id, 0);
4177 return try self.ptrAccessChain(ptr_ty_ref, slice_ptr, index_id, &.{});4162 return try self.ptrAccessChain(ptr_ty_id, slice_ptr, index_id, &.{});
4178 }4163 }
41794164
4180 fn airSliceElemVal(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {4165 fn airSliceElemVal(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
...@@ -4187,10 +4172,10 @@ const DeclGen = struct {...@@ -4187,10 +4172,10 @@ const DeclGen = struct {
4187 const index_id = try self.resolve(bin_op.rhs);4172 const index_id = try self.resolve(bin_op.rhs);
41884173
4189 const ptr_ty = slice_ty.slicePtrFieldType(mod);4174 const ptr_ty = slice_ty.slicePtrFieldType(mod);
4190 const ptr_ty_ref = try self.resolveType(ptr_ty, .direct);4175 const ptr_ty_id = try self.resolveType(ptr_ty, .direct);
41914176
4192 const slice_ptr = try self.extractField(ptr_ty, slice_id, 0);4177 const slice_ptr = try self.extractField(ptr_ty, slice_id, 0);
4193 const elem_ptr = try self.ptrAccessChain(ptr_ty_ref, slice_ptr, index_id, &.{});4178 const elem_ptr = try self.ptrAccessChain(ptr_ty_id, slice_ptr, index_id, &.{});
4194 return try self.load(slice_ty.childType(mod), elem_ptr, .{ .is_volatile = slice_ty.isVolatilePtr(mod) });4179 return try self.load(slice_ty.childType(mod), elem_ptr, .{ .is_volatile = slice_ty.isVolatilePtr(mod) });
4195 }4180 }
41964181
...@@ -4198,14 +4183,14 @@ const DeclGen = struct {...@@ -4198,14 +4183,14 @@ const DeclGen = struct {
4198 const mod = self.module;4183 const mod = self.module;
4199 // Construct new pointer type for the resulting pointer4184 // Construct new pointer type for the resulting pointer
4200 const elem_ty = ptr_ty.elemType2(mod); // use elemType() so that we get T for *[N]T.4185 const elem_ty = ptr_ty.elemType2(mod); // use elemType() so that we get T for *[N]T.
4201 const elem_ptr_ty_ref = try self.ptrType(elem_ty, self.spvStorageClass(ptr_ty.ptrAddressSpace(mod)));4186 const elem_ptr_ty_id = try self.ptrType(elem_ty, self.spvStorageClass(ptr_ty.ptrAddressSpace(mod)));
4202 if (ptr_ty.isSinglePointer(mod)) {4187 if (ptr_ty.isSinglePointer(mod)) {
4203 // Pointer-to-array. In this case, the resulting pointer is not of the same type4188 // Pointer-to-array. In this case, the resulting pointer is not of the same type
4204 // as the ptr_ty (we want a *T, not a *[N]T), and hence we need to use accessChain.4189 // as the ptr_ty (we want a *T, not a *[N]T), and hence we need to use accessChain.
4205 return try self.accessChainId(elem_ptr_ty_ref, ptr_id, &.{index_id});4190 return try self.accessChainId(elem_ptr_ty_id, ptr_id, &.{index_id});
4206 } else {4191 } else {
4207 // Resulting pointer type is the same as the ptr_ty, so use ptrAccessChain4192 // Resulting pointer type is the same as the ptr_ty, so use ptrAccessChain
4208 return try self.ptrAccessChain(elem_ptr_ty_ref, ptr_id, index_id, &.{});4193 return try self.ptrAccessChain(elem_ptr_ty_id, ptr_id, index_id, &.{});
4209 }4194 }
4210 }4195 }
42114196
...@@ -4238,11 +4223,11 @@ const DeclGen = struct {...@@ -4238,11 +4223,11 @@ const DeclGen = struct {
4238 // For now, just generate a temporary and use that.4223 // For now, just generate a temporary and use that.
4239 // TODO: This backend probably also should use isByRef from llvm...4224 // TODO: This backend probably also should use isByRef from llvm...
42404225
4241 const elem_ptr_ty_ref = try self.ptrType(elem_ty, .Function);4226 const elem_ptr_ty_id = try self.ptrType(elem_ty, .Function);
42424227
4243 const tmp_id = try self.alloc(array_ty, .{ .storage_class = .Function });4228 const tmp_id = try self.alloc(array_ty, .{ .storage_class = .Function });
4244 try self.store(array_ty, tmp_id, array_id, .{});4229 try self.store(array_ty, tmp_id, array_id, .{});
4245 const elem_ptr_id = try self.accessChainId(elem_ptr_ty_ref, tmp_id, &.{index_id});4230 const elem_ptr_id = try self.accessChainId(elem_ptr_ty_id, tmp_id, &.{index_id});
4246 return try self.load(elem_ty, elem_ptr_id, .{});4231 return try self.load(elem_ty, elem_ptr_id, .{});
4247 }4232 }
42484233
...@@ -4267,13 +4252,13 @@ const DeclGen = struct {...@@ -4267,13 +4252,13 @@ const DeclGen = struct {
4267 const scalar_ty = vector_ty.scalarType(mod);4252 const scalar_ty = vector_ty.scalarType(mod);
42684253
4269 const storage_class = self.spvStorageClass(vector_ptr_ty.ptrAddressSpace(mod));4254 const storage_class = self.spvStorageClass(vector_ptr_ty.ptrAddressSpace(mod));
4270 const scalar_ptr_ty_ref = try self.ptrType(scalar_ty, storage_class);4255 const scalar_ptr_ty_id = try self.ptrType(scalar_ty, storage_class);
42714256
4272 const vector_ptr = try self.resolve(data.vector_ptr);4257 const vector_ptr = try self.resolve(data.vector_ptr);
4273 const index = try self.resolve(extra.lhs);4258 const index = try self.resolve(extra.lhs);
4274 const operand = try self.resolve(extra.rhs);4259 const operand = try self.resolve(extra.rhs);
42754260
4276 const elem_ptr_id = try self.accessChainId(scalar_ptr_ty_ref, vector_ptr, &.{index});4261 const elem_ptr_id = try self.accessChainId(scalar_ptr_ty_id, vector_ptr, &.{index});
4277 try self.store(scalar_ty, elem_ptr_id, operand, .{4262 try self.store(scalar_ty, elem_ptr_id, operand, .{
4278 .is_volatile = vector_ptr_ty.isVolatilePtr(mod),4263 .is_volatile = vector_ptr_ty.isVolatilePtr(mod),
4279 });4264 });
...@@ -4289,7 +4274,7 @@ const DeclGen = struct {...@@ -4289,7 +4274,7 @@ const DeclGen = struct {
4289 if (layout.tag_size == 0) return;4274 if (layout.tag_size == 0) return;
42904275
4291 const tag_ty = un_ty.unionTagTypeSafety(mod).?;4276 const tag_ty = un_ty.unionTagTypeSafety(mod).?;
4292 const tag_ptr_ty_ref = try self.ptrType(tag_ty, self.spvStorageClass(un_ptr_ty.ptrAddressSpace(mod)));4277 const tag_ptr_ty_id = try self.ptrType(tag_ty, self.spvStorageClass(un_ptr_ty.ptrAddressSpace(mod)));
42934278
4294 const union_ptr_id = try self.resolve(bin_op.lhs);4279 const union_ptr_id = try self.resolve(bin_op.lhs);
4295 const new_tag_id = try self.resolve(bin_op.rhs);4280 const new_tag_id = try self.resolve(bin_op.rhs);
...@@ -4297,7 +4282,7 @@ const DeclGen = struct {...@@ -4297,7 +4282,7 @@ const DeclGen = struct {
4297 if (!layout.has_payload) {4282 if (!layout.has_payload) {
4298 try self.store(tag_ty, union_ptr_id, new_tag_id, .{ .is_volatile = un_ptr_ty.isVolatilePtr(mod) });4283 try self.store(tag_ty, union_ptr_id, new_tag_id, .{ .is_volatile = un_ptr_ty.isVolatilePtr(mod) });
4299 } else {4284 } else {
4300 const ptr_id = try self.accessChain(tag_ptr_ty_ref, union_ptr_id, &.{layout.tag_index});4285 const ptr_id = try self.accessChain(tag_ptr_ty_id, union_ptr_id, &.{layout.tag_index});
4301 try self.store(tag_ty, ptr_id, new_tag_id, .{ .is_volatile = un_ptr_ty.isVolatilePtr(mod) });4286 try self.store(tag_ty, ptr_id, new_tag_id, .{ .is_volatile = un_ptr_ty.isVolatilePtr(mod) });
4302 }4287 }
4303 }4288 }
...@@ -4353,20 +4338,20 @@ const DeclGen = struct {...@@ -4353,20 +4338,20 @@ const DeclGen = struct {
4353 const tmp_id = try self.alloc(ty, .{ .storage_class = .Function });4338 const tmp_id = try self.alloc(ty, .{ .storage_class = .Function });
43544339
4355 if (layout.tag_size != 0) {4340 if (layout.tag_size != 0) {
4356 const tag_ptr_ty_ref = try self.ptrType(tag_ty, .Function);4341 const tag_ptr_ty_id = try self.ptrType(tag_ty, .Function);
4357 const ptr_id = try self.accessChain(tag_ptr_ty_ref, tmp_id, &.{@as(u32, @intCast(layout.tag_index))});4342 const ptr_id = try self.accessChain(tag_ptr_ty_id, tmp_id, &.{@as(u32, @intCast(layout.tag_index))});
4358 const tag_id = try self.constInt(tag_ty, tag_int, .direct);4343 const tag_id = try self.constInt(tag_ty, tag_int, .direct);
4359 try self.store(tag_ty, ptr_id, tag_id, .{});4344 try self.store(tag_ty, ptr_id, tag_id, .{});
4360 }4345 }
43614346
4362 const payload_ty = Type.fromInterned(union_ty.field_types.get(ip)[active_field]);4347 const payload_ty = Type.fromInterned(union_ty.field_types.get(ip)[active_field]);
4363 if (payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {4348 if (payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
4364 const pl_ptr_ty_ref = try self.ptrType(layout.payload_ty, .Function);4349 const pl_ptr_ty_id = try self.ptrType(layout.payload_ty, .Function);
4365 const pl_ptr_id = try self.accessChain(pl_ptr_ty_ref, tmp_id, &.{layout.payload_index});4350 const pl_ptr_id = try self.accessChain(pl_ptr_ty_id, tmp_id, &.{layout.payload_index});
4366 const active_pl_ptr_ty_ref = try self.ptrType(payload_ty, .Function);4351 const active_pl_ptr_ty_id = try self.ptrType(payload_ty, .Function);
4367 const active_pl_ptr_id = self.spv.allocId();4352 const active_pl_ptr_id = self.spv.allocId();
4368 try self.func.body.emit(self.spv.gpa, .OpBitcast, .{4353 try self.func.body.emit(self.spv.gpa, .OpBitcast, .{
4369 .id_result_type = self.typeId(active_pl_ptr_ty_ref),4354 .id_result_type = active_pl_ptr_ty_id,
4370 .id_result = active_pl_ptr_id,4355 .id_result = active_pl_ptr_id,
4371 .operand = pl_ptr_id,4356 .operand = pl_ptr_id,
4372 });4357 });
...@@ -4425,13 +4410,13 @@ const DeclGen = struct {...@@ -4425,13 +4410,13 @@ const DeclGen = struct {
4425 const tmp_id = try self.alloc(object_ty, .{ .storage_class = .Function });4410 const tmp_id = try self.alloc(object_ty, .{ .storage_class = .Function });
4426 try self.store(object_ty, tmp_id, object_id, .{});4411 try self.store(object_ty, tmp_id, object_id, .{});
44274412
4428 const pl_ptr_ty_ref = try self.ptrType(layout.payload_ty, .Function);4413 const pl_ptr_ty_id = try self.ptrType(layout.payload_ty, .Function);
4429 const pl_ptr_id = try self.accessChain(pl_ptr_ty_ref, tmp_id, &.{layout.payload_index});4414 const pl_ptr_id = try self.accessChain(pl_ptr_ty_id, tmp_id, &.{layout.payload_index});
44304415
4431 const active_pl_ptr_ty_ref = try self.ptrType(field_ty, .Function);4416 const active_pl_ptr_ty_id = try self.ptrType(field_ty, .Function);
4432 const active_pl_ptr_id = self.spv.allocId();4417 const active_pl_ptr_id = self.spv.allocId();
4433 try self.func.body.emit(self.spv.gpa, .OpBitcast, .{4418 try self.func.body.emit(self.spv.gpa, .OpBitcast, .{
4434 .id_result_type = self.typeId(active_pl_ptr_ty_ref),4419 .id_result_type = active_pl_ptr_ty_id,
4435 .id_result = active_pl_ptr_id,4420 .id_result = active_pl_ptr_id,
4436 .operand = pl_ptr_id,4421 .operand = pl_ptr_id,
4437 });4422 });
...@@ -4448,7 +4433,7 @@ const DeclGen = struct {...@@ -4448,7 +4433,7 @@ const DeclGen = struct {
4448 const extra = self.air.extraData(Air.FieldParentPtr, ty_pl.payload).data;4433 const extra = self.air.extraData(Air.FieldParentPtr, ty_pl.payload).data;
44494434
4450 const parent_ty = ty_pl.ty.toType().childType(mod);4435 const parent_ty = ty_pl.ty.toType().childType(mod);
4451 const res_ty = try self.resolveType(ty_pl.ty.toType(), .indirect);4436 const result_ty_id = try self.resolveType(ty_pl.ty.toType(), .indirect);
44524437
4453 const field_ptr = try self.resolve(extra.field_ptr);4438 const field_ptr = try self.resolve(extra.field_ptr);
4454 const field_ptr_int = try self.intFromPtr(field_ptr);4439 const field_ptr_int = try self.intFromPtr(field_ptr);
...@@ -4463,7 +4448,7 @@ const DeclGen = struct {...@@ -4463,7 +4448,7 @@ const DeclGen = struct {
44634448
4464 const base_ptr = self.spv.allocId();4449 const base_ptr = self.spv.allocId();
4465 try self.func.body.emit(self.spv.gpa, .OpConvertUToPtr, .{4450 try self.func.body.emit(self.spv.gpa, .OpConvertUToPtr, .{
4466 .id_result_type = self.spv.resultId(res_ty),4451 .id_result_type = result_ty_id,
4467 .id_result = base_ptr,4452 .id_result = base_ptr,
4468 .integer_value = base_ptr_int,4453 .integer_value = base_ptr_int,
4469 });4454 });
...@@ -4478,7 +4463,7 @@ const DeclGen = struct {...@@ -4478,7 +4463,7 @@ const DeclGen = struct {
4478 object_ptr: IdRef,4463 object_ptr: IdRef,
4479 field_index: u32,4464 field_index: u32,
4480 ) !IdRef {4465 ) !IdRef {
4481 const result_ty_ref = try self.resolveType(result_ptr_ty, .direct);4466 const result_ty_id = try self.resolveType(result_ptr_ty, .direct);
44824467
4483 const mod = self.module;4468 const mod = self.module;
4484 const object_ty = object_ptr_ty.childType(mod);4469 const object_ty = object_ptr_ty.childType(mod);
...@@ -4486,7 +4471,7 @@ const DeclGen = struct {...@@ -4486,7 +4471,7 @@ const DeclGen = struct {
4486 .Struct => switch (object_ty.containerLayout(mod)) {4471 .Struct => switch (object_ty.containerLayout(mod)) {
4487 .@"packed" => unreachable, // TODO4472 .@"packed" => unreachable, // TODO
4488 else => {4473 else => {
4489 return try self.accessChain(result_ty_ref, object_ptr, &.{field_index});4474 return try self.accessChain(result_ty_id, object_ptr, &.{field_index});
4490 },4475 },
4491 },4476 },
4492 .Union => switch (object_ty.containerLayout(mod)) {4477 .Union => switch (object_ty.containerLayout(mod)) {
...@@ -4496,16 +4481,16 @@ const DeclGen = struct {...@@ -4496,16 +4481,16 @@ const DeclGen = struct {
4496 if (!layout.has_payload) {4481 if (!layout.has_payload) {
4497 // Asked to get a pointer to a zero-sized field. Just lower this4482 // Asked to get a pointer to a zero-sized field. Just lower this
4498 // to undefined, there is no reason to make it be a valid pointer.4483 // to undefined, there is no reason to make it be a valid pointer.
4499 return try self.spv.constUndef(self.typeId(result_ty_ref));4484 return try self.spv.constUndef(result_ty_id);
4500 }4485 }
45014486
4502 const storage_class = self.spvStorageClass(object_ptr_ty.ptrAddressSpace(mod));4487 const storage_class = self.spvStorageClass(object_ptr_ty.ptrAddressSpace(mod));
4503 const pl_ptr_ty_ref = try self.ptrType(layout.payload_ty, storage_class);4488 const pl_ptr_ty_id = try self.ptrType(layout.payload_ty, storage_class);
4504 const pl_ptr_id = try self.accessChain(pl_ptr_ty_ref, object_ptr, &.{layout.payload_index});4489 const pl_ptr_id = try self.accessChain(pl_ptr_ty_id, object_ptr, &.{layout.payload_index});
45054490
4506 const active_pl_ptr_id = self.spv.allocId();4491 const active_pl_ptr_id = self.spv.allocId();
4507 try self.func.body.emit(self.spv.gpa, .OpBitcast, .{4492 try self.func.body.emit(self.spv.gpa, .OpBitcast, .{
4508 .id_result_type = self.typeId(result_ty_ref),4493 .id_result_type = result_ty_id,
4509 .id_result = active_pl_ptr_id,4494 .id_result = active_pl_ptr_id,
4510 .operand = pl_ptr_id,4495 .operand = pl_ptr_id,
4511 });4496 });
...@@ -4533,7 +4518,7 @@ const DeclGen = struct {...@@ -4533,7 +4518,7 @@ const DeclGen = struct {
4533 };4518 };
45344519
4535 // Allocate a function-local variable, with possible initializer.4520 // Allocate a function-local variable, with possible initializer.
4536 // This function returns a pointer to a variable of type `ty_ref`,4521 // This function returns a pointer to a variable of type `ty`,
4537 // which is in the Generic address space. The variable is actually4522 // which is in the Generic address space. The variable is actually
4538 // placed in the Function address space.4523 // placed in the Function address space.
4539 fn alloc(4524 fn alloc(
...@@ -4541,13 +4526,13 @@ const DeclGen = struct {...@@ -4541,13 +4526,13 @@ const DeclGen = struct {
4541 ty: Type,4526 ty: Type,
4542 options: AllocOptions,4527 options: AllocOptions,
4543 ) !IdRef {4528 ) !IdRef {
4544 const ptr_fn_ty_ref = try self.ptrType(ty, .Function);4529 const ptr_fn_ty_id = try self.ptrType(ty, .Function);
45454530
4546 // SPIR-V requires that OpVariable declarations for locals go into the first block, so we are just going to4531 // SPIR-V requires that OpVariable declarations for locals go into the first block, so we are just going to
4547 // directly generate them into func.prologue instead of the body.4532 // directly generate them into func.prologue instead of the body.
4548 const var_id = self.spv.allocId();4533 const var_id = self.spv.allocId();
4549 try self.func.prologue.emit(self.spv.gpa, .OpVariable, .{4534 try self.func.prologue.emit(self.spv.gpa, .OpVariable, .{
4550 .id_result_type = self.typeId(ptr_fn_ty_ref),4535 .id_result_type = ptr_fn_ty_id,
4551 .id_result = var_id,4536 .id_result = var_id,
4552 .storage_class = .Function,4537 .storage_class = .Function,
4553 .initializer = options.initializer,4538 .initializer = options.initializer,
...@@ -4560,9 +4545,9 @@ const DeclGen = struct {...@@ -4560,9 +4545,9 @@ const DeclGen = struct {
45604545
4561 switch (options.storage_class) {4546 switch (options.storage_class) {
4562 .Generic => {4547 .Generic => {
4563 const ptr_gn_ty_ref = try self.ptrType(ty, .Generic);4548 const ptr_gn_ty_id = try self.ptrType(ty, .Generic);
4564 // Convert to a generic pointer4549 // Convert to a generic pointer
4565 return self.castToGeneric(self.typeId(ptr_gn_ty_ref), var_id);4550 return self.castToGeneric(ptr_gn_ty_id, var_id);
4566 },4551 },
4567 .Function => return var_id,4552 .Function => return var_id,
4568 else => unreachable,4553 else => unreachable,
...@@ -4590,9 +4575,9 @@ const DeclGen = struct {...@@ -4590,9 +4575,9 @@ const DeclGen = struct {
4590 assert(self.control_flow == .structured);4575 assert(self.control_flow == .structured);
45914576
4592 const result_id = self.spv.allocId();4577 const result_id = self.spv.allocId();
4593 const block_id_ty_ref = try self.resolveType(Type.u32, .direct);4578 const block_id_ty_id = try self.resolveType(Type.u32, .direct);
4594 try self.func.body.emitRaw(self.spv.gpa, .OpPhi, @intCast(2 + incoming.len * 2)); // result type + result + variable/parent...4579 try self.func.body.emitRaw(self.spv.gpa, .OpPhi, @intCast(2 + incoming.len * 2)); // result type + result + variable/parent...
4595 self.func.body.writeOperand(spec.IdResultType, self.typeId(block_id_ty_ref));4580 self.func.body.writeOperand(spec.IdResultType, block_id_ty_id);
4596 self.func.body.writeOperand(spec.IdRef, result_id);4581 self.func.body.writeOperand(spec.IdRef, result_id);
45974582
4598 for (incoming) |incoming_block| {4583 for (incoming) |incoming_block| {
...@@ -4690,8 +4675,8 @@ const DeclGen = struct {...@@ -4690,8 +4675,8 @@ const DeclGen = struct {
4690 // Make sure that we are still in a block when exiting the function.4675 // Make sure that we are still in a block when exiting the function.
4691 // TODO: Can we get rid of that?4676 // TODO: Can we get rid of that?
4692 try self.beginSpvBlock(self.spv.allocId());4677 try self.beginSpvBlock(self.spv.allocId());
4693 const block_id_ty_ref = try self.resolveType(Type.u32, .direct);4678 const block_id_ty_id = try self.resolveType(Type.u32, .direct);
4694 return try self.spv.constUndef(self.typeId(block_id_ty_ref));4679 return try self.spv.constUndef(block_id_ty_id);
4695 }4680 }
46964681
4697 // The top-most merge actually only has a single source, the4682 // The top-most merge actually only has a single source, the
...@@ -4772,7 +4757,7 @@ const DeclGen = struct {...@@ -4772,7 +4757,7 @@ const DeclGen = struct {
47724757
4773 assert(block.label != null);4758 assert(block.label != null);
4774 const result_id = self.spv.allocId();4759 const result_id = self.spv.allocId();
4775 const result_type_id = try self.resolveTypeId(ty);4760 const result_type_id = try self.resolveType(ty, .direct);
47764761
4777 try self.func.body.emitRaw(4762 try self.func.body.emitRaw(
4778 self.spv.gpa,4763 self.spv.gpa,
...@@ -4810,9 +4795,9 @@ const DeclGen = struct {...@@ -4810,9 +4795,9 @@ const DeclGen = struct {
4810 // Check if the target of the branch was this current block.4795 // Check if the target of the branch was this current block.
4811 const this_block = try self.constInt(Type.u32, @intFromEnum(inst), .direct);4796 const this_block = try self.constInt(Type.u32, @intFromEnum(inst), .direct);
4812 const jump_to_this_block_id = self.spv.allocId();4797 const jump_to_this_block_id = self.spv.allocId();
4813 const bool_ty_ref = try self.resolveType(Type.bool, .direct);4798 const bool_ty_id = try self.resolveType(Type.bool, .direct);
4814 try self.func.body.emit(self.spv.gpa, .OpIEqual, .{4799 try self.func.body.emit(self.spv.gpa, .OpIEqual, .{
4815 .id_result_type = self.typeId(bool_ty_ref),4800 .id_result_type = bool_ty_id,
4816 .id_result = jump_to_this_block_id,4801 .id_result = jump_to_this_block_id,
4817 .operand_1 = next_block,4802 .operand_1 = next_block,
4818 .operand_2 = this_block,4803 .operand_2 = this_block,
...@@ -5099,7 +5084,7 @@ const DeclGen = struct {...@@ -5099,7 +5084,7 @@ const DeclGen = struct {
5099 const err_union_ty = self.typeOf(pl_op.operand);5084 const err_union_ty = self.typeOf(pl_op.operand);
5100 const payload_ty = self.typeOfIndex(inst);5085 const payload_ty = self.typeOfIndex(inst);
51015086
5102 const bool_ty_ref = try self.resolveType(Type.bool, .direct);5087 const bool_ty_id = try self.resolveType(Type.bool, .direct);
51035088
5104 const eu_layout = self.errorUnionLayout(payload_ty);5089 const eu_layout = self.errorUnionLayout(payload_ty);
51055090
...@@ -5112,7 +5097,7 @@ const DeclGen = struct {...@@ -5112,7 +5097,7 @@ const DeclGen = struct {
5112 const zero_id = try self.constInt(Type.anyerror, 0, .direct);5097 const zero_id = try self.constInt(Type.anyerror, 0, .direct);
5113 const is_err_id = self.spv.allocId();5098 const is_err_id = self.spv.allocId();
5114 try self.func.body.emit(self.spv.gpa, .OpINotEqual, .{5099 try self.func.body.emit(self.spv.gpa, .OpINotEqual, .{
5115 .id_result_type = self.typeId(bool_ty_ref),5100 .id_result_type = bool_ty_id,
5116 .id_result = is_err_id,5101 .id_result = is_err_id,
5117 .operand_1 = err_id,5102 .operand_1 = err_id,
5118 .operand_2 = zero_id,5103 .operand_2 = zero_id,
...@@ -5164,11 +5149,11 @@ const DeclGen = struct {...@@ -5164,11 +5149,11 @@ const DeclGen = struct {
5164 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;5149 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
5165 const operand_id = try self.resolve(ty_op.operand);5150 const operand_id = try self.resolve(ty_op.operand);
5166 const err_union_ty = self.typeOf(ty_op.operand);5151 const err_union_ty = self.typeOf(ty_op.operand);
5167 const err_ty_ref = try self.resolveType(Type.anyerror, .direct);5152 const err_ty_id = try self.resolveType(Type.anyerror, .direct);
51685153
5169 if (err_union_ty.errorUnionSet(mod).errorSetIsEmpty(mod)) {5154 if (err_union_ty.errorUnionSet(mod).errorSetIsEmpty(mod)) {
5170 // No error possible, so just return undefined.5155 // No error possible, so just return undefined.
5171 return try self.spv.constUndef(self.typeId(err_ty_ref));5156 return try self.spv.constUndef(err_ty_id);
5172 }5157 }
51735158
5174 const payload_ty = err_union_ty.errorUnionPayload(mod);5159 const payload_ty = err_union_ty.errorUnionPayload(mod);
...@@ -5207,11 +5192,11 @@ const DeclGen = struct {...@@ -5207,11 +5192,11 @@ const DeclGen = struct {
5207 return operand_id;5192 return operand_id;
5208 }5193 }
52095194
5210 const payload_ty_ref = try self.resolveType(payload_ty, .indirect);5195 const payload_ty_id = try self.resolveType(payload_ty, .indirect);
52115196
5212 var members: [2]IdRef = undefined;5197 var members: [2]IdRef = undefined;
5213 members[eu_layout.errorFieldIndex()] = operand_id;5198 members[eu_layout.errorFieldIndex()] = operand_id;
5214 members[eu_layout.payloadFieldIndex()] = try self.spv.constUndef(self.typeId(payload_ty_ref));5199 members[eu_layout.payloadFieldIndex()] = try self.spv.constUndef(payload_ty_id);
52155200
5216 var types: [2]Type = undefined;5201 var types: [2]Type = undefined;
5217 types[eu_layout.errorFieldIndex()] = Type.anyerror;5202 types[eu_layout.errorFieldIndex()] = Type.anyerror;
...@@ -5250,7 +5235,7 @@ const DeclGen = struct {...@@ -5250,7 +5235,7 @@ const DeclGen = struct {
5250 const optional_ty = if (is_pointer) operand_ty.childType(mod) else operand_ty;5235 const optional_ty = if (is_pointer) operand_ty.childType(mod) else operand_ty;
5251 const payload_ty = optional_ty.optionalChild(mod);5236 const payload_ty = optional_ty.optionalChild(mod);
52525237
5253 const bool_ty_ref = try self.resolveType(Type.bool, .direct);5238 const bool_ty_id = try self.resolveType(Type.bool, .direct);
52545239
5255 if (optional_ty.optionalReprIsPayload(mod)) {5240 if (optional_ty.optionalReprIsPayload(mod)) {
5256 // Pointer payload represents nullability: pointer or slice.5241 // Pointer payload represents nullability: pointer or slice.
...@@ -5269,7 +5254,7 @@ const DeclGen = struct {...@@ -5269,7 +5254,7 @@ const DeclGen = struct {
5269 else5254 else
5270 loaded_id;5255 loaded_id;
52715256
5272 const payload_ty_id = try self.resolveType2(ptr_ty, .direct);5257 const payload_ty_id = try self.resolveType(ptr_ty, .direct);
5273 const null_id = try self.spv.constNull(payload_ty_id);5258 const null_id = try self.spv.constNull(payload_ty_id);
5274 const op: std.math.CompareOperator = switch (pred) {5259 const op: std.math.CompareOperator = switch (pred) {
5275 .is_null => .eq,5260 .is_null => .eq,
...@@ -5282,8 +5267,8 @@ const DeclGen = struct {...@@ -5282,8 +5267,8 @@ const DeclGen = struct {
5282 if (is_pointer) {5267 if (is_pointer) {
5283 if (payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {5268 if (payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
5284 const storage_class = self.spvStorageClass(operand_ty.ptrAddressSpace(mod));5269 const storage_class = self.spvStorageClass(operand_ty.ptrAddressSpace(mod));
5285 const bool_ptr_ty = try self.ptrType(Type.bool, storage_class);5270 const bool_ptr_ty_id = try self.ptrType(Type.bool, storage_class);
5286 const tag_ptr_id = try self.accessChain(bool_ptr_ty, operand_id, &.{1});5271 const tag_ptr_id = try self.accessChain(bool_ptr_ty_id, operand_id, &.{1});
5287 break :blk try self.load(Type.bool, tag_ptr_id, .{});5272 break :blk try self.load(Type.bool, tag_ptr_id, .{});
5288 }5273 }
52895274
...@@ -5304,7 +5289,7 @@ const DeclGen = struct {...@@ -5304,7 +5289,7 @@ const DeclGen = struct {
5304 // Invert condition5289 // Invert condition
5305 const result_id = self.spv.allocId();5290 const result_id = self.spv.allocId();
5306 try self.func.body.emit(self.spv.gpa, .OpLogicalNot, .{5291 try self.func.body.emit(self.spv.gpa, .OpLogicalNot, .{
5307 .id_result_type = self.typeId(bool_ty_ref),5292 .id_result_type = bool_ty_id,
5308 .id_result = result_id,5293 .id_result = result_id,
5309 .operand = is_non_null_id,5294 .operand = is_non_null_id,
5310 });5295 });
...@@ -5326,7 +5311,7 @@ const DeclGen = struct {...@@ -5326,7 +5311,7 @@ const DeclGen = struct {
53265311
5327 const payload_ty = err_union_ty.errorUnionPayload(mod);5312 const payload_ty = err_union_ty.errorUnionPayload(mod);
5328 const eu_layout = self.errorUnionLayout(payload_ty);5313 const eu_layout = self.errorUnionLayout(payload_ty);
5329 const bool_ty_ref = try self.resolveType(Type.bool, .direct);5314 const bool_ty_id = try self.resolveType(Type.bool, .direct);
53305315
5331 const error_id = if (!eu_layout.payload_has_bits)5316 const error_id = if (!eu_layout.payload_has_bits)
5332 operand_id5317 operand_id
...@@ -5335,7 +5320,7 @@ const DeclGen = struct {...@@ -5335,7 +5320,7 @@ const DeclGen = struct {
53355320
5336 const result_id = self.spv.allocId();5321 const result_id = self.spv.allocId();
5337 const operands = .{5322 const operands = .{
5338 .id_result_type = self.typeId(bool_ty_ref),5323 .id_result_type = bool_ty_id,
5339 .id_result = result_id,5324 .id_result = result_id,
5340 .operand_1 = error_id,5325 .operand_1 = error_id,
5341 .operand_2 = try self.constInt(Type.anyerror, 0, .direct),5326 .operand_2 = try self.constInt(Type.anyerror, 0, .direct),
...@@ -5371,7 +5356,7 @@ const DeclGen = struct {...@@ -5371,7 +5356,7 @@ const DeclGen = struct {
5371 const optional_ty = operand_ty.childType(mod);5356 const optional_ty = operand_ty.childType(mod);
5372 const payload_ty = optional_ty.optionalChild(mod);5357 const payload_ty = optional_ty.optionalChild(mod);
5373 const result_ty = self.typeOfIndex(inst);5358 const result_ty = self.typeOfIndex(inst);
5374 const result_ty_ref = try self.resolveType(result_ty, .direct);5359 const result_ty_id = try self.resolveType(result_ty, .direct);
53755360
5376 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {5361 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
5377 // There is no payload, but we still need to return a valid pointer.5362 // There is no payload, but we still need to return a valid pointer.
...@@ -5384,7 +5369,7 @@ const DeclGen = struct {...@@ -5384,7 +5369,7 @@ const DeclGen = struct {
5384 return try self.bitCast(result_ty, operand_ty, operand_id);5369 return try self.bitCast(result_ty, operand_ty, operand_id);
5385 }5370 }
53865371
5387 return try self.accessChain(result_ty_ref, operand_id, &.{0});5372 return try self.accessChain(result_ty_id, operand_id, &.{0});
5388 }5373 }
53895374
5390 fn airWrapOptional(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {5375 fn airWrapOptional(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
...@@ -5586,9 +5571,8 @@ const DeclGen = struct {...@@ -5586,9 +5571,8 @@ const DeclGen = struct {
5586 const mod = self.module;5571 const mod = self.module;
5587 const decl = mod.declPtr(self.decl_index);5572 const decl = mod.declPtr(self.decl_index);
5588 const path = decl.getFileScope(mod).sub_file_path;5573 const path = decl.getFileScope(mod).sub_file_path;
5589 const src_fname_id = try self.spv.resolveSourceFileName(path);
5590 try self.func.body.emit(self.spv.gpa, .OpLine, .{5574 try self.func.body.emit(self.spv.gpa, .OpLine, .{
5591 .file = src_fname_id,5575 .file = try self.spv.resolveString(path),
5592 .line = self.base_line + dbg_stmt.line + 1,5576 .line = self.base_line + dbg_stmt.line + 1,
5593 .column = dbg_stmt.column + 1,5577 .column = dbg_stmt.column + 1,
5594 });5578 });
...@@ -5757,7 +5741,7 @@ const DeclGen = struct {...@@ -5757,7 +5741,7 @@ const DeclGen = struct {
5757 const fn_info = mod.typeToFunc(zig_fn_ty).?;5741 const fn_info = mod.typeToFunc(zig_fn_ty).?;
5758 const return_type = fn_info.return_type;5742 const return_type = fn_info.return_type;
57595743
5760 const result_type_ref = try self.resolveFnReturnType(Type.fromInterned(return_type));5744 const result_type_id = try self.resolveFnReturnType(Type.fromInterned(return_type));
5761 const result_id = self.spv.allocId();5745 const result_id = self.spv.allocId();
5762 const callee_id = try self.resolve(pl_op.operand);5746 const callee_id = try self.resolve(pl_op.operand);
57635747
...@@ -5778,7 +5762,7 @@ const DeclGen = struct {...@@ -5778,7 +5762,7 @@ const DeclGen = struct {
5778 }5762 }
57795763
5780 try self.func.body.emit(self.spv.gpa, .OpFunctionCall, .{5764 try self.func.body.emit(self.spv.gpa, .OpFunctionCall, .{
5781 .id_result_type = self.typeId(result_type_ref),5765 .id_result_type = result_type_id,
5782 .id_result = result_id,5766 .id_result = result_id,
5783 .function = callee_id,5767 .function = callee_id,
5784 .id_ref_3 = params[0..n_params],5768 .id_ref_3 = params[0..n_params],
src/codegen/spirv/Assembler.zig+13-12
...@@ -296,18 +296,19 @@ fn processTypeInstruction(self: *Assembler) !AsmValue {...@@ -296,18 +296,19 @@ fn processTypeInstruction(self: *Assembler) !AsmValue {
296 .OpTypeVoid => try self.spv.resolve(.void_type),296 .OpTypeVoid => try self.spv.resolve(.void_type),
297 .OpTypeBool => try self.spv.resolve(.bool_type),297 .OpTypeBool => try self.spv.resolve(.bool_type),
298 .OpTypeInt => blk: {298 .OpTypeInt => blk: {
299 const signedness: std.builtin.Signedness = switch (operands[2].literal32) {299 // const signedness: std.builtin.Signedness = switch (operands[2].literal32) {
300 0 => .unsigned,300 // 0 => .unsigned,
301 1 => .signed,301 // 1 => .signed,
302 else => {302 // else => {
303 // TODO: Improve source location.303 // // TODO: Improve source location.
304 return self.fail(0, "{} is not a valid signedness (expected 0 or 1)", .{operands[2].literal32});304 // return self.fail(0, "{} is not a valid signedness (expected 0 or 1)", .{operands[2].literal32});
305 },305 // },
306 };306 // };
307 const width = std.math.cast(u16, operands[1].literal32) orelse {307 // const width = std.math.cast(u16, operands[1].literal32) orelse {
308 return self.fail(0, "int type of {} bits is too large", .{operands[1].literal32});308 // return self.fail(0, "int type of {} bits is too large", .{operands[1].literal32});
309 };309 // };
310 break :blk try self.spv.intType(signedness, width);310 // break :blk try self.spv.intType(signedness, width);
311 break :blk @as(CacheRef, @enumFromInt(0)); // TODO(robin): fix
311 },312 },
312 .OpTypeFloat => blk: {313 .OpTypeFloat => blk: {
313 const bits = operands[1].literal32;314 const bits = operands[1].literal32;
src/codegen/spirv/Module.zig+123-50
...@@ -23,7 +23,6 @@ const Section = @import("Section.zig");...@@ -23,7 +23,6 @@ const Section = @import("Section.zig");
23const Cache = @import("Cache.zig");23const Cache = @import("Cache.zig");
24pub const CacheKey = Cache.Key;24pub const CacheKey = Cache.Key;
25pub const CacheRef = Cache.Ref;25pub const CacheRef = Cache.Ref;
26pub const CacheString = Cache.String;
2726
28/// This structure represents a function that isc in-progress of being emitted.27/// This structure represents a function that isc in-progress of being emitted.
29/// Commonly, the contents of this structure will be merged with the appropriate28/// Commonly, the contents of this structure will be merged with the appropriate
...@@ -98,7 +97,7 @@ pub const EntryPoint = struct {...@@ -98,7 +97,7 @@ pub const EntryPoint = struct {
98 /// The declaration that should be exported.97 /// The declaration that should be exported.
99 decl_index: Decl.Index,98 decl_index: Decl.Index,
100 /// The name of the kernel to be exported.99 /// The name of the kernel to be exported.
101 name: CacheString,100 name: []const u8,
102 /// Calling Convention101 /// Calling Convention
103 execution_model: spec.ExecutionModel,102 execution_model: spec.ExecutionModel,
104};103};
...@@ -106,6 +105,9 @@ pub const EntryPoint = struct {...@@ -106,6 +105,9 @@ pub const EntryPoint = struct {
106/// A general-purpose allocator which may be used to allocate resources for this module105/// A general-purpose allocator which may be used to allocate resources for this module
107gpa: Allocator,106gpa: Allocator,
108107
108/// Arena for things that need to live for the length of this program.
109arena: std.heap.ArenaAllocator,
110
109/// Module layout, according to SPIR-V Spec section 2.4, "Logical Layout of a Module".111/// Module layout, according to SPIR-V Spec section 2.4, "Logical Layout of a Module".
110sections: struct {112sections: struct {
111 /// Capability instructions113 /// Capability instructions
...@@ -143,15 +145,26 @@ sections: struct {...@@ -143,15 +145,26 @@ sections: struct {
143/// SPIR-V instructions return result-ids. This variable holds the module-wide counter for these.145/// SPIR-V instructions return result-ids. This variable holds the module-wide counter for these.
144next_result_id: Word,146next_result_id: Word,
145147
146/// Cache for results of OpString instructions for module file names fed to OpSource.148/// Cache for results of OpString instructions.
147/// Since OpString is pretty much only used for those, we don't need to keep track of all strings,149strings: std.StringArrayHashMapUnmanaged(IdRef) = .{},
148/// just the ones for OpLine. Note that OpLine needs the result of OpString, and not that of OpSource.
149source_file_names: std.AutoArrayHashMapUnmanaged(CacheString, IdRef) = .{},
150150
151/// SPIR-V type- and constant cache. This structure is used to store information about these in a more151/// SPIR-V type- and constant cache. This structure is used to store information about these in a more
152/// efficient manner.152/// efficient manner.
153cache: Cache = .{},153cache: Cache = .{},
154154
155/// Some types shouldn't be emitted more than one time, but cannot be caught by
156/// the `intern_map` during codegen. Sometimes, IDs are compared to check if
157/// types are the same, so we can't delay until the dedup pass. Therefore,
158/// this is an ad-hoc structure to cache types where required.
159/// According to the SPIR-V specification, section 2.8, this includes all non-aggregate
160/// non-pointer types.
161cache2: struct {
162 bool_type: ?IdRef = null,
163 void_type: ?IdRef = null,
164 int_types: std.AutoHashMapUnmanaged(std.builtin.Type.Int, IdRef) = .{},
165 float_types: std.AutoHashMapUnmanaged(std.builtin.Type.Float, IdRef) = .{},
166} = .{},
167
155/// Set of Decls, referred to by Decl.Index.168/// Set of Decls, referred to by Decl.Index.
156decls: std.ArrayListUnmanaged(Decl) = .{},169decls: std.ArrayListUnmanaged(Decl) = .{},
157170
...@@ -168,6 +181,7 @@ extended_instruction_set: std.AutoHashMapUnmanaged(spec.InstructionSet, IdRef) =...@@ -168,6 +181,7 @@ extended_instruction_set: std.AutoHashMapUnmanaged(spec.InstructionSet, IdRef) =
168pub fn init(gpa: Allocator) Module {181pub fn init(gpa: Allocator) Module {
169 return .{182 return .{
170 .gpa = gpa,183 .gpa = gpa,
184 .arena = std.heap.ArenaAllocator.init(gpa),
171 .next_result_id = 1, // 0 is an invalid SPIR-V result id, so start counting at 1.185 .next_result_id = 1, // 0 is an invalid SPIR-V result id, so start counting at 1.
172 };186 };
173}187}
...@@ -184,15 +198,19 @@ pub fn deinit(self: *Module) void {...@@ -184,15 +198,19 @@ pub fn deinit(self: *Module) void {
184 self.sections.types_globals_constants.deinit(self.gpa);198 self.sections.types_globals_constants.deinit(self.gpa);
185 self.sections.functions.deinit(self.gpa);199 self.sections.functions.deinit(self.gpa);
186200
187 self.source_file_names.deinit(self.gpa);201 self.strings.deinit(self.gpa);
188 self.cache.deinit(self);202 self.cache.deinit(self);
189203
204 self.cache2.int_types.deinit(self.gpa);
205 self.cache2.float_types.deinit(self.gpa);
206
190 self.decls.deinit(self.gpa);207 self.decls.deinit(self.gpa);
191 self.decl_deps.deinit(self.gpa);208 self.decl_deps.deinit(self.gpa);
192209
193 self.entry_points.deinit(self.gpa);210 self.entry_points.deinit(self.gpa);
194211
195 self.extended_instruction_set.deinit(self.gpa);212 self.extended_instruction_set.deinit(self.gpa);
213 self.arena.deinit();
196214
197 self.* = undefined;215 self.* = undefined;
198}216}
...@@ -235,10 +253,6 @@ pub fn resolveId(self: *Module, key: CacheKey) !IdResult {...@@ -235,10 +253,6 @@ pub fn resolveId(self: *Module, key: CacheKey) !IdResult {
235 return self.resultId(try self.resolve(key));253 return self.resultId(try self.resolve(key));
236}254}
237255
238pub fn resolveString(self: *Module, str: []const u8) !CacheString {
239 return try self.cache.addString(self, str);
240}
241
242fn addEntryPointDeps(256fn addEntryPointDeps(
243 self: *Module,257 self: *Module,
244 decl_index: Decl.Index,258 decl_index: Decl.Index,
...@@ -283,7 +297,7 @@ fn entryPoints(self: *Module) !Section {...@@ -283,7 +297,7 @@ fn entryPoints(self: *Module) !Section {
283 try entry_points.emit(self.gpa, .OpEntryPoint, .{297 try entry_points.emit(self.gpa, .OpEntryPoint, .{
284 .execution_model = entry_point.execution_model,298 .execution_model = entry_point.execution_model,
285 .entry_point = entry_point_id,299 .entry_point = entry_point_id,
286 .name = self.cache.getString(entry_point.name).?,300 .name = entry_point.name,
287 .interface = interface.items,301 .interface = interface.items,
288 });302 });
289 }303 }
...@@ -388,51 +402,110 @@ pub fn importInstructionSet(self: *Module, set: spec.InstructionSet) !IdRef {...@@ -388,51 +402,110 @@ pub fn importInstructionSet(self: *Module, set: spec.InstructionSet) !IdRef {
388 return result_id;402 return result_id;
389}403}
390404
391/// Fetch the result-id of an OpString instruction that encodes the path of the source405/// Fetch the result-id of an instruction corresponding to a string.
392/// file of the decl. This function may also emit an OpSource with source-level information regarding406pub fn resolveString(self: *Module, string: []const u8) !IdRef {
393/// the decl.407 if (self.strings.get(string)) |id| {
394pub fn resolveSourceFileName(self: *Module, path: []const u8) !IdRef {408 return id;
395 const path_ref = try self.resolveString(path);
396 const result = try self.source_file_names.getOrPut(self.gpa, path_ref);
397 if (!result.found_existing) {
398 const file_result_id = self.allocId();
399 result.value_ptr.* = file_result_id;
400 try self.sections.debug_strings.emit(self.gpa, .OpString, .{
401 .id_result = file_result_id,
402 .string = path,
403 });
404 }409 }
405410
406 return result.value_ptr.*;411 const id = self.allocId();
412 try self.strings.put(self.gpa, try self.arena.allocator().dupe(u8, string), id);
413
414 try self.sections.debug_strings.emit(self.gpa, .OpString, .{
415 .id_result = id,
416 .string = string,
417 });
418
419 return id;
407}420}
408421
409pub fn intType(self: *Module, signedness: std.builtin.Signedness, bits: u16) !CacheRef {422pub fn structType(self: *Module, types: []const IdRef, maybe_names: ?[]const []const u8) !IdRef {
410 return try self.resolve(.{ .int_type = .{423 const result_id = self.allocId();
411 .signedness = signedness,424
412 .bits = bits,425 try self.sections.types_globals_constants.emit(self.gpa, .OpTypeStruct, .{
413 } });426 .id_result = result_id,
427 .id_ref = types,
428 });
429
430 if (maybe_names) |names| {
431 assert(names.len == types.len);
432 for (names, 0..) |name, i| {
433 try self.memberDebugName(result_id, @intCast(i), name);
434 }
435 }
436
437 return result_id;
414}438}
415439
416pub fn vectorType(self: *Module, len: u32, elem_ty_ref: CacheRef) !CacheRef {440pub fn boolType(self: *Module) !IdRef {
417 return try self.resolve(.{ .vector_type = .{441 if (self.cache2.bool_type) |id| return id;
418 .component_type = elem_ty_ref,442
419 .component_count = len,443 const result_id = self.allocId();
420 } });444 try self.sections.types_globals_constants.emit(self.gpa, .OpTypeBool, .{
445 .id_result = result_id,
446 });
447 self.cache2.bool_type = result_id;
448 return result_id;
449}
450
451pub fn voidType(self: *Module) !IdRef {
452 if (self.cache2.void_type) |id| return id;
453
454 const result_id = self.allocId();
455 try self.sections.types_globals_constants.emit(self.gpa, .OpTypeVoid, .{
456 .id_result = result_id,
457 });
458 self.cache2.void_type = result_id;
459 try self.debugName(result_id, "void");
460 return result_id;
421}461}
422462
423pub fn arrayType(self: *Module, len: u32, elem_ty_ref: CacheRef) !CacheRef {463pub fn intType(self: *Module, signedness: std.builtin.Signedness, bits: u16) !IdRef {
424 const len_ty_ref = try self.resolve(.{ .int_type = .{464 assert(bits > 0);
425 .signedness = .unsigned,465 const entry = try self.cache2.int_types.getOrPut(self.gpa, .{ .signedness = signedness, .bits = bits });
426 .bits = 32,466 if (!entry.found_existing) {
427 } });467 const result_id = self.allocId();
428 const len_ref = try self.resolve(.{ .int = .{468 entry.value_ptr.* = result_id;
429 .ty = len_ty_ref,469 try self.sections.types_globals_constants.emit(self.gpa, .OpTypeInt, .{
430 .value = .{ .uint64 = len },470 .id_result = result_id,
431 } });471 .width = bits,
432 return try self.resolve(.{ .array_type = .{472 .signedness = switch (signedness) {
433 .element_type = elem_ty_ref,473 .signed => 1,
434 .length = len_ref,474 .unsigned => 0,
435 } });475 },
476 });
477
478 switch (signedness) {
479 .signed => try self.debugNameFmt(result_id, "i{}", .{bits}),
480 .unsigned => try self.debugNameFmt(result_id, "u{}", .{bits}),
481 }
482 }
483 return entry.value_ptr.*;
484}
485
486pub fn floatType(self: *Module, bits: u16) !IdRef {
487 assert(bits > 0);
488 const entry = try self.cache2.float_types.getOrPut(self.gpa, .{ .bits = bits });
489 if (!entry.found_existing) {
490 const result_id = self.allocId();
491 entry.value_ptr.* = result_id;
492 try self.sections.types_globals_constants.emit(self.gpa, .OpTypeFloat, .{
493 .id_result = result_id,
494 .width = bits,
495 });
496 try self.debugNameFmt(result_id, "f{}", .{bits});
497 }
498 return entry.value_ptr.*;
499}
500
501pub fn vectorType(self: *Module, len: u32, child_id: IdRef) !IdRef {
502 const result_id = self.allocId();
503 try self.sections.types_globals_constants.emit(self.gpa, .OpTypeVector, .{
504 .id_result = result_id,
505 .component_type = child_id,
506 .component_count = len,
507 });
508 return result_id;
436}509}
437510
438pub fn constUndef(self: *Module, ty_id: IdRef) !IdRef {511pub fn constUndef(self: *Module, ty_id: IdRef) !IdRef {
...@@ -526,7 +599,7 @@ pub fn declareEntryPoint(...@@ -526,7 +599,7 @@ pub fn declareEntryPoint(
526) !void {599) !void {
527 try self.entry_points.append(self.gpa, .{600 try self.entry_points.append(self.gpa, .{
528 .decl_index = decl_index,601 .decl_index = decl_index,
529 .name = try self.resolveString(name),602 .name = try self.arena.allocator().dupe(u8, name),
530 .execution_model = execution_model,603 .execution_model = execution_model,
531 });604 });
532}605}
src/link/SpirV/BinaryModule.zig+2-1
...@@ -116,7 +116,8 @@ pub const Instruction = struct {...@@ -116,7 +116,8 @@ pub const Instruction = struct {
116 const instruction_len = self.words[self.offset] >> 16;116 const instruction_len = self.words[self.offset] >> 16;
117 defer self.offset += instruction_len;117 defer self.offset += instruction_len;
118 defer self.index += 1;118 defer self.index += 1;
119 assert(instruction_len != 0 and self.offset < self.words.len); // Verified in BinaryModule.parse.119 assert(instruction_len != 0);
120 assert(self.offset < self.words.len);
120121
121 return Instruction{122 return Instruction{
122 .opcode = @enumFromInt(self.words[self.offset] & 0xFFFF),123 .opcode = @enumFromInt(self.words[self.offset] & 0xFFFF),