| ... | ... | @@ -451,12 +451,12 @@ const DeclGen = struct { |
| 451 | 451 | const spv_decl_index = blk: { |
| 452 | 452 | const entry = try self.object.anon_decl_link.getOrPut(self.object.gpa, .{ val, storage_class }); |
| 453 | 453 | if (entry.found_existing) { |
| 454 | | try self.func.decl_deps.put(self.spv.gpa, entry.value_ptr.*, {}); |
| 454 | try self.addFunctionDep(entry.value_ptr.*, storage_class); |
| 455 | 455 | return self.spv.declPtr(entry.value_ptr.*).result_id; |
| 456 | 456 | } |
| 457 | 457 | |
| 458 | 458 | const spv_decl_index = try self.spv.allocDecl(.global); |
| 459 | | try self.func.decl_deps.put(self.spv.gpa, spv_decl_index, {}); |
| 459 | try self.addFunctionDep(spv_decl_index, storage_class); |
| 460 | 460 | entry.value_ptr.* = spv_decl_index; |
| 461 | 461 | break :blk spv_decl_index; |
| 462 | 462 | }; |
| ... | ... | @@ -529,6 +529,37 @@ const DeclGen = struct { |
| 529 | 529 | return var_id; |
| 530 | 530 | } |
| 531 | 531 | |
| 532 | fn addFunctionDep(self: *DeclGen, decl_index: SpvModule.Decl.Index, storage_class: StorageClass) !void { |
| 533 | const target = self.getTarget(); |
| 534 | if (target.os.tag == .vulkan) { |
| 535 | // Shader entry point dependencies must be variables with Input or Output storage class |
| 536 | switch (storage_class) { |
| 537 | .Input, .Output => { |
| 538 | try self.func.decl_deps.put(self.spv.gpa, decl_index, {}); |
| 539 | }, |
| 540 | else => {}, |
| 541 | } |
| 542 | } else { |
| 543 | try self.func.decl_deps.put(self.spv.gpa, decl_index, {}); |
| 544 | } |
| 545 | } |
| 546 | |
| 547 | fn castToGeneric(self: *DeclGen, type_id: IdRef, ptr_id: IdRef) !IdRef { |
| 548 | const target = self.getTarget(); |
| 549 | |
| 550 | if (target.os.tag == .vulkan) { |
| 551 | return ptr_id; |
| 552 | } else { |
| 553 | const result_id = self.spv.allocId(); |
| 554 | try self.func.body.emit(self.spv.gpa, .OpPtrCastToGeneric, .{ |
| 555 | .id_result_type = type_id, |
| 556 | .id_result = result_id, |
| 557 | .pointer = ptr_id, |
| 558 | }); |
| 559 | return result_id; |
| 560 | } |
| 561 | } |
| 562 | |
| 532 | 563 | /// Start a new SPIR-V block, Emits the label of the new block, and stores which |
| 533 | 564 | /// block we are currently generating. |
| 534 | 565 | /// Note that there is no such thing as nested blocks like in ZIR or AIR, so we don't need to |
| ... | ... | @@ -713,6 +744,30 @@ const DeclGen = struct { |
| 713 | 744 | return try self.load(ty, ptr_composite_id, .{}); |
| 714 | 745 | } |
| 715 | 746 | |
| 747 | /// Construct a vector at runtime. |
| 748 | /// ty must be an vector type. |
| 749 | /// Constituents should be in `indirect` representation (as the elements of an vector should be). |
| 750 | /// Result is in `direct` representation. |
| 751 | fn constructVector(self: *DeclGen, ty: Type, constituents: []const IdRef) !IdRef { |
| 752 | // The Khronos LLVM-SPIRV translator crashes because it cannot construct structs which' |
| 753 | // operands are not constant. |
| 754 | // See https://github.com/KhronosGroup/SPIRV-LLVM-Translator/issues/1349 |
| 755 | // For now, just initialize the struct by setting the fields manually... |
| 756 | // TODO: Make this OpCompositeConstruct when we can |
| 757 | const mod = self.module; |
| 758 | const ptr_composite_id = try self.alloc(ty, .{ .storage_class = .Function }); |
| 759 | const ptr_elem_ty_ref = try self.ptrType(ty.elemType2(mod), .Function); |
| 760 | for (constituents, 0..) |constitent_id, index| { |
| 761 | const ptr_id = try self.accessChain(ptr_elem_ty_ref, ptr_composite_id, &.{@as(u32, @intCast(index))}); |
| 762 | try self.func.body.emit(self.spv.gpa, .OpStore, .{ |
| 763 | .pointer = ptr_id, |
| 764 | .object = constitent_id, |
| 765 | }); |
| 766 | } |
| 767 | |
| 768 | return try self.load(ty, ptr_composite_id, .{}); |
| 769 | } |
| 770 | |
| 716 | 771 | /// Construct an array at runtime. |
| 717 | 772 | /// ty must be an array type. |
| 718 | 773 | /// Constituents should be in `indirect` representation (as the elements of an array should be). |
| ... | ... | @@ -932,13 +987,16 @@ const DeclGen = struct { |
| 932 | 987 | } |
| 933 | 988 | |
| 934 | 989 | switch (tag) { |
| 935 | | inline .array_type => if (array_type.sentinel != .none) { |
| 936 | | constituents[constituents.len - 1] = try self.constant(elem_ty, Value.fromInterned(array_type.sentinel), .indirect); |
| 990 | inline .array_type => { |
| 991 | if (array_type.sentinel != .none) { |
| 992 | const sentinel = Value.fromInterned(array_type.sentinel); |
| 993 | constituents[constituents.len - 1] = try self.constant(elem_ty, sentinel, .indirect); |
| 994 | } |
| 995 | return self.constructArray(ty, constituents); |
| 937 | 996 | }, |
| 938 | | else => {}, |
| 997 | inline .vector_type => return self.constructVector(ty, constituents), |
| 998 | else => unreachable, |
| 939 | 999 | } |
| 940 | | |
| 941 | | return try self.constructArray(ty, constituents); |
| 942 | 1000 | }, |
| 943 | 1001 | .struct_type => { |
| 944 | 1002 | const struct_type = mod.typeToStruct(ty).?; |
| ... | ... | @@ -1019,7 +1077,7 @@ const DeclGen = struct { |
| 1019 | 1077 | |
| 1020 | 1078 | // TODO: Can we consolidate this in ptrElemPtr? |
| 1021 | 1079 | const elem_ty = parent_ptr_ty.elemType2(mod); // use elemType() so that we get T for *[N]T. |
| 1022 | | const elem_ptr_ty_ref = try self.ptrType(elem_ty, spvStorageClass(parent_ptr_ty.ptrAddressSpace(mod))); |
| 1080 | const elem_ptr_ty_ref = try self.ptrType(elem_ty, self.spvStorageClass(parent_ptr_ty.ptrAddressSpace(mod))); |
| 1023 | 1081 | |
| 1024 | 1082 | if (elem_ptr_ty_ref == result_ty_ref) { |
| 1025 | 1083 | return elem_ptr_id; |
| ... | ... | @@ -1074,7 +1132,7 @@ const DeclGen = struct { |
| 1074 | 1132 | unreachable; // TODO |
| 1075 | 1133 | } |
| 1076 | 1134 | |
| 1077 | | const final_storage_class = spvStorageClass(ty.ptrAddressSpace(mod)); |
| 1135 | const final_storage_class = self.spvStorageClass(ty.ptrAddressSpace(mod)); |
| 1078 | 1136 | const actual_storage_class = switch (final_storage_class) { |
| 1079 | 1137 | .Generic => .CrossWorkgroup, |
| 1080 | 1138 | else => |other| other, |
| ... | ... | @@ -1084,15 +1142,7 @@ const DeclGen = struct { |
| 1084 | 1142 | const decl_ptr_ty_ref = try self.ptrType(decl_ty, final_storage_class); |
| 1085 | 1143 | |
| 1086 | 1144 | const ptr_id = switch (final_storage_class) { |
| 1087 | | .Generic => blk: { |
| 1088 | | const result_id = self.spv.allocId(); |
| 1089 | | try self.func.body.emit(self.spv.gpa, .OpPtrCastToGeneric, .{ |
| 1090 | | .id_result_type = self.typeId(decl_ptr_ty_ref), |
| 1091 | | .id_result = result_id, |
| 1092 | | .pointer = decl_id, |
| 1093 | | }); |
| 1094 | | break :blk result_id; |
| 1095 | | }, |
| 1145 | .Generic => try self.castToGeneric(self.typeId(decl_ptr_ty_ref), decl_id), |
| 1096 | 1146 | else => decl_id, |
| 1097 | 1147 | }; |
| 1098 | 1148 | |
| ... | ... | @@ -1115,6 +1165,7 @@ const DeclGen = struct { |
| 1115 | 1165 | const ty_ref = try self.resolveType(ty, .direct); |
| 1116 | 1166 | const ty_id = self.typeId(ty_ref); |
| 1117 | 1167 | const decl = mod.declPtr(decl_index); |
| 1168 | |
| 1118 | 1169 | switch (mod.intern_pool.indexToKey(decl.val.ip_index)) { |
| 1119 | 1170 | .func => { |
| 1120 | 1171 | // TODO: Properly lower function pointers. For now we are going to hack around it and |
| ... | ... | @@ -1133,23 +1184,13 @@ const DeclGen = struct { |
| 1133 | 1184 | const spv_decl_index = try self.object.resolveDecl(mod, decl_index); |
| 1134 | 1185 | |
| 1135 | 1186 | const decl_id = self.spv.declPtr(spv_decl_index).result_id; |
| 1136 | | try self.func.decl_deps.put(self.spv.gpa, spv_decl_index, {}); |
| 1137 | | |
| 1138 | | const final_storage_class = spvStorageClass(decl.@"addrspace"); |
| 1187 | const final_storage_class = self.spvStorageClass(decl.@"addrspace"); |
| 1188 | try self.addFunctionDep(spv_decl_index, final_storage_class); |
| 1139 | 1189 | |
| 1140 | 1190 | const decl_ptr_ty_ref = try self.ptrType(decl.ty, final_storage_class); |
| 1141 | 1191 | |
| 1142 | 1192 | const ptr_id = switch (final_storage_class) { |
| 1143 | | .Generic => blk: { |
| 1144 | | // Pointer should be Generic, but is actually placed in CrossWorkgroup. |
| 1145 | | const result_id = self.spv.allocId(); |
| 1146 | | try self.func.body.emit(self.spv.gpa, .OpPtrCastToGeneric, .{ |
| 1147 | | .id_result_type = self.typeId(decl_ptr_ty_ref), |
| 1148 | | .id_result = result_id, |
| 1149 | | .pointer = decl_id, |
| 1150 | | }); |
| 1151 | | break :blk result_id; |
| 1152 | | }, |
| 1193 | .Generic => try self.castToGeneric(self.typeId(decl_ptr_ty_ref), decl_id), |
| 1153 | 1194 | else => decl_id, |
| 1154 | 1195 | }; |
| 1155 | 1196 | |
| ... | ... | @@ -1195,8 +1236,12 @@ const DeclGen = struct { |
| 1195 | 1236 | // An array of largestSupportedIntBits. |
| 1196 | 1237 | return self.todo("Implement {s} composite int type of {} bits", .{ @tagName(signedness), bits }); |
| 1197 | 1238 | }; |
| 1239 | |
| 1198 | 1240 | // Kernel only supports unsigned ints. |
| 1199 | | // TODO: Only do this with Kernels |
| 1241 | if (self.getTarget().os.tag == .vulkan) { |
| 1242 | return self.spv.intType(signedness, backing_bits); |
| 1243 | } |
| 1244 | |
| 1200 | 1245 | return self.spv.intType(.unsigned, backing_bits); |
| 1201 | 1246 | } |
| 1202 | 1247 | |
| ... | ... | @@ -1453,7 +1498,7 @@ const DeclGen = struct { |
| 1453 | 1498 | // Note: Don't cache this pointer type, it would mess up the recursive pointer functionality |
| 1454 | 1499 | // in ptrType()! |
| 1455 | 1500 | |
| 1456 | | const storage_class = spvStorageClass(ptr_info.flags.address_space); |
| 1501 | const storage_class = self.spvStorageClass(ptr_info.flags.address_space); |
| 1457 | 1502 | const ptr_ty_ref = try self.ptrType(Type.fromInterned(ptr_info.child), storage_class); |
| 1458 | 1503 | |
| 1459 | 1504 | if (ptr_info.flags.size != .Slice) { |
| ... | ... | @@ -1474,8 +1519,14 @@ const DeclGen = struct { |
| 1474 | 1519 | |
| 1475 | 1520 | const elem_ty = ty.childType(mod); |
| 1476 | 1521 | const elem_ty_ref = try self.resolveType(elem_ty, .indirect); |
| 1522 | const len = ty.vectorLen(mod); |
| 1523 | const is_scalar = elem_ty.isNumeric(mod) or elem_ty.toIntern() == .bool_type; |
| 1524 | |
| 1525 | const ty_ref = if (is_scalar and len > 1 and len <= 4) |
| 1526 | try self.spv.vectorType(ty.vectorLen(mod), elem_ty_ref) |
| 1527 | else |
| 1528 | try self.spv.arrayType(ty.vectorLen(mod), elem_ty_ref); |
| 1477 | 1529 | |
| 1478 | | const ty_ref = try self.spv.arrayType(ty.vectorLen(mod), elem_ty_ref); |
| 1479 | 1530 | try self.type_map.put(self.gpa, ty.toIntern(), .{ .ty_ref = ty_ref }); |
| 1480 | 1531 | return ty_ref; |
| 1481 | 1532 | }, |
| ... | ... | @@ -1634,13 +1685,20 @@ const DeclGen = struct { |
| 1634 | 1685 | } |
| 1635 | 1686 | } |
| 1636 | 1687 | |
| 1637 | | fn spvStorageClass(as: std.builtin.AddressSpace) StorageClass { |
| 1688 | fn spvStorageClass(self: *DeclGen, as: std.builtin.AddressSpace) StorageClass { |
| 1689 | const target = self.getTarget(); |
| 1638 | 1690 | return switch (as) { |
| 1639 | | .generic => .Generic, |
| 1691 | .generic => switch (target.os.tag) { |
| 1692 | .vulkan => .Private, |
| 1693 | else => .Generic, |
| 1694 | }, |
| 1640 | 1695 | .shared => .Workgroup, |
| 1641 | 1696 | .local => .Private, |
| 1642 | 1697 | .global => .CrossWorkgroup, |
| 1643 | 1698 | .constant => .UniformConstant, |
| 1699 | .input => .Input, |
| 1700 | .output => .Output, |
| 1701 | .uniform => .Uniform, |
| 1644 | 1702 | .gs, |
| 1645 | 1703 | .fs, |
| 1646 | 1704 | .ss, |
| ... | ... | @@ -1920,7 +1978,7 @@ const DeclGen = struct { |
| 1920 | 1978 | // point name is the same as a different OpName. |
| 1921 | 1979 | const test_name = try std.fmt.allocPrint(self.gpa, "test {s}", .{name}); |
| 1922 | 1980 | defer self.gpa.free(test_name); |
| 1923 | | try self.spv.declareEntryPoint(spv_decl_index, test_name); |
| 1981 | try self.spv.declareEntryPoint(spv_decl_index, test_name, .Kernel); |
| 1924 | 1982 | } |
| 1925 | 1983 | |
| 1926 | 1984 | fn genDecl(self: *DeclGen) !void { |
| ... | ... | @@ -1928,6 +1986,7 @@ const DeclGen = struct { |
| 1928 | 1986 | const ip = &mod.intern_pool; |
| 1929 | 1987 | const decl = mod.declPtr(self.decl_index); |
| 1930 | 1988 | const spv_decl_index = try self.object.resolveDecl(mod, self.decl_index); |
| 1989 | const target = self.getTarget(); |
| 1931 | 1990 | |
| 1932 | 1991 | const decl_id = self.spv.declPtr(spv_decl_index).result_id; |
| 1933 | 1992 | |
| ... | ... | @@ -1994,30 +2053,24 @@ const DeclGen = struct { |
| 1994 | 2053 | try self.generateTestEntryPoint(fqn, spv_decl_index); |
| 1995 | 2054 | } |
| 1996 | 2055 | } else { |
| 1997 | | const init_val = if (decl.val.getVariable(mod)) |payload| |
| 1998 | | Value.fromInterned(payload.init) |
| 1999 | | else |
| 2000 | | decl.val; |
| 2001 | | |
| 2002 | | if (init_val.ip_index == .unreachable_value) { |
| 2003 | | return self.todo("importing extern variables", .{}); |
| 2004 | | } |
| 2005 | | |
| 2006 | | // Currently, initializers for CrossWorkgroup variables is not implemented |
| 2007 | | // in Mesa. Therefore we generate an initialization kernel instead. |
| 2008 | | |
| 2009 | | const void_ty_ref = try self.resolveType(Type.void, .direct); |
| 2010 | | |
| 2011 | | const initializer_proto_ty_ref = try self.spv.resolve(.{ .function_type = .{ |
| 2012 | | .return_type = void_ty_ref, |
| 2013 | | .parameters = &.{}, |
| 2014 | | } }); |
| 2056 | const opt_init_val: ?Value = blk: { |
| 2057 | if (decl.val.getVariable(mod)) |payload| { |
| 2058 | if (payload.is_extern) break :blk null; |
| 2059 | break :blk Value.fromInterned(payload.init); |
| 2060 | } |
| 2061 | break :blk decl.val; |
| 2062 | }; |
| 2015 | 2063 | |
| 2016 | 2064 | // Generate the actual variable for the global... |
| 2017 | | const final_storage_class = spvStorageClass(decl.@"addrspace"); |
| 2018 | | const actual_storage_class = switch (final_storage_class) { |
| 2019 | | .Generic => .CrossWorkgroup, |
| 2020 | | else => final_storage_class, |
| 2065 | const final_storage_class = self.spvStorageClass(decl.@"addrspace"); |
| 2066 | const actual_storage_class = blk: { |
| 2067 | if (target.os.tag != .vulkan) { |
| 2068 | break :blk switch (final_storage_class) { |
| 2069 | .Generic => .CrossWorkgroup, |
| 2070 | else => final_storage_class, |
| 2071 | }; |
| 2072 | } |
| 2073 | break :blk final_storage_class; |
| 2021 | 2074 | }; |
| 2022 | 2075 | |
| 2023 | 2076 | const ptr_ty_ref = try self.ptrType(decl.ty, actual_storage_class); |
| ... | ... | @@ -2028,37 +2081,51 @@ const DeclGen = struct { |
| 2028 | 2081 | .id_result = decl_id, |
| 2029 | 2082 | .storage_class = actual_storage_class, |
| 2030 | 2083 | }); |
| 2084 | const fqn = ip.stringToSlice(try decl.getFullyQualifiedName(self.module)); |
| 2085 | try self.spv.debugName(decl_id, fqn); |
| 2031 | 2086 | |
| 2032 | | // Now emit the instructions that initialize the variable. |
| 2033 | | const initializer_id = self.spv.allocId(); |
| 2034 | | try self.func.prologue.emit(self.spv.gpa, .OpFunction, .{ |
| 2035 | | .id_result_type = self.typeId(void_ty_ref), |
| 2036 | | .id_result = initializer_id, |
| 2037 | | .function_control = .{}, |
| 2038 | | .function_type = self.typeId(initializer_proto_ty_ref), |
| 2039 | | }); |
| 2040 | | const root_block_id = self.spv.allocId(); |
| 2041 | | try self.func.prologue.emit(self.spv.gpa, .OpLabel, .{ |
| 2042 | | .id_result = root_block_id, |
| 2043 | | }); |
| 2044 | | self.current_block_label = root_block_id; |
| 2087 | if (opt_init_val) |init_val| { |
| 2088 | // Currently, initializers for CrossWorkgroup variables is not implemented |
| 2089 | // in Mesa. Therefore we generate an initialization kernel instead. |
| 2090 | const void_ty_ref = try self.resolveType(Type.void, .direct); |
| 2045 | 2091 | |
| 2046 | | const val_id = try self.constant(decl.ty, init_val, .indirect); |
| 2047 | | try self.func.body.emit(self.spv.gpa, .OpStore, .{ |
| 2048 | | .pointer = decl_id, |
| 2049 | | .object = val_id, |
| 2050 | | }); |
| 2092 | const initializer_proto_ty_ref = try self.spv.resolve(.{ .function_type = .{ |
| 2093 | .return_type = void_ty_ref, |
| 2094 | .parameters = &.{}, |
| 2095 | } }); |
| 2096 | |
| 2097 | // Now emit the instructions that initialize the variable. |
| 2098 | const initializer_id = self.spv.allocId(); |
| 2099 | try self.func.prologue.emit(self.spv.gpa, .OpFunction, .{ |
| 2100 | .id_result_type = self.typeId(void_ty_ref), |
| 2101 | .id_result = initializer_id, |
| 2102 | .function_control = .{}, |
| 2103 | .function_type = self.typeId(initializer_proto_ty_ref), |
| 2104 | }); |
| 2105 | const root_block_id = self.spv.allocId(); |
| 2106 | try self.func.prologue.emit(self.spv.gpa, .OpLabel, .{ |
| 2107 | .id_result = root_block_id, |
| 2108 | }); |
| 2109 | self.current_block_label = root_block_id; |
| 2051 | 2110 | |
| 2052 | | // TODO: We should be able to get rid of this by now... |
| 2053 | | self.spv.endGlobal(spv_decl_index, begin, decl_id, initializer_id); |
| 2111 | const val_id = try self.constant(decl.ty, init_val, .indirect); |
| 2112 | try self.func.body.emit(self.spv.gpa, .OpStore, .{ |
| 2113 | .pointer = decl_id, |
| 2114 | .object = val_id, |
| 2115 | }); |
| 2054 | 2116 | |
| 2055 | | try self.func.body.emit(self.spv.gpa, .OpReturn, {}); |
| 2056 | | try self.func.body.emit(self.spv.gpa, .OpFunctionEnd, {}); |
| 2057 | | try self.spv.addFunction(spv_decl_index, self.func); |
| 2117 | // TODO: We should be able to get rid of this by now... |
| 2118 | self.spv.endGlobal(spv_decl_index, begin, decl_id, initializer_id); |
| 2058 | 2119 | |
| 2059 | | const fqn = ip.stringToSlice(try decl.getFullyQualifiedName(self.module)); |
| 2060 | | try self.spv.debugName(decl_id, fqn); |
| 2061 | | try self.spv.debugNameFmt(initializer_id, "initializer of {s}", .{fqn}); |
| 2120 | try self.func.body.emit(self.spv.gpa, .OpReturn, {}); |
| 2121 | try self.func.body.emit(self.spv.gpa, .OpFunctionEnd, {}); |
| 2122 | try self.spv.addFunction(spv_decl_index, self.func); |
| 2123 | |
| 2124 | try self.spv.debugNameFmt(initializer_id, "initializer of {s}", .{fqn}); |
| 2125 | } else { |
| 2126 | self.spv.endGlobal(spv_decl_index, begin, decl_id, null); |
| 2127 | try self.spv.declareDeclDeps(spv_decl_index, &.{}); |
| 2128 | } |
| 2062 | 2129 | } |
| 2063 | 2130 | } |
| 2064 | 2131 | |
| ... | ... | @@ -3654,7 +3721,19 @@ const DeclGen = struct { |
| 3654 | 3721 | constituents[0..index], |
| 3655 | 3722 | ); |
| 3656 | 3723 | }, |
| 3657 | | .Vector, .Array => { |
| 3724 | .Vector => { |
| 3725 | const n_elems = result_ty.vectorLen(mod); |
| 3726 | const elem_ids = try self.gpa.alloc(IdRef, n_elems); |
| 3727 | defer self.gpa.free(elem_ids); |
| 3728 | |
| 3729 | for (elements, 0..) |element, i| { |
| 3730 | const id = try self.resolve(element); |
| 3731 | elem_ids[i] = try self.convertToIndirect(result_ty.childType(mod), id); |
| 3732 | } |
| 3733 | |
| 3734 | return try self.constructVector(result_ty, elem_ids); |
| 3735 | }, |
| 3736 | .Array => { |
| 3658 | 3737 | const array_info = result_ty.arrayInfo(mod); |
| 3659 | 3738 | const n_elems: usize = @intCast(result_ty.arrayLenIncludingSentinel(mod)); |
| 3660 | 3739 | const elem_ids = try self.gpa.alloc(IdRef, n_elems); |
| ... | ... | @@ -3761,7 +3840,7 @@ const DeclGen = struct { |
| 3761 | 3840 | const mod = self.module; |
| 3762 | 3841 | // Construct new pointer type for the resulting pointer |
| 3763 | 3842 | const elem_ty = ptr_ty.elemType2(mod); // use elemType() so that we get T for *[N]T. |
| 3764 | | const elem_ptr_ty_ref = try self.ptrType(elem_ty, spvStorageClass(ptr_ty.ptrAddressSpace(mod))); |
| 3843 | const elem_ptr_ty_ref = try self.ptrType(elem_ty, self.spvStorageClass(ptr_ty.ptrAddressSpace(mod))); |
| 3765 | 3844 | if (ptr_ty.isSinglePointer(mod)) { |
| 3766 | 3845 | // Pointer-to-array. In this case, the resulting pointer is not of the same type |
| 3767 | 3846 | // as the ptr_ty (we want a *T, not a *[N]T), and hence we need to use accessChain. |
| ... | ... | @@ -3835,7 +3914,7 @@ const DeclGen = struct { |
| 3835 | 3914 | const vector_ty = vector_ptr_ty.childType(mod); |
| 3836 | 3915 | const scalar_ty = vector_ty.scalarType(mod); |
| 3837 | 3916 | |
| 3838 | | const storage_class = spvStorageClass(vector_ptr_ty.ptrAddressSpace(mod)); |
| 3917 | const storage_class = self.spvStorageClass(vector_ptr_ty.ptrAddressSpace(mod)); |
| 3839 | 3918 | const scalar_ptr_ty_ref = try self.ptrType(scalar_ty, storage_class); |
| 3840 | 3919 | |
| 3841 | 3920 | const vector_ptr = try self.resolve(data.vector_ptr); |
| ... | ... | @@ -3858,7 +3937,7 @@ const DeclGen = struct { |
| 3858 | 3937 | if (layout.tag_size == 0) return; |
| 3859 | 3938 | |
| 3860 | 3939 | const tag_ty = un_ty.unionTagTypeSafety(mod).?; |
| 3861 | | const tag_ptr_ty_ref = try self.ptrType(tag_ty, spvStorageClass(un_ptr_ty.ptrAddressSpace(mod))); |
| 3940 | const tag_ptr_ty_ref = try self.ptrType(tag_ty, self.spvStorageClass(un_ptr_ty.ptrAddressSpace(mod))); |
| 3862 | 3941 | |
| 3863 | 3942 | const union_ptr_id = try self.resolve(bin_op.lhs); |
| 3864 | 3943 | const new_tag_id = try self.resolve(bin_op.rhs); |
| ... | ... | @@ -4079,7 +4158,7 @@ const DeclGen = struct { |
| 4079 | 4158 | return try self.spv.constUndef(result_ty_ref); |
| 4080 | 4159 | } |
| 4081 | 4160 | |
| 4082 | | const storage_class = spvStorageClass(object_ptr_ty.ptrAddressSpace(mod)); |
| 4161 | const storage_class = self.spvStorageClass(object_ptr_ty.ptrAddressSpace(mod)); |
| 4083 | 4162 | const pl_ptr_ty_ref = try self.ptrType(layout.payload_ty, storage_class); |
| 4084 | 4163 | const pl_ptr_id = try self.accessChain(pl_ptr_ty_ref, object_ptr, &.{layout.payload_index}); |
| 4085 | 4164 | |
| ... | ... | @@ -4134,17 +4213,16 @@ const DeclGen = struct { |
| 4134 | 4213 | .initializer = options.initializer, |
| 4135 | 4214 | }); |
| 4136 | 4215 | |
| 4216 | const target = self.getTarget(); |
| 4217 | if (target.os.tag == .vulkan) { |
| 4218 | return var_id; |
| 4219 | } |
| 4220 | |
| 4137 | 4221 | switch (options.storage_class) { |
| 4138 | 4222 | .Generic => { |
| 4139 | 4223 | const ptr_gn_ty_ref = try self.ptrType(ty, .Generic); |
| 4140 | 4224 | // Convert to a generic pointer |
| 4141 | | const result_id = self.spv.allocId(); |
| 4142 | | try self.func.body.emit(self.spv.gpa, .OpPtrCastToGeneric, .{ |
| 4143 | | .id_result_type = self.typeId(ptr_gn_ty_ref), |
| 4144 | | .id_result = result_id, |
| 4145 | | .pointer = var_id, |
| 4146 | | }); |
| 4147 | | return result_id; |
| 4225 | return self.castToGeneric(self.typeId(ptr_gn_ty_ref), var_id); |
| 4148 | 4226 | }, |
| 4149 | 4227 | .Function => return var_id, |
| 4150 | 4228 | else => unreachable, |
| ... | ... | @@ -4880,7 +4958,7 @@ const DeclGen = struct { |
| 4880 | 4958 | const is_non_null_id = blk: { |
| 4881 | 4959 | if (is_pointer) { |
| 4882 | 4960 | if (payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 4883 | | const storage_class = spvStorageClass(operand_ty.ptrAddressSpace(mod)); |
| 4961 | const storage_class = self.spvStorageClass(operand_ty.ptrAddressSpace(mod)); |
| 4884 | 4962 | const bool_ptr_ty = try self.ptrType(Type.bool, storage_class); |
| 4885 | 4963 | const tag_ptr_id = try self.accessChain(bool_ptr_ty, operand_id, &.{1}); |
| 4886 | 4964 | break :blk try self.load(Type.bool, tag_ptr_id, .{}); |