| ... | ... | @@ -358,8 +358,7 @@ const DeclGen = struct { |
| 358 | 358 | |
| 359 | 359 | const mod = self.module; |
| 360 | 360 | 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); |
| 363 | 362 | |
| 364 | 363 | const var_id = self.spv.declPtr(spv_decl_index).result_id; |
| 365 | 364 | |
| ... | ... | @@ -623,25 +622,15 @@ const DeclGen = struct { |
| 623 | 622 | /// result_ty_ref must be an array type. |
| 624 | 623 | /// Constituents should be in `indirect` representation (as the elements of an array should be). |
| 625 | 624 | /// 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 { |
| 627 | 626 | // The Khronos LLVM-SPIRV translator crashes because it cannot construct structs which' |
| 628 | 627 | // operands are not constant. |
| 629 | 628 | // See https://github.com/KhronosGroup/SPIRV-LLVM-Translator/issues/1349 |
| 630 | 629 | // For now, just initialize the struct by setting the fields manually... |
| 631 | 630 | // 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); |
| 645 | 634 | for (constituents, 0..) |constitent_id, index| { |
| 646 | 635 | const ptr_id = try self.accessChain(ptr_elem_ty_ref, ptr_composite_id, &.{@as(u32, @intCast(index))}); |
| 647 | 636 | try self.func.body.emit(self.spv.gpa, .OpStore, .{ |
| ... | ... | @@ -649,13 +638,8 @@ const DeclGen = struct { |
| 649 | 638 | .object = constitent_id, |
| 650 | 639 | }); |
| 651 | 640 | } |
| 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, .{}); |
| 659 | 643 | } |
| 660 | 644 | |
| 661 | 645 | /// This function generates a load for a constant in direct (ie, non-memory) representation. |
| ... | ... | @@ -857,7 +841,7 @@ const DeclGen = struct { |
| 857 | 841 | else => {}, |
| 858 | 842 | } |
| 859 | 843 | |
| 860 | | return try self.constructArray(result_ty_ref, constituents); |
| 844 | return try self.constructArray(ty, constituents); |
| 861 | 845 | }, |
| 862 | 846 | .struct_type => { |
| 863 | 847 | const struct_type = mod.typeToStruct(ty).?; |
| ... | ... | @@ -892,7 +876,7 @@ const DeclGen = struct { |
| 892 | 876 | const active_field = ty.unionTagFieldIndex(un.tag.toValue(), mod).?; |
| 893 | 877 | const layout = self.unionLayout(ty, active_field); |
| 894 | 878 | 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) |
| 896 | 880 | else |
| 897 | 881 | null; |
| 898 | 882 | |
| ... | ... | @@ -934,8 +918,7 @@ const DeclGen = struct { |
| 934 | 918 | |
| 935 | 919 | // TODO: Can we consolidate this in ptrElemPtr? |
| 936 | 920 | 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))); |
| 939 | 922 | |
| 940 | 923 | if (elem_ptr_ty_ref == result_ty_ref) { |
| 941 | 924 | return elem_ptr_id; |
| ... | ... | @@ -992,8 +975,7 @@ const DeclGen = struct { |
| 992 | 975 | }; |
| 993 | 976 | |
| 994 | 977 | 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); |
| 997 | 979 | |
| 998 | 980 | const ptr_id = switch (final_storage_class) { |
| 999 | 981 | .Generic => blk: { |
| ... | ... | @@ -1049,8 +1031,7 @@ const DeclGen = struct { |
| 1049 | 1031 | |
| 1050 | 1032 | const final_storage_class = spvStorageClass(decl.@"addrspace"); |
| 1051 | 1033 | |
| 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); |
| 1054 | 1035 | |
| 1055 | 1036 | const ptr_id = switch (final_storage_class) { |
| 1056 | 1037 | .Generic => blk: { |
| ... | ... | @@ -1118,6 +1099,12 @@ const DeclGen = struct { |
| 1118 | 1099 | return try self.intType(.unsigned, self.getTarget().ptrBitWidth()); |
| 1119 | 1100 | } |
| 1120 | 1101 | |
| 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 | |
| 1121 | 1108 | /// Generate a union type, optionally with a known field. If the tag alignment is greater |
| 1122 | 1109 | /// than that of the payload, a regular union (non-packed, with both tag and payload), will |
| 1123 | 1110 | /// be generated as follows: |
| ... | ... | @@ -1678,7 +1665,7 @@ const DeclGen = struct { |
| 1678 | 1665 | /// the name of an error in the text executor. |
| 1679 | 1666 | fn generateTestEntryPoint(self: *DeclGen, name: []const u8, spv_test_decl_index: SpvModule.Decl.Index) !void { |
| 1680 | 1667 | 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); |
| 1682 | 1669 | const void_ty_ref = try self.resolveType(Type.void, .direct); |
| 1683 | 1670 | |
| 1684 | 1671 | const kernel_proto_ty_ref = try self.spv.resolve(.{ .function_type = .{ |
| ... | ... | @@ -1713,6 +1700,7 @@ const DeclGen = struct { |
| 1713 | 1700 | .id_result = error_id, |
| 1714 | 1701 | .function = test_id, |
| 1715 | 1702 | }); |
| 1703 | // Note: Convert to direct not required. |
| 1716 | 1704 | try section.emit(self.spv.gpa, .OpStore, .{ |
| 1717 | 1705 | .pointer = p_error_id, |
| 1718 | 1706 | .object = error_id, |
| ... | ... | @@ -1817,8 +1805,7 @@ const DeclGen = struct { |
| 1817 | 1805 | else => final_storage_class, |
| 1818 | 1806 | }; |
| 1819 | 1807 | |
| 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); |
| 1822 | 1809 | |
| 1823 | 1810 | const begin = self.spv.beginGlobal(); |
| 1824 | 1811 | try self.spv.globals.section.emit(self.spv.gpa, .OpVariable, .{ |
| ... | ... | @@ -2113,9 +2100,7 @@ const DeclGen = struct { |
| 2113 | 2100 | constituent.* = try self.convertToIndirect(child_ty, result_id); |
| 2114 | 2101 | } |
| 2115 | 2102 | |
| 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); |
| 2119 | 2104 | } |
| 2120 | 2105 | |
| 2121 | 2106 | const result_id = self.spv.allocId(); |
| ... | ... | @@ -2176,7 +2161,7 @@ const DeclGen = struct { |
| 2176 | 2161 | |
| 2177 | 2162 | const info = try self.arithmeticTypeInfo(result_ty); |
| 2178 | 2163 | // 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); |
| 2180 | 2165 | const selection_id = switch (info.class) { |
| 2181 | 2166 | .float => blk: { |
| 2182 | 2167 | // cmp uses OpFOrd. When we have 0 [<>] nan this returns false, |
| ... | ... | @@ -2311,7 +2296,7 @@ const DeclGen = struct { |
| 2311 | 2296 | constituent.* = try self.arithOp(child_ty, lhs_index_id, rhs_index_id, fop, sop, uop, modular); |
| 2312 | 2297 | } |
| 2313 | 2298 | |
| 2314 | | return self.constructArray(result_ty_ref, constituents); |
| 2299 | return self.constructArray(ty, constituents); |
| 2315 | 2300 | } |
| 2316 | 2301 | |
| 2317 | 2302 | // Binary operations are generally applicable to both scalar and vector operations |
| ... | ... | @@ -2629,6 +2614,7 @@ const DeclGen = struct { |
| 2629 | 2614 | fn cmp( |
| 2630 | 2615 | self: *DeclGen, |
| 2631 | 2616 | op: std.math.CompareOperator, |
| 2617 | result_ty: Type, |
| 2632 | 2618 | ty: Type, |
| 2633 | 2619 | lhs_id: IdRef, |
| 2634 | 2620 | rhs_id: IdRef, |
| ... | ... | @@ -2669,7 +2655,7 @@ const DeclGen = struct { |
| 2669 | 2655 | if (ty.optionalReprIsPayload(mod)) { |
| 2670 | 2656 | assert(payload_ty.hasRuntimeBitsIgnoreComptime(mod)); |
| 2671 | 2657 | 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); |
| 2673 | 2659 | } |
| 2674 | 2660 | |
| 2675 | 2661 | const lhs_valid_id = if (payload_ty.hasRuntimeBitsIgnoreComptime(mod)) |
| ... | ... | @@ -2682,7 +2668,7 @@ const DeclGen = struct { |
| 2682 | 2668 | else |
| 2683 | 2669 | try self.convertToDirect(Type.bool, rhs_id); |
| 2684 | 2670 | |
| 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); |
| 2686 | 2672 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 2687 | 2673 | return valid_cmp_id; |
| 2688 | 2674 | } |
| ... | ... | @@ -2693,7 +2679,7 @@ const DeclGen = struct { |
| 2693 | 2679 | const lhs_pl_id = try self.extractField(payload_ty, lhs_id, 0); |
| 2694 | 2680 | const rhs_pl_id = try self.extractField(payload_ty, rhs_id, 0); |
| 2695 | 2681 | |
| 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); |
| 2697 | 2683 | |
| 2698 | 2684 | // op == .eq => lhs_valid == rhs_valid && lhs_pl == rhs_pl |
| 2699 | 2685 | // op == .neq => lhs_valid != rhs_valid || lhs_pl != rhs_pl |
| ... | ... | @@ -2715,7 +2701,6 @@ const DeclGen = struct { |
| 2715 | 2701 | .Vector => { |
| 2716 | 2702 | const child_ty = ty.childType(mod); |
| 2717 | 2703 | const vector_len = ty.vectorLen(mod); |
| 2718 | | const bool_ty_ref_indirect = try self.resolveType(Type.bool, .indirect); |
| 2719 | 2704 | |
| 2720 | 2705 | var constituents = try self.gpa.alloc(IdRef, vector_len); |
| 2721 | 2706 | defer self.gpa.free(constituents); |
| ... | ... | @@ -2723,12 +2708,11 @@ const DeclGen = struct { |
| 2723 | 2708 | for (constituents, 0..) |*constituent, i| { |
| 2724 | 2709 | const lhs_index_id = try self.extractField(child_ty, cmp_lhs_id, @intCast(i)); |
| 2725 | 2710 | 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); |
| 2727 | 2712 | constituent.* = try self.convertToIndirect(Type.bool, result_id); |
| 2728 | 2713 | } |
| 2729 | 2714 | |
| 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); |
| 2732 | 2716 | }, |
| 2733 | 2717 | else => unreachable, |
| 2734 | 2718 | }; |
| ... | ... | @@ -2801,8 +2785,9 @@ const DeclGen = struct { |
| 2801 | 2785 | const lhs_id = try self.resolve(bin_op.lhs); |
| 2802 | 2786 | const rhs_id = try self.resolve(bin_op.rhs); |
| 2803 | 2787 | const ty = self.typeOf(bin_op.lhs); |
| 2788 | const result_ty = self.typeOfIndex(inst); |
| 2804 | 2789 | |
| 2805 | | return try self.cmp(op, ty, lhs_id, rhs_id); |
| 2790 | return try self.cmp(op, result_ty, ty, lhs_id, rhs_id); |
| 2806 | 2791 | } |
| 2807 | 2792 | |
| 2808 | 2793 | fn airVectorCmp(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { |
| ... | ... | @@ -2814,8 +2799,9 @@ const DeclGen = struct { |
| 2814 | 2799 | const rhs_id = try self.resolve(vec_cmp.rhs); |
| 2815 | 2800 | const op = vec_cmp.compareOperator(); |
| 2816 | 2801 | const ty = self.typeOf(vec_cmp.lhs); |
| 2802 | const result_ty = self.typeOfIndex(inst); |
| 2817 | 2803 | |
| 2818 | | return try self.cmp(op, ty, lhs_id, rhs_id); |
| 2804 | return try self.cmp(op, result_ty, ty, lhs_id, rhs_id); |
| 2819 | 2805 | } |
| 2820 | 2806 | |
| 2821 | 2807 | fn bitCast( |
| ... | ... | @@ -2860,15 +2846,9 @@ const DeclGen = struct { |
| 2860 | 2846 | return result_id; |
| 2861 | 2847 | } |
| 2862 | 2848 | |
| 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); |
| 2865 | 2850 | |
| 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 }); |
| 2872 | 2852 | try self.store(src_ty, tmp_id, src_id, false); |
| 2873 | 2853 | const casted_ptr_id = self.spv.allocId(); |
| 2874 | 2854 | try self.func.body.emit(self.spv.gpa, .OpBitcast, .{ |
| ... | ... | @@ -3154,7 +3134,7 @@ const DeclGen = struct { |
| 3154 | 3134 | elem_ids[n_elems - 1] = try self.constant(array_info.elem_type, sentinel_val, .indirect); |
| 3155 | 3135 | } |
| 3156 | 3136 | |
| 3157 | | return try self.constructArray(result_ty_ref, elem_ids); |
| 3137 | return try self.constructArray(result_ty, elem_ids); |
| 3158 | 3138 | }, |
| 3159 | 3139 | else => unreachable, |
| 3160 | 3140 | } |
| ... | ... | @@ -3246,8 +3226,7 @@ const DeclGen = struct { |
| 3246 | 3226 | const mod = self.module; |
| 3247 | 3227 | // Construct new pointer type for the resulting pointer |
| 3248 | 3228 | 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))); |
| 3251 | 3230 | if (ptr_ty.isSinglePointer(mod)) { |
| 3252 | 3231 | // Pointer-to-array. In this case, the resulting pointer is not of the same type |
| 3253 | 3232 | // 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 { |
| 3283 | 3262 | const mod = self.module; |
| 3284 | 3263 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 3285 | 3264 | const array_ty = self.typeOf(bin_op.lhs); |
| 3286 | | const array_ty_ref = try self.resolveType(array_ty, .direct); |
| 3287 | 3265 | const elem_ty = array_ty.childType(mod); |
| 3288 | | const elem_ty_ref = try self.resolveType(elem_ty, .indirect); |
| 3289 | 3266 | const array_id = try self.resolve(bin_op.lhs); |
| 3290 | 3267 | const index_id = try self.resolve(bin_op.rhs); |
| 3291 | 3268 | |
| ... | ... | @@ -3293,20 +3270,10 @@ const DeclGen = struct { |
| 3293 | 3270 | // For now, just generate a temporary and use that. |
| 3294 | 3271 | // TODO: This backend probably also should use isByRef from llvm... |
| 3295 | 3272 | |
| 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); |
| 3309 | 3274 | |
| 3275 | const tmp_id = try self.alloc(array_ty, .{ .storage_class = .Function }); |
| 3276 | try self.store(array_ty, tmp_id, array_id, false); |
| 3310 | 3277 | const elem_ptr_id = try self.accessChainId(elem_ptr_ty_ref, tmp_id, &.{index_id}); |
| 3311 | 3278 | return try self.load(elem_ty, elem_ptr_id, false); |
| 3312 | 3279 | } |
| ... | ... | @@ -3334,8 +3301,7 @@ const DeclGen = struct { |
| 3334 | 3301 | if (layout.tag_size == 0) return; |
| 3335 | 3302 | |
| 3336 | 3303 | 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))); |
| 3339 | 3305 | |
| 3340 | 3306 | const union_ptr_id = try self.resolve(bin_op.lhs); |
| 3341 | 3307 | const new_tag_id = try self.resolve(bin_op.rhs); |
| ... | ... | @@ -3400,6 +3366,7 @@ const DeclGen = struct { |
| 3400 | 3366 | return try self.constInt(tag_ty_ref, tag_int); |
| 3401 | 3367 | } |
| 3402 | 3368 | |
| 3369 | // TODO: Make this use self.ptrType |
| 3403 | 3370 | const un_active_ty_ref = try self.resolveUnionType(ty, active_field); |
| 3404 | 3371 | const un_active_ptr_ty_ref = try self.spv.ptrType(un_active_ty_ref, .Function); |
| 3405 | 3372 | const un_general_ty_ref = try self.resolveType(ty, .direct); |
| ... | ... | @@ -3414,23 +3381,16 @@ const DeclGen = struct { |
| 3414 | 3381 | |
| 3415 | 3382 | if (layout.tag_size != 0) { |
| 3416 | 3383 | 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); |
| 3418 | 3385 | const ptr_id = try self.accessChain(tag_ptr_ty_ref, tmp_id, &.{@as(u32, @intCast(layout.tag_index))}); |
| 3419 | 3386 | 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); |
| 3424 | 3388 | } |
| 3425 | 3389 | |
| 3426 | 3390 | 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); |
| 3429 | 3392 | 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); |
| 3434 | 3394 | } else { |
| 3435 | 3395 | assert(payload == null); |
| 3436 | 3396 | } |
| ... | ... | @@ -3603,23 +3563,13 @@ const DeclGen = struct { |
| 3603 | 3563 | return try self.structFieldPtr(result_ptr_ty, struct_ptr_ty, struct_ptr, field_index); |
| 3604 | 3564 | } |
| 3605 | 3565 | |
| 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 | }; |
| 3623 | 3573 | |
| 3624 | 3574 | // Allocate a function-local variable, with possible initializer. |
| 3625 | 3575 | // This function returns a pointer to a variable of type `ty_ref`, |
| ... | ... | @@ -3627,30 +3577,36 @@ const DeclGen = struct { |
| 3627 | 3577 | // placed in the Function address space. |
| 3628 | 3578 | fn alloc( |
| 3629 | 3579 | self: *DeclGen, |
| 3630 | | ty_ref: CacheRef, |
| 3631 | | initializer: ?IdRef, |
| 3580 | ty: Type, |
| 3581 | options: AllocOptions, |
| 3632 | 3582 | ) !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); |
| 3635 | 3584 | |
| 3636 | 3585 | // SPIR-V requires that OpVariable declarations for locals go into the first block, so we are just going to |
| 3637 | 3586 | // directly generate them into func.prologue instead of the body. |
| 3638 | 3587 | const var_id = self.spv.allocId(); |
| 3639 | 3588 | 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), |
| 3641 | 3590 | .id_result = var_id, |
| 3642 | 3591 | .storage_class = .Function, |
| 3643 | | .initializer = initializer, |
| 3592 | .initializer = options.initializer, |
| 3644 | 3593 | }); |
| 3645 | 3594 | |
| 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 | } |
| 3654 | 3610 | } |
| 3655 | 3611 | |
| 3656 | 3612 | fn airAlloc(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { |
| ... | ... | @@ -3659,8 +3615,7 @@ const DeclGen = struct { |
| 3659 | 3615 | const ptr_ty = self.typeOfIndex(inst); |
| 3660 | 3616 | assert(ptr_ty.ptrAddressSpace(mod) == .generic); |
| 3661 | 3617 | 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, .{}); |
| 3664 | 3619 | } |
| 3665 | 3620 | |
| 3666 | 3621 | fn airArg(self: *DeclGen) IdRef { |
| ... | ... | @@ -4032,7 +3987,7 @@ const DeclGen = struct { |
| 4032 | 3987 | .is_null => .eq, |
| 4033 | 3988 | .is_non_null => .neq, |
| 4034 | 3989 | }; |
| 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); |
| 4036 | 3991 | } |
| 4037 | 3992 | |
| 4038 | 3993 | const is_non_null_id = if (payload_ty.hasRuntimeBitsIgnoreComptime(mod)) |