authorgravatar for robin@voetter.nlRobin Voetter <robin@voetter.nl> 2023-10-21 12:53:13+02:00
committergravatar for robin@voetter.nlRobin Voetter <robin@voetter.nl> 2023-10-21 17:46:50+02:00
log200bca360e333abeb29f4af6d050adf42c2ca5a7
treefed7782d93a84b7b0bfa53d200b1ce25538cb20d
parentb403ca0aabb4529949b48e68f1392afc31098a98
signaturebadge-check Signed by SSH key SHA256:CQ99aPxq+RueiL9u7z0FEki5Fm7V6T8q4PrEGmINrA4

spirv: replace most use of spv.ptrType with self.ptrType

To support self-referential pointers, in the future we will need to pass the Zig type to any pointer that is created. This lays some ground work for that by replacing most uses of spv.ptrType with a new ptrType function that also accepts the Zig type. This function's contents will soon be replaced by a version that also supports self-referential pointers. Also fixed some bugs regarding the use of direct/indirect.

1 files changed, 76 insertions(+), 121 deletions(-)

src/codegen/spirv.zig+76-121
......@@ -358,8 +358,7 @@ const DeclGen = struct {
358358
359359 const mod = self.module;
360360 const ty = mod.intern_pool.typeOf(val).toType();
361 const ty_ref = try self.resolveType(ty, .indirect);
362 const ptr_ty_ref = try self.spv.ptrType(ty_ref, storage_class);
361 const ptr_ty_ref = try self.ptrType(ty, storage_class);
363362
364363 const var_id = self.spv.declPtr(spv_decl_index).result_id;
365364
......@@ -623,25 +622,15 @@ const DeclGen = struct {
623622 /// result_ty_ref must be an array type.
624623 /// Constituents should be in `indirect` representation (as the elements of an array should be).
625624 /// Result is in `direct` representation.
626 fn constructArray(self: *DeclGen, result_ty_ref: CacheRef, constituents: []const IdRef) !IdRef {
625 fn constructArray(self: *DeclGen, ty: Type, constituents: []const IdRef) !IdRef {
627626 // The Khronos LLVM-SPIRV translator crashes because it cannot construct structs which'
628627 // operands are not constant.
629628 // See https://github.com/KhronosGroup/SPIRV-LLVM-Translator/issues/1349
630629 // For now, just initialize the struct by setting the fields manually...
631630 // TODO: Make this OpCompositeConstruct when we can
632 // TODO: Make this Function storage type
633 const ptr_ty_ref = try self.spv.ptrType(result_ty_ref, .Function);
634 const ptr_composite_id = self.spv.allocId();
635 try self.func.prologue.emit(self.spv.gpa, .OpVariable, .{
636 .id_result_type = self.typeId(ptr_ty_ref),
637 .id_result = ptr_composite_id,
638 .storage_class = .Function,
639 });
640
641 const spv_composite_ty = self.spv.cache.lookup(result_ty_ref).array_type;
642 const elem_ty_ref = spv_composite_ty.element_type;
643 const ptr_elem_ty_ref = try self.spv.ptrType(elem_ty_ref, .Function);
644
631 const mod = self.module;
632 const ptr_composite_id = try self.alloc(ty, .{ .storage_class = .Function });
633 const ptr_elem_ty_ref = try self.ptrType(ty.elemType2(mod), .Function);
645634 for (constituents, 0..) |constitent_id, index| {
646635 const ptr_id = try self.accessChain(ptr_elem_ty_ref, ptr_composite_id, &.{@as(u32, @intCast(index))});
647636 try self.func.body.emit(self.spv.gpa, .OpStore, .{
......@@ -649,13 +638,8 @@ const DeclGen = struct {
649638 .object = constitent_id,
650639 });
651640 }
652 const result_id = self.spv.allocId();
653 try self.func.body.emit(self.spv.gpa, .OpLoad, .{
654 .id_result_type = self.typeId(result_ty_ref),
655 .id_result = result_id,
656 .pointer = ptr_composite_id,
657 });
658 return result_id;
641
642 return try self.load(ty, ptr_composite_id, .{});
659643 }
660644
661645 /// This function generates a load for a constant in direct (ie, non-memory) representation.
......@@ -857,7 +841,7 @@ const DeclGen = struct {
857841 else => {},
858842 }
859843
860 return try self.constructArray(result_ty_ref, constituents);
844 return try self.constructArray(ty, constituents);
861845 },
862846 .struct_type => {
863847 const struct_type = mod.typeToStruct(ty).?;
......@@ -892,7 +876,7 @@ const DeclGen = struct {
892876 const active_field = ty.unionTagFieldIndex(un.tag.toValue(), mod).?;
893877 const layout = self.unionLayout(ty, active_field);
894878 const payload = if (layout.active_field_size != 0)
895 try self.constant(layout.active_field_ty, un.val.toValue(), .indirect)
879 try self.constant(layout.active_field_ty, un.val.toValue(), .direct)
896880 else
897881 null;
898882
......@@ -934,8 +918,7 @@ const DeclGen = struct {
934918
935919 // TODO: Can we consolidate this in ptrElemPtr?
936920 const elem_ty = parent_ptr_ty.elemType2(mod); // use elemType() so that we get T for *[N]T.
937 const elem_ty_ref = try self.resolveType(elem_ty, .direct);
938 const elem_ptr_ty_ref = try self.spv.ptrType(elem_ty_ref, spvStorageClass(parent_ptr_ty.ptrAddressSpace(mod)));
921 const elem_ptr_ty_ref = try self.ptrType(elem_ty, spvStorageClass(parent_ptr_ty.ptrAddressSpace(mod)));
939922
940923 if (elem_ptr_ty_ref == result_ty_ref) {
941924 return elem_ptr_id;
......@@ -992,8 +975,7 @@ const DeclGen = struct {
992975 };
993976
994977 const decl_id = try self.resolveAnonDecl(decl_val, actual_storage_class);
995 const decl_ty_ref = try self.resolveType(decl_ty, .indirect);
996 const decl_ptr_ty_ref = try self.spv.ptrType(decl_ty_ref, final_storage_class);
978 const decl_ptr_ty_ref = try self.ptrType(decl_ty, final_storage_class);
997979
998980 const ptr_id = switch (final_storage_class) {
999981 .Generic => blk: {
......@@ -1049,8 +1031,7 @@ const DeclGen = struct {
10491031
10501032 const final_storage_class = spvStorageClass(decl.@"addrspace");
10511033
1052 const decl_ty_ref = try self.resolveType(decl.ty, .indirect);
1053 const decl_ptr_ty_ref = try self.spv.ptrType(decl_ty_ref, final_storage_class);
1034 const decl_ptr_ty_ref = try self.ptrType(decl.ty, final_storage_class);
10541035
10551036 const ptr_id = switch (final_storage_class) {
10561037 .Generic => blk: {
......@@ -1118,6 +1099,12 @@ const DeclGen = struct {
11181099 return try self.intType(.unsigned, self.getTarget().ptrBitWidth());
11191100 }
11201101
1102 fn ptrType(self: *DeclGen, child_ty: Type, storage_class: StorageClass) !CacheRef {
1103 // TODO: This function will be rewritten so that forward declarations work properly
1104 const child_ty_ref = try self.resolveType(child_ty, .indirect);
1105 return try self.spv.ptrType(child_ty_ref, storage_class);
1106 }
1107
11211108 /// Generate a union type, optionally with a known field. If the tag alignment is greater
11221109 /// than that of the payload, a regular union (non-packed, with both tag and payload), will
11231110 /// be generated as follows:
......@@ -1678,7 +1665,7 @@ const DeclGen = struct {
16781665 /// the name of an error in the text executor.
16791666 fn generateTestEntryPoint(self: *DeclGen, name: []const u8, spv_test_decl_index: SpvModule.Decl.Index) !void {
16801667 const anyerror_ty_ref = try self.resolveType(Type.anyerror, .direct);
1681 const ptr_anyerror_ty_ref = try self.spv.ptrType(anyerror_ty_ref, .CrossWorkgroup);
1668 const ptr_anyerror_ty_ref = try self.ptrType(Type.anyerror, .CrossWorkgroup);
16821669 const void_ty_ref = try self.resolveType(Type.void, .direct);
16831670
16841671 const kernel_proto_ty_ref = try self.spv.resolve(.{ .function_type = .{
......@@ -1713,6 +1700,7 @@ const DeclGen = struct {
17131700 .id_result = error_id,
17141701 .function = test_id,
17151702 });
1703 // Note: Convert to direct not required.
17161704 try section.emit(self.spv.gpa, .OpStore, .{
17171705 .pointer = p_error_id,
17181706 .object = error_id,
......@@ -1817,8 +1805,7 @@ const DeclGen = struct {
18171805 else => final_storage_class,
18181806 };
18191807
1820 const ty_ref = try self.resolveType(decl.ty, .indirect);
1821 const ptr_ty_ref = try self.spv.ptrType(ty_ref, actual_storage_class);
1808 const ptr_ty_ref = try self.ptrType(decl.ty, actual_storage_class);
18221809
18231810 const begin = self.spv.beginGlobal();
18241811 try self.spv.globals.section.emit(self.spv.gpa, .OpVariable, .{
......@@ -2113,9 +2100,7 @@ const DeclGen = struct {
21132100 constituent.* = try self.convertToIndirect(child_ty, result_id);
21142101 }
21152102
2116 const result_ty = try self.resolveType(child_ty, .indirect);
2117 const result_ty_ref = try self.spv.arrayType(vector_len, result_ty);
2118 return try self.constructArray(result_ty_ref, constituents);
2103 return try self.constructArray(ty, constituents);
21192104 }
21202105
21212106 const result_id = self.spv.allocId();
......@@ -2176,7 +2161,7 @@ const DeclGen = struct {
21762161
21772162 const info = try self.arithmeticTypeInfo(result_ty);
21782163 // TODO: Use fmin for OpenCL
2179 const cmp_id = try self.cmp(op, result_ty, lhs_id, rhs_id);
2164 const cmp_id = try self.cmp(op, Type.bool, result_ty, lhs_id, rhs_id);
21802165 const selection_id = switch (info.class) {
21812166 .float => blk: {
21822167 // cmp uses OpFOrd. When we have 0 [<>] nan this returns false,
......@@ -2311,7 +2296,7 @@ const DeclGen = struct {
23112296 constituent.* = try self.arithOp(child_ty, lhs_index_id, rhs_index_id, fop, sop, uop, modular);
23122297 }
23132298
2314 return self.constructArray(result_ty_ref, constituents);
2299 return self.constructArray(ty, constituents);
23152300 }
23162301
23172302 // Binary operations are generally applicable to both scalar and vector operations
......@@ -2629,6 +2614,7 @@ const DeclGen = struct {
26292614 fn cmp(
26302615 self: *DeclGen,
26312616 op: std.math.CompareOperator,
2617 result_ty: Type,
26322618 ty: Type,
26332619 lhs_id: IdRef,
26342620 rhs_id: IdRef,
......@@ -2669,7 +2655,7 @@ const DeclGen = struct {
26692655 if (ty.optionalReprIsPayload(mod)) {
26702656 assert(payload_ty.hasRuntimeBitsIgnoreComptime(mod));
26712657 assert(!payload_ty.isSlice(mod));
2672 return self.cmp(op, payload_ty, lhs_id, rhs_id);
2658 return self.cmp(op, Type.bool, payload_ty, lhs_id, rhs_id);
26732659 }
26742660
26752661 const lhs_valid_id = if (payload_ty.hasRuntimeBitsIgnoreComptime(mod))
......@@ -2682,7 +2668,7 @@ const DeclGen = struct {
26822668 else
26832669 try self.convertToDirect(Type.bool, rhs_id);
26842670
2685 const valid_cmp_id = try self.cmp(op, Type.bool, lhs_valid_id, rhs_valid_id);
2671 const valid_cmp_id = try self.cmp(op, Type.bool, Type.bool, lhs_valid_id, rhs_valid_id);
26862672 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
26872673 return valid_cmp_id;
26882674 }
......@@ -2693,7 +2679,7 @@ const DeclGen = struct {
26932679 const lhs_pl_id = try self.extractField(payload_ty, lhs_id, 0);
26942680 const rhs_pl_id = try self.extractField(payload_ty, rhs_id, 0);
26952681
2696 const pl_cmp_id = try self.cmp(op, payload_ty, lhs_pl_id, rhs_pl_id);
2682 const pl_cmp_id = try self.cmp(op, Type.bool, payload_ty, lhs_pl_id, rhs_pl_id);
26972683
26982684 // op == .eq => lhs_valid == rhs_valid && lhs_pl == rhs_pl
26992685 // op == .neq => lhs_valid != rhs_valid || lhs_pl != rhs_pl
......@@ -2715,7 +2701,6 @@ const DeclGen = struct {
27152701 .Vector => {
27162702 const child_ty = ty.childType(mod);
27172703 const vector_len = ty.vectorLen(mod);
2718 const bool_ty_ref_indirect = try self.resolveType(Type.bool, .indirect);
27192704
27202705 var constituents = try self.gpa.alloc(IdRef, vector_len);
27212706 defer self.gpa.free(constituents);
......@@ -2723,12 +2708,11 @@ const DeclGen = struct {
27232708 for (constituents, 0..) |*constituent, i| {
27242709 const lhs_index_id = try self.extractField(child_ty, cmp_lhs_id, @intCast(i));
27252710 const rhs_index_id = try self.extractField(child_ty, cmp_rhs_id, @intCast(i));
2726 const result_id = try self.cmp(op, child_ty, lhs_index_id, rhs_index_id);
2711 const result_id = try self.cmp(op, Type.bool, child_ty, lhs_index_id, rhs_index_id);
27272712 constituent.* = try self.convertToIndirect(Type.bool, result_id);
27282713 }
27292714
2730 const result_ty_ref = try self.spv.arrayType(vector_len, bool_ty_ref_indirect);
2731 return try self.constructArray(result_ty_ref, constituents);
2715 return try self.constructArray(result_ty, constituents);
27322716 },
27332717 else => unreachable,
27342718 };
......@@ -2801,8 +2785,9 @@ const DeclGen = struct {
28012785 const lhs_id = try self.resolve(bin_op.lhs);
28022786 const rhs_id = try self.resolve(bin_op.rhs);
28032787 const ty = self.typeOf(bin_op.lhs);
2788 const result_ty = self.typeOfIndex(inst);
28042789
2805 return try self.cmp(op, ty, lhs_id, rhs_id);
2790 return try self.cmp(op, result_ty, ty, lhs_id, rhs_id);
28062791 }
28072792
28082793 fn airVectorCmp(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
......@@ -2814,8 +2799,9 @@ const DeclGen = struct {
28142799 const rhs_id = try self.resolve(vec_cmp.rhs);
28152800 const op = vec_cmp.compareOperator();
28162801 const ty = self.typeOf(vec_cmp.lhs);
2802 const result_ty = self.typeOfIndex(inst);
28172803
2818 return try self.cmp(op, ty, lhs_id, rhs_id);
2804 return try self.cmp(op, result_ty, ty, lhs_id, rhs_id);
28192805 }
28202806
28212807 fn bitCast(
......@@ -2860,15 +2846,9 @@ const DeclGen = struct {
28602846 return result_id;
28612847 }
28622848
2863 const src_ptr_ty_ref = try self.spv.ptrType(src_ty_ref, .Function);
2864 const dst_ptr_ty_ref = try self.spv.ptrType(dst_ty_ref, .Function);
2849 const dst_ptr_ty_ref = try self.ptrType(dst_ty, .Function);
28652850
2866 const tmp_id = self.spv.allocId();
2867 try self.func.prologue.emit(self.spv.gpa, .OpVariable, .{
2868 .id_result_type = self.typeId(src_ptr_ty_ref),
2869 .id_result = tmp_id,
2870 .storage_class = .Function,
2871 });
2851 const tmp_id = try self.alloc(src_ty, .{ .storage_class = .Function });
28722852 try self.store(src_ty, tmp_id, src_id, false);
28732853 const casted_ptr_id = self.spv.allocId();
28742854 try self.func.body.emit(self.spv.gpa, .OpBitcast, .{
......@@ -3154,7 +3134,7 @@ const DeclGen = struct {
31543134 elem_ids[n_elems - 1] = try self.constant(array_info.elem_type, sentinel_val, .indirect);
31553135 }
31563136
3157 return try self.constructArray(result_ty_ref, elem_ids);
3137 return try self.constructArray(result_ty, elem_ids);
31583138 },
31593139 else => unreachable,
31603140 }
......@@ -3246,8 +3226,7 @@ const DeclGen = struct {
32463226 const mod = self.module;
32473227 // Construct new pointer type for the resulting pointer
32483228 const elem_ty = ptr_ty.elemType2(mod); // use elemType() so that we get T for *[N]T.
3249 const elem_ty_ref = try self.resolveType(elem_ty, .direct);
3250 const elem_ptr_ty_ref = try self.spv.ptrType(elem_ty_ref, spvStorageClass(ptr_ty.ptrAddressSpace(mod)));
3229 const elem_ptr_ty_ref = try self.ptrType(elem_ty, spvStorageClass(ptr_ty.ptrAddressSpace(mod)));
32513230 if (ptr_ty.isSinglePointer(mod)) {
32523231 // Pointer-to-array. In this case, the resulting pointer is not of the same type
32533232 // as the ptr_ty (we want a *T, not a *[N]T), and hence we need to use accessChain.
......@@ -3283,9 +3262,7 @@ const DeclGen = struct {
32833262 const mod = self.module;
32843263 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
32853264 const array_ty = self.typeOf(bin_op.lhs);
3286 const array_ty_ref = try self.resolveType(array_ty, .direct);
32873265 const elem_ty = array_ty.childType(mod);
3288 const elem_ty_ref = try self.resolveType(elem_ty, .indirect);
32893266 const array_id = try self.resolve(bin_op.lhs);
32903267 const index_id = try self.resolve(bin_op.rhs);
32913268
......@@ -3293,20 +3270,10 @@ const DeclGen = struct {
32933270 // For now, just generate a temporary and use that.
32943271 // TODO: This backend probably also should use isByRef from llvm...
32953272
3296 const array_ptr_ty_ref = try self.spv.ptrType(array_ty_ref, .Function);
3297 const elem_ptr_ty_ref = try self.spv.ptrType(elem_ty_ref, .Function);
3298
3299 const tmp_id = self.spv.allocId();
3300 try self.func.prologue.emit(self.spv.gpa, .OpVariable, .{
3301 .id_result_type = self.typeId(array_ptr_ty_ref),
3302 .id_result = tmp_id,
3303 .storage_class = .Function,
3304 });
3305 try self.func.body.emit(self.spv.gpa, .OpStore, .{
3306 .pointer = tmp_id,
3307 .object = array_id,
3308 });
3273 const elem_ptr_ty_ref = try self.ptrType(elem_ty, .Function);
33093274
3275 const tmp_id = try self.alloc(array_ty, .{ .storage_class = .Function });
3276 try self.store(array_ty, tmp_id, array_id, false);
33103277 const elem_ptr_id = try self.accessChainId(elem_ptr_ty_ref, tmp_id, &.{index_id});
33113278 return try self.load(elem_ty, elem_ptr_id, false);
33123279 }
......@@ -3334,8 +3301,7 @@ const DeclGen = struct {
33343301 if (layout.tag_size == 0) return;
33353302
33363303 const tag_ty = un_ty.unionTagTypeSafety(mod).?;
3337 const tag_ty_ref = try self.resolveType(tag_ty, .indirect);
3338 const tag_ptr_ty_ref = try self.spv.ptrType(tag_ty_ref, spvStorageClass(un_ptr_ty.ptrAddressSpace(mod)));
3304 const tag_ptr_ty_ref = try self.ptrType(tag_ty, spvStorageClass(un_ptr_ty.ptrAddressSpace(mod)));
33393305
33403306 const union_ptr_id = try self.resolve(bin_op.lhs);
33413307 const new_tag_id = try self.resolve(bin_op.rhs);
......@@ -3400,6 +3366,7 @@ const DeclGen = struct {
34003366 return try self.constInt(tag_ty_ref, tag_int);
34013367 }
34023368
3369 // TODO: Make this use self.ptrType
34033370 const un_active_ty_ref = try self.resolveUnionType(ty, active_field);
34043371 const un_active_ptr_ty_ref = try self.spv.ptrType(un_active_ty_ref, .Function);
34053372 const un_general_ty_ref = try self.resolveType(ty, .direct);
......@@ -3414,23 +3381,16 @@ const DeclGen = struct {
34143381
34153382 if (layout.tag_size != 0) {
34163383 const tag_ty_ref = try self.resolveType(maybe_tag_ty.?, .direct);
3417 const tag_ptr_ty_ref = try self.spv.ptrType(tag_ty_ref, .Function);
3384 const tag_ptr_ty_ref = try self.ptrType(maybe_tag_ty.?, .Function);
34183385 const ptr_id = try self.accessChain(tag_ptr_ty_ref, tmp_id, &.{@as(u32, @intCast(layout.tag_index))});
34193386 const tag_id = try self.constInt(tag_ty_ref, tag_int);
3420 try self.func.body.emit(self.spv.gpa, .OpStore, .{
3421 .pointer = ptr_id,
3422 .object = tag_id,
3423 });
3387 try self.store(maybe_tag_ty.?, ptr_id, tag_id, false);
34243388 }
34253389
34263390 if (layout.active_field_size != 0) {
3427 const active_field_ty_ref = try self.resolveType(layout.active_field_ty, .indirect);
3428 const active_field_ptr_ty_ref = try self.spv.ptrType(active_field_ty_ref, .Function);
3391 const active_field_ptr_ty_ref = try self.ptrType(layout.active_field_ty, .Function);
34293392 const ptr_id = try self.accessChain(active_field_ptr_ty_ref, tmp_id, &.{@as(u32, @intCast(layout.active_field_index))});
3430 try self.func.body.emit(self.spv.gpa, .OpStore, .{
3431 .pointer = ptr_id,
3432 .object = payload.?,
3433 });
3393 try self.store(layout.active_field_ty, ptr_id, payload.?, false);
34343394 } else {
34353395 assert(payload == null);
34363396 }
......@@ -3603,23 +3563,13 @@ const DeclGen = struct {
36033563 return try self.structFieldPtr(result_ptr_ty, struct_ptr_ty, struct_ptr, field_index);
36043564 }
36053565
3606 /// We cannot use an OpVariable directly in an OpSpecConstantOp, but we can
3607 /// after we insert a dummy AccessChain...
3608 /// TODO: Get rid of this
3609 fn makePointerConstant(
3610 self: *DeclGen,
3611 section: *SpvSection,
3612 ptr_ty_ref: CacheRef,
3613 ptr_id: IdRef,
3614 ) !IdRef {
3615 const result_id = self.spv.allocId();
3616 try section.emitSpecConstantOp(self.spv.gpa, .OpInBoundsAccessChain, .{
3617 .id_result_type = self.typeId(ptr_ty_ref),
3618 .id_result = result_id,
3619 .base = ptr_id,
3620 });
3621 return result_id;
3622 }
3566 const AllocOptions = struct {
3567 initializer: ?IdRef = null,
3568 /// The final storage class of the pointer. This may be either `.Generic` or `.Function`.
3569 /// In either case, the local is allocated in the `.Function` storage class, and optionally
3570 /// cast back to `.Generic`.
3571 storage_class: StorageClass = .Generic,
3572 };
36233573
36243574 // Allocate a function-local variable, with possible initializer.
36253575 // This function returns a pointer to a variable of type `ty_ref`,
......@@ -3627,30 +3577,36 @@ const DeclGen = struct {
36273577 // placed in the Function address space.
36283578 fn alloc(
36293579 self: *DeclGen,
3630 ty_ref: CacheRef,
3631 initializer: ?IdRef,
3580 ty: Type,
3581 options: AllocOptions,
36323582 ) !IdRef {
3633 const fn_ptr_ty_ref = try self.spv.ptrType(ty_ref, .Function);
3634 const general_ptr_ty_ref = try self.spv.ptrType(ty_ref, .Generic);
3583 const ptr_fn_ty_ref = try self.ptrType(ty, .Function);
36353584
36363585 // SPIR-V requires that OpVariable declarations for locals go into the first block, so we are just going to
36373586 // directly generate them into func.prologue instead of the body.
36383587 const var_id = self.spv.allocId();
36393588 try self.func.prologue.emit(self.spv.gpa, .OpVariable, .{
3640 .id_result_type = self.typeId(fn_ptr_ty_ref),
3589 .id_result_type = self.typeId(ptr_fn_ty_ref),
36413590 .id_result = var_id,
36423591 .storage_class = .Function,
3643 .initializer = initializer,
3592 .initializer = options.initializer,
36443593 });
36453594
3646 // Convert to a generic pointer
3647 const result_id = self.spv.allocId();
3648 try self.func.body.emit(self.spv.gpa, .OpPtrCastToGeneric, .{
3649 .id_result_type = self.typeId(general_ptr_ty_ref),
3650 .id_result = result_id,
3651 .pointer = var_id,
3652 });
3653 return result_id;
3595 switch (options.storage_class) {
3596 .Generic => {
3597 const ptr_gn_ty_ref = try self.ptrType(ty, .Generic);
3598 // Convert to a generic pointer
3599 const result_id = self.spv.allocId();
3600 try self.func.body.emit(self.spv.gpa, .OpPtrCastToGeneric, .{
3601 .id_result_type = self.typeId(ptr_gn_ty_ref),
3602 .id_result = result_id,
3603 .pointer = var_id,
3604 });
3605 return result_id;
3606 },
3607 .Function => return var_id,
3608 else => unreachable,
3609 }
36543610 }
36553611
36563612 fn airAlloc(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
......@@ -3659,8 +3615,7 @@ const DeclGen = struct {
36593615 const ptr_ty = self.typeOfIndex(inst);
36603616 assert(ptr_ty.ptrAddressSpace(mod) == .generic);
36613617 const child_ty = ptr_ty.childType(mod);
3662 const child_ty_ref = try self.resolveType(child_ty, .indirect);
3663 return try self.alloc(child_ty_ref, null);
3618 return try self.alloc(child_ty, .{});
36643619 }
36653620
36663621 fn airArg(self: *DeclGen) IdRef {
......@@ -4032,7 +3987,7 @@ const DeclGen = struct {
40323987 .is_null => .eq,
40333988 .is_non_null => .neq,
40343989 };
4035 return try self.cmp(op, ptr_ty, ptr_id, null_id);
3990 return try self.cmp(op, Type.bool, ptr_ty, ptr_id, null_id);
40363991 }
40373992
40383993 const is_non_null_id = if (payload_ty.hasRuntimeBitsIgnoreComptime(mod))