| ... | @@ -159,7 +159,7 @@ pub const Object = struct { | ... | @@ -159,7 +159,7 @@ pub const Object = struct { |
| 159 | uav_link: std.AutoHashMapUnmanaged(struct { InternPool.Index, StorageClass }, SpvModule.Decl.Index) = .empty, | 159 | uav_link: std.AutoHashMapUnmanaged(struct { InternPool.Index, StorageClass }, SpvModule.Decl.Index) = .empty, |
| 160 | | 160 | |
| 161 | /// A map that maps AIR intern pool indices to SPIR-V result-ids. | 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 | /// This map serves a dual purpose: | 164 | /// This map serves a dual purpose: |
| 165 | /// - It keeps track of pointers that are currently being emitted, so that we can tell | 165 | /// - It keeps track of pointers that are currently being emitted, so that we can tell |
| ... | @@ -314,7 +314,7 @@ const NavGen = struct { | ... | @@ -314,7 +314,7 @@ const NavGen = struct { |
| 314 | next_arg_index: u32 = 0, | 314 | next_arg_index: u32 = 0, |
| 315 | | 315 | |
| 316 | /// A map keeping track of which instruction generated which result-id. | 316 | /// A map keeping track of which instruction generated which result-id. |
| 317 | inst_results: InstMap = .{}, | 317 | inst_results: InstMap = .empty, |
| 318 | | 318 | |
| 319 | /// A map that maps AIR intern pool indices to SPIR-V result-ids. | 319 | /// A map that maps AIR intern pool indices to SPIR-V result-ids. |
| 320 | /// See `Object.intern_map`. | 320 | /// See `Object.intern_map`. |
| ... | @@ -469,7 +469,7 @@ const NavGen = struct { | ... | @@ -469,7 +469,7 @@ const NavGen = struct { |
| 469 | | 469 | |
| 470 | const zcu = self.pt.zcu; | 470 | const zcu = self.pt.zcu; |
| 471 | const ty = Type.fromInterned(zcu.intern_pool.typeOf(val)); | 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 | const spv_decl_index = blk: { | 474 | const spv_decl_index = blk: { |
| 475 | const entry = try self.object.uav_link.getOrPut(self.object.gpa, .{ val, .Function }); | 475 | const entry = try self.object.uav_link.getOrPut(self.object.gpa, .{ val, .Function }); |
| ... | @@ -532,7 +532,7 @@ const NavGen = struct { | ... | @@ -532,7 +532,7 @@ const NavGen = struct { |
| 532 | | 532 | |
| 533 | try self.spv.debugNameFmt(initializer_id, "initializer of __anon_{d}", .{@intFromEnum(val)}); | 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 | try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpExtInst, .{ | 536 | try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpExtInst, .{ |
| 537 | .id_result_type = fn_decl_ptr_ty_id, | 537 | .id_result_type = fn_decl_ptr_ty_id, |
| 538 | .id_result = result_id, | 538 | .id_result = result_id, |
| ... | @@ -721,36 +721,16 @@ const NavGen = struct { | ... | @@ -721,36 +721,16 @@ const NavGen = struct { |
| 721 | | 721 | |
| 722 | /// Emits a bool constant in a particular representation. | 722 | /// Emits a bool constant in a particular representation. |
| 723 | fn constBool(self: *NavGen, value: bool, repr: Repr) !IdRef { | 723 | fn constBool(self: *NavGen, value: bool, repr: Repr) !IdRef { |
| 724 | // TODO: Cache? | 724 | return switch (repr) { |
| 725 | | 725 | .indirect => self.constInt(Type.u1, @intFromBool(value)), |
| 726 | const section = &self.spv.sections.types_globals_constants; | 726 | .direct => self.spv.constBool(value), |
| 727 | switch (repr) { | 727 | }; |
| 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 | } | | |
| 747 | } | 728 | } |
| 748 | | 729 | |
| 749 | /// Emits an integer constant. | 730 | /// Emits an integer constant. |
| 750 | /// This function, unlike SpvModule.constInt, takes care to bitcast | 731 | /// This function, unlike SpvModule.constInt, takes care to bitcast |
| 751 | /// the value to an unsigned int first for Kernels. | 732 | /// the value to an unsigned int first for Kernels. |
| 752 | fn constInt(self: *NavGen, ty: Type, value: anytype, repr: Repr) !IdRef { | 733 | fn constInt(self: *NavGen, ty: Type, value: anytype) !IdRef { |
| 753 | // TODO: Cache? | | |
| 754 | const zcu = self.pt.zcu; | 734 | const zcu = self.pt.zcu; |
| 755 | const scalar_ty = ty.scalarType(zcu); | 735 | const scalar_ty = ty.scalarType(zcu); |
| 756 | const int_info = scalar_ty.intInfo(zcu); | 736 | const int_info = scalar_ty.intInfo(zcu); |
| ... | @@ -763,18 +743,18 @@ const NavGen = struct { | ... | @@ -763,18 +743,18 @@ const NavGen = struct { |
| 763 | else => unreachable, | 743 | else => unreachable, |
| 764 | }; | 744 | }; |
| 765 | | 745 | |
| 766 | const bits: u64 = switch (signedness) { | 746 | const value64: u64 = switch (signedness) { |
| 767 | .signed => @bitCast(@as(i64, @intCast(value))), | 747 | .signed => @bitCast(@as(i64, @intCast(value))), |
| 768 | .unsigned => @as(u64, @intCast(value)), | 748 | .unsigned => @as(u64, @intCast(value)), |
| 769 | }; | 749 | }; |
| 770 | | 750 | |
| 771 | // Manually truncate the value to the right amount of bits. | 751 | // Manually truncate the value to the right amount of bits. |
| 772 | const truncated_bits = if (backing_bits == 64) | 752 | const truncated_value = if (backing_bits == 64) |
| 773 | bits | 753 | value64 |
| 774 | else | 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 | const result_id = self.spv.allocId(); | 758 | const result_id = self.spv.allocId(); |
| 779 | | 759 | |
| 780 | const section = &self.spv.sections.types_globals_constants; | 760 | const section = &self.spv.sections.types_globals_constants; |
| ... | @@ -783,100 +763,42 @@ const NavGen = struct { | ... | @@ -783,100 +763,42 @@ const NavGen = struct { |
| 783 | 1...32 => try section.emit(self.spv.gpa, .OpConstant, .{ | 763 | 1...32 => try section.emit(self.spv.gpa, .OpConstant, .{ |
| 784 | .id_result_type = result_ty_id, | 764 | .id_result_type = result_ty_id, |
| 785 | .id_result = result_id, | 765 | .id_result = result_id, |
| 786 | .value = .{ .uint32 = @truncate(truncated_bits) }, | 766 | .value = .{ .uint32 = @truncate(truncated_value) }, |
| 787 | }), | 767 | }), |
| 788 | 33...64 => try section.emit(self.spv.gpa, .OpConstant, .{ | 768 | 33...64 => try section.emit(self.spv.gpa, .OpConstant, .{ |
| 789 | .id_result_type = result_ty_id, | 769 | .id_result_type = result_ty_id, |
| 790 | .id_result = result_id, | 770 | .id_result = result_id, |
| 791 | .value = .{ .uint64 = truncated_bits }, | 771 | .value = .{ .uint64 = truncated_value }, |
| 792 | }), | 772 | }), |
| 793 | else => unreachable, // TODO: Large integer constants | 773 | else => unreachable, // TODO: Large integer constants |
| 794 | } | 774 | } |
| 795 | | 775 | |
| 796 | if (!ty.isVector(zcu)) { | 776 | if (!ty.isVector(zcu)) return result_id; |
| 797 | return result_id; | 777 | return self.constructCompositeSplat(ty, 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; | | |
| 813 | } | 778 | } |
| 814 | | 779 | |
| 815 | /// Construct a struct at runtime. | 780 | pub fn constructComposite(self: *NavGen, result_ty_id: IdRef, constituents: []const IdRef) !IdRef { |
| 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 | | | |
| 822 | const result_id = self.spv.allocId(); | 781 | const result_id = self.spv.allocId(); |
| 823 | try self.func.body.emit(self.spv.gpa, .OpCompositeConstruct, .{ | 782 | try self.func.body.emit(self.gpa, .OpCompositeConstruct, .{ |
| 824 | .id_result_type = try self.resolveType(ty, .direct), | 783 | .id_result_type = result_ty_id, |
| 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), | | |
| 849 | .id_result = result_id, | 784 | .id_result = result_id, |
| 850 | .constituents = constituents, | 785 | .constituents = constituents, |
| 851 | }); | 786 | }); |
| 852 | return result_id; | 787 | return result_id; |
| 853 | } | 788 | } |
| 854 | | 789 | |
| 855 | /// Construct a vector at runtime with all lanes set to the same value. | 790 | /// Construct a composite at runtime with all lanes set to the same value. |
| 856 | /// ty must be an vector type. | 791 | /// ty must be an aggregate type. |
| 857 | fn constructVectorSplat(self: *NavGen, ty: Type, constituent: IdRef) !IdRef { | 792 | fn constructCompositeSplat(self: *NavGen, ty: Type, constituent: IdRef) !IdRef { |
| 858 | const zcu = self.pt.zcu; | 793 | const zcu = self.pt.zcu; |
| 859 | const n = ty.vectorLen(zcu); | 794 | const n = ty.arrayLen(zcu); |
| 860 | | 795 | |
| 861 | const constituents = try self.gpa.alloc(IdRef, n); | 796 | const constituents = try self.gpa.alloc(IdRef, n); |
| 862 | defer self.gpa.free(constituents); | 797 | defer self.gpa.free(constituents); |
| 863 | @memset(constituents, constituent); | 798 | @memset(constituents, constituent); |
| 864 | | 799 | |
| 865 | return try self.constructVector(ty, constituents); | 800 | const result_ty_id = try self.resolveType(ty, .direct); |
| 866 | } | 801 | return self.constructComposite(result_ty_id, constituents); |
| 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; | | |
| 880 | } | 802 | } |
| 881 | | 803 | |
| 882 | /// This function generates a load for a constant in direct (ie, non-memory) representation. | 804 | /// This function generates a load for a constant in direct (ie, non-memory) representation. |
| ... | @@ -947,9 +869,9 @@ const NavGen = struct { | ... | @@ -947,9 +869,9 @@ const NavGen = struct { |
| 947 | }, | 869 | }, |
| 948 | .int => { | 870 | .int => { |
| 949 | if (ty.isSignedInt(zcu)) { | 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 | } else { | 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 | .float => { | 877 | .float => { |
| ... | @@ -970,7 +892,7 @@ const NavGen = struct { | ... | @@ -970,7 +892,7 @@ const NavGen = struct { |
| 970 | }, | 892 | }, |
| 971 | .err => |err| { | 893 | .err => |err| { |
| 972 | const value = try pt.getErrorValue(err.name); | 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 | .error_union => |error_union| { | 897 | .error_union => |error_union| { |
| 976 | // TODO: Error unions may be constructed with constant instructions if the payload type | 898 | // TODO: Error unions may be constructed with constant instructions if the payload type |
| ... | @@ -1011,7 +933,8 @@ const NavGen = struct { | ... | @@ -1011,7 +933,8 @@ const NavGen = struct { |
| 1011 | types = .{ payload_ty, err_ty }; | 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 | .enum_tag => { | 939 | .enum_tag => { |
| 1017 | const int_val = try val.intFromEnum(ty, pt); | 940 | const int_val = try val.intFromEnum(ty, pt); |
| ... | @@ -1020,14 +943,10 @@ const NavGen = struct { | ... | @@ -1020,14 +943,10 @@ const NavGen = struct { |
| 1020 | }, | 943 | }, |
| 1021 | .ptr => return self.constantPtr(val), | 944 | .ptr => return self.constantPtr(val), |
| 1022 | .slice => |slice| { | 945 | .slice => |slice| { |
| 1023 | const ptr_ty = ty.slicePtrFieldType(zcu); | | |
| 1024 | const ptr_id = try self.constantPtr(Value.fromInterned(slice.ptr)); | 946 | const ptr_id = try self.constantPtr(Value.fromInterned(slice.ptr)); |
| 1025 | const len_id = try self.constant(Type.usize, Value.fromInterned(slice.len), .indirect); | 947 | const len_id = try self.constant(Type.usize, Value.fromInterned(slice.len), .indirect); |
| 1026 | return self.constructStruct( | 948 | const comp_ty_id = try self.resolveType(ty, .direct); |
| 1027 | ty, | 949 | return try self.constructComposite(comp_ty_id, &.{ ptr_id, len_id }); |
| 1028 | &.{ ptr_ty, Type.usize }, | | |
| 1029 | &.{ ptr_id, len_id }, | | |
| 1030 | ); | | |
| 1031 | }, | 950 | }, |
| 1032 | .opt => { | 951 | .opt => { |
| 1033 | const payload_ty = ty.optionalChild(zcu); | 952 | const payload_ty = ty.optionalChild(zcu); |
| ... | @@ -1053,11 +972,8 @@ const NavGen = struct { | ... | @@ -1053,11 +972,8 @@ const NavGen = struct { |
| 1053 | else | 972 | else |
| 1054 | try self.spv.constUndef(try self.resolveType(payload_ty, .indirect)); | 973 | try self.spv.constUndef(try self.resolveType(payload_ty, .indirect)); |
| 1055 | | 974 | |
| 1056 | return try self.constructStruct( | 975 | const comp_ty_id = try self.resolveType(ty, .direct); |
| 1057 | ty, | 976 | return try self.constructComposite(comp_ty_id, &.{ payload_id, has_pl_id }); |
| 1058 | &.{ payload_ty, Type.bool }, | | |
| 1059 | &.{ payload_id, has_pl_id }, | | |
| 1060 | ); | | |
| 1061 | }, | 977 | }, |
| 1062 | .aggregate => |aggregate| switch (ip.indexToKey(ty.ip_index)) { | 978 | .aggregate => |aggregate| switch (ip.indexToKey(ty.ip_index)) { |
| 1063 | inline .array_type, .vector_type => |array_type, tag| { | 979 | inline .array_type, .vector_type => |array_type, tag| { |
| ... | @@ -1077,7 +993,7 @@ const NavGen = struct { | ... | @@ -1077,7 +993,7 @@ const NavGen = struct { |
| 1077 | // TODO: This is really space inefficient, perhaps there is a better | 993 | // TODO: This is really space inefficient, perhaps there is a better |
| 1078 | // way to do it? | 994 | // way to do it? |
| 1079 | for (constituents, bytes.toSlice(constituents.len, ip)) |*constituent, byte| { | 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 | .elems => |elems| { | 999 | .elems => |elems| { |
| ... | @@ -1090,11 +1006,8 @@ const NavGen = struct { | ... | @@ -1090,11 +1006,8 @@ const NavGen = struct { |
| 1090 | }, | 1006 | }, |
| 1091 | } | 1007 | } |
| 1092 | | 1008 | |
| 1093 | switch (tag) { | 1009 | const comp_ty_id = try self.resolveType(ty, .direct); |
| 1094 | .array_type => return self.constructArray(ty, constituents), | 1010 | return self.constructComposite(comp_ty_id, constituents); |
| 1095 | .vector_type => return self.constructVector(ty, constituents), | | |
| 1096 | else => unreachable, | | |
| 1097 | } | | |
| 1098 | }, | 1011 | }, |
| 1099 | .struct_type => { | 1012 | .struct_type => { |
| 1100 | const struct_type = zcu.typeToStruct(ty).?; | 1013 | const struct_type = zcu.typeToStruct(ty).?; |
| ... | @@ -1124,7 +1037,8 @@ const NavGen = struct { | ... | @@ -1124,7 +1037,8 @@ const NavGen = struct { |
| 1124 | try constituents.append(field_id); | 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 | .tuple_type => unreachable, // TODO | 1043 | .tuple_type => unreachable, // TODO |
| 1130 | else => unreachable, | 1044 | else => unreachable, |
| ... | @@ -1149,8 +1063,6 @@ const NavGen = struct { | ... | @@ -1149,8 +1063,6 @@ const NavGen = struct { |
| 1149 | } | 1063 | } |
| 1150 | | 1064 | |
| 1151 | fn constantPtr(self: *NavGen, ptr_val: Value) Error!IdRef { | 1065 | fn constantPtr(self: *NavGen, ptr_val: Value) Error!IdRef { |
| 1152 | // TODO: Caching?? | | |
| 1153 | | | |
| 1154 | const pt = self.pt; | 1066 | const pt = self.pt; |
| 1155 | | 1067 | |
| 1156 | if (ptr_val.isUndef(pt.zcu)) { | 1068 | if (ptr_val.isUndef(pt.zcu)) { |
| ... | @@ -1201,7 +1113,7 @@ const NavGen = struct { | ... | @@ -1201,7 +1113,7 @@ const NavGen = struct { |
| 1201 | .elem_ptr => |elem| { | 1113 | .elem_ptr => |elem| { |
| 1202 | const parent_ptr_id = try self.derivePtr(elem.parent.*); | 1114 | const parent_ptr_id = try self.derivePtr(elem.parent.*); |
| 1203 | const parent_ptr_ty = try elem.parent.ptrType(pt); | 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 | return self.ptrElemPtr(parent_ptr_ty, parent_ptr_id, index_id); | 1117 | return self.ptrElemPtr(parent_ptr_ty, parent_ptr_id, index_id); |
| 1206 | }, | 1118 | }, |
| 1207 | .offset_and_cast => |oac| { | 1119 | .offset_and_cast => |oac| { |
| ... | @@ -1255,7 +1167,7 @@ const NavGen = struct { | ... | @@ -1255,7 +1167,7 @@ const NavGen = struct { |
| 1255 | | 1167 | |
| 1256 | // Uav refs are always generic. | 1168 | // Uav refs are always generic. |
| 1257 | assert(ty.ptrAddressSpace(zcu) == .generic); | 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 | const ptr_id = try self.resolveUav(uav.val); | 1171 | const ptr_id = try self.resolveUav(uav.val); |
| 1260 | | 1172 | |
| 1261 | if (decl_ptr_ty_id != ty_id) { | 1173 | if (decl_ptr_ty_id != ty_id) { |
| ... | @@ -1310,7 +1222,7 @@ const NavGen = struct { | ... | @@ -1310,7 +1222,7 @@ const NavGen = struct { |
| 1310 | const storage_class = self.spvStorageClass(nav.getAddrspace()); | 1222 | const storage_class = self.spvStorageClass(nav.getAddrspace()); |
| 1311 | try self.addFunctionDep(spv_decl_index, storage_class); | 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 | const ptr_id = switch (storage_class) { | 1227 | const ptr_id = switch (storage_class) { |
| 1316 | .Generic => try self.castToGeneric(decl_ptr_ty_id, decl_id), | 1228 | .Generic => try self.castToGeneric(decl_ptr_ty_id, decl_id), |
| ... | @@ -1359,23 +1271,11 @@ const NavGen = struct { | ... | @@ -1359,23 +1271,11 @@ const NavGen = struct { |
| 1359 | } | 1271 | } |
| 1360 | | 1272 | |
| 1361 | fn arrayType(self: *NavGen, len: u32, child_ty: IdRef) !IdRef { | 1273 | fn arrayType(self: *NavGen, len: u32, child_ty: IdRef) !IdRef { |
| 1362 | // TODO: Cache?? | 1274 | const len_id = try self.constInt(Type.u32, len); |
| 1363 | const len_id = try self.constInt(Type.u32, len, .direct); | 1275 | return self.spv.arrayType(len_id, child_ty); |
| 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); | | |
| 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 | const key = .{ child_ty.toIntern(), storage_class, child_repr }; | 1279 | const key = .{ child_ty.toIntern(), storage_class, child_repr }; |
| 1380 | const entry = try self.ptr_types.getOrPut(self.gpa, key); | 1280 | const entry = try self.ptr_types.getOrPut(self.gpa, key); |
| 1381 | if (entry.found_existing) { | 1281 | if (entry.found_existing) { |
| ... | @@ -1408,8 +1308,7 @@ const NavGen = struct { | ... | @@ -1408,8 +1308,7 @@ const NavGen = struct { |
| 1408 | } | 1308 | } |
| 1409 | | 1309 | |
| 1410 | fn functionType(self: *NavGen, return_ty: Type, param_types: []const Type) !IdRef { | 1310 | fn functionType(self: *NavGen, return_ty: Type, param_types: []const Type) !IdRef { |
| 1411 | // TODO: Cache?? | 1311 | const return_ty_id = try self.resolveFnReturnType(return_ty); |
| 1412 | | | |
| 1413 | const param_ids = try self.gpa.alloc(IdRef, param_types.len); | 1312 | const param_ids = try self.gpa.alloc(IdRef, param_types.len); |
| 1414 | defer self.gpa.free(param_ids); | 1313 | defer self.gpa.free(param_ids); |
| 1415 | | 1314 | |
| ... | @@ -1417,14 +1316,7 @@ const NavGen = struct { | ... | @@ -1417,14 +1316,7 @@ const NavGen = struct { |
| 1417 | param_id.* = try self.resolveType(param_ty, .direct); | 1316 | param_id.* = try self.resolveType(param_ty, .direct); |
| 1418 | } | 1317 | } |
| 1419 | | 1318 | |
| 1420 | const ty_id = self.spv.allocId(); | 1319 | return self.spv.functionType(return_ty_id, param_ids); |
| 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; | | |
| 1428 | } | 1320 | } |
| 1429 | | 1321 | |
| 1430 | fn zigScalarOrVectorTypeLike(self: *NavGen, new_ty: Type, base_ty: Type) !Type { | 1322 | fn zigScalarOrVectorTypeLike(self: *NavGen, new_ty: Type, base_ty: Type) !Type { |
| ... | @@ -1702,13 +1594,7 @@ const NavGen = struct { | ... | @@ -1702,13 +1594,7 @@ const NavGen = struct { |
| 1702 | | 1594 | |
| 1703 | const child_ty = Type.fromInterned(ptr_info.child); | 1595 | const child_ty = Type.fromInterned(ptr_info.child); |
| 1704 | const storage_class = self.spvStorageClass(ptr_info.flags.address_space); | 1596 | const storage_class = self.spvStorageClass(ptr_info.flags.address_space); |
| 1705 | const ptr_ty_id = try self.ptrType(child_ty, storage_class); | 1597 | const ptr_ty_id = try self.ptrType(child_ty, storage_class, .indirect); |
| 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 | } | | |
| 1712 | | 1598 | |
| 1713 | if (ptr_info.flags.size != .slice) { | 1599 | if (ptr_info.flags.size != .slice) { |
| 1714 | return ptr_ty_id; | 1600 | return ptr_ty_id; |
| ... | @@ -1755,10 +1641,6 @@ const NavGen = struct { | ... | @@ -1755,10 +1641,6 @@ const NavGen = struct { |
| 1755 | defer self.gpa.free(type_name); | 1641 | defer self.gpa.free(type_name); |
| 1756 | try self.spv.debugName(result_id, type_name); | 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 | return result_id; | 1644 | return result_id; |
| 1763 | }, | 1645 | }, |
| 1764 | .struct_type => ip.loadStructType(ty.toIntern()), | 1646 | .struct_type => ip.loadStructType(ty.toIntern()), |
| ... | @@ -1804,10 +1686,6 @@ const NavGen = struct { | ... | @@ -1804,10 +1686,6 @@ const NavGen = struct { |
| 1804 | defer self.gpa.free(type_name); | 1686 | defer self.gpa.free(type_name); |
| 1805 | try self.spv.debugName(result_id, type_name); | 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 | return result_id; | 1689 | return result_id; |
| 1812 | }, | 1690 | }, |
| 1813 | .optional => { | 1691 | .optional => { |
| ... | @@ -2073,12 +1951,13 @@ const NavGen = struct { | ... | @@ -2073,12 +1951,13 @@ const NavGen = struct { |
| 2073 | .exploded_vector => |range| { | 1951 | .exploded_vector => |range| { |
| 2074 | assert(self.ty.isVector(zcu)); | 1952 | assert(self.ty.isVector(zcu)); |
| 2075 | assert(self.ty.vectorLen(zcu) == range.len); | 1953 | assert(self.ty.vectorLen(zcu) == range.len); |
| 2076 | const consituents = try ng.gpa.alloc(IdRef, range.len); | 1954 | const constituents = try ng.gpa.alloc(IdRef, range.len); |
| 2077 | defer ng.gpa.free(consituents); | 1955 | defer ng.gpa.free(constituents); |
| 2078 | for (consituents, 0..range.len) |*id, i| { | 1956 | for (constituents, 0..range.len) |*id, i| { |
| 2079 | id.* = range.at(i); | 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,7 +2161,7 @@ const NavGen = struct { |
| 2282 | .child = tmp.ty.toIntern(), | 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 | return .{ | 2165 | return .{ |
| 2287 | .ty = vector_ty, | 2166 | .ty = vector_ty, |
| 2288 | .value = .{ .spv_vectorwise = vector }, | 2167 | .value = .{ .spv_vectorwise = vector }, |
| ... | @@ -3045,7 +2924,7 @@ const NavGen = struct { | ... | @@ -3045,7 +2924,7 @@ const NavGen = struct { |
| 3045 | const spv_err_decl_index = self.object.error_push_constant.?.push_constant_ptr; | 2924 | const spv_err_decl_index = self.object.error_push_constant.?.push_constant_ptr; |
| 3046 | const push_constant_id = self.spv.declPtr(spv_err_decl_index).result_id; | 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 | // We cannot use OpInBoundsAccessChain to dereference cross-storage class, so we have to use | 2928 | // We cannot use OpInBoundsAccessChain to dereference cross-storage class, so we have to use |
| 3050 | // a load. | 2929 | // a load. |
| 3051 | const tmp = self.spv.allocId(); | 2930 | const tmp = self.spv.allocId(); |
| ... | @@ -3187,7 +3066,7 @@ const NavGen = struct { | ... | @@ -3187,7 +3066,7 @@ const NavGen = struct { |
| 3187 | const storage_class = self.spvStorageClass(nav.getAddrspace()); | 3066 | const storage_class = self.spvStorageClass(nav.getAddrspace()); |
| 3188 | assert(storage_class != .Generic); // These should be instance globals | 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 | try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpVariable, .{ | 3071 | try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpVariable, .{ |
| 3193 | .id_result_type = ptr_ty_id, | 3072 | .id_result_type = ptr_ty_id, |
| ... | @@ -3208,7 +3087,7 @@ const NavGen = struct { | ... | @@ -3208,7 +3087,7 @@ const NavGen = struct { |
| 3208 | | 3087 | |
| 3209 | try self.spv.declareDeclDeps(spv_decl_index, &.{}); | 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 | if (maybe_init_val) |init_val| { | 3092 | if (maybe_init_val) |init_val| { |
| 3214 | // TODO: Combine with resolveAnonDecl? | 3093 | // TODO: Combine with resolveAnonDecl? |
| ... | @@ -3265,8 +3144,8 @@ const NavGen = struct { | ... | @@ -3265,8 +3144,8 @@ const NavGen = struct { |
| 3265 | } | 3144 | } |
| 3266 | | 3145 | |
| 3267 | fn intFromBool2(self: *NavGen, value: Temporary, result_ty: Type) !Temporary { | 3146 | fn intFromBool2(self: *NavGen, value: Temporary, result_ty: Type) !Temporary { |
| 3268 | const zero_id = try self.constInt(result_ty, 0, .direct); | 3147 | const zero_id = try self.constInt(result_ty, 0); |
| 3269 | const one_id = try self.constInt(result_ty, 1, .direct); | 3148 | const one_id = try self.constInt(result_ty, 1); |
| 3270 | | 3149 | |
| 3271 | return try self.buildSelect( | 3150 | return try self.buildSelect( |
| 3272 | value, | 3151 | value, |
| ... | @@ -3648,12 +3527,12 @@ const NavGen = struct { | ... | @@ -3648,12 +3527,12 @@ const NavGen = struct { |
| 3648 | .strange_integer => switch (info.signedness) { | 3527 | .strange_integer => switch (info.signedness) { |
| 3649 | .unsigned => { | 3528 | .unsigned => { |
| 3650 | const mask_value = if (info.bits == 64) 0xFFFF_FFFF_FFFF_FFFF else (@as(u64, 1) << @as(u6, @intCast(info.bits))) - 1; | 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 | return try self.buildBinary(.bit_and, value, Temporary.init(ty.scalarType(zcu), mask_id)); | 3531 | return try self.buildBinary(.bit_and, value, Temporary.init(ty.scalarType(zcu), mask_id)); |
| 3653 | }, | 3532 | }, |
| 3654 | .signed => { | 3533 | .signed => { |
| 3655 | // Shift left and right so that we can copy the sight bit that way. | 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 | const shift_amt = Temporary.init(ty.scalarType(zcu), shift_amt_id); | 3536 | const shift_amt = Temporary.init(ty.scalarType(zcu), shift_amt_id); |
| 3658 | const left = try self.buildBinary(.sll, value, shift_amt); | 3537 | const left = try self.buildBinary(.sll, value, shift_amt); |
| 3659 | return try self.buildBinary(.sra, left, shift_amt); | 3538 | return try self.buildBinary(.sra, left, shift_amt); |
| ... | @@ -3687,7 +3566,7 @@ const NavGen = struct { | ... | @@ -3687,7 +3566,7 @@ const NavGen = struct { |
| 3687 | const div = try self.buildBinary(.s_div, lhs, rhs); | 3566 | const div = try self.buildBinary(.s_div, lhs, rhs); |
| 3688 | const rem = try self.buildBinary(.s_rem, lhs, rhs); | 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 | const rem_is_not_zero = try self.buildCmp(.i_ne, rem, zero); | 3571 | const rem_is_not_zero = try self.buildCmp(.i_ne, rem, zero); |
| 3693 | | 3572 | |
| ... | @@ -3863,7 +3742,7 @@ const NavGen = struct { | ... | @@ -3863,7 +3742,7 @@ const NavGen = struct { |
| 3863 | // = (rhs < 0) == (value < lhs) | 3742 | // = (rhs < 0) == (value < lhs) |
| 3864 | // = (rhs < 0) == (lhs > value) | 3743 | // = (rhs < 0) == (lhs > value) |
| 3865 | .signed => blk: { | 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 | const rhs_lt_zero = try self.buildCmp(.s_lt, rhs, zero); | 3746 | const rhs_lt_zero = try self.buildCmp(.s_lt, rhs, zero); |
| 3868 | const result_gt_lhs = try self.buildCmp(scmp, lhs, result); | 3747 | const result_gt_lhs = try self.buildCmp(scmp, lhs, result); |
| 3869 | break :blk try self.buildCmp(.l_eq, rhs_lt_zero, result_gt_lhs); | 3748 | break :blk try self.buildCmp(.l_eq, rhs_lt_zero, result_gt_lhs); |
| ... | @@ -3872,11 +3751,8 @@ const NavGen = struct { | ... | @@ -3872,11 +3751,8 @@ const NavGen = struct { |
| 3872 | | 3751 | |
| 3873 | const ov = try self.intFromBool(overflowed); | 3752 | const ov = try self.intFromBool(overflowed); |
| 3874 | | 3753 | |
| 3875 | return try self.constructStruct( | 3754 | const result_ty_id = try self.resolveType(result_ty, .direct); |
| 3876 | result_ty, | 3755 | return try self.constructComposite(result_ty_id, &.{ try result.materialize(self), try ov.materialize(self) }); |
| 3877 | &.{ result.ty, ov.ty }, | | |
| 3878 | &.{ try result.materialize(self), try ov.materialize(self) }, | | |
| 3879 | ); | | |
| 3880 | } | 3756 | } |
| 3881 | | 3757 | |
| 3882 | fn airMulOverflow(self: *NavGen, inst: Air.Inst.Index) !?IdRef { | 3758 | fn airMulOverflow(self: *NavGen, inst: Air.Inst.Index) !?IdRef { |
| ... | @@ -3928,11 +3804,11 @@ const NavGen = struct { | ... | @@ -3928,11 +3804,11 @@ const NavGen = struct { |
| 3928 | const result = try self.normalize(low_bits, info); | 3804 | const result = try self.normalize(low_bits, info); |
| 3929 | | 3805 | |
| 3930 | // Shift the result bits away to get the overflow bits. | 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 | const overflow = try self.buildBinary(.srl, full_result, shift); | 3808 | const overflow = try self.buildBinary(.srl, full_result, shift); |
| 3933 | | 3809 | |
| 3934 | // Directly check if its zero in the op_ty without converting first. | 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 | const overflowed = try self.buildCmp(.i_ne, zero, overflow); | 3812 | const overflowed = try self.buildCmp(.i_ne, zero, overflow); |
| 3937 | | 3813 | |
| 3938 | break :blk .{ result, overflowed }; | 3814 | break :blk .{ result, overflowed }; |
| ... | @@ -3946,7 +3822,7 @@ const NavGen = struct { | ... | @@ -3946,7 +3822,7 @@ const NavGen = struct { |
| 3946 | // Overflow happened if the high-bits of the result are non-zero OR if the | 3822 | // Overflow happened if the high-bits of the result are non-zero OR if the |
| 3947 | // high bits of the low word of the result (those outside the range of the | 3823 | // high bits of the low word of the result (those outside the range of the |
| 3948 | // int) are nonzero. | 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 | const high_overflowed = try self.buildCmp(.i_ne, zero, high_bits); | 3826 | const high_overflowed = try self.buildCmp(.i_ne, zero, high_bits); |
| 3951 | | 3827 | |
| 3952 | // If no overflow bits in low_bits, no extra work needs to be done. | 3828 | // If no overflow bits in low_bits, no extra work needs to be done. |
| ... | @@ -3955,7 +3831,7 @@ const NavGen = struct { | ... | @@ -3955,7 +3831,7 @@ const NavGen = struct { |
| 3955 | } | 3831 | } |
| 3956 | | 3832 | |
| 3957 | // Shift the result bits away to get the overflow bits. | 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 | const low_overflow = try self.buildBinary(.srl, low_bits, shift); | 3835 | const low_overflow = try self.buildBinary(.srl, low_bits, shift); |
| 3960 | const low_overflowed = try self.buildCmp(.i_ne, zero, low_overflow); | 3836 | const low_overflowed = try self.buildCmp(.i_ne, zero, low_overflow); |
| 3961 | | 3837 | |
| ... | @@ -3974,7 +3850,7 @@ const NavGen = struct { | ... | @@ -3974,7 +3850,7 @@ const NavGen = struct { |
| 3974 | // overflow should be -1 when | 3850 | // overflow should be -1 when |
| 3975 | // (lhs > 0 && rhs < 0) || (lhs < 0 && rhs > 0) | 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 | const lhs_negative = try self.buildCmp(.s_lt, lhs, zero); | 3854 | const lhs_negative = try self.buildCmp(.s_lt, lhs, zero); |
| 3979 | const rhs_negative = try self.buildCmp(.s_lt, rhs, zero); | 3855 | const rhs_negative = try self.buildCmp(.s_lt, rhs, zero); |
| 3980 | const lhs_positive = try self.buildCmp(.s_gt, lhs, zero); | 3856 | const lhs_positive = try self.buildCmp(.s_gt, lhs, zero); |
| ... | @@ -4003,13 +3879,13 @@ const NavGen = struct { | ... | @@ -4003,13 +3879,13 @@ const NavGen = struct { |
| 4003 | // bit for the expected overflow bits. | 3879 | // bit for the expected overflow bits. |
| 4004 | // To do that, shift out everything bit the sign bit and | 3880 | // To do that, shift out everything bit the sign bit and |
| 4005 | // then check what remains. | 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 | // Use SRA so that any sign bits are duplicated. Now we can just check if ALL bits are set | 3883 | // Use SRA so that any sign bits are duplicated. Now we can just check if ALL bits are set |
| 4008 | // for negative cases. | 3884 | // for negative cases. |
| 4009 | const overflow = try self.buildBinary(.sra, full_result, shift); | 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)); | 3887 | const long_all_set = Temporary.init(full_result.ty, try self.constInt(full_result.ty, -1)); |
| 4012 | const long_zero = Temporary.init(full_result.ty, try self.constInt(full_result.ty, 0, .direct)); | 3888 | const long_zero = Temporary.init(full_result.ty, try self.constInt(full_result.ty, 0)); |
| 4013 | const mask = try self.buildSelect(expected_overflow_bit, long_all_set, long_zero); | 3889 | const mask = try self.buildSelect(expected_overflow_bit, long_all_set, long_zero); |
| 4014 | | 3890 | |
| 4015 | const overflowed = try self.buildCmp(.i_ne, mask, overflow); | 3891 | const overflowed = try self.buildCmp(.i_ne, mask, overflow); |
| ... | @@ -4022,7 +3898,7 @@ const NavGen = struct { | ... | @@ -4022,7 +3898,7 @@ const NavGen = struct { |
| 4022 | // Truncate result if required. | 3898 | // Truncate result if required. |
| 4023 | const result = try self.normalize(low_bits, info); | 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 | const mask = try self.buildSelect(expected_overflow_bit, all_set, zero); | 3902 | const mask = try self.buildSelect(expected_overflow_bit, all_set, zero); |
| 4027 | | 3903 | |
| 4028 | // Like with unsigned, overflow happened if high_bits are not the ones we expect, | 3904 | // Like with unsigned, overflow happened if high_bits are not the ones we expect, |
| ... | @@ -4038,7 +3914,7 @@ const NavGen = struct { | ... | @@ -4038,7 +3914,7 @@ const NavGen = struct { |
| 4038 | } | 3914 | } |
| 4039 | | 3915 | |
| 4040 | // Shift the result bits away to get the overflow bits. | 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 | // Use SRA so that any sign bits are duplicated. Now we can just check if ALL bits are set | 3918 | // Use SRA so that any sign bits are duplicated. Now we can just check if ALL bits are set |
| 4043 | // for negative cases. | 3919 | // for negative cases. |
| 4044 | const low_overflow = try self.buildBinary(.sra, low_bits, shift); | 3920 | const low_overflow = try self.buildBinary(.sra, low_bits, shift); |
| ... | @@ -4052,11 +3928,8 @@ const NavGen = struct { | ... | @@ -4052,11 +3928,8 @@ const NavGen = struct { |
| 4052 | | 3928 | |
| 4053 | const ov = try self.intFromBool(overflowed); | 3929 | const ov = try self.intFromBool(overflowed); |
| 4054 | | 3930 | |
| 4055 | return try self.constructStruct( | 3931 | const result_ty_id = try self.resolveType(result_ty, .direct); |
| 4056 | result_ty, | 3932 | return try self.constructComposite(result_ty_id, &.{ try result.materialize(self), try ov.materialize(self) }); |
| 4057 | &.{ result.ty, ov.ty }, | | |
| 4058 | &.{ try result.materialize(self), try ov.materialize(self) }, | | |
| 4059 | ); | | |
| 4060 | } | 3933 | } |
| 4061 | | 3934 | |
| 4062 | fn airShlOverflow(self: *NavGen, inst: Air.Inst.Index) !?IdRef { | 3935 | fn airShlOverflow(self: *NavGen, inst: Air.Inst.Index) !?IdRef { |
| ... | @@ -4092,11 +3965,8 @@ const NavGen = struct { | ... | @@ -4092,11 +3965,8 @@ const NavGen = struct { |
| 4092 | const overflowed = try self.buildCmp(.i_ne, base, right); | 3965 | const overflowed = try self.buildCmp(.i_ne, base, right); |
| 4093 | const ov = try self.intFromBool(overflowed); | 3966 | const ov = try self.intFromBool(overflowed); |
| 4094 | | 3967 | |
| 4095 | return try self.constructStruct( | 3968 | const result_ty_id = try self.resolveType(result_ty, .direct); |
| 4096 | result_ty, | 3969 | return try self.constructComposite(result_ty_id, &.{ try result.materialize(self), try ov.materialize(self) }); |
| 4097 | &.{ result.ty, ov.ty }, | | |
| 4098 | &.{ try result.materialize(self), try ov.materialize(self) }, | | |
| 4099 | ); | | |
| 4100 | } | 3970 | } |
| 4101 | | 3971 | |
| 4102 | fn airMulAdd(self: *NavGen, inst: Air.Inst.Index) !?IdRef { | 3972 | fn airMulAdd(self: *NavGen, inst: Air.Inst.Index) !?IdRef { |
| ... | @@ -4163,7 +4033,7 @@ const NavGen = struct { | ... | @@ -4163,7 +4033,7 @@ const NavGen = struct { |
| 4163 | const operand_id = try self.resolve(ty_op.operand); | 4033 | const operand_id = try self.resolve(ty_op.operand); |
| 4164 | const result_ty = self.typeOfIndex(inst); | 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 | fn airReduce(self: *NavGen, inst: Air.Inst.Index) !?IdRef { | 4039 | fn airReduce(self: *NavGen, inst: Air.Inst.Index) !?IdRef { |
| ... | @@ -4297,10 +4167,10 @@ const NavGen = struct { | ... | @@ -4297,10 +4167,10 @@ const NavGen = struct { |
| 4297 | | 4167 | |
| 4298 | // Fall back to manually extracting and inserting components. | 4168 | // Fall back to manually extracting and inserting components. |
| 4299 | | 4169 | |
| 4300 | const components = try self.gpa.alloc(IdRef, result_ty.vectorLen(zcu)); | 4170 | const constituents = try self.gpa.alloc(IdRef, result_ty.vectorLen(zcu)); |
| 4301 | defer self.gpa.free(components); | 4171 | defer self.gpa.free(constituents); |
| 4302 | | 4172 | |
| 4303 | for (components, 0..) |*id, i| { | 4173 | for (constituents, 0..) |*id, i| { |
| 4304 | const elem = try mask.elemValue(pt, i); | 4174 | const elem = try mask.elemValue(pt, i); |
| 4305 | if (elem.isUndef(zcu)) { | 4175 | if (elem.isUndef(zcu)) { |
| 4306 | id.* = try self.spv.constUndef(scalar_ty_id); | 4176 | id.* = try self.spv.constUndef(scalar_ty_id); |
| ... | @@ -4315,14 +4185,15 @@ const NavGen = struct { | ... | @@ -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 | fn indicesToIds(self: *NavGen, indices: []const u32) ![]IdRef { | 4192 | fn indicesToIds(self: *NavGen, indices: []const u32) ![]IdRef { |
| 4322 | const ids = try self.gpa.alloc(IdRef, indices.len); | 4193 | const ids = try self.gpa.alloc(IdRef, indices.len); |
| 4323 | errdefer self.gpa.free(ids); | 4194 | errdefer self.gpa.free(ids); |
| 4324 | for (indices, ids) |index, *id| { | 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 | return ids; | 4199 | return ids; |
| ... | @@ -4676,7 +4547,7 @@ const NavGen = struct { | ... | @@ -4676,7 +4547,7 @@ const NavGen = struct { |
| 4676 | break :blk result_id; | 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 | const tmp_id = try self.alloc(src_ty, .{ .storage_class = .Function }); | 4552 | const tmp_id = try self.alloc(src_ty, .{ .storage_class = .Function }); |
| 4682 | try self.store(src_ty, tmp_id, src_id, .{}); | 4553 | try self.store(src_ty, tmp_id, src_id, .{}); |
| ... | @@ -4851,7 +4722,7 @@ const NavGen = struct { | ... | @@ -4851,7 +4722,7 @@ const NavGen = struct { |
| 4851 | const elem_ptr_ty_id = try self.resolveType(elem_ptr_ty, .direct); | 4722 | const elem_ptr_ty_id = try self.resolveType(elem_ptr_ty, .direct); |
| 4852 | | 4723 | |
| 4853 | const array_ptr_id = try self.resolve(ty_op.operand); | 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 | const elem_ptr_id = if (!array_ty.hasRuntimeBitsIgnoreComptime(zcu)) | 4727 | const elem_ptr_id = if (!array_ty.hasRuntimeBitsIgnoreComptime(zcu)) |
| 4857 | // Note: The pointer is something like *opaque{}, so we need to bitcast it to the element type. | 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,11 +4731,8 @@ const NavGen = struct { |
| 4860 | // Convert the pointer-to-array to a pointer to the first element. | 4731 | // Convert the pointer-to-array to a pointer to the first element. |
| 4861 | try self.accessChain(elem_ptr_ty_id, array_ptr_id, &.{0}); | 4732 | try self.accessChain(elem_ptr_ty_id, array_ptr_id, &.{0}); |
| 4862 | | 4733 | |
| 4863 | return try self.constructStruct( | 4734 | const slice_ty_id = try self.resolveType(slice_ty, .direct); |
| 4864 | slice_ty, | 4735 | return try self.constructComposite(slice_ty_id, &.{ elem_ptr_id, len_id }); |
| 4865 | &.{ elem_ptr_ty, Type.usize }, | | |
| 4866 | &.{ elem_ptr_id, len_id }, | | |
| 4867 | ); | | |
| 4868 | } | 4736 | } |
| 4869 | | 4737 | |
| 4870 | fn airSlice(self: *NavGen, inst: Air.Inst.Index) !?IdRef { | 4738 | fn airSlice(self: *NavGen, inst: Air.Inst.Index) !?IdRef { |
| ... | @@ -4872,16 +4740,9 @@ const NavGen = struct { | ... | @@ -4872,16 +4740,9 @@ const NavGen = struct { |
| 4872 | const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data; | 4740 | const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data; |
| 4873 | const ptr_id = try self.resolve(bin_op.lhs); | 4741 | const ptr_id = try self.resolve(bin_op.lhs); |
| 4874 | const len_id = try self.resolve(bin_op.rhs); | 4742 | const len_id = try self.resolve(bin_op.rhs); |
| 4875 | const ptr_ty = self.typeOf(bin_op.lhs); | | |
| 4876 | const slice_ty = self.typeOfIndex(inst); | 4743 | const slice_ty = self.typeOfIndex(inst); |
| 4877 | | 4744 | const slice_ty_id = try self.resolveType(slice_ty, .direct); |
| 4878 | // Note: Types should not need to be converted to direct, these types | 4745 | return try self.constructComposite(slice_ty_id, &.{ ptr_id, len_id }); |
| 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 | ); | | |
| 4885 | } | 4746 | } |
| 4886 | | 4747 | |
| 4887 | fn airAggregateInit(self: *NavGen, inst: Air.Inst.Index) !?IdRef { | 4748 | fn airAggregateInit(self: *NavGen, inst: Air.Inst.Index) !?IdRef { |
| ... | @@ -4936,11 +4797,8 @@ const NavGen = struct { | ... | @@ -4936,11 +4797,8 @@ const NavGen = struct { |
| 4936 | else => unreachable, | 4797 | else => unreachable, |
| 4937 | } | 4798 | } |
| 4938 | | 4799 | |
| 4939 | return try self.constructStruct( | 4800 | const result_ty_id = try self.resolveType(result_ty, .direct); |
| 4940 | result_ty, | 4801 | return try self.constructComposite(result_ty_id, constituents[0..index]); |
| 4941 | types[0..index], | | |
| 4942 | constituents[0..index], | | |
| 4943 | ); | | |
| 4944 | }, | 4802 | }, |
| 4945 | .vector => { | 4803 | .vector => { |
| 4946 | const n_elems = result_ty.vectorLen(zcu); | 4804 | const n_elems = result_ty.vectorLen(zcu); |
| ... | @@ -4951,7 +4809,8 @@ const NavGen = struct { | ... | @@ -4951,7 +4809,8 @@ const NavGen = struct { |
| 4951 | elem_ids[i] = try self.resolve(element); | 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 | .array => { | 4815 | .array => { |
| 4957 | const array_info = result_ty.arrayInfo(zcu); | 4816 | const array_info = result_ty.arrayInfo(zcu); |
| ... | @@ -4968,7 +4827,8 @@ const NavGen = struct { | ... | @@ -4968,7 +4827,8 @@ const NavGen = struct { |
| 4968 | elem_ids[n_elems - 1] = try self.constant(array_info.elem_type, sentinel_val, .indirect); | 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 | else => unreachable, | 4833 | else => unreachable, |
| 4974 | } | 4834 | } |
| ... | @@ -4984,7 +4844,7 @@ const NavGen = struct { | ... | @@ -4984,7 +4844,7 @@ const NavGen = struct { |
| 4984 | const elem_ty = array_ty.childType(zcu); | 4844 | const elem_ty = array_ty.childType(zcu); |
| 4985 | const abi_size = elem_ty.abiSize(zcu); | 4845 | const abi_size = elem_ty.abiSize(zcu); |
| 4986 | const size = array_ty.arrayLenIncludingSentinel(zcu) * abi_size; | 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 | .many, .c => unreachable, | 4849 | .many, .c => unreachable, |
| 4990 | } | 4850 | } |
| ... | @@ -5060,7 +4920,7 @@ const NavGen = struct { | ... | @@ -5060,7 +4920,7 @@ const NavGen = struct { |
| 5060 | const zcu = self.pt.zcu; | 4920 | const zcu = self.pt.zcu; |
| 5061 | // Construct new pointer type for the resulting pointer | 4921 | // Construct new pointer type for the resulting pointer |
| 5062 | const elem_ty = ptr_ty.elemType2(zcu); // use elemType() so that we get T for *[N]T. | 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 | if (ptr_ty.isSinglePointer(zcu)) { | 4924 | if (ptr_ty.isSinglePointer(zcu)) { |
| 5065 | // Pointer-to-array. In this case, the resulting pointer is not of the same type | 4925 | // Pointer-to-array. In this case, the resulting pointer is not of the same type |
| 5066 | // as the ptr_ty (we want a *T, not a *[N]T), and hence we need to use accessChain. | 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,8 +4975,8 @@ const NavGen = struct { |
| 5115 | const is_vector = array_ty.isVector(zcu); | 4975 | const is_vector = array_ty.isVector(zcu); |
| 5116 | | 4976 | |
| 5117 | const elem_repr: Repr = if (is_vector) .direct else .indirect; | 4977 | const elem_repr: Repr = if (is_vector) .direct else .indirect; |
| 5118 | const ptr_array_ty_id = try self.ptrType2(array_ty, .Function, .direct); | 4978 | const ptr_array_ty_id = try self.ptrType(array_ty, .Function, .direct); |
| 5119 | const ptr_elem_ty_id = try self.ptrType2(elem_ty, .Function, elem_repr); | 4979 | const ptr_elem_ty_id = try self.ptrType(elem_ty, .Function, elem_repr); |
| 5120 | | 4980 | |
| 5121 | const tmp_id = self.spv.allocId(); | 4981 | const tmp_id = self.spv.allocId(); |
| 5122 | try self.func.prologue.emit(self.spv.gpa, .OpVariable, .{ | 4982 | try self.func.prologue.emit(self.spv.gpa, .OpVariable, .{ |
| ... | @@ -5171,7 +5031,7 @@ const NavGen = struct { | ... | @@ -5171,7 +5031,7 @@ const NavGen = struct { |
| 5171 | const scalar_ty = vector_ty.scalarType(zcu); | 5031 | const scalar_ty = vector_ty.scalarType(zcu); |
| 5172 | | 5032 | |
| 5173 | const storage_class = self.spvStorageClass(vector_ptr_ty.ptrAddressSpace(zcu)); | 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 | const vector_ptr = try self.resolve(data.vector_ptr); | 5036 | const vector_ptr = try self.resolve(data.vector_ptr); |
| 5177 | const index = try self.resolve(extra.lhs); | 5037 | const index = try self.resolve(extra.lhs); |
| ... | @@ -5193,7 +5053,7 @@ const NavGen = struct { | ... | @@ -5193,7 +5053,7 @@ const NavGen = struct { |
| 5193 | if (layout.tag_size == 0) return; | 5053 | if (layout.tag_size == 0) return; |
| 5194 | | 5054 | |
| 5195 | const tag_ty = un_ty.unionTagTypeSafety(zcu).?; | 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 | const union_ptr_id = try self.resolve(bin_op.lhs); | 5058 | const union_ptr_id = try self.resolve(bin_op.lhs); |
| 5199 | const new_tag_id = try self.resolve(bin_op.rhs); | 5059 | const new_tag_id = try self.resolve(bin_op.rhs); |
| ... | @@ -5252,23 +5112,23 @@ const NavGen = struct { | ... | @@ -5252,23 +5112,23 @@ const NavGen = struct { |
| 5252 | } else 0; | 5112 | } else 0; |
| 5253 | | 5113 | |
| 5254 | if (!layout.has_payload) { | 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 | const tmp_id = try self.alloc(ty, .{ .storage_class = .Function }); | 5118 | const tmp_id = try self.alloc(ty, .{ .storage_class = .Function }); |
| 5259 | | 5119 | |
| 5260 | if (layout.tag_size != 0) { | 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 | const ptr_id = try self.accessChain(tag_ptr_ty_id, tmp_id, &.{@as(u32, @intCast(layout.tag_index))}); | 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 | try self.store(tag_ty, ptr_id, tag_id, .{}); | 5124 | try self.store(tag_ty, ptr_id, tag_id, .{}); |
| 5265 | } | 5125 | } |
| 5266 | | 5126 | |
| 5267 | const payload_ty = Type.fromInterned(union_ty.field_types.get(ip)[active_field]); | 5127 | const payload_ty = Type.fromInterned(union_ty.field_types.get(ip)[active_field]); |
| 5268 | if (payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | 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 | const pl_ptr_id = try self.accessChain(pl_ptr_ty_id, tmp_id, &.{layout.payload_index}); | 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 | const active_pl_ptr_id = self.spv.allocId(); | 5132 | const active_pl_ptr_id = self.spv.allocId(); |
| 5273 | try self.func.body.emit(self.spv.gpa, .OpBitcast, .{ | 5133 | try self.func.body.emit(self.spv.gpa, .OpBitcast, .{ |
| 5274 | .id_result_type = active_pl_ptr_ty_id, | 5134 | .id_result_type = active_pl_ptr_ty_id, |
| ... | @@ -5332,10 +5192,10 @@ const NavGen = struct { | ... | @@ -5332,10 +5192,10 @@ const NavGen = struct { |
| 5332 | const tmp_id = try self.alloc(object_ty, .{ .storage_class = .Function }); | 5192 | const tmp_id = try self.alloc(object_ty, .{ .storage_class = .Function }); |
| 5333 | try self.store(object_ty, tmp_id, object_id, .{}); | 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 | const pl_ptr_id = try self.accessChain(pl_ptr_ty_id, tmp_id, &.{layout.payload_index}); | 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 | const active_pl_ptr_id = self.spv.allocId(); | 5199 | const active_pl_ptr_id = self.spv.allocId(); |
| 5340 | try self.func.body.emit(self.spv.gpa, .OpBitcast, .{ | 5200 | try self.func.body.emit(self.spv.gpa, .OpBitcast, .{ |
| 5341 | .id_result_type = active_pl_ptr_ty_id, | 5201 | .id_result_type = active_pl_ptr_ty_id, |
| ... | @@ -5365,7 +5225,7 @@ const NavGen = struct { | ... | @@ -5365,7 +5225,7 @@ const NavGen = struct { |
| 5365 | const base_ptr_int = base_ptr_int: { | 5225 | const base_ptr_int = base_ptr_int: { |
| 5366 | if (field_offset == 0) break :base_ptr_int field_ptr_int; | 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 | const field_ptr_tmp = Temporary.init(Type.usize, field_ptr_int); | 5229 | const field_ptr_tmp = Temporary.init(Type.usize, field_ptr_int); |
| 5370 | const field_offset_tmp = Temporary.init(Type.usize, field_offset_id); | 5230 | const field_offset_tmp = Temporary.init(Type.usize, field_offset_id); |
| 5371 | const result = try self.buildBinary(.i_sub, field_ptr_tmp, field_offset_tmp); | 5231 | const result = try self.buildBinary(.i_sub, field_ptr_tmp, field_offset_tmp); |
| ... | @@ -5415,7 +5275,7 @@ const NavGen = struct { | ... | @@ -5415,7 +5275,7 @@ const NavGen = struct { |
| 5415 | } | 5275 | } |
| 5416 | | 5276 | |
| 5417 | const storage_class = self.spvStorageClass(object_ptr_ty.ptrAddressSpace(zcu)); | 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 | const pl_ptr_id = try self.accessChain(pl_ptr_ty_id, object_ptr, &.{layout.payload_index}); | 5279 | const pl_ptr_id = try self.accessChain(pl_ptr_ty_id, object_ptr, &.{layout.payload_index}); |
| 5420 | | 5280 | |
| 5421 | const active_pl_ptr_id = self.spv.allocId(); | 5281 | const active_pl_ptr_id = self.spv.allocId(); |
| ... | @@ -5456,7 +5316,7 @@ const NavGen = struct { | ... | @@ -5456,7 +5316,7 @@ const NavGen = struct { |
| 5456 | ty: Type, | 5316 | ty: Type, |
| 5457 | options: AllocOptions, | 5317 | options: AllocOptions, |
| 5458 | ) !IdRef { | 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 | // SPIR-V requires that OpVariable declarations for locals go into the first block, so we are just going to | 5321 | // SPIR-V requires that OpVariable declarations for locals go into the first block, so we are just going to |
| 5462 | // directly generate them into func.prologue instead of the body. | 5322 | // directly generate them into func.prologue instead of the body. |
| ... | @@ -5475,7 +5335,7 @@ const NavGen = struct { | ... | @@ -5475,7 +5335,7 @@ const NavGen = struct { |
| 5475 | | 5335 | |
| 5476 | switch (options.storage_class) { | 5336 | switch (options.storage_class) { |
| 5477 | .Generic => { | 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 | // Convert to a generic pointer | 5339 | // Convert to a generic pointer |
| 5480 | return self.castToGeneric(ptr_gn_ty_id, var_id); | 5340 | return self.castToGeneric(ptr_gn_ty_id, var_id); |
| 5481 | }, | 5341 | }, |
| ... | @@ -5724,7 +5584,7 @@ const NavGen = struct { | ... | @@ -5724,7 +5584,7 @@ const NavGen = struct { |
| 5724 | assert(cf.block_stack.items.len > 0); | 5584 | assert(cf.block_stack.items.len > 0); |
| 5725 | | 5585 | |
| 5726 | // Check if the target of the branch was this current block. | 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 | const jump_to_this_block_id = self.spv.allocId(); | 5588 | const jump_to_this_block_id = self.spv.allocId(); |
| 5729 | const bool_ty_id = try self.resolveType(Type.bool, .direct); | 5589 | const bool_ty_id = try self.resolveType(Type.bool, .direct); |
| 5730 | try self.func.body.emit(self.spv.gpa, .OpIEqual, .{ | 5590 | try self.func.body.emit(self.spv.gpa, .OpIEqual, .{ |
| ... | @@ -5804,7 +5664,7 @@ const NavGen = struct { | ... | @@ -5804,7 +5664,7 @@ const NavGen = struct { |
| 5804 | try self.store(operand_ty, block_result_var_id, operand_id, .{}); | 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 | try self.structuredBreak(next_block); | 5668 | try self.structuredBreak(next_block); |
| 5809 | }, | 5669 | }, |
| 5810 | .unstructured => |cf| { | 5670 | .unstructured => |cf| { |
| ... | @@ -5968,7 +5828,7 @@ const NavGen = struct { | ... | @@ -5968,7 +5828,7 @@ const NavGen = struct { |
| 5968 | // Functions with an empty error set are emitted with an error code | 5828 | // Functions with an empty error set are emitted with an error code |
| 5969 | // return type and return zero so they can be function pointers coerced | 5829 | // return type and return zero so they can be function pointers coerced |
| 5970 | // to functions that return anyerror. | 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 | return try self.func.body.emit(self.spv.gpa, .OpReturnValue, .{ .value = no_err_id }); | 5832 | return try self.func.body.emit(self.spv.gpa, .OpReturnValue, .{ .value = no_err_id }); |
| 5973 | } else { | 5833 | } else { |
| 5974 | return try self.func.body.emit(self.spv.gpa, .OpReturn, {}); | 5834 | return try self.func.body.emit(self.spv.gpa, .OpReturn, {}); |
| ... | @@ -5992,7 +5852,7 @@ const NavGen = struct { | ... | @@ -5992,7 +5852,7 @@ const NavGen = struct { |
| 5992 | // Functions with an empty error set are emitted with an error code | 5852 | // Functions with an empty error set are emitted with an error code |
| 5993 | // return type and return zero so they can be function pointers coerced | 5853 | // return type and return zero so they can be function pointers coerced |
| 5994 | // to functions that return anyerror. | 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 | return try self.func.body.emit(self.spv.gpa, .OpReturnValue, .{ .value = no_err_id }); | 5856 | return try self.func.body.emit(self.spv.gpa, .OpReturnValue, .{ .value = no_err_id }); |
| 5997 | } else { | 5857 | } else { |
| 5998 | return try self.func.body.emit(self.spv.gpa, .OpReturn, {}); | 5858 | return try self.func.body.emit(self.spv.gpa, .OpReturn, {}); |
| ... | @@ -6026,7 +5886,7 @@ const NavGen = struct { | ... | @@ -6026,7 +5886,7 @@ const NavGen = struct { |
| 6026 | else | 5886 | else |
| 6027 | err_union_id; | 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 | const is_err_id = self.spv.allocId(); | 5890 | const is_err_id = self.spv.allocId(); |
| 6031 | try self.func.body.emit(self.spv.gpa, .OpINotEqual, .{ | 5891 | try self.func.body.emit(self.spv.gpa, .OpINotEqual, .{ |
| 6032 | .id_result_type = bool_ty_id, | 5892 | .id_result_type = bool_ty_id, |
| ... | @@ -6134,7 +5994,8 @@ const NavGen = struct { | ... | @@ -6134,7 +5994,8 @@ const NavGen = struct { |
| 6134 | types[eu_layout.errorFieldIndex()] = Type.anyerror; | 5994 | types[eu_layout.errorFieldIndex()] = Type.anyerror; |
| 6135 | types[eu_layout.payloadFieldIndex()] = payload_ty; | 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 | fn airWrapErrUnionPayload(self: *NavGen, inst: Air.Inst.Index) !?IdRef { | 6001 | fn airWrapErrUnionPayload(self: *NavGen, inst: Air.Inst.Index) !?IdRef { |
| ... | @@ -6145,18 +6006,19 @@ const NavGen = struct { | ... | @@ -6145,18 +6006,19 @@ const NavGen = struct { |
| 6145 | const eu_layout = self.errorUnionLayout(payload_ty); | 6006 | const eu_layout = self.errorUnionLayout(payload_ty); |
| 6146 | | 6007 | |
| 6147 | if (!eu_layout.payload_has_bits) { | 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 | var members: [2]IdRef = undefined; | 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 | members[eu_layout.payloadFieldIndex()] = try self.convertToIndirect(payload_ty, operand_id); | 6014 | members[eu_layout.payloadFieldIndex()] = try self.convertToIndirect(payload_ty, operand_id); |
| 6154 | | 6015 | |
| 6155 | var types: [2]Type = undefined; | 6016 | var types: [2]Type = undefined; |
| 6156 | types[eu_layout.errorFieldIndex()] = Type.anyerror; | 6017 | types[eu_layout.errorFieldIndex()] = Type.anyerror; |
| 6157 | types[eu_layout.payloadFieldIndex()] = payload_ty; | 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 | fn airIsNull(self: *NavGen, inst: Air.Inst.Index, is_pointer: bool, pred: enum { is_null, is_non_null }) !?IdRef { | 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,7 +6066,7 @@ const NavGen = struct { |
| 6204 | if (is_pointer) { | 6066 | if (is_pointer) { |
| 6205 | if (payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | 6067 | if (payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { |
| 6206 | const storage_class = self.spvStorageClass(operand_ty.ptrAddressSpace(zcu)); | 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 | const tag_ptr_id = try self.accessChain(bool_ptr_ty_id, operand_id, &.{1}); | 6070 | const tag_ptr_id = try self.accessChain(bool_ptr_ty_id, operand_id, &.{1}); |
| 6209 | break :blk try self.load(Type.bool, tag_ptr_id, .{}); | 6071 | break :blk try self.load(Type.bool, tag_ptr_id, .{}); |
| 6210 | } | 6072 | } |
| ... | @@ -6267,7 +6129,7 @@ const NavGen = struct { | ... | @@ -6267,7 +6129,7 @@ const NavGen = struct { |
| 6267 | .id_result_type = bool_ty_id, | 6129 | .id_result_type = bool_ty_id, |
| 6268 | .id_result = result_id, | 6130 | .id_result = result_id, |
| 6269 | .operand_1 = error_id, | 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,8 +6197,8 @@ const NavGen = struct { |
| 6335 | | 6197 | |
| 6336 | const payload_id = try self.convertToIndirect(payload_ty, operand_id); | 6198 | const payload_id = try self.convertToIndirect(payload_ty, operand_id); |
| 6337 | const members = [_]IdRef{ payload_id, try self.constBool(true, .indirect) }; | 6199 | const members = [_]IdRef{ payload_id, try self.constBool(true, .indirect) }; |
| 6338 | const types = [_]Type{ payload_ty, Type.bool }; | 6200 | const optional_ty_id = try self.resolveType(optional_ty, .direct); |
| 6339 | return try self.constructStruct(optional_ty, &types, &members); | 6201 | return try self.constructComposite(optional_ty_id, &members); |
| 6340 | } | 6202 | } |
| 6341 | | 6203 | |
| 6342 | fn airSwitchBr(self: *NavGen, inst: Air.Inst.Index) !void { | 6204 | fn airSwitchBr(self: *NavGen, inst: Air.Inst.Index) !void { |
| ... | @@ -6752,13 +6614,13 @@ const NavGen = struct { | ... | @@ -6752,13 +6614,13 @@ const NavGen = struct { |
| 6752 | | 6614 | |
| 6753 | fn builtin3D(self: *NavGen, result_ty: Type, builtin: spec.BuiltIn, dimension: u32, out_of_range_value: anytype) !IdRef { | 6615 | fn builtin3D(self: *NavGen, result_ty: Type, builtin: spec.BuiltIn, dimension: u32, out_of_range_value: anytype) !IdRef { |
| 6754 | if (dimension >= 3) { | 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 | const vec_ty = try self.pt.vectorType(.{ | 6619 | const vec_ty = try self.pt.vectorType(.{ |
| 6758 | .len = 3, | 6620 | .len = 3, |
| 6759 | .child = result_ty.toIntern(), | 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 | const spv_decl_index = try self.spv.builtin(ptr_ty_id, builtin); | 6624 | const spv_decl_index = try self.spv.builtin(ptr_ty_id, builtin); |
| 6763 | try self.func.decl_deps.put(self.spv.gpa, spv_decl_index, {}); | 6625 | try self.func.decl_deps.put(self.spv.gpa, spv_decl_index, {}); |
| 6764 | const ptr = self.spv.declPtr(spv_decl_index).result_id; | 6626 | const ptr = self.spv.declPtr(spv_decl_index).result_id; |