| ... | @@ -17,6 +17,8 @@ uav_link: std.AutoHashMapUnmanaged(struct { InternPool.Index, spec.StorageClass | ... | @@ -17,6 +17,8 @@ uav_link: std.AutoHashMapUnmanaged(struct { InternPool.Index, spec.StorageClass |
| 17 | entry_points: std.array_hash_map.Auto(Id, EntryPoint) = .empty, | 17 | entry_points: std.array_hash_map.Auto(Id, EntryPoint) = .empty, |
| 18 | error_buffer: ?Decl.Index = null, | 18 | error_buffer: ?Decl.Index = null, |
| 19 | struct_types: std.array_hash_map.Custom(StructType, Id, StructType.HashContext, true) = .empty, | 19 | struct_types: std.array_hash_map.Custom(StructType, Id, StructType.HashContext, true) = .empty, |
| | 20 | /// SPIR-V ids of OpVariables whose pointee is a Block struct |
| | 21 | block_var_ids: std.AutoHashMapUnmanaged(Id, void) = .empty, |
| 20 | builtins: std.AutoHashMapUnmanaged(struct { spec.BuiltIn, spec.StorageClass }, Decl.Index) = .empty, | 22 | builtins: std.AutoHashMapUnmanaged(struct { spec.BuiltIn, spec.StorageClass }, Decl.Index) = .empty, |
| 21 | sections: struct { | 23 | sections: struct { |
| 22 | // Module layout, according to SPIR-V Spec section 2.4, "Logical Layout of a Module". | 24 | // Module layout, according to SPIR-V Spec section 2.4, "Logical Layout of a Module". |
| ... | @@ -181,6 +183,7 @@ pub fn deinit(cg: *CodeGen) void { | ... | @@ -181,6 +183,7 @@ pub fn deinit(cg: *CodeGen) void { |
| 181 | cg.sections.functions.deinit(gpa); | 183 | cg.sections.functions.deinit(gpa); |
| 182 | | 184 | |
| 183 | cg.struct_types.deinit(gpa); | 185 | cg.struct_types.deinit(gpa); |
| | 186 | cg.block_var_ids.deinit(gpa); |
| 184 | cg.builtins.deinit(gpa); | 187 | cg.builtins.deinit(gpa); |
| 185 | | 188 | |
| 186 | cg.decls.deinit(gpa); | 189 | cg.decls.deinit(gpa); |
| ... | @@ -587,6 +590,71 @@ pub fn structType( | ... | @@ -587,6 +590,71 @@ pub fn structType( |
| 587 | return result_id; | 590 | return result_id; |
| 588 | } | 591 | } |
| 589 | | 592 | |
| | 593 | /// Returns the layout-decorated variant of `ty` for use inside a Vulkan/OpenGL |
| | 594 | /// interface block. Vulkan forbids nested Block decorations, so recursive calls |
| | 595 | /// always pass `false`. |
| | 596 | /// |
| | 597 | /// This is distinct from `resolveType` because SPIR-V forbids such decorations |
| | 598 | /// on the pointee of a Function-scope variable. |
| | 599 | pub fn layoutType(cg: *CodeGen, ty: Type, is_block_root: bool) Error!Id { |
| | 600 | const gpa = cg.gpa; |
| | 601 | const zcu = cg.zcu; |
| | 602 | const ip = &zcu.intern_pool; |
| | 603 | |
| | 604 | const result_id: Id = switch (ty.zigTypeTag(zcu)) { |
| | 605 | .@"struct" => id: { |
| | 606 | const struct_type = ip.loadStructType(ty.toIntern()); |
| | 607 | if (struct_type.layout == .@"packed") return cg.resolveType(ty, .indirect); |
| | 608 | |
| | 609 | var member_types: std.ArrayList(Id) = .empty; |
| | 610 | defer member_types.deinit(gpa); |
| | 611 | const id = cg.allocId(); |
| | 612 | if (is_block_root) try cg.decorate(id, .block); |
| | 613 | var it = struct_type.iterateRuntimeOrder(ip); |
| | 614 | while (it.next()) |field_index| { |
| | 615 | const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[field_index]); |
| | 616 | if (!field_ty.hasRuntimeBits(zcu)) continue; |
| | 617 | try cg.decorateMember(id, @intCast(member_types.items.len), .{ .offset = .{ |
| | 618 | .byte_offset = @intCast(ty.structFieldOffset(field_index, zcu)), |
| | 619 | } }); |
| | 620 | try member_types.append(gpa, try cg.layoutType(field_ty, false)); |
| | 621 | } |
| | 622 | try cg.sections.globals.emit(gpa, .OpTypeStruct, .{ |
| | 623 | .id_result = id, |
| | 624 | .id_ref = member_types.items, |
| | 625 | }); |
| | 626 | break :id id; |
| | 627 | }, |
| | 628 | .array => id: { |
| | 629 | const elem_ty = ty.childType(zcu); |
| | 630 | const elem_ty_id = try cg.layoutType(elem_ty, false); |
| | 631 | const total_len = std.math.cast(u32, ty.arrayLenIncludingSentinel(zcu)) orelse |
| | 632 | return cg.fail("array type of {} elements is too large", .{ty.arrayLenIncludingSentinel(zcu)}); |
| | 633 | const id = try cg.arrayType(try cg.constInt(.u32, total_len), elem_ty_id); |
| | 634 | if (elem_ty.hasRuntimeBits(zcu)) try cg.decorate(id, .{ |
| | 635 | .array_stride = .{ .array_stride = @intCast(elem_ty.abiSize(zcu)) }, |
| | 636 | }); |
| | 637 | break :id id; |
| | 638 | }, |
| | 639 | .spirv => if (ty.isSpirvRuntimeArray(zcu)) id: { |
| | 640 | const elem_ty = ty.childType(zcu); |
| | 641 | const elem_ty_id = try cg.layoutType(elem_ty, false); |
| | 642 | const id = cg.allocId(); |
| | 643 | try cg.sections.globals.emit(gpa, .OpTypeRuntimeArray, .{ |
| | 644 | .id_result = id, |
| | 645 | .element_type = elem_ty_id, |
| | 646 | }); |
| | 647 | if (elem_ty.hasRuntimeBits(zcu)) try cg.decorate(id, .{ |
| | 648 | .array_stride = .{ .array_stride = @intCast(elem_ty.abiSize(zcu)) }, |
| | 649 | }); |
| | 650 | break :id id; |
| | 651 | } else return cg.resolveType(ty, .indirect), |
| | 652 | else => return cg.resolveType(ty, .indirect), |
| | 653 | }; |
| | 654 | |
| | 655 | return result_id; |
| | 656 | } |
| | 657 | |
| 590 | pub fn functionType(cg: *CodeGen, return_ty_id: Id, param_type_ids: []const Id) !Id { | 658 | pub fn functionType(cg: *CodeGen, return_ty_id: Id, param_type_ids: []const Id) !Id { |
| 591 | const result_id = cg.allocId(); | 659 | const result_id = cg.allocId(); |
| 592 | try cg.sections.globals.emit(cg.gpa, .OpTypeFunction, .{ | 660 | try cg.sections.globals.emit(cg.gpa, .OpTypeFunction, .{ |
| ... | @@ -806,7 +874,8 @@ pub fn genNav(cg: *CodeGen, do_codegen: bool) Error!void { | ... | @@ -806,7 +874,8 @@ pub fn genNav(cg: *CodeGen, do_codegen: bool) Error!void { |
| 806 | const storage_class = cg.storageClass(nav.resolved.?.@"addrspace"); | 874 | const storage_class = cg.storageClass(nav.resolved.?.@"addrspace"); |
| 807 | assert(storage_class != .generic); // These should be instance globals | 875 | assert(storage_class != .generic); // These should be instance globals |
| 808 | | 876 | |
| 809 | const ty_id = try cg.resolveType(ty, .indirect); | 877 | const as = nav.resolved.?.@"addrspace"; |
| | 878 | const ty_id = try cg.pointeeType(as, ty, true); |
| 810 | const ptr_ty_id = try cg.ptrType(ty_id, storage_class); | 879 | const ptr_ty_id = try cg.ptrType(ty_id, storage_class); |
| 811 | | 880 | |
| 812 | try cg.sections.globals.emit(gpa, .OpVariable, .{ | 881 | try cg.sections.globals.emit(gpa, .OpVariable, .{ |
| ... | @@ -819,15 +888,11 @@ pub fn genNav(cg: *CodeGen, do_codegen: bool) Error!void { | ... | @@ -819,15 +888,11 @@ pub fn genNav(cg: *CodeGen, do_codegen: bool) Error!void { |
| 819 | .vulkan, .opengl => { | 888 | .vulkan, .opengl => { |
| 820 | switch (storage_class) { | 889 | switch (storage_class) { |
| 821 | .uniform, .push_constant, .storage_buffer, .physical_storage_buffer => { | 890 | .uniform, .push_constant, .storage_buffer, .physical_storage_buffer => { |
| 822 | if (ty.zigTypeTag(zcu) == .@"struct" and storage_class != .physical_storage_buffer) { | | |
| 823 | try cg.decorate(ty_id, .block); | | |
| 824 | } | | |
| 825 | | | |
| 826 | if (ty.hasRuntimeBits(zcu)) { | 891 | if (ty.hasRuntimeBits(zcu)) { |
| 827 | try cg.decorate(ptr_ty_id, .{ | 892 | try cg.decorate(ptr_ty_id, .{ |
| 828 | .array_stride = .{ .array_stride = @intCast(ty.abiSize(zcu)) }, | 893 | .array_stride = .{ .array_stride = @intCast(ty.abiSize(zcu)) }, |
| 829 | }); | 894 | }); |
| 830 | try cg.decorateLayout(ty, ty_id); | 895 | if (!cg.needsLayout(as, ty)) try cg.decorateLayout(ty, ty_id); |
| 831 | } | 896 | } |
| 832 | }, | 897 | }, |
| 833 | else => {}, | 898 | else => {}, |
| ... | @@ -1815,6 +1880,9 @@ fn derivePtr(cg: *CodeGen, derivation: Value.PointerDeriveStep) !Id { | ... | @@ -1815,6 +1880,9 @@ fn derivePtr(cg: *CodeGen, derivation: Value.PointerDeriveStep) !Id { |
| 1815 | | 1880 | |
| 1816 | const nav_ty_id = try cg.resolveType(nav_ty, .indirect); | 1881 | const nav_ty_id = try cg.resolveType(nav_ty, .indirect); |
| 1817 | const decl_ptr_ty_id = try cg.ptrType(nav_ty_id, storage_class); | 1882 | const decl_ptr_ty_id = try cg.ptrType(nav_ty_id, storage_class); |
| | 1883 | if (nav_ty.zigTypeTag(zcu) == .@"struct" and cg.needsLayout(nav.resolved.?.@"addrspace", nav_ty)) { |
| | 1884 | try cg.block_var_ids.put(gpa, spv_decl.result_id, {}); |
| | 1885 | } |
| 1818 | if (decl_ptr_ty_id == ty_id) return spv_decl.result_id; | 1886 | if (decl_ptr_ty_id == ty_id) return spv_decl.result_id; |
| 1819 | switch (target.os.tag) { | 1887 | switch (target.os.tag) { |
| 1820 | .vulkan, .opengl => return spv_decl.result_id, | 1888 | .vulkan, .opengl => return spv_decl.result_id, |
| ... | @@ -1879,7 +1947,6 @@ fn derivePtr(cg: *CodeGen, derivation: Value.PointerDeriveStep) !Id { | ... | @@ -1879,7 +1947,6 @@ fn derivePtr(cg: *CodeGen, derivation: Value.PointerDeriveStep) !Id { |
| 1879 | .offset_and_cast => |oac| { | 1947 | .offset_and_cast => |oac| { |
| 1880 | const parent_ptr_id = try cg.derivePtr(oac.parent.*); | 1948 | const parent_ptr_id = try cg.derivePtr(oac.parent.*); |
| 1881 | const parent_ptr_ty = try oac.parent.ptrType(pt); | 1949 | const parent_ptr_ty = try oac.parent.ptrType(pt); |
| 1882 | const result_ty_id = try cg.resolveType(oac.new_ptr_ty, .direct); | | |
| 1883 | | 1950 | |
| 1884 | if (oac.new_ptr_ty.ptrInfo(zcu).flags.vector_index != .none) { | 1951 | if (oac.new_ptr_ty.ptrInfo(zcu).flags.vector_index != .none) { |
| 1885 | return parent_ptr_id; | 1952 | return parent_ptr_id; |
| ... | @@ -1890,13 +1957,25 @@ fn derivePtr(cg: *CodeGen, derivation: Value.PointerDeriveStep) !Id { | ... | @@ -1890,13 +1957,25 @@ fn derivePtr(cg: *CodeGen, derivation: Value.PointerDeriveStep) !Id { |
| 1890 | var cur = parent_ptr_ty.childType(zcu); | 1957 | var cur = parent_ptr_ty.childType(zcu); |
| 1891 | const dst_child = oac.new_ptr_ty.childType(zcu); | 1958 | const dst_child = oac.new_ptr_ty.childType(zcu); |
| 1892 | while (cur.toIntern() != dst_child.toIntern()) { | 1959 | while (cur.toIntern() != dst_child.toIntern()) { |
| 1893 | if (cur.zigTypeTag(zcu) == .array) { | 1960 | switch (cur.zigTypeTag(zcu)) { |
| 1894 | cur = cur.childType(zcu); | 1961 | .array => { |
| 1895 | depth += 1; | 1962 | cur = cur.childType(zcu); |
| 1896 | } else break; | 1963 | depth += 1; |
| | 1964 | }, |
| | 1965 | .@"struct" => { |
| | 1966 | if (cur.structFieldCount(zcu) == 0) break; |
| | 1967 | if (cur.structFieldOffset(0, zcu) != 0) break; |
| | 1968 | cur = cur.fieldType(0, zcu); |
| | 1969 | depth += 1; |
| | 1970 | }, |
| | 1971 | else => break, |
| | 1972 | } |
| 1897 | } | 1973 | } |
| 1898 | if (cur.toIntern() == dst_child.toIntern()) { | 1974 | if (cur.toIntern() == dst_child.toIntern()) { |
| 1899 | if (depth != 0) { | 1975 | if (depth != 0) { |
| | 1976 | const as = oac.new_ptr_ty.ptrAddressSpace(zcu); |
| | 1977 | const child_ty_id = try cg.pointeeType(as, dst_child, false); |
| | 1978 | const result_ty_id = try cg.ptrType(child_ty_id, cg.storageClass(as)); |
| 1900 | const scratch_top = cg.id_scratch.items.len; | 1979 | const scratch_top = cg.id_scratch.items.len; |
| 1901 | defer cg.id_scratch.shrinkRetainingCapacity(scratch_top); | 1980 | defer cg.id_scratch.shrinkRetainingCapacity(scratch_top); |
| 1902 | const zero = try cg.constInt(.u32, 0); | 1981 | const zero = try cg.constInt(.u32, 0); |
| ... | @@ -1907,6 +1986,7 @@ fn derivePtr(cg: *CodeGen, derivation: Value.PointerDeriveStep) !Id { | ... | @@ -1907,6 +1986,7 @@ fn derivePtr(cg: *CodeGen, derivation: Value.PointerDeriveStep) !Id { |
| 1907 | return parent_ptr_id; | 1986 | return parent_ptr_id; |
| 1908 | } | 1987 | } |
| 1909 | } | 1988 | } |
| | 1989 | const result_ty_id = try cg.resolveType(oac.new_ptr_ty, .direct); |
| 1910 | if (target.os.tag == .opencl) { | 1990 | if (target.os.tag == .opencl) { |
| 1911 | const result_ptr_id = cg.allocId(); | 1991 | const result_ptr_id = cg.allocId(); |
| 1912 | try cg.body.emit(gpa, .OpBitcast, .{ | 1992 | try cg.body.emit(gpa, .OpBitcast, .{ |
| ... | @@ -4079,33 +4159,77 @@ fn extractVectorComponent(cg: *CodeGen, result_ty: Type, vector_id: Id, field: u | ... | @@ -4079,33 +4159,77 @@ fn extractVectorComponent(cg: *CodeGen, result_ty: Type, vector_id: Id, field: u |
| 4079 | | 4159 | |
| 4080 | const MemoryOptions = struct { | 4160 | const MemoryOptions = struct { |
| 4081 | is_volatile: bool = false, | 4161 | is_volatile: bool = false, |
| | 4162 | ptr_address_space: std.lang.AddressSpace = .generic, |
| 4082 | }; | 4163 | }; |
| 4083 | | 4164 | |
| | 4165 | /// Returns true if a pointee at address space must use the |
| | 4166 | /// layout-decorated variant rather than the bare type. |
| | 4167 | fn needsLayout(cg: *CodeGen, as: std.lang.AddressSpace, pointee_ty: Type) bool { |
| | 4168 | const target = cg.zcu.getTarget(); |
| | 4169 | if (target.os.tag != .vulkan and target.os.tag != .opengl) return false; |
| | 4170 | switch (as) { |
| | 4171 | .uniform, .push_constant, .storage_buffer => {}, |
| | 4172 | else => return false, |
| | 4173 | } |
| | 4174 | return switch (pointee_ty.zigTypeTag(cg.zcu)) { |
| | 4175 | .@"struct", .array => true, |
| | 4176 | .spirv => pointee_ty.isSpirvRuntimeArray(cg.zcu), |
| | 4177 | else => false, |
| | 4178 | }; |
| | 4179 | } |
| | 4180 | |
| | 4181 | fn pointeeType(cg: *CodeGen, as: std.lang.AddressSpace, ty: Type, is_block_root: bool) !Id { |
| | 4182 | return if (cg.needsLayout(as, ty)) |
| | 4183 | cg.layoutType(ty, is_block_root) |
| | 4184 | else |
| | 4185 | cg.resolveType(ty, .indirect); |
| | 4186 | } |
| | 4187 | |
| | 4188 | fn convertLayout(cg: *CodeGen, dst_ty_id: Id, src_id: Id, src_ty_id: Id) !Id { |
| | 4189 | if (dst_ty_id == src_ty_id) return src_id; |
| | 4190 | const id = cg.allocId(); |
| | 4191 | try cg.body.emit(cg.gpa, .OpCopyLogical, .{ |
| | 4192 | .id_result_type = dst_ty_id, |
| | 4193 | .id_result = id, |
| | 4194 | .operand = src_id, |
| | 4195 | }); |
| | 4196 | return id; |
| | 4197 | } |
| | 4198 | |
| 4084 | fn load(cg: *CodeGen, value_ty: Type, ptr_id: Id, options: MemoryOptions) !Id { | 4199 | fn load(cg: *CodeGen, value_ty: Type, ptr_id: Id, options: MemoryOptions) !Id { |
| 4085 | const zcu = cg.zcu; | 4200 | const zcu = cg.zcu; |
| 4086 | const alignment: u32 = @intCast(value_ty.abiAlignment(zcu).toByteUnits().?); | 4201 | const alignment: u32 = @intCast(value_ty.abiAlignment(zcu).toByteUnits().?); |
| 4087 | const indirect_value_ty_id = try cg.resolveType(value_ty, .indirect); | 4202 | const bare_ty_id = try cg.resolveType(value_ty, .indirect); |
| 4088 | const result_id = cg.allocId(); | 4203 | const load_ty_id = if (cg.needsLayout(options.ptr_address_space, value_ty)) |
| 4089 | const access: spec.MemoryAccess.Extended = .{ | 4204 | try cg.layoutType(value_ty, cg.block_var_ids.contains(ptr_id)) |
| 4090 | .@"volatile" = options.is_volatile, | 4205 | else |
| 4091 | .aligned = .{ .literal_integer = alignment }, | 4206 | bare_ty_id; |
| 4092 | }; | 4207 | const loaded_id = cg.allocId(); |
| 4093 | try cg.body.emit(cg.gpa, .OpLoad, .{ | 4208 | try cg.body.emit(cg.gpa, .OpLoad, .{ |
| 4094 | .id_result_type = indirect_value_ty_id, | 4209 | .id_result_type = load_ty_id, |
| 4095 | .id_result = result_id, | 4210 | .id_result = loaded_id, |
| 4096 | .pointer = ptr_id, | 4211 | .pointer = ptr_id, |
| 4097 | .memory_access = access, | 4212 | .memory_access = .{ |
| | 4213 | .@"volatile" = options.is_volatile, |
| | 4214 | .aligned = .{ .literal_integer = alignment }, |
| | 4215 | }, |
| 4098 | }); | 4216 | }); |
| | 4217 | const result_id = try cg.convertLayout(bare_ty_id, loaded_id, load_ty_id); |
| 4099 | return try cg.convertToDirect(value_ty, result_id); | 4218 | return try cg.convertToDirect(value_ty, result_id); |
| 4100 | } | 4219 | } |
| 4101 | | 4220 | |
| 4102 | fn store(cg: *CodeGen, value_ty: Type, ptr_id: Id, value_id: Id, options: MemoryOptions) !void { | 4221 | fn store(cg: *CodeGen, value_ty: Type, ptr_id: Id, value_id: Id, options: MemoryOptions) !void { |
| 4103 | const indirect_value_id = try cg.convertToIndirect(value_ty, value_id); | 4222 | const bare_value_id = try cg.convertToIndirect(value_ty, value_id); |
| 4104 | const access: spec.MemoryAccess.Extended = .{ .@"volatile" = options.is_volatile }; | 4223 | const bare_ty_id = try cg.resolveType(value_ty, .indirect); |
| | 4224 | const store_ty_id = if (cg.needsLayout(options.ptr_address_space, value_ty)) |
| | 4225 | try cg.layoutType(value_ty, cg.block_var_ids.contains(ptr_id)) |
| | 4226 | else |
| | 4227 | bare_ty_id; |
| | 4228 | const object_id = try cg.convertLayout(store_ty_id, bare_value_id, bare_ty_id); |
| 4105 | try cg.body.emit(cg.gpa, .OpStore, .{ | 4229 | try cg.body.emit(cg.gpa, .OpStore, .{ |
| 4106 | .pointer = ptr_id, | 4230 | .pointer = ptr_id, |
| 4107 | .object = indirect_value_id, | 4231 | .object = object_id, |
| 4108 | .memory_access = access, | 4232 | .memory_access = .{ .@"volatile" = options.is_volatile }, |
| 4109 | }); | 4233 | }); |
| 4110 | } | 4234 | } |
| 4111 | | 4235 | |
| ... | @@ -5520,23 +5644,18 @@ fn ptrAccessChain( | ... | @@ -5520,23 +5644,18 @@ fn ptrAccessChain( |
| 5520 | | 5644 | |
| 5521 | fn ptrAdd(cg: *CodeGen, result_ty: Type, ptr_ty: Type, ptr_id: Id, offset_id: Id) !Id { | 5645 | fn ptrAdd(cg: *CodeGen, result_ty: Type, ptr_ty: Type, ptr_id: Id, offset_id: Id) !Id { |
| 5522 | const zcu = cg.zcu; | 5646 | const zcu = cg.zcu; |
| 5523 | const result_ty_id = try cg.resolveType(result_ty, .direct); | 5647 | const as = result_ty.ptrAddressSpace(zcu); |
| 5524 | | 5648 | const child_ty_id = try cg.pointeeType(as, result_ty.childType(zcu), false); |
| 5525 | switch (ptr_ty.ptrSize(zcu)) { | 5649 | const result_ty_id = try cg.ptrType(child_ty_id, cg.storageClass(as)); |
| 5526 | .one => { | 5650 | return switch (ptr_ty.ptrSize(zcu)) { |
| 5527 | // Pointer to array | 5651 | .one => cg.accessChainId(result_ty_id, ptr_id, &.{offset_id}), |
| 5528 | // TODO: Is this correct? | 5652 | .c, .many => cg.ptrAccessChain(result_ty_id, ptr_id, offset_id, &.{}), |
| 5529 | return try cg.accessChainId(result_ty_id, ptr_id, &.{offset_id}); | 5653 | .slice => blk: { |
| 5530 | }, | | |
| 5531 | .c, .many => { | | |
| 5532 | return try cg.ptrAccessChain(result_ty_id, ptr_id, offset_id, &.{}); | | |
| 5533 | }, | | |
| 5534 | .slice => { | | |
| 5535 | // TODO: This is probably incorrect. A slice should be returned here, though this is what llvm does. | 5654 | // TODO: This is probably incorrect. A slice should be returned here, though this is what llvm does. |
| 5536 | const slice_ptr_id = try cg.extractField(result_ty, ptr_id, 0); | 5655 | const slice_ptr_id = try cg.extractField(result_ty, ptr_id, 0); |
| 5537 | return try cg.ptrAccessChain(result_ty_id, slice_ptr_id, offset_id, &.{}); | 5656 | break :blk cg.ptrAccessChain(result_ty_id, slice_ptr_id, offset_id, &.{}); |
| 5538 | }, | 5657 | }, |
| 5539 | } | 5658 | }; |
| 5540 | } | 5659 | } |
| 5541 | | 5660 | |
| 5542 | fn airPtrAdd(cg: *CodeGen, inst: Air.Inst.Index) !?Id { | 5661 | fn airPtrAdd(cg: *CodeGen, inst: Air.Inst.Index) !?Id { |
| ... | @@ -6482,16 +6601,16 @@ fn airSliceElemVal(cg: *CodeGen, inst: Air.Inst.Index) !?Id { | ... | @@ -6482,16 +6601,16 @@ fn airSliceElemVal(cg: *CodeGen, inst: Air.Inst.Index) !?Id { |
| 6482 | fn ptrElemPtr(cg: *CodeGen, ptr_ty: Type, ptr_id: Id, index_id: Id) !Id { | 6601 | fn ptrElemPtr(cg: *CodeGen, ptr_ty: Type, ptr_id: Id, index_id: Id) !Id { |
| 6483 | const zcu = cg.zcu; | 6602 | const zcu = cg.zcu; |
| 6484 | // Construct new pointer type for the resulting pointer | 6603 | // Construct new pointer type for the resulting pointer |
| 6485 | const elem_ty = ptr_ty.indexableElem(zcu); | 6604 | const as = ptr_ty.ptrAddressSpace(zcu); |
| 6486 | const elem_ty_id = try cg.resolveType(elem_ty, .indirect); | 6605 | const elem_ty_id = try cg.pointeeType(as, ptr_ty.indexableElem(zcu), false); |
| 6487 | const elem_ptr_ty_id = try cg.ptrType(elem_ty_id, cg.storageClass(ptr_ty.ptrAddressSpace(zcu))); | 6606 | const elem_ptr_ty_id = try cg.ptrType(elem_ty_id, cg.storageClass(as)); |
| 6488 | if (ptr_ty.isSinglePointer(zcu)) { | 6607 | if (ptr_ty.isSinglePointer(zcu)) { |
| 6489 | // Pointer-to-array. In this case, the resulting pointer is not of the same type | 6608 | // Pointer-to-array. In this case, the resulting pointer is not of the same type |
| 6490 | // as the ptr_ty (we want a *T, not a *[N]T), and hence we need to use accessChain. | 6609 | // as the ptr_ty (we want a *T, not a *[N]T), and hence we need to use accessChain. |
| 6491 | return try cg.accessChainId(elem_ptr_ty_id, ptr_id, &.{index_id}); | 6610 | return cg.accessChainId(elem_ptr_ty_id, ptr_id, &.{index_id}); |
| 6492 | } else { | 6611 | } else { |
| 6493 | // Resulting pointer type is the same as the ptr_ty, so use ptrAccessChain | 6612 | // Resulting pointer type is the same as the ptr_ty, so use ptrAccessChain |
| 6494 | return try cg.ptrAccessChain(elem_ptr_ty_id, ptr_id, index_id, &.{}); | 6613 | return cg.ptrAccessChain(elem_ptr_ty_id, ptr_id, index_id, &.{}); |
| 6495 | } | 6614 | } |
| 6496 | } | 6615 | } |
| 6497 | | 6616 | |
| ... | @@ -7375,7 +7494,10 @@ fn airLoad(cg: *CodeGen, inst: Air.Inst.Index) !?Id { | ... | @@ -7375,7 +7494,10 @@ fn airLoad(cg: *CodeGen, inst: Air.Inst.Index) !?Id { |
| 7375 | break :ptr_id try cg.accessChain(elem_ptr_ty_id, operand_ptr_id, &.{@intFromEnum(index)}); | 7494 | break :ptr_id try cg.accessChain(elem_ptr_ty_id, operand_ptr_id, &.{@intFromEnum(index)}); |
| 7376 | }, | 7495 | }, |
| 7377 | }; | 7496 | }; |
| 7378 | return try cg.load(elem_ty, ptr_id, .{ .is_volatile = ptr_info.flags.is_volatile }); | 7497 | return try cg.load(elem_ty, ptr_id, .{ |
| | 7498 | .is_volatile = ptr_info.flags.is_volatile, |
| | 7499 | .ptr_address_space = ptr_info.flags.address_space, |
| | 7500 | }); |
| 7379 | } | 7501 | } |
| 7380 | | 7502 | |
| 7381 | fn airStore(cg: *CodeGen, inst: Air.Inst.Index) !void { | 7503 | fn airStore(cg: *CodeGen, inst: Air.Inst.Index) !void { |
| ... | @@ -7447,7 +7569,10 @@ fn airStore(cg: *CodeGen, inst: Air.Inst.Index) !void { | ... | @@ -7447,7 +7569,10 @@ fn airStore(cg: *CodeGen, inst: Air.Inst.Index) !void { |
| 7447 | }, | 7569 | }, |
| 7448 | }; | 7570 | }; |
| 7449 | | 7571 | |
| 7450 | try cg.store(elem_ty, ptr_id, value_id, .{ .is_volatile = ptr_info.flags.is_volatile }); | 7572 | try cg.store(elem_ty, ptr_id, value_id, .{ |
| | 7573 | .is_volatile = ptr_info.flags.is_volatile, |
| | 7574 | .ptr_address_space = ptr_info.flags.address_space, |
| | 7575 | }); |
| 7451 | } | 7576 | } |
| 7452 | | 7577 | |
| 7453 | fn airRet(cg: *CodeGen, inst: Air.Inst.Index) !void { | 7578 | fn airRet(cg: *CodeGen, inst: Air.Inst.Index) !void { |