| ... | @@ -1008,8 +1008,7 @@ const DeclGen = struct { | ... | @@ -1008,8 +1008,7 @@ const DeclGen = struct { |
| 1008 | .func => { | 1008 | .func => { |
| 1009 | // TODO: Properly lower function pointers. For now we are going to hack around it and | 1009 | // TODO: Properly lower function pointers. For now we are going to hack around it and |
| 1010 | // just generate an empty pointer. Function pointers are represented by a pointer to usize. | 1010 | // just generate an empty pointer. Function pointers are represented by a pointer to usize. |
| 1011 | // TODO: Add dependency | 1011 | return try self.spv.constUndef(ty_ref); |
| 1012 | return try self.spv.constNull(ty_ref); | | |
| 1013 | }, | 1012 | }, |
| 1014 | .extern_func => unreachable, // TODO | 1013 | .extern_func => unreachable, // TODO |
| 1015 | else => {}, | 1014 | else => {}, |
| ... | @@ -1253,6 +1252,18 @@ const DeclGen = struct { | ... | @@ -1253,6 +1252,18 @@ const DeclGen = struct { |
| 1253 | const total_len = std.math.cast(u32, ty.arrayLenIncludingSentinel(mod)) orelse { | 1252 | const total_len = std.math.cast(u32, ty.arrayLenIncludingSentinel(mod)) orelse { |
| 1254 | return self.fail("array type of {} elements is too large", .{ty.arrayLenIncludingSentinel(mod)}); | 1253 | return self.fail("array type of {} elements is too large", .{ty.arrayLenIncludingSentinel(mod)}); |
| 1255 | }; | 1254 | }; |
| | 1255 | if (!ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| | 1256 | // The size of the array would be 0, but that is not allowed in SPIR-V. |
| | 1257 | // This path can be reached for example when there is a slicing of a pointer |
| | 1258 | // that produces a zero-length array. In all cases where this type can be generated, |
| | 1259 | // we should be in an indirect path (direct uses of this type should be filtered out in Sema). |
| | 1260 | assert(repr == .indirect); |
| | 1261 | |
| | 1262 | return try self.spv.resolve(.{ .opaque_type = .{ |
| | 1263 | .name = try self.spv.resolveString("zero-sized array"), |
| | 1264 | } }); |
| | 1265 | } |
| | 1266 | |
| 1256 | const ty_ref = try self.spv.arrayType(total_len, elem_ty_ref); | 1267 | const ty_ref = try self.spv.arrayType(total_len, elem_ty_ref); |
| 1257 | try self.type_map.put(self.gpa, ty.toIntern(), .{ .ty_ref = ty_ref }); | 1268 | try self.type_map.put(self.gpa, ty.toIntern(), .{ .ty_ref = ty_ref }); |
| 1258 | return ty_ref; | 1269 | return ty_ref; |
| ... | @@ -2742,22 +2753,23 @@ const DeclGen = struct { | ... | @@ -2742,22 +2753,23 @@ const DeclGen = struct { |
| 2742 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 2753 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 2743 | const array_ptr_ty = self.typeOf(ty_op.operand); | 2754 | const array_ptr_ty = self.typeOf(ty_op.operand); |
| 2744 | const array_ty = array_ptr_ty.childType(mod); | 2755 | const array_ty = array_ptr_ty.childType(mod); |
| 2745 | const elem_ty = array_ptr_ty.elemType2(mod); // use elemType() so that we get T for *[N]T. | | |
| 2746 | const elem_ty_ref = try self.resolveType(elem_ty, .indirect); | | |
| 2747 | const elem_ptr_ty_ref = try self.spv.ptrType(elem_ty_ref, spvStorageClass(array_ptr_ty.ptrAddressSpace(mod))); | | |
| 2748 | const slice_ty = self.typeOfIndex(inst); | 2756 | const slice_ty = self.typeOfIndex(inst); |
| | 2757 | const elem_ptr_ty = slice_ty.slicePtrFieldType(mod); |
| | 2758 | |
| | 2759 | const elem_ptr_ty_ref = try self.resolveType(elem_ptr_ty, .direct); |
| 2749 | const slice_ty_ref = try self.resolveType(slice_ty, .direct); | 2760 | const slice_ty_ref = try self.resolveType(slice_ty, .direct); |
| 2750 | const size_ty_ref = try self.sizeType(); | 2761 | const size_ty_ref = try self.sizeType(); |
| 2751 | | 2762 | |
| 2752 | const array_ptr_id = try self.resolve(ty_op.operand); | 2763 | const array_ptr_id = try self.resolve(ty_op.operand); |
| 2753 | const len_id = try self.constInt(size_ty_ref, array_ty.arrayLen(mod)); | 2764 | const len_id = try self.constInt(size_ty_ref, array_ty.arrayLen(mod)); |
| 2754 | | 2765 | |
| 2755 | if (!array_ty.hasRuntimeBitsIgnoreComptime(mod)) { | 2766 | const elem_ptr_id = if (!array_ty.hasRuntimeBitsIgnoreComptime(mod)) |
| 2756 | unreachable; // TODO | 2767 | // Note: The pointer is something like *opaque{}, so we need to bitcast it to the element type. |
| 2757 | } | 2768 | try self.bitCast(elem_ptr_ty, array_ptr_ty, array_ptr_id) |
| | 2769 | else |
| | 2770 | // Convert the pointer-to-array to a pointer to the first element. |
| | 2771 | try self.accessChain(elem_ptr_ty_ref, array_ptr_id, &.{0}); |
| 2758 | | 2772 | |
| 2759 | // Convert the pointer-to-array to a pointer to the first element. | | |
| 2760 | const elem_ptr_id = try self.accessChain(elem_ptr_ty_ref, array_ptr_id, &.{0}); | | |
| 2761 | return try self.constructStruct(slice_ty_ref, &.{ elem_ptr_id, len_id }); | 2773 | return try self.constructStruct(slice_ty_ref, &.{ elem_ptr_id, len_id }); |
| 2762 | } | 2774 | } |
| 2763 | | 2775 | |
| ... | @@ -2916,8 +2928,10 @@ const DeclGen = struct { | ... | @@ -2916,8 +2928,10 @@ const DeclGen = struct { |
| 2916 | const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data; | 2928 | const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data; |
| 2917 | const ptr_ty = self.typeOf(bin_op.lhs); | 2929 | const ptr_ty = self.typeOf(bin_op.lhs); |
| 2918 | const elem_ty = ptr_ty.childType(mod); | 2930 | const elem_ty = ptr_ty.childType(mod); |
| 2919 | // TODO: Make this return a null ptr or something | 2931 | if (!elem_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 2920 | if (!elem_ty.hasRuntimeBitsIgnoreComptime(mod)) return null; | 2932 | const ptr_ty_ref = try self.resolveType(ptr_ty, .direct); |
| | 2933 | return try self.spv.constUndef(ptr_ty_ref); |
| | 2934 | } |
| 2921 | | 2935 | |
| 2922 | const ptr_id = try self.resolve(bin_op.lhs); | 2936 | const ptr_id = try self.resolve(bin_op.lhs); |
| 2923 | const index_id = try self.resolve(bin_op.rhs); | 2937 | const index_id = try self.resolve(bin_op.rhs); |