| ... | ... | @@ -159,7 +159,7 @@ pub const Object = struct { |
| 159 | 159 | uav_link: std.AutoHashMapUnmanaged(struct { InternPool.Index, StorageClass }, SpvModule.Decl.Index) = .empty, |
| 160 | 160 | |
| 161 | 161 | /// A map that maps AIR intern pool indices to SPIR-V result-ids. |
| 162 | | intern_map: InternMap = .{}, |
| 162 | intern_map: InternMap = .empty, |
| 163 | 163 | |
| 164 | 164 | /// This map serves a dual purpose: |
| 165 | 165 | /// - It keeps track of pointers that are currently being emitted, so that we can tell |
| ... | ... | @@ -314,7 +314,7 @@ const NavGen = struct { |
| 314 | 314 | next_arg_index: u32 = 0, |
| 315 | 315 | |
| 316 | 316 | /// A map keeping track of which instruction generated which result-id. |
| 317 | | inst_results: InstMap = .{}, |
| 317 | inst_results: InstMap = .empty, |
| 318 | 318 | |
| 319 | 319 | /// A map that maps AIR intern pool indices to SPIR-V result-ids. |
| 320 | 320 | /// See `Object.intern_map`. |
| ... | ... | @@ -469,7 +469,7 @@ const NavGen = struct { |
| 469 | 469 | |
| 470 | 470 | const zcu = self.pt.zcu; |
| 471 | 471 | const ty = Type.fromInterned(zcu.intern_pool.typeOf(val)); |
| 472 | | const decl_ptr_ty_id = try self.ptrType(ty, .Generic); |
| 472 | const decl_ptr_ty_id = try self.ptrType(ty, .Generic, .indirect); |
| 473 | 473 | |
| 474 | 474 | const spv_decl_index = blk: { |
| 475 | 475 | const entry = try self.object.uav_link.getOrPut(self.object.gpa, .{ val, .Function }); |
| ... | ... | @@ -532,7 +532,7 @@ const NavGen = struct { |
| 532 | 532 | |
| 533 | 533 | try self.spv.debugNameFmt(initializer_id, "initializer of __anon_{d}", .{@intFromEnum(val)}); |
| 534 | 534 | |
| 535 | | const fn_decl_ptr_ty_id = try self.ptrType(ty, .Function); |
| 535 | const fn_decl_ptr_ty_id = try self.ptrType(ty, .Function, .indirect); |
| 536 | 536 | try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpExtInst, .{ |
| 537 | 537 | .id_result_type = fn_decl_ptr_ty_id, |
| 538 | 538 | .id_result = result_id, |
| ... | ... | @@ -721,36 +721,16 @@ const NavGen = struct { |
| 721 | 721 | |
| 722 | 722 | /// Emits a bool constant in a particular representation. |
| 723 | 723 | fn constBool(self: *NavGen, value: bool, repr: Repr) !IdRef { |
| 724 | | // TODO: Cache? |
| 725 | | |
| 726 | | const section = &self.spv.sections.types_globals_constants; |
| 727 | | switch (repr) { |
| 728 | | .indirect => { |
| 729 | | return try self.constInt(Type.u1, @intFromBool(value), .indirect); |
| 730 | | }, |
| 731 | | .direct => { |
| 732 | | const result_ty_id = try self.resolveType(Type.bool, .direct); |
| 733 | | const result_id = self.spv.allocId(); |
| 734 | | switch (value) { |
| 735 | | inline else => |val_ct| try section.emit( |
| 736 | | self.spv.gpa, |
| 737 | | if (val_ct) .OpConstantTrue else .OpConstantFalse, |
| 738 | | .{ |
| 739 | | .id_result_type = result_ty_id, |
| 740 | | .id_result = result_id, |
| 741 | | }, |
| 742 | | ), |
| 743 | | } |
| 744 | | return result_id; |
| 745 | | }, |
| 746 | | } |
| 724 | return switch (repr) { |
| 725 | .indirect => self.constInt(Type.u1, @intFromBool(value)), |
| 726 | .direct => self.spv.constBool(value), |
| 727 | }; |
| 747 | 728 | } |
| 748 | 729 | |
| 749 | 730 | /// Emits an integer constant. |
| 750 | 731 | /// This function, unlike SpvModule.constInt, takes care to bitcast |
| 751 | 732 | /// the value to an unsigned int first for Kernels. |
| 752 | | fn constInt(self: *NavGen, ty: Type, value: anytype, repr: Repr) !IdRef { |
| 753 | | // TODO: Cache? |
| 733 | fn constInt(self: *NavGen, ty: Type, value: anytype) !IdRef { |
| 754 | 734 | const zcu = self.pt.zcu; |
| 755 | 735 | const scalar_ty = ty.scalarType(zcu); |
| 756 | 736 | const int_info = scalar_ty.intInfo(zcu); |
| ... | ... | @@ -763,18 +743,18 @@ const NavGen = struct { |
| 763 | 743 | else => unreachable, |
| 764 | 744 | }; |
| 765 | 745 | |
| 766 | | const bits: u64 = switch (signedness) { |
| 746 | const value64: u64 = switch (signedness) { |
| 767 | 747 | .signed => @bitCast(@as(i64, @intCast(value))), |
| 768 | 748 | .unsigned => @as(u64, @intCast(value)), |
| 769 | 749 | }; |
| 770 | 750 | |
| 771 | 751 | // Manually truncate the value to the right amount of bits. |
| 772 | | const truncated_bits = if (backing_bits == 64) |
| 773 | | bits |
| 752 | const truncated_value = if (backing_bits == 64) |
| 753 | value64 |
| 774 | 754 | else |
| 775 | | bits & (@as(u64, 1) << @intCast(backing_bits)) - 1; |
| 755 | value64 & (@as(u64, 1) << @intCast(backing_bits)) - 1; |
| 776 | 756 | |
| 777 | | const result_ty_id = try self.resolveType(scalar_ty, repr); |
| 757 | const result_ty_id = try self.resolveType(scalar_ty, .indirect); |
| 778 | 758 | const result_id = self.spv.allocId(); |
| 779 | 759 | |
| 780 | 760 | const section = &self.spv.sections.types_globals_constants; |
| ... | ... | @@ -783,100 +763,42 @@ const NavGen = struct { |
| 783 | 763 | 1...32 => try section.emit(self.spv.gpa, .OpConstant, .{ |
| 784 | 764 | .id_result_type = result_ty_id, |
| 785 | 765 | .id_result = result_id, |
| 786 | | .value = .{ .uint32 = @truncate(truncated_bits) }, |
| 766 | .value = .{ .uint32 = @truncate(truncated_value) }, |
| 787 | 767 | }), |
| 788 | 768 | 33...64 => try section.emit(self.spv.gpa, .OpConstant, .{ |
| 789 | 769 | .id_result_type = result_ty_id, |
| 790 | 770 | .id_result = result_id, |
| 791 | | .value = .{ .uint64 = truncated_bits }, |
| 771 | .value = .{ .uint64 = truncated_value }, |
| 792 | 772 | }), |
| 793 | 773 | else => unreachable, // TODO: Large integer constants |
| 794 | 774 | } |
| 795 | 775 | |
| 796 | | if (!ty.isVector(zcu)) { |
| 797 | | return result_id; |
| 798 | | } |
| 799 | | |
| 800 | | const n = ty.vectorLen(zcu); |
| 801 | | const ids = try self.gpa.alloc(IdRef, n); |
| 802 | | defer self.gpa.free(ids); |
| 803 | | @memset(ids, result_id); |
| 804 | | |
| 805 | | const vec_ty_id = try self.resolveType(ty, repr); |
| 806 | | const vec_result_id = self.spv.allocId(); |
| 807 | | try self.func.body.emit(self.spv.gpa, .OpCompositeConstruct, .{ |
| 808 | | .id_result_type = vec_ty_id, |
| 809 | | .id_result = vec_result_id, |
| 810 | | .constituents = ids, |
| 811 | | }); |
| 812 | | return vec_result_id; |
| 776 | if (!ty.isVector(zcu)) return result_id; |
| 777 | return self.constructCompositeSplat(ty, result_id); |
| 813 | 778 | } |
| 814 | 779 | |
| 815 | | /// Construct a struct at runtime. |
| 816 | | /// ty must be a struct type. |
| 817 | | /// Constituents should be in `indirect` representation (as the elements of a struct should be). |
| 818 | | /// Result is in `direct` representation. |
| 819 | | fn constructStruct(self: *NavGen, ty: Type, types: []const Type, constituents: []const IdRef) !IdRef { |
| 820 | | assert(types.len == constituents.len); |
| 821 | | |
| 780 | pub fn constructComposite(self: *NavGen, result_ty_id: IdRef, constituents: []const IdRef) !IdRef { |
| 822 | 781 | const result_id = self.spv.allocId(); |
| 823 | | try self.func.body.emit(self.spv.gpa, .OpCompositeConstruct, .{ |
| 824 | | .id_result_type = try self.resolveType(ty, .direct), |
| 825 | | .id_result = result_id, |
| 826 | | .constituents = constituents, |
| 827 | | }); |
| 828 | | return result_id; |
| 829 | | } |
| 830 | | |
| 831 | | /// Construct a vector at runtime. |
| 832 | | /// ty must be an vector type. |
| 833 | | fn constructVector(self: *NavGen, ty: Type, constituents: []const IdRef) !IdRef { |
| 834 | | const zcu = self.pt.zcu; |
| 835 | | assert(ty.vectorLen(zcu) == constituents.len); |
| 836 | | |
| 837 | | // Note: older versions of the Khronos SPRIV-LLVM translator crash on this instruction |
| 838 | | // because it cannot construct structs which' operands are not constant. |
| 839 | | // See https://github.com/KhronosGroup/SPIRV-LLVM-Translator/issues/1349 |
| 840 | | // Currently this is the case for Intel OpenCL CPU runtime (2023-WW46), but the |
| 841 | | // alternatives dont work properly: |
| 842 | | // - using temporaries/pointers doesn't work properly with vectors of bool, causes |
| 843 | | // backends that use llvm to crash |
| 844 | | // - using OpVectorInsertDynamic doesn't work for non-spirv-vectors of bool. |
| 845 | | |
| 846 | | const result_id = self.spv.allocId(); |
| 847 | | try self.func.body.emit(self.spv.gpa, .OpCompositeConstruct, .{ |
| 848 | | .id_result_type = try self.resolveType(ty, .direct), |
| 782 | try self.func.body.emit(self.gpa, .OpCompositeConstruct, .{ |
| 783 | .id_result_type = result_ty_id, |
| 849 | 784 | .id_result = result_id, |
| 850 | 785 | .constituents = constituents, |
| 851 | 786 | }); |
| 852 | 787 | return result_id; |
| 853 | 788 | } |
| 854 | 789 | |
| 855 | | /// Construct a vector at runtime with all lanes set to the same value. |
| 856 | | /// ty must be an vector type. |
| 857 | | fn constructVectorSplat(self: *NavGen, ty: Type, constituent: IdRef) !IdRef { |
| 790 | /// Construct a composite at runtime with all lanes set to the same value. |
| 791 | /// ty must be an aggregate type. |
| 792 | fn constructCompositeSplat(self: *NavGen, ty: Type, constituent: IdRef) !IdRef { |
| 858 | 793 | const zcu = self.pt.zcu; |
| 859 | | const n = ty.vectorLen(zcu); |
| 794 | const n = ty.arrayLen(zcu); |
| 860 | 795 | |
| 861 | 796 | const constituents = try self.gpa.alloc(IdRef, n); |
| 862 | 797 | defer self.gpa.free(constituents); |
| 863 | 798 | @memset(constituents, constituent); |
| 864 | 799 | |
| 865 | | return try self.constructVector(ty, constituents); |
| 866 | | } |
| 867 | | |
| 868 | | /// Construct an array at runtime. |
| 869 | | /// ty must be an array type. |
| 870 | | /// Constituents should be in `indirect` representation (as the elements of an array should be). |
| 871 | | /// Result is in `direct` representation. |
| 872 | | fn constructArray(self: *NavGen, ty: Type, constituents: []const IdRef) !IdRef { |
| 873 | | const result_id = self.spv.allocId(); |
| 874 | | try self.func.body.emit(self.spv.gpa, .OpCompositeConstruct, .{ |
| 875 | | .id_result_type = try self.resolveType(ty, .direct), |
| 876 | | .id_result = result_id, |
| 877 | | .constituents = constituents, |
| 878 | | }); |
| 879 | | return result_id; |
| 800 | const result_ty_id = try self.resolveType(ty, .direct); |
| 801 | return self.constructComposite(result_ty_id, constituents); |
| 880 | 802 | } |
| 881 | 803 | |
| 882 | 804 | /// This function generates a load for a constant in direct (ie, non-memory) representation. |
| ... | ... | @@ -947,9 +869,9 @@ const NavGen = struct { |
| 947 | 869 | }, |
| 948 | 870 | .int => { |
| 949 | 871 | if (ty.isSignedInt(zcu)) { |
| 950 | | break :cache try self.constInt(ty, val.toSignedInt(zcu), repr); |
| 872 | break :cache try self.constInt(ty, val.toSignedInt(zcu)); |
| 951 | 873 | } else { |
| 952 | | break :cache try self.constInt(ty, val.toUnsignedInt(zcu), repr); |
| 874 | break :cache try self.constInt(ty, val.toUnsignedInt(zcu)); |
| 953 | 875 | } |
| 954 | 876 | }, |
| 955 | 877 | .float => { |
| ... | ... | @@ -970,7 +892,7 @@ const NavGen = struct { |
| 970 | 892 | }, |
| 971 | 893 | .err => |err| { |
| 972 | 894 | const value = try pt.getErrorValue(err.name); |
| 973 | | break :cache try self.constInt(ty, value, repr); |
| 895 | break :cache try self.constInt(ty, value); |
| 974 | 896 | }, |
| 975 | 897 | .error_union => |error_union| { |
| 976 | 898 | // TODO: Error unions may be constructed with constant instructions if the payload type |
| ... | ... | @@ -1011,7 +933,8 @@ const NavGen = struct { |
| 1011 | 933 | types = .{ payload_ty, err_ty }; |
| 1012 | 934 | } |
| 1013 | 935 | |
| 1014 | | return try self.constructStruct(ty, &types, &constituents); |
| 936 | const comp_ty_id = try self.resolveType(ty, .direct); |
| 937 | return try self.constructComposite(comp_ty_id, &constituents); |
| 1015 | 938 | }, |
| 1016 | 939 | .enum_tag => { |
| 1017 | 940 | const int_val = try val.intFromEnum(ty, pt); |
| ... | ... | @@ -1020,14 +943,10 @@ const NavGen = struct { |
| 1020 | 943 | }, |
| 1021 | 944 | .ptr => return self.constantPtr(val), |
| 1022 | 945 | .slice => |slice| { |
| 1023 | | const ptr_ty = ty.slicePtrFieldType(zcu); |
| 1024 | 946 | const ptr_id = try self.constantPtr(Value.fromInterned(slice.ptr)); |
| 1025 | 947 | const len_id = try self.constant(Type.usize, Value.fromInterned(slice.len), .indirect); |
| 1026 | | return self.constructStruct( |
| 1027 | | ty, |
| 1028 | | &.{ ptr_ty, Type.usize }, |
| 1029 | | &.{ ptr_id, len_id }, |
| 1030 | | ); |
| 948 | const comp_ty_id = try self.resolveType(ty, .direct); |
| 949 | return try self.constructComposite(comp_ty_id, &.{ ptr_id, len_id }); |
| 1031 | 950 | }, |
| 1032 | 951 | .opt => { |
| 1033 | 952 | const payload_ty = ty.optionalChild(zcu); |
| ... | ... | @@ -1053,11 +972,8 @@ const NavGen = struct { |
| 1053 | 972 | else |
| 1054 | 973 | try self.spv.constUndef(try self.resolveType(payload_ty, .indirect)); |
| 1055 | 974 | |
| 1056 | | return try self.constructStruct( |
| 1057 | | ty, |
| 1058 | | &.{ payload_ty, Type.bool }, |
| 1059 | | &.{ payload_id, has_pl_id }, |
| 1060 | | ); |
| 975 | const comp_ty_id = try self.resolveType(ty, .direct); |
| 976 | return try self.constructComposite(comp_ty_id, &.{ payload_id, has_pl_id }); |
| 1061 | 977 | }, |
| 1062 | 978 | .aggregate => |aggregate| switch (ip.indexToKey(ty.ip_index)) { |
| 1063 | 979 | inline .array_type, .vector_type => |array_type, tag| { |
| ... | ... | @@ -1077,7 +993,7 @@ const NavGen = struct { |
| 1077 | 993 | // TODO: This is really space inefficient, perhaps there is a better |
| 1078 | 994 | // way to do it? |
| 1079 | 995 | for (constituents, bytes.toSlice(constituents.len, ip)) |*constituent, byte| { |
| 1080 | | constituent.* = try self.constInt(elem_ty, byte, child_repr); |
| 996 | constituent.* = try self.constInt(elem_ty, byte); |
| 1081 | 997 | } |
| 1082 | 998 | }, |
| 1083 | 999 | .elems => |elems| { |
| ... | ... | @@ -1090,11 +1006,8 @@ const NavGen = struct { |
| 1090 | 1006 | }, |
| 1091 | 1007 | } |
| 1092 | 1008 | |
| 1093 | | switch (tag) { |
| 1094 | | .array_type => return self.constructArray(ty, constituents), |
| 1095 | | .vector_type => return self.constructVector(ty, constituents), |
| 1096 | | else => unreachable, |
| 1097 | | } |
| 1009 | const comp_ty_id = try self.resolveType(ty, .direct); |
| 1010 | return self.constructComposite(comp_ty_id, constituents); |
| 1098 | 1011 | }, |
| 1099 | 1012 | .struct_type => { |
| 1100 | 1013 | const struct_type = zcu.typeToStruct(ty).?; |
| ... | ... | @@ -1124,7 +1037,8 @@ const NavGen = struct { |
| 1124 | 1037 | try constituents.append(field_id); |
| 1125 | 1038 | } |
| 1126 | 1039 | |
| 1127 | | return try self.constructStruct(ty, types.items, constituents.items); |
| 1040 | const comp_ty_id = try self.resolveType(ty, .direct); |
| 1041 | return try self.constructComposite(comp_ty_id, constituents.items); |
| 1128 | 1042 | }, |
| 1129 | 1043 | .tuple_type => unreachable, // TODO |
| 1130 | 1044 | else => unreachable, |
| ... | ... | @@ -1149,8 +1063,6 @@ const NavGen = struct { |
| 1149 | 1063 | } |
| 1150 | 1064 | |
| 1151 | 1065 | fn constantPtr(self: *NavGen, ptr_val: Value) Error!IdRef { |
| 1152 | | // TODO: Caching?? |
| 1153 | | |
| 1154 | 1066 | const pt = self.pt; |
| 1155 | 1067 | |
| 1156 | 1068 | if (ptr_val.isUndef(pt.zcu)) { |
| ... | ... | @@ -1201,7 +1113,7 @@ const NavGen = struct { |
| 1201 | 1113 | .elem_ptr => |elem| { |
| 1202 | 1114 | const parent_ptr_id = try self.derivePtr(elem.parent.*); |
| 1203 | 1115 | const parent_ptr_ty = try elem.parent.ptrType(pt); |
| 1204 | | const index_id = try self.constInt(Type.usize, elem.elem_idx, .direct); |
| 1116 | const index_id = try self.constInt(Type.usize, elem.elem_idx); |
| 1205 | 1117 | return self.ptrElemPtr(parent_ptr_ty, parent_ptr_id, index_id); |
| 1206 | 1118 | }, |
| 1207 | 1119 | .offset_and_cast => |oac| { |
| ... | ... | @@ -1255,7 +1167,7 @@ const NavGen = struct { |
| 1255 | 1167 | |
| 1256 | 1168 | // Uav refs are always generic. |
| 1257 | 1169 | assert(ty.ptrAddressSpace(zcu) == .generic); |
| 1258 | | const decl_ptr_ty_id = try self.ptrType(uav_ty, .Generic); |
| 1170 | const decl_ptr_ty_id = try self.ptrType(uav_ty, .Generic, .indirect); |
| 1259 | 1171 | const ptr_id = try self.resolveUav(uav.val); |
| 1260 | 1172 | |
| 1261 | 1173 | if (decl_ptr_ty_id != ty_id) { |
| ... | ... | @@ -1310,7 +1222,7 @@ const NavGen = struct { |
| 1310 | 1222 | const storage_class = self.spvStorageClass(nav.getAddrspace()); |
| 1311 | 1223 | try self.addFunctionDep(spv_decl_index, storage_class); |
| 1312 | 1224 | |
| 1313 | | const decl_ptr_ty_id = try self.ptrType(nav_ty, storage_class); |
| 1225 | const decl_ptr_ty_id = try self.ptrType(nav_ty, storage_class, .indirect); |
| 1314 | 1226 | |
| 1315 | 1227 | const ptr_id = switch (storage_class) { |
| 1316 | 1228 | .Generic => try self.castToGeneric(decl_ptr_ty_id, decl_id), |
| ... | ... | @@ -1359,23 +1271,11 @@ const NavGen = struct { |
| 1359 | 1271 | } |
| 1360 | 1272 | |
| 1361 | 1273 | fn arrayType(self: *NavGen, len: u32, child_ty: IdRef) !IdRef { |
| 1362 | | // TODO: Cache?? |
| 1363 | | const len_id = try self.constInt(Type.u32, len, .direct); |
| 1364 | | const result_id = self.spv.allocId(); |
| 1365 | | |
| 1366 | | try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpTypeArray, .{ |
| 1367 | | .id_result = result_id, |
| 1368 | | .element_type = child_ty, |
| 1369 | | .length = len_id, |
| 1370 | | }); |
| 1371 | | return result_id; |
| 1372 | | } |
| 1373 | | |
| 1374 | | fn ptrType(self: *NavGen, child_ty: Type, storage_class: StorageClass) !IdRef { |
| 1375 | | return try self.ptrType2(child_ty, storage_class, .indirect); |
| 1274 | const len_id = try self.constInt(Type.u32, len); |
| 1275 | return self.spv.arrayType(len_id, child_ty); |
| 1376 | 1276 | } |
| 1377 | 1277 | |
| 1378 | | fn ptrType2(self: *NavGen, child_ty: Type, storage_class: StorageClass, child_repr: Repr) !IdRef { |
| 1278 | fn ptrType(self: *NavGen, child_ty: Type, storage_class: StorageClass, child_repr: Repr) !IdRef { |
| 1379 | 1279 | const key = .{ child_ty.toIntern(), storage_class, child_repr }; |
| 1380 | 1280 | const entry = try self.ptr_types.getOrPut(self.gpa, key); |
| 1381 | 1281 | if (entry.found_existing) { |
| ... | ... | @@ -1408,8 +1308,7 @@ const NavGen = struct { |
| 1408 | 1308 | } |
| 1409 | 1309 | |
| 1410 | 1310 | fn functionType(self: *NavGen, return_ty: Type, param_types: []const Type) !IdRef { |
| 1411 | | // TODO: Cache?? |
| 1412 | | |
| 1311 | const return_ty_id = try self.resolveFnReturnType(return_ty); |
| 1413 | 1312 | const param_ids = try self.gpa.alloc(IdRef, param_types.len); |
| 1414 | 1313 | defer self.gpa.free(param_ids); |
| 1415 | 1314 | |
| ... | ... | @@ -1417,14 +1316,7 @@ const NavGen = struct { |
| 1417 | 1316 | param_id.* = try self.resolveType(param_ty, .direct); |
| 1418 | 1317 | } |
| 1419 | 1318 | |
| 1420 | | const ty_id = self.spv.allocId(); |
| 1421 | | try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpTypeFunction, .{ |
| 1422 | | .id_result = ty_id, |
| 1423 | | .return_type = try self.resolveFnReturnType(return_ty), |
| 1424 | | .id_ref_2 = param_ids, |
| 1425 | | }); |
| 1426 | | |
| 1427 | | return ty_id; |
| 1319 | return self.spv.functionType(return_ty_id, param_ids); |
| 1428 | 1320 | } |
| 1429 | 1321 | |
| 1430 | 1322 | fn zigScalarOrVectorTypeLike(self: *NavGen, new_ty: Type, base_ty: Type) !Type { |
| ... | ... | @@ -1702,13 +1594,7 @@ const NavGen = struct { |
| 1702 | 1594 | |
| 1703 | 1595 | const child_ty = Type.fromInterned(ptr_info.child); |
| 1704 | 1596 | const storage_class = self.spvStorageClass(ptr_info.flags.address_space); |
| 1705 | | const ptr_ty_id = try self.ptrType(child_ty, storage_class); |
| 1706 | | |
| 1707 | | if (target.os.tag == .vulkan and ptr_info.flags.size == .many) { |
| 1708 | | try self.spv.decorate(ptr_ty_id, .{ .ArrayStride = .{ |
| 1709 | | .array_stride = @intCast(child_ty.abiSize(zcu)), |
| 1710 | | } }); |
| 1711 | | } |
| 1597 | const ptr_ty_id = try self.ptrType(child_ty, storage_class, .indirect); |
| 1712 | 1598 | |
| 1713 | 1599 | if (ptr_info.flags.size != .slice) { |
| 1714 | 1600 | return ptr_ty_id; |
| ... | ... | @@ -1755,10 +1641,6 @@ const NavGen = struct { |
| 1755 | 1641 | defer self.gpa.free(type_name); |
| 1756 | 1642 | try self.spv.debugName(result_id, type_name); |
| 1757 | 1643 | |
| 1758 | | if (target.os.tag == .vulkan) { |
| 1759 | | try self.spv.decorate(result_id, .Block); // Decorate all structs as block for now... |
| 1760 | | } |
| 1761 | | |
| 1762 | 1644 | return result_id; |
| 1763 | 1645 | }, |
| 1764 | 1646 | .struct_type => ip.loadStructType(ty.toIntern()), |
| ... | ... | @@ -1804,10 +1686,6 @@ const NavGen = struct { |
| 1804 | 1686 | defer self.gpa.free(type_name); |
| 1805 | 1687 | try self.spv.debugName(result_id, type_name); |
| 1806 | 1688 | |
| 1807 | | if (target.os.tag == .vulkan) { |
| 1808 | | try self.spv.decorate(result_id, .Block); // Decorate all structs as block for now... |
| 1809 | | } |
| 1810 | | |
| 1811 | 1689 | return result_id; |
| 1812 | 1690 | }, |
| 1813 | 1691 | .optional => { |
| ... | ... | @@ -2073,12 +1951,13 @@ const NavGen = struct { |
| 2073 | 1951 | .exploded_vector => |range| { |
| 2074 | 1952 | assert(self.ty.isVector(zcu)); |
| 2075 | 1953 | assert(self.ty.vectorLen(zcu) == range.len); |
| 2076 | | const consituents = try ng.gpa.alloc(IdRef, range.len); |
| 2077 | | defer ng.gpa.free(consituents); |
| 2078 | | for (consituents, 0..range.len) |*id, i| { |
| 1954 | const constituents = try ng.gpa.alloc(IdRef, range.len); |
| 1955 | defer ng.gpa.free(constituents); |
| 1956 | for (constituents, 0..range.len) |*id, i| { |
| 2079 | 1957 | id.* = range.at(i); |
| 2080 | 1958 | } |
| 2081 | | return ng.constructVector(self.ty, consituents); |
| 1959 | const result_ty_id = try ng.resolveType(self.ty, .direct); |
| 1960 | return ng.constructComposite(result_ty_id, constituents); |
| 2082 | 1961 | }, |
| 2083 | 1962 | } |
| 2084 | 1963 | } |
| ... | ... | @@ -2282,7 +2161,7 @@ const NavGen = struct { |
| 2282 | 2161 | .child = tmp.ty.toIntern(), |
| 2283 | 2162 | }); |
| 2284 | 2163 | |
| 2285 | | const vector = try ng.constructVectorSplat(vector_ty, id); |
| 2164 | const vector = try ng.constructCompositeSplat(vector_ty, id); |
| 2286 | 2165 | return .{ |
| 2287 | 2166 | .ty = vector_ty, |
| 2288 | 2167 | .value = .{ .spv_vectorwise = vector }, |
| ... | ... | @@ -3045,7 +2924,7 @@ const NavGen = struct { |
| 3045 | 2924 | const spv_err_decl_index = self.object.error_push_constant.?.push_constant_ptr; |
| 3046 | 2925 | const push_constant_id = self.spv.declPtr(spv_err_decl_index).result_id; |
| 3047 | 2926 | |
| 3048 | | const zero_id = try self.constInt(Type.u32, 0, .direct); |
| 2927 | const zero_id = try self.constInt(Type.u32, 0); |
| 3049 | 2928 | // We cannot use OpInBoundsAccessChain to dereference cross-storage class, so we have to use |
| 3050 | 2929 | // a load. |
| 3051 | 2930 | const tmp = self.spv.allocId(); |
| ... | ... | @@ -3187,7 +3066,7 @@ const NavGen = struct { |
| 3187 | 3066 | const storage_class = self.spvStorageClass(nav.getAddrspace()); |
| 3188 | 3067 | assert(storage_class != .Generic); // These should be instance globals |
| 3189 | 3068 | |
| 3190 | | const ptr_ty_id = try self.ptrType(ty, storage_class); |
| 3069 | const ptr_ty_id = try self.ptrType(ty, storage_class, .indirect); |
| 3191 | 3070 | |
| 3192 | 3071 | try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpVariable, .{ |
| 3193 | 3072 | .id_result_type = ptr_ty_id, |
| ... | ... | @@ -3208,7 +3087,7 @@ const NavGen = struct { |
| 3208 | 3087 | |
| 3209 | 3088 | try self.spv.declareDeclDeps(spv_decl_index, &.{}); |
| 3210 | 3089 | |
| 3211 | | const ptr_ty_id = try self.ptrType(ty, .Function); |
| 3090 | const ptr_ty_id = try self.ptrType(ty, .Function, .indirect); |
| 3212 | 3091 | |
| 3213 | 3092 | if (maybe_init_val) |init_val| { |
| 3214 | 3093 | // TODO: Combine with resolveAnonDecl? |
| ... | ... | @@ -3265,8 +3144,8 @@ const NavGen = struct { |
| 3265 | 3144 | } |
| 3266 | 3145 | |
| 3267 | 3146 | fn intFromBool2(self: *NavGen, value: Temporary, result_ty: Type) !Temporary { |
| 3268 | | const zero_id = try self.constInt(result_ty, 0, .direct); |
| 3269 | | const one_id = try self.constInt(result_ty, 1, .direct); |
| 3147 | const zero_id = try self.constInt(result_ty, 0); |
| 3148 | const one_id = try self.constInt(result_ty, 1); |
| 3270 | 3149 | |
| 3271 | 3150 | return try self.buildSelect( |
| 3272 | 3151 | value, |
| ... | ... | @@ -3648,12 +3527,12 @@ const NavGen = struct { |
| 3648 | 3527 | .strange_integer => switch (info.signedness) { |
| 3649 | 3528 | .unsigned => { |
| 3650 | 3529 | const mask_value = if (info.bits == 64) 0xFFFF_FFFF_FFFF_FFFF else (@as(u64, 1) << @as(u6, @intCast(info.bits))) - 1; |
| 3651 | | const mask_id = try self.constInt(ty.scalarType(zcu), mask_value, .direct); |
| 3530 | const mask_id = try self.constInt(ty.scalarType(zcu), mask_value); |
| 3652 | 3531 | return try self.buildBinary(.bit_and, value, Temporary.init(ty.scalarType(zcu), mask_id)); |
| 3653 | 3532 | }, |
| 3654 | 3533 | .signed => { |
| 3655 | 3534 | // Shift left and right so that we can copy the sight bit that way. |
| 3656 | | const shift_amt_id = try self.constInt(ty.scalarType(zcu), info.backing_bits - info.bits, .direct); |
| 3535 | const shift_amt_id = try self.constInt(ty.scalarType(zcu), info.backing_bits - info.bits); |
| 3657 | 3536 | const shift_amt = Temporary.init(ty.scalarType(zcu), shift_amt_id); |
| 3658 | 3537 | const left = try self.buildBinary(.sll, value, shift_amt); |
| 3659 | 3538 | return try self.buildBinary(.sra, left, shift_amt); |
| ... | ... | @@ -3687,7 +3566,7 @@ const NavGen = struct { |
| 3687 | 3566 | const div = try self.buildBinary(.s_div, lhs, rhs); |
| 3688 | 3567 | const rem = try self.buildBinary(.s_rem, lhs, rhs); |
| 3689 | 3568 | |
| 3690 | | const zero = Temporary.init(lhs.ty, try self.constInt(lhs.ty, 0, .direct)); |
| 3569 | const zero = Temporary.init(lhs.ty, try self.constInt(lhs.ty, 0)); |
| 3691 | 3570 | |
| 3692 | 3571 | const rem_is_not_zero = try self.buildCmp(.i_ne, rem, zero); |
| 3693 | 3572 | |
| ... | ... | @@ -3863,7 +3742,7 @@ const NavGen = struct { |
| 3863 | 3742 | // = (rhs < 0) == (value < lhs) |
| 3864 | 3743 | // = (rhs < 0) == (lhs > value) |
| 3865 | 3744 | .signed => blk: { |
| 3866 | | const zero = Temporary.init(rhs.ty, try self.constInt(rhs.ty, 0, .direct)); |
| 3745 | const zero = Temporary.init(rhs.ty, try self.constInt(rhs.ty, 0)); |
| 3867 | 3746 | const rhs_lt_zero = try self.buildCmp(.s_lt, rhs, zero); |
| 3868 | 3747 | const result_gt_lhs = try self.buildCmp(scmp, lhs, result); |
| 3869 | 3748 | break :blk try self.buildCmp(.l_eq, rhs_lt_zero, result_gt_lhs); |
| ... | ... | @@ -3872,11 +3751,8 @@ const NavGen = struct { |
| 3872 | 3751 | |
| 3873 | 3752 | const ov = try self.intFromBool(overflowed); |
| 3874 | 3753 | |
| 3875 | | return try self.constructStruct( |
| 3876 | | result_ty, |
| 3877 | | &.{ result.ty, ov.ty }, |
| 3878 | | &.{ try result.materialize(self), try ov.materialize(self) }, |
| 3879 | | ); |
| 3754 | const result_ty_id = try self.resolveType(result_ty, .direct); |
| 3755 | return try self.constructComposite(result_ty_id, &.{ try result.materialize(self), try ov.materialize(self) }); |
| 3880 | 3756 | } |
| 3881 | 3757 | |
| 3882 | 3758 | fn airMulOverflow(self: *NavGen, inst: Air.Inst.Index) !?IdRef { |
| ... | ... | @@ -3928,11 +3804,11 @@ const NavGen = struct { |
| 3928 | 3804 | const result = try self.normalize(low_bits, info); |
| 3929 | 3805 | |
| 3930 | 3806 | // Shift the result bits away to get the overflow bits. |
| 3931 | | const shift = Temporary.init(full_result.ty, try self.constInt(full_result.ty, info.bits, .direct)); |
| 3807 | const shift = Temporary.init(full_result.ty, try self.constInt(full_result.ty, info.bits)); |
| 3932 | 3808 | const overflow = try self.buildBinary(.srl, full_result, shift); |
| 3933 | 3809 | |
| 3934 | 3810 | // Directly check if its zero in the op_ty without converting first. |
| 3935 | | const zero = Temporary.init(full_result.ty, try self.constInt(full_result.ty, 0, .direct)); |
| 3811 | const zero = Temporary.init(full_result.ty, try self.constInt(full_result.ty, 0)); |
| 3936 | 3812 | const overflowed = try self.buildCmp(.i_ne, zero, overflow); |
| 3937 | 3813 | |
| 3938 | 3814 | break :blk .{ result, overflowed }; |
| ... | ... | @@ -3946,7 +3822,7 @@ const NavGen = struct { |
| 3946 | 3822 | // Overflow happened if the high-bits of the result are non-zero OR if the |
| 3947 | 3823 | // high bits of the low word of the result (those outside the range of the |
| 3948 | 3824 | // int) are nonzero. |
| 3949 | | const zero = Temporary.init(lhs.ty, try self.constInt(lhs.ty, 0, .direct)); |
| 3825 | const zero = Temporary.init(lhs.ty, try self.constInt(lhs.ty, 0)); |
| 3950 | 3826 | const high_overflowed = try self.buildCmp(.i_ne, zero, high_bits); |
| 3951 | 3827 | |
| 3952 | 3828 | // If no overflow bits in low_bits, no extra work needs to be done. |
| ... | ... | @@ -3955,7 +3831,7 @@ const NavGen = struct { |
| 3955 | 3831 | } |
| 3956 | 3832 | |
| 3957 | 3833 | // Shift the result bits away to get the overflow bits. |
| 3958 | | const shift = Temporary.init(lhs.ty, try self.constInt(lhs.ty, info.bits, .direct)); |
| 3834 | const shift = Temporary.init(lhs.ty, try self.constInt(lhs.ty, info.bits)); |
| 3959 | 3835 | const low_overflow = try self.buildBinary(.srl, low_bits, shift); |
| 3960 | 3836 | const low_overflowed = try self.buildCmp(.i_ne, zero, low_overflow); |
| 3961 | 3837 | |
| ... | ... | @@ -3974,7 +3850,7 @@ const NavGen = struct { |
| 3974 | 3850 | // overflow should be -1 when |
| 3975 | 3851 | // (lhs > 0 && rhs < 0) || (lhs < 0 && rhs > 0) |
| 3976 | 3852 | |
| 3977 | | const zero = Temporary.init(lhs.ty, try self.constInt(lhs.ty, 0, .direct)); |
| 3853 | const zero = Temporary.init(lhs.ty, try self.constInt(lhs.ty, 0)); |
| 3978 | 3854 | const lhs_negative = try self.buildCmp(.s_lt, lhs, zero); |
| 3979 | 3855 | const rhs_negative = try self.buildCmp(.s_lt, rhs, zero); |
| 3980 | 3856 | const lhs_positive = try self.buildCmp(.s_gt, lhs, zero); |
| ... | ... | @@ -4003,13 +3879,13 @@ const NavGen = struct { |
| 4003 | 3879 | // bit for the expected overflow bits. |
| 4004 | 3880 | // To do that, shift out everything bit the sign bit and |
| 4005 | 3881 | // then check what remains. |
| 4006 | | const shift = Temporary.init(full_result.ty, try self.constInt(full_result.ty, info.bits - 1, .direct)); |
| 3882 | const shift = Temporary.init(full_result.ty, try self.constInt(full_result.ty, info.bits - 1)); |
| 4007 | 3883 | // Use SRA so that any sign bits are duplicated. Now we can just check if ALL bits are set |
| 4008 | 3884 | // for negative cases. |
| 4009 | 3885 | const overflow = try self.buildBinary(.sra, full_result, shift); |
| 4010 | 3886 | |
| 4011 | | const long_all_set = Temporary.init(full_result.ty, try self.constInt(full_result.ty, -1, .direct)); |
| 4012 | | const long_zero = Temporary.init(full_result.ty, try self.constInt(full_result.ty, 0, .direct)); |
| 3887 | const long_all_set = Temporary.init(full_result.ty, try self.constInt(full_result.ty, -1)); |
| 3888 | const long_zero = Temporary.init(full_result.ty, try self.constInt(full_result.ty, 0)); |
| 4013 | 3889 | const mask = try self.buildSelect(expected_overflow_bit, long_all_set, long_zero); |
| 4014 | 3890 | |
| 4015 | 3891 | const overflowed = try self.buildCmp(.i_ne, mask, overflow); |
| ... | ... | @@ -4022,7 +3898,7 @@ const NavGen = struct { |
| 4022 | 3898 | // Truncate result if required. |
| 4023 | 3899 | const result = try self.normalize(low_bits, info); |
| 4024 | 3900 | |
| 4025 | | const all_set = Temporary.init(lhs.ty, try self.constInt(lhs.ty, -1, .direct)); |
| 3901 | const all_set = Temporary.init(lhs.ty, try self.constInt(lhs.ty, -1)); |
| 4026 | 3902 | const mask = try self.buildSelect(expected_overflow_bit, all_set, zero); |
| 4027 | 3903 | |
| 4028 | 3904 | // Like with unsigned, overflow happened if high_bits are not the ones we expect, |
| ... | ... | @@ -4038,7 +3914,7 @@ const NavGen = struct { |
| 4038 | 3914 | } |
| 4039 | 3915 | |
| 4040 | 3916 | // Shift the result bits away to get the overflow bits. |
| 4041 | | const shift = Temporary.init(lhs.ty, try self.constInt(lhs.ty, info.bits - 1, .direct)); |
| 3917 | const shift = Temporary.init(lhs.ty, try self.constInt(lhs.ty, info.bits - 1)); |
| 4042 | 3918 | // Use SRA so that any sign bits are duplicated. Now we can just check if ALL bits are set |
| 4043 | 3919 | // for negative cases. |
| 4044 | 3920 | const low_overflow = try self.buildBinary(.sra, low_bits, shift); |
| ... | ... | @@ -4052,11 +3928,8 @@ const NavGen = struct { |
| 4052 | 3928 | |
| 4053 | 3929 | const ov = try self.intFromBool(overflowed); |
| 4054 | 3930 | |
| 4055 | | return try self.constructStruct( |
| 4056 | | result_ty, |
| 4057 | | &.{ result.ty, ov.ty }, |
| 4058 | | &.{ try result.materialize(self), try ov.materialize(self) }, |
| 4059 | | ); |
| 3931 | const result_ty_id = try self.resolveType(result_ty, .direct); |
| 3932 | return try self.constructComposite(result_ty_id, &.{ try result.materialize(self), try ov.materialize(self) }); |
| 4060 | 3933 | } |
| 4061 | 3934 | |
| 4062 | 3935 | fn airShlOverflow(self: *NavGen, inst: Air.Inst.Index) !?IdRef { |
| ... | ... | @@ -4092,11 +3965,8 @@ const NavGen = struct { |
| 4092 | 3965 | const overflowed = try self.buildCmp(.i_ne, base, right); |
| 4093 | 3966 | const ov = try self.intFromBool(overflowed); |
| 4094 | 3967 | |
| 4095 | | return try self.constructStruct( |
| 4096 | | result_ty, |
| 4097 | | &.{ result.ty, ov.ty }, |
| 4098 | | &.{ try result.materialize(self), try ov.materialize(self) }, |
| 4099 | | ); |
| 3968 | const result_ty_id = try self.resolveType(result_ty, .direct); |
| 3969 | return try self.constructComposite(result_ty_id, &.{ try result.materialize(self), try ov.materialize(self) }); |
| 4100 | 3970 | } |
| 4101 | 3971 | |
| 4102 | 3972 | fn airMulAdd(self: *NavGen, inst: Air.Inst.Index) !?IdRef { |
| ... | ... | @@ -4163,7 +4033,7 @@ const NavGen = struct { |
| 4163 | 4033 | const operand_id = try self.resolve(ty_op.operand); |
| 4164 | 4034 | const result_ty = self.typeOfIndex(inst); |
| 4165 | 4035 | |
| 4166 | | return try self.constructVectorSplat(result_ty, operand_id); |
| 4036 | return try self.constructCompositeSplat(result_ty, operand_id); |
| 4167 | 4037 | } |
| 4168 | 4038 | |
| 4169 | 4039 | fn airReduce(self: *NavGen, inst: Air.Inst.Index) !?IdRef { |
| ... | ... | @@ -4297,10 +4167,10 @@ const NavGen = struct { |
| 4297 | 4167 | |
| 4298 | 4168 | // Fall back to manually extracting and inserting components. |
| 4299 | 4169 | |
| 4300 | | const components = try self.gpa.alloc(IdRef, result_ty.vectorLen(zcu)); |
| 4301 | | defer self.gpa.free(components); |
| 4170 | const constituents = try self.gpa.alloc(IdRef, result_ty.vectorLen(zcu)); |
| 4171 | defer self.gpa.free(constituents); |
| 4302 | 4172 | |
| 4303 | | for (components, 0..) |*id, i| { |
| 4173 | for (constituents, 0..) |*id, i| { |
| 4304 | 4174 | const elem = try mask.elemValue(pt, i); |
| 4305 | 4175 | if (elem.isUndef(zcu)) { |
| 4306 | 4176 | id.* = try self.spv.constUndef(scalar_ty_id); |
| ... | ... | @@ -4315,14 +4185,15 @@ const NavGen = struct { |
| 4315 | 4185 | } |
| 4316 | 4186 | } |
| 4317 | 4187 | |
| 4318 | | return try self.constructVector(result_ty, components); |
| 4188 | const result_ty_id = try self.resolveType(result_ty, .direct); |
| 4189 | return try self.constructComposite(result_ty_id, constituents); |
| 4319 | 4190 | } |
| 4320 | 4191 | |
| 4321 | 4192 | fn indicesToIds(self: *NavGen, indices: []const u32) ![]IdRef { |
| 4322 | 4193 | const ids = try self.gpa.alloc(IdRef, indices.len); |
| 4323 | 4194 | errdefer self.gpa.free(ids); |
| 4324 | 4195 | for (indices, ids) |index, *id| { |
| 4325 | | id.* = try self.constInt(Type.u32, index, .direct); |
| 4196 | id.* = try self.constInt(Type.u32, index); |
| 4326 | 4197 | } |
| 4327 | 4198 | |
| 4328 | 4199 | return ids; |
| ... | ... | @@ -4676,7 +4547,7 @@ const NavGen = struct { |
| 4676 | 4547 | break :blk result_id; |
| 4677 | 4548 | } |
| 4678 | 4549 | |
| 4679 | | const dst_ptr_ty_id = try self.ptrType(dst_ty, .Function); |
| 4550 | const dst_ptr_ty_id = try self.ptrType(dst_ty, .Function, .indirect); |
| 4680 | 4551 | |
| 4681 | 4552 | const tmp_id = try self.alloc(src_ty, .{ .storage_class = .Function }); |
| 4682 | 4553 | try self.store(src_ty, tmp_id, src_id, .{}); |
| ... | ... | @@ -4851,7 +4722,7 @@ const NavGen = struct { |
| 4851 | 4722 | const elem_ptr_ty_id = try self.resolveType(elem_ptr_ty, .direct); |
| 4852 | 4723 | |
| 4853 | 4724 | const array_ptr_id = try self.resolve(ty_op.operand); |
| 4854 | | const len_id = try self.constInt(Type.usize, array_ty.arrayLen(zcu), .direct); |
| 4725 | const len_id = try self.constInt(Type.usize, array_ty.arrayLen(zcu)); |
| 4855 | 4726 | |
| 4856 | 4727 | const elem_ptr_id = if (!array_ty.hasRuntimeBitsIgnoreComptime(zcu)) |
| 4857 | 4728 | // Note: The pointer is something like *opaque{}, so we need to bitcast it to the element type. |
| ... | ... | @@ -4860,11 +4731,8 @@ const NavGen = struct { |
| 4860 | 4731 | // Convert the pointer-to-array to a pointer to the first element. |
| 4861 | 4732 | try self.accessChain(elem_ptr_ty_id, array_ptr_id, &.{0}); |
| 4862 | 4733 | |
| 4863 | | return try self.constructStruct( |
| 4864 | | slice_ty, |
| 4865 | | &.{ elem_ptr_ty, Type.usize }, |
| 4866 | | &.{ elem_ptr_id, len_id }, |
| 4867 | | ); |
| 4734 | const slice_ty_id = try self.resolveType(slice_ty, .direct); |
| 4735 | return try self.constructComposite(slice_ty_id, &.{ elem_ptr_id, len_id }); |
| 4868 | 4736 | } |
| 4869 | 4737 | |
| 4870 | 4738 | fn airSlice(self: *NavGen, inst: Air.Inst.Index) !?IdRef { |
| ... | ... | @@ -4872,16 +4740,9 @@ const NavGen = struct { |
| 4872 | 4740 | const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data; |
| 4873 | 4741 | const ptr_id = try self.resolve(bin_op.lhs); |
| 4874 | 4742 | const len_id = try self.resolve(bin_op.rhs); |
| 4875 | | const ptr_ty = self.typeOf(bin_op.lhs); |
| 4876 | 4743 | const slice_ty = self.typeOfIndex(inst); |
| 4877 | | |
| 4878 | | // Note: Types should not need to be converted to direct, these types |
| 4879 | | // dont need to be converted. |
| 4880 | | return try self.constructStruct( |
| 4881 | | slice_ty, |
| 4882 | | &.{ ptr_ty, Type.usize }, |
| 4883 | | &.{ ptr_id, len_id }, |
| 4884 | | ); |
| 4744 | const slice_ty_id = try self.resolveType(slice_ty, .direct); |
| 4745 | return try self.constructComposite(slice_ty_id, &.{ ptr_id, len_id }); |
| 4885 | 4746 | } |
| 4886 | 4747 | |
| 4887 | 4748 | fn airAggregateInit(self: *NavGen, inst: Air.Inst.Index) !?IdRef { |
| ... | ... | @@ -4936,11 +4797,8 @@ const NavGen = struct { |
| 4936 | 4797 | else => unreachable, |
| 4937 | 4798 | } |
| 4938 | 4799 | |
| 4939 | | return try self.constructStruct( |
| 4940 | | result_ty, |
| 4941 | | types[0..index], |
| 4942 | | constituents[0..index], |
| 4943 | | ); |
| 4800 | const result_ty_id = try self.resolveType(result_ty, .direct); |
| 4801 | return try self.constructComposite(result_ty_id, constituents[0..index]); |
| 4944 | 4802 | }, |
| 4945 | 4803 | .vector => { |
| 4946 | 4804 | const n_elems = result_ty.vectorLen(zcu); |
| ... | ... | @@ -4951,7 +4809,8 @@ const NavGen = struct { |
| 4951 | 4809 | elem_ids[i] = try self.resolve(element); |
| 4952 | 4810 | } |
| 4953 | 4811 | |
| 4954 | | return try self.constructVector(result_ty, elem_ids); |
| 4812 | const result_ty_id = try self.resolveType(result_ty, .direct); |
| 4813 | return try self.constructComposite(result_ty_id, elem_ids); |
| 4955 | 4814 | }, |
| 4956 | 4815 | .array => { |
| 4957 | 4816 | const array_info = result_ty.arrayInfo(zcu); |
| ... | ... | @@ -4968,7 +4827,8 @@ const NavGen = struct { |
| 4968 | 4827 | elem_ids[n_elems - 1] = try self.constant(array_info.elem_type, sentinel_val, .indirect); |
| 4969 | 4828 | } |
| 4970 | 4829 | |
| 4971 | | return try self.constructArray(result_ty, elem_ids); |
| 4830 | const result_ty_id = try self.resolveType(result_ty, .direct); |
| 4831 | return try self.constructComposite(result_ty_id, elem_ids); |
| 4972 | 4832 | }, |
| 4973 | 4833 | else => unreachable, |
| 4974 | 4834 | } |
| ... | ... | @@ -4984,7 +4844,7 @@ const NavGen = struct { |
| 4984 | 4844 | const elem_ty = array_ty.childType(zcu); |
| 4985 | 4845 | const abi_size = elem_ty.abiSize(zcu); |
| 4986 | 4846 | const size = array_ty.arrayLenIncludingSentinel(zcu) * abi_size; |
| 4987 | | return try self.constInt(Type.usize, size, .direct); |
| 4847 | return try self.constInt(Type.usize, size); |
| 4988 | 4848 | }, |
| 4989 | 4849 | .many, .c => unreachable, |
| 4990 | 4850 | } |
| ... | ... | @@ -5060,7 +4920,7 @@ const NavGen = struct { |
| 5060 | 4920 | const zcu = self.pt.zcu; |
| 5061 | 4921 | // Construct new pointer type for the resulting pointer |
| 5062 | 4922 | const elem_ty = ptr_ty.elemType2(zcu); // use elemType() so that we get T for *[N]T. |
| 5063 | | const elem_ptr_ty_id = try self.ptrType(elem_ty, self.spvStorageClass(ptr_ty.ptrAddressSpace(zcu))); |
| 4923 | const elem_ptr_ty_id = try self.ptrType(elem_ty, self.spvStorageClass(ptr_ty.ptrAddressSpace(zcu)), .indirect); |
| 5064 | 4924 | if (ptr_ty.isSinglePointer(zcu)) { |
| 5065 | 4925 | // Pointer-to-array. In this case, the resulting pointer is not of the same type |
| 5066 | 4926 | // as the ptr_ty (we want a *T, not a *[N]T), and hence we need to use accessChain. |
| ... | ... | @@ -5115,8 +4975,8 @@ const NavGen = struct { |
| 5115 | 4975 | const is_vector = array_ty.isVector(zcu); |
| 5116 | 4976 | |
| 5117 | 4977 | const elem_repr: Repr = if (is_vector) .direct else .indirect; |
| 5118 | | const ptr_array_ty_id = try self.ptrType2(array_ty, .Function, .direct); |
| 5119 | | const ptr_elem_ty_id = try self.ptrType2(elem_ty, .Function, elem_repr); |
| 4978 | const ptr_array_ty_id = try self.ptrType(array_ty, .Function, .direct); |
| 4979 | const ptr_elem_ty_id = try self.ptrType(elem_ty, .Function, elem_repr); |
| 5120 | 4980 | |
| 5121 | 4981 | const tmp_id = self.spv.allocId(); |
| 5122 | 4982 | try self.func.prologue.emit(self.spv.gpa, .OpVariable, .{ |
| ... | ... | @@ -5171,7 +5031,7 @@ const NavGen = struct { |
| 5171 | 5031 | const scalar_ty = vector_ty.scalarType(zcu); |
| 5172 | 5032 | |
| 5173 | 5033 | const storage_class = self.spvStorageClass(vector_ptr_ty.ptrAddressSpace(zcu)); |
| 5174 | | const scalar_ptr_ty_id = try self.ptrType(scalar_ty, storage_class); |
| 5034 | const scalar_ptr_ty_id = try self.ptrType(scalar_ty, storage_class, .indirect); |
| 5175 | 5035 | |
| 5176 | 5036 | const vector_ptr = try self.resolve(data.vector_ptr); |
| 5177 | 5037 | const index = try self.resolve(extra.lhs); |
| ... | ... | @@ -5193,7 +5053,7 @@ const NavGen = struct { |
| 5193 | 5053 | if (layout.tag_size == 0) return; |
| 5194 | 5054 | |
| 5195 | 5055 | const tag_ty = un_ty.unionTagTypeSafety(zcu).?; |
| 5196 | | const tag_ptr_ty_id = try self.ptrType(tag_ty, self.spvStorageClass(un_ptr_ty.ptrAddressSpace(zcu))); |
| 5056 | const tag_ptr_ty_id = try self.ptrType(tag_ty, self.spvStorageClass(un_ptr_ty.ptrAddressSpace(zcu)), .indirect); |
| 5197 | 5057 | |
| 5198 | 5058 | const union_ptr_id = try self.resolve(bin_op.lhs); |
| 5199 | 5059 | const new_tag_id = try self.resolve(bin_op.rhs); |
| ... | ... | @@ -5252,23 +5112,23 @@ const NavGen = struct { |
| 5252 | 5112 | } else 0; |
| 5253 | 5113 | |
| 5254 | 5114 | if (!layout.has_payload) { |
| 5255 | | return try self.constInt(tag_ty, tag_int, .direct); |
| 5115 | return try self.constInt(tag_ty, tag_int); |
| 5256 | 5116 | } |
| 5257 | 5117 | |
| 5258 | 5118 | const tmp_id = try self.alloc(ty, .{ .storage_class = .Function }); |
| 5259 | 5119 | |
| 5260 | 5120 | if (layout.tag_size != 0) { |
| 5261 | | const tag_ptr_ty_id = try self.ptrType(tag_ty, .Function); |
| 5121 | const tag_ptr_ty_id = try self.ptrType(tag_ty, .Function, .indirect); |
| 5262 | 5122 | const ptr_id = try self.accessChain(tag_ptr_ty_id, tmp_id, &.{@as(u32, @intCast(layout.tag_index))}); |
| 5263 | | const tag_id = try self.constInt(tag_ty, tag_int, .direct); |
| 5123 | const tag_id = try self.constInt(tag_ty, tag_int); |
| 5264 | 5124 | try self.store(tag_ty, ptr_id, tag_id, .{}); |
| 5265 | 5125 | } |
| 5266 | 5126 | |
| 5267 | 5127 | const payload_ty = Type.fromInterned(union_ty.field_types.get(ip)[active_field]); |
| 5268 | 5128 | if (payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { |
| 5269 | | const pl_ptr_ty_id = try self.ptrType(layout.payload_ty, .Function); |
| 5129 | const pl_ptr_ty_id = try self.ptrType(layout.payload_ty, .Function, .indirect); |
| 5270 | 5130 | const pl_ptr_id = try self.accessChain(pl_ptr_ty_id, tmp_id, &.{layout.payload_index}); |
| 5271 | | const active_pl_ptr_ty_id = try self.ptrType(payload_ty, .Function); |
| 5131 | const active_pl_ptr_ty_id = try self.ptrType(payload_ty, .Function, .indirect); |
| 5272 | 5132 | const active_pl_ptr_id = self.spv.allocId(); |
| 5273 | 5133 | try self.func.body.emit(self.spv.gpa, .OpBitcast, .{ |
| 5274 | 5134 | .id_result_type = active_pl_ptr_ty_id, |
| ... | ... | @@ -5332,10 +5192,10 @@ const NavGen = struct { |
| 5332 | 5192 | const tmp_id = try self.alloc(object_ty, .{ .storage_class = .Function }); |
| 5333 | 5193 | try self.store(object_ty, tmp_id, object_id, .{}); |
| 5334 | 5194 | |
| 5335 | | const pl_ptr_ty_id = try self.ptrType(layout.payload_ty, .Function); |
| 5195 | const pl_ptr_ty_id = try self.ptrType(layout.payload_ty, .Function, .indirect); |
| 5336 | 5196 | const pl_ptr_id = try self.accessChain(pl_ptr_ty_id, tmp_id, &.{layout.payload_index}); |
| 5337 | 5197 | |
| 5338 | | const active_pl_ptr_ty_id = try self.ptrType(field_ty, .Function); |
| 5198 | const active_pl_ptr_ty_id = try self.ptrType(field_ty, .Function, .indirect); |
| 5339 | 5199 | const active_pl_ptr_id = self.spv.allocId(); |
| 5340 | 5200 | try self.func.body.emit(self.spv.gpa, .OpBitcast, .{ |
| 5341 | 5201 | .id_result_type = active_pl_ptr_ty_id, |
| ... | ... | @@ -5365,7 +5225,7 @@ const NavGen = struct { |
| 5365 | 5225 | const base_ptr_int = base_ptr_int: { |
| 5366 | 5226 | if (field_offset == 0) break :base_ptr_int field_ptr_int; |
| 5367 | 5227 | |
| 5368 | | const field_offset_id = try self.constInt(Type.usize, field_offset, .direct); |
| 5228 | const field_offset_id = try self.constInt(Type.usize, field_offset); |
| 5369 | 5229 | const field_ptr_tmp = Temporary.init(Type.usize, field_ptr_int); |
| 5370 | 5230 | const field_offset_tmp = Temporary.init(Type.usize, field_offset_id); |
| 5371 | 5231 | const result = try self.buildBinary(.i_sub, field_ptr_tmp, field_offset_tmp); |
| ... | ... | @@ -5415,7 +5275,7 @@ const NavGen = struct { |
| 5415 | 5275 | } |
| 5416 | 5276 | |
| 5417 | 5277 | const storage_class = self.spvStorageClass(object_ptr_ty.ptrAddressSpace(zcu)); |
| 5418 | | const pl_ptr_ty_id = try self.ptrType(layout.payload_ty, storage_class); |
| 5278 | const pl_ptr_ty_id = try self.ptrType(layout.payload_ty, storage_class, .indirect); |
| 5419 | 5279 | const pl_ptr_id = try self.accessChain(pl_ptr_ty_id, object_ptr, &.{layout.payload_index}); |
| 5420 | 5280 | |
| 5421 | 5281 | const active_pl_ptr_id = self.spv.allocId(); |
| ... | ... | @@ -5456,7 +5316,7 @@ const NavGen = struct { |
| 5456 | 5316 | ty: Type, |
| 5457 | 5317 | options: AllocOptions, |
| 5458 | 5318 | ) !IdRef { |
| 5459 | | const ptr_fn_ty_id = try self.ptrType(ty, .Function); |
| 5319 | const ptr_fn_ty_id = try self.ptrType(ty, .Function, .indirect); |
| 5460 | 5320 | |
| 5461 | 5321 | // SPIR-V requires that OpVariable declarations for locals go into the first block, so we are just going to |
| 5462 | 5322 | // directly generate them into func.prologue instead of the body. |
| ... | ... | @@ -5475,7 +5335,7 @@ const NavGen = struct { |
| 5475 | 5335 | |
| 5476 | 5336 | switch (options.storage_class) { |
| 5477 | 5337 | .Generic => { |
| 5478 | | const ptr_gn_ty_id = try self.ptrType(ty, .Generic); |
| 5338 | const ptr_gn_ty_id = try self.ptrType(ty, .Generic, .indirect); |
| 5479 | 5339 | // Convert to a generic pointer |
| 5480 | 5340 | return self.castToGeneric(ptr_gn_ty_id, var_id); |
| 5481 | 5341 | }, |
| ... | ... | @@ -5724,7 +5584,7 @@ const NavGen = struct { |
| 5724 | 5584 | assert(cf.block_stack.items.len > 0); |
| 5725 | 5585 | |
| 5726 | 5586 | // Check if the target of the branch was this current block. |
| 5727 | | const this_block = try self.constInt(Type.u32, @intFromEnum(inst), .direct); |
| 5587 | const this_block = try self.constInt(Type.u32, @intFromEnum(inst)); |
| 5728 | 5588 | const jump_to_this_block_id = self.spv.allocId(); |
| 5729 | 5589 | const bool_ty_id = try self.resolveType(Type.bool, .direct); |
| 5730 | 5590 | try self.func.body.emit(self.spv.gpa, .OpIEqual, .{ |
| ... | ... | @@ -5804,7 +5664,7 @@ const NavGen = struct { |
| 5804 | 5664 | try self.store(operand_ty, block_result_var_id, operand_id, .{}); |
| 5805 | 5665 | } |
| 5806 | 5666 | |
| 5807 | | const next_block = try self.constInt(Type.u32, @intFromEnum(br.block_inst), .direct); |
| 5667 | const next_block = try self.constInt(Type.u32, @intFromEnum(br.block_inst)); |
| 5808 | 5668 | try self.structuredBreak(next_block); |
| 5809 | 5669 | }, |
| 5810 | 5670 | .unstructured => |cf| { |
| ... | ... | @@ -5968,7 +5828,7 @@ const NavGen = struct { |
| 5968 | 5828 | // Functions with an empty error set are emitted with an error code |
| 5969 | 5829 | // return type and return zero so they can be function pointers coerced |
| 5970 | 5830 | // to functions that return anyerror. |
| 5971 | | const no_err_id = try self.constInt(Type.anyerror, 0, .direct); |
| 5831 | const no_err_id = try self.constInt(Type.anyerror, 0); |
| 5972 | 5832 | return try self.func.body.emit(self.spv.gpa, .OpReturnValue, .{ .value = no_err_id }); |
| 5973 | 5833 | } else { |
| 5974 | 5834 | return try self.func.body.emit(self.spv.gpa, .OpReturn, {}); |
| ... | ... | @@ -5992,7 +5852,7 @@ const NavGen = struct { |
| 5992 | 5852 | // Functions with an empty error set are emitted with an error code |
| 5993 | 5853 | // return type and return zero so they can be function pointers coerced |
| 5994 | 5854 | // to functions that return anyerror. |
| 5995 | | const no_err_id = try self.constInt(Type.anyerror, 0, .direct); |
| 5855 | const no_err_id = try self.constInt(Type.anyerror, 0); |
| 5996 | 5856 | return try self.func.body.emit(self.spv.gpa, .OpReturnValue, .{ .value = no_err_id }); |
| 5997 | 5857 | } else { |
| 5998 | 5858 | return try self.func.body.emit(self.spv.gpa, .OpReturn, {}); |
| ... | ... | @@ -6026,7 +5886,7 @@ const NavGen = struct { |
| 6026 | 5886 | else |
| 6027 | 5887 | err_union_id; |
| 6028 | 5888 | |
| 6029 | | const zero_id = try self.constInt(Type.anyerror, 0, .direct); |
| 5889 | const zero_id = try self.constInt(Type.anyerror, 0); |
| 6030 | 5890 | const is_err_id = self.spv.allocId(); |
| 6031 | 5891 | try self.func.body.emit(self.spv.gpa, .OpINotEqual, .{ |
| 6032 | 5892 | .id_result_type = bool_ty_id, |
| ... | ... | @@ -6134,7 +5994,8 @@ const NavGen = struct { |
| 6134 | 5994 | types[eu_layout.errorFieldIndex()] = Type.anyerror; |
| 6135 | 5995 | types[eu_layout.payloadFieldIndex()] = payload_ty; |
| 6136 | 5996 | |
| 6137 | | return try self.constructStruct(err_union_ty, &types, &members); |
| 5997 | const err_union_ty_id = try self.resolveType(err_union_ty, .direct); |
| 5998 | return try self.constructComposite(err_union_ty_id, &members); |
| 6138 | 5999 | } |
| 6139 | 6000 | |
| 6140 | 6001 | fn airWrapErrUnionPayload(self: *NavGen, inst: Air.Inst.Index) !?IdRef { |
| ... | ... | @@ -6145,18 +6006,19 @@ const NavGen = struct { |
| 6145 | 6006 | const eu_layout = self.errorUnionLayout(payload_ty); |
| 6146 | 6007 | |
| 6147 | 6008 | if (!eu_layout.payload_has_bits) { |
| 6148 | | return try self.constInt(Type.anyerror, 0, .direct); |
| 6009 | return try self.constInt(Type.anyerror, 0); |
| 6149 | 6010 | } |
| 6150 | 6011 | |
| 6151 | 6012 | var members: [2]IdRef = undefined; |
| 6152 | | members[eu_layout.errorFieldIndex()] = try self.constInt(Type.anyerror, 0, .direct); |
| 6013 | members[eu_layout.errorFieldIndex()] = try self.constInt(Type.anyerror, 0); |
| 6153 | 6014 | members[eu_layout.payloadFieldIndex()] = try self.convertToIndirect(payload_ty, operand_id); |
| 6154 | 6015 | |
| 6155 | 6016 | var types: [2]Type = undefined; |
| 6156 | 6017 | types[eu_layout.errorFieldIndex()] = Type.anyerror; |
| 6157 | 6018 | types[eu_layout.payloadFieldIndex()] = payload_ty; |
| 6158 | 6019 | |
| 6159 | | return try self.constructStruct(err_union_ty, &types, &members); |
| 6020 | const err_union_ty_id = try self.resolveType(err_union_ty, .direct); |
| 6021 | return try self.constructComposite(err_union_ty_id, &members); |
| 6160 | 6022 | } |
| 6161 | 6023 | |
| 6162 | 6024 | fn airIsNull(self: *NavGen, inst: Air.Inst.Index, is_pointer: bool, pred: enum { is_null, is_non_null }) !?IdRef { |
| ... | ... | @@ -6204,7 +6066,7 @@ const NavGen = struct { |
| 6204 | 6066 | if (is_pointer) { |
| 6205 | 6067 | if (payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { |
| 6206 | 6068 | const storage_class = self.spvStorageClass(operand_ty.ptrAddressSpace(zcu)); |
| 6207 | | const bool_ptr_ty_id = try self.ptrType(Type.bool, storage_class); |
| 6069 | const bool_ptr_ty_id = try self.ptrType(Type.bool, storage_class, .indirect); |
| 6208 | 6070 | const tag_ptr_id = try self.accessChain(bool_ptr_ty_id, operand_id, &.{1}); |
| 6209 | 6071 | break :blk try self.load(Type.bool, tag_ptr_id, .{}); |
| 6210 | 6072 | } |
| ... | ... | @@ -6267,7 +6129,7 @@ const NavGen = struct { |
| 6267 | 6129 | .id_result_type = bool_ty_id, |
| 6268 | 6130 | .id_result = result_id, |
| 6269 | 6131 | .operand_1 = error_id, |
| 6270 | | .operand_2 = try self.constInt(Type.anyerror, 0, .direct), |
| 6132 | .operand_2 = try self.constInt(Type.anyerror, 0), |
| 6271 | 6133 | }, |
| 6272 | 6134 | ), |
| 6273 | 6135 | } |
| ... | ... | @@ -6335,8 +6197,8 @@ const NavGen = struct { |
| 6335 | 6197 | |
| 6336 | 6198 | const payload_id = try self.convertToIndirect(payload_ty, operand_id); |
| 6337 | 6199 | const members = [_]IdRef{ payload_id, try self.constBool(true, .indirect) }; |
| 6338 | | const types = [_]Type{ payload_ty, Type.bool }; |
| 6339 | | return try self.constructStruct(optional_ty, &types, &members); |
| 6200 | const optional_ty_id = try self.resolveType(optional_ty, .direct); |
| 6201 | return try self.constructComposite(optional_ty_id, &members); |
| 6340 | 6202 | } |
| 6341 | 6203 | |
| 6342 | 6204 | fn airSwitchBr(self: *NavGen, inst: Air.Inst.Index) !void { |
| ... | ... | @@ -6752,13 +6614,13 @@ const NavGen = struct { |
| 6752 | 6614 | |
| 6753 | 6615 | fn builtin3D(self: *NavGen, result_ty: Type, builtin: spec.BuiltIn, dimension: u32, out_of_range_value: anytype) !IdRef { |
| 6754 | 6616 | if (dimension >= 3) { |
| 6755 | | return try self.constInt(result_ty, out_of_range_value, .direct); |
| 6617 | return try self.constInt(result_ty, out_of_range_value); |
| 6756 | 6618 | } |
| 6757 | 6619 | const vec_ty = try self.pt.vectorType(.{ |
| 6758 | 6620 | .len = 3, |
| 6759 | 6621 | .child = result_ty.toIntern(), |
| 6760 | 6622 | }); |
| 6761 | | const ptr_ty_id = try self.ptrType(vec_ty, .Input); |
| 6623 | const ptr_ty_id = try self.ptrType(vec_ty, .Input, .indirect); |
| 6762 | 6624 | const spv_decl_index = try self.spv.builtin(ptr_ty_id, builtin); |
| 6763 | 6625 | try self.func.decl_deps.put(self.spv.gpa, spv_decl_index, {}); |
| 6764 | 6626 | const ptr = self.spv.declPtr(spv_decl_index).result_id; |