| ... | @@ -1684,6 +1684,13 @@ fn constantPtr(cg: *CodeGen, ptr_val: Value) !Id { | ... | @@ -1684,6 +1684,13 @@ fn constantPtr(cg: *CodeGen, ptr_val: Value) !Id { |
| 1684 | return cg.derivePtr(ptr_val.typeOf(zcu).ptrAddressSpace(zcu), derivation); | 1684 | return cg.derivePtr(ptr_val.typeOf(zcu).ptrAddressSpace(zcu), derivation); |
| 1685 | } | 1685 | } |
| 1686 | | 1686 | |
| | 1687 | /// Emits the pointer type that one step of a pointer derivation results in, along with its |
| | 1688 | /// pointee type. A derivation is the sequence of steps that builds a comptime-known pointer: a |
| | 1689 | /// base address, such as a declaration, an anonymous value or an integer, followed by field, |
| | 1690 | /// element and cast steps, each of which is lowered on its own. |
| | 1691 | /// This function emits instructions on every call, and they stay in the module whether or not they |
| | 1692 | /// are read, so it should only be called where the resulting type is used: a buffer struct emitted |
| | 1693 | /// without `Block` fails validation even when nothing refers to it. |
| 1687 | fn derivedPtrType(cg: *CodeGen, @"addrspace": std.lang.AddressSpace, derivation: Value.PointerDerivation) !Id { | 1694 | fn derivedPtrType(cg: *CodeGen, @"addrspace": std.lang.AddressSpace, derivation: Value.PointerDerivation) !Id { |
| 1688 | return cg.ptrType( | 1695 | return cg.ptrType( |
| 1689 | try cg.pointeeType(@"addrspace", derivation.elem_ty, false), | 1696 | try cg.pointeeType(@"addrspace", derivation.elem_ty, false), |
| ... | @@ -1696,13 +1703,6 @@ fn derivePtr(cg: *CodeGen, @"addrspace": std.lang.AddressSpace, derivation: Valu | ... | @@ -1696,13 +1703,6 @@ fn derivePtr(cg: *CodeGen, @"addrspace": std.lang.AddressSpace, derivation: Valu |
| 1696 | const zcu = cg.zcu; | 1703 | const zcu = cg.zcu; |
| 1697 | const target = zcu.getTarget(); | 1704 | const target = zcu.getTarget(); |
| 1698 | | 1705 | |
| 1699 | // A variable on Vulkan and OpenGL is used through its own pointer, so a `nav` resolves this only | | |
| 1700 | // where it is used; a type emitted and left unused stays in the module. | | |
| 1701 | const result_ty_id = switch (derivation.addr) { | | |
| 1702 | .nav => undefined, | | |
| 1703 | else => try cg.derivedPtrType(@"addrspace", derivation), | | |
| 1704 | }; | | |
| 1705 | | | |
| 1706 | switch (derivation.addr) { | 1706 | switch (derivation.addr) { |
| 1707 | .comptime_alloc, .comptime_field => unreachable, | 1707 | .comptime_alloc, .comptime_field => unreachable, |
| 1708 | .int => |int| { | 1708 | .int => |int| { |
| ... | @@ -1717,6 +1717,7 @@ fn derivePtr(cg: *CodeGen, @"addrspace": std.lang.AddressSpace, derivation: Valu | ... | @@ -1717,6 +1717,7 @@ fn derivePtr(cg: *CodeGen, @"addrspace": std.lang.AddressSpace, derivation: Valu |
| 1717 | // TODO: This can probably be an OpSpecConstantOp Bitcast, but | 1717 | // TODO: This can probably be an OpSpecConstantOp Bitcast, but |
| 1718 | // that is not implemented by Mesa yet. Therefore, just generate it | 1718 | // that is not implemented by Mesa yet. Therefore, just generate it |
| 1719 | // as a runtime operation. | 1719 | // as a runtime operation. |
| | 1720 | const result_ty_id = try cg.derivedPtrType(@"addrspace", derivation); |
| 1720 | const result_ptr_id = cg.allocId(); | 1721 | const result_ptr_id = cg.allocId(); |
| 1721 | const value_id = try cg.constInt(.usize, int); | 1722 | const value_id = try cg.constInt(.usize, int); |
| 1722 | try cg.body.emit(gpa, .OpConvertUToPtr, .{ | 1723 | try cg.body.emit(gpa, .OpConvertUToPtr, .{ |
| ... | @@ -1759,12 +1760,12 @@ fn derivePtr(cg: *CodeGen, @"addrspace": std.lang.AddressSpace, derivation: Valu | ... | @@ -1759,12 +1760,12 @@ fn derivePtr(cg: *CodeGen, @"addrspace": std.lang.AddressSpace, derivation: Valu |
| 1759 | | 1760 | |
| 1760 | const nav_ty_id = try cg.resolveType(nav_ty, .indirect); | 1761 | const nav_ty_id = try cg.resolveType(nav_ty, .indirect); |
| 1761 | const decl_ptr_ty_id = try cg.ptrType(nav_ty_id, cg.storageClass(as)); | 1762 | const decl_ptr_ty_id = try cg.ptrType(nav_ty_id, cg.storageClass(as)); |
| 1762 | const nav_result_ty_id = try cg.derivedPtrType(@"addrspace", derivation); | 1763 | const result_ty_id = try cg.derivedPtrType(@"addrspace", derivation); |
| 1763 | if (decl_ptr_ty_id == nav_result_ty_id) return var_id; | 1764 | if (decl_ptr_ty_id == result_ty_id) return var_id; |
| 1764 | | 1765 | |
| 1765 | const casted_ptr_id = cg.allocId(); | 1766 | const casted_ptr_id = cg.allocId(); |
| 1766 | try cg.body.emit(gpa, .OpBitcast, .{ | 1767 | try cg.body.emit(gpa, .OpBitcast, .{ |
| 1767 | .id_result_type = nav_result_ty_id, | 1768 | .id_result_type = result_ty_id, |
| 1768 | .id_result = casted_ptr_id, | 1769 | .id_result = casted_ptr_id, |
| 1769 | .operand = var_id, | 1770 | .operand = var_id, |
| 1770 | }); | 1771 | }); |
| ... | @@ -1781,7 +1782,7 @@ fn derivePtr(cg: *CodeGen, @"addrspace": std.lang.AddressSpace, derivation: Valu | ... | @@ -1781,7 +1782,7 @@ fn derivePtr(cg: *CodeGen, @"addrspace": std.lang.AddressSpace, derivation: Valu |
| 1781 | } | 1782 | } |
| 1782 | | 1783 | |
| 1783 | if (!uav_ty.hasRuntimeBits(zcu) and uav_ty.zigTypeTag(zcu) != .spirv) { | 1784 | if (!uav_ty.hasRuntimeBits(zcu) and uav_ty.zigTypeTag(zcu) != .spirv) { |
| 1784 | return cg.constUndef(result_ty_id); | 1785 | return cg.constUndef(try cg.derivedPtrType(@"addrspace", derivation)); |
| 1785 | } | 1786 | } |
| 1786 | | 1787 | |
| 1787 | if (cg.storageClass(@"addrspace") != .function) { | 1788 | if (cg.storageClass(@"addrspace") != .function) { |
| ... | @@ -1798,7 +1799,7 @@ fn derivePtr(cg: *CodeGen, @"addrspace": std.lang.AddressSpace, derivation: Valu | ... | @@ -1798,7 +1799,7 @@ fn derivePtr(cg: *CodeGen, @"addrspace": std.lang.AddressSpace, derivation: Valu |
| 1798 | .opt_payload => @panic("TODO"), | 1799 | .opt_payload => @panic("TODO"), |
| 1799 | .field => |derived| return cg.structFieldPtr( | 1800 | .field => |derived| return cg.structFieldPtr( |
| 1800 | @"addrspace", | 1801 | @"addrspace", |
| 1801 | result_ty_id, | 1802 | try cg.derivedPtrType(@"addrspace", derivation), |
| 1802 | derivation.elem_ty, | 1803 | derivation.elem_ty, |
| 1803 | derived.parent.elem_ty, | 1804 | derived.parent.elem_ty, |
| 1804 | try cg.derivePtr(@"addrspace", derived.parent.*), | 1805 | try cg.derivePtr(@"addrspace", derived.parent.*), |
| ... | @@ -1850,12 +1851,13 @@ fn derivePtr(cg: *CodeGen, @"addrspace": std.lang.AddressSpace, derivation: Valu | ... | @@ -1850,12 +1851,13 @@ fn derivePtr(cg: *CodeGen, @"addrspace": std.lang.AddressSpace, derivation: Valu |
| 1850 | const zero = try cg.constInt(.u32, 0); | 1851 | const zero = try cg.constInt(.u32, 0); |
| 1851 | const ids = try cg.id_scratch.addManyAsSlice(gpa, depth); | 1852 | const ids = try cg.id_scratch.addManyAsSlice(gpa, depth); |
| 1852 | @memset(ids, zero); | 1853 | @memset(ids, zero); |
| 1853 | return cg.accessChainId(result_ty_id, parent_ptr_id, ids); | 1854 | return cg.accessChainId(try cg.derivedPtrType(@"addrspace", derivation), parent_ptr_id, ids); |
| 1854 | } else { | 1855 | } else { |
| 1855 | return parent_ptr_id; | 1856 | return parent_ptr_id; |
| 1856 | } | 1857 | } |
| 1857 | } | 1858 | } |
| 1858 | if (target.os.tag == .opencl) { | 1859 | if (target.os.tag == .opencl) { |
| | 1860 | const result_ty_id = try cg.derivedPtrType(@"addrspace", derivation); |
| 1859 | const result_ptr_id = cg.allocId(); | 1861 | const result_ptr_id = cg.allocId(); |
| 1860 | try cg.body.emit(gpa, .OpBitcast, .{ | 1862 | try cg.body.emit(gpa, .OpBitcast, .{ |
| 1861 | .id_result_type = result_ty_id, | 1863 | .id_result_type = result_ty_id, |