| ... | @@ -1684,16 +1684,25 @@ fn constantPtr(cg: *CodeGen, ptr_val: Value) !Id { | ... | @@ -1684,16 +1684,25 @@ 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. |
| | 1694 | fn derivedPtrType(cg: *CodeGen, @"addrspace": std.lang.AddressSpace, derivation: Value.PointerDerivation) !Id { |
| | 1695 | return cg.ptrType( |
| | 1696 | try cg.pointeeType(@"addrspace", derivation.elem_ty, false), |
| | 1697 | cg.storageClass(@"addrspace"), |
| | 1698 | ); |
| | 1699 | } |
| | 1700 | |
| 1687 | fn derivePtr(cg: *CodeGen, @"addrspace": std.lang.AddressSpace, derivation: Value.PointerDerivation) !Id { | 1701 | fn derivePtr(cg: *CodeGen, @"addrspace": std.lang.AddressSpace, derivation: Value.PointerDerivation) !Id { |
| 1688 | const gpa = cg.gpa; | 1702 | const gpa = cg.gpa; |
| 1689 | const zcu = cg.zcu; | 1703 | const zcu = cg.zcu; |
| 1690 | const target = zcu.getTarget(); | 1704 | const target = zcu.getTarget(); |
| 1691 | | 1705 | |
| 1692 | const result_ty_id = try cg.ptrType( | | |
| 1693 | try cg.pointeeType(@"addrspace", derivation.elem_ty, false), | | |
| 1694 | cg.storageClass(@"addrspace"), | | |
| 1695 | ); | | |
| 1696 | | | |
| 1697 | switch (derivation.addr) { | 1706 | switch (derivation.addr) { |
| 1698 | .comptime_alloc, .comptime_field => unreachable, | 1707 | .comptime_alloc, .comptime_field => unreachable, |
| 1699 | .int => |int| { | 1708 | .int => |int| { |
| ... | @@ -1708,6 +1717,7 @@ fn derivePtr(cg: *CodeGen, @"addrspace": std.lang.AddressSpace, derivation: Valu | ... | @@ -1708,6 +1717,7 @@ fn derivePtr(cg: *CodeGen, @"addrspace": std.lang.AddressSpace, derivation: Valu |
| 1708 | // TODO: This can probably be an OpSpecConstantOp Bitcast, but | 1717 | // TODO: This can probably be an OpSpecConstantOp Bitcast, but |
| 1709 | // that is not implemented by Mesa yet. Therefore, just generate it | 1718 | // that is not implemented by Mesa yet. Therefore, just generate it |
| 1710 | // as a runtime operation. | 1719 | // as a runtime operation. |
| | 1720 | const result_ty_id = try cg.derivedPtrType(@"addrspace", derivation); |
| 1711 | const result_ptr_id = cg.allocId(); | 1721 | const result_ptr_id = cg.allocId(); |
| 1712 | const value_id = try cg.constInt(.usize, int); | 1722 | const value_id = try cg.constInt(.usize, int); |
| 1713 | try cg.body.emit(gpa, .OpConvertUToPtr, .{ | 1723 | try cg.body.emit(gpa, .OpConvertUToPtr, .{ |
| ... | @@ -1727,10 +1737,10 @@ fn derivePtr(cg: *CodeGen, @"addrspace": std.lang.AddressSpace, derivation: Valu | ... | @@ -1727,10 +1737,10 @@ fn derivePtr(cg: *CodeGen, @"addrspace": std.lang.AddressSpace, derivation: Valu |
| 1727 | | 1737 | |
| 1728 | if (ip.isFunctionType(nav_ty.toIntern())) { | 1738 | if (ip.isFunctionType(nav_ty.toIntern())) { |
| 1729 | if (is_extern) return try cg.resolveExternFn(nav_index); | 1739 | if (is_extern) return try cg.resolveExternFn(nav_index); |
| 1730 | return try cg.constUndef(result_ty_id); | 1740 | return try cg.constUndef(try cg.derivedPtrType(@"addrspace", derivation)); |
| 1731 | } | 1741 | } |
| 1732 | if (!nav_ty.hasRuntimeBits(zcu) and nav_ty.zigTypeTag(zcu) != .spirv) { | 1742 | if (!nav_ty.hasRuntimeBits(zcu) and nav_ty.zigTypeTag(zcu) != .spirv) { |
| 1733 | return cg.constUndef(result_ty_id); | 1743 | return cg.constUndef(try cg.derivedPtrType(@"addrspace", derivation)); |
| 1734 | } | 1744 | } |
| 1735 | if (!is_extern) { | 1745 | if (!is_extern) { |
| 1736 | return cg.todo("pointer to constant '{f}'", .{nav.fqn.fmt(ip)}); | 1746 | return cg.todo("pointer to constant '{f}'", .{nav.fqn.fmt(ip)}); |
| ... | @@ -1739,20 +1749,20 @@ fn derivePtr(cg: *CodeGen, @"addrspace": std.lang.AddressSpace, derivation: Valu | ... | @@ -1739,20 +1749,20 @@ fn derivePtr(cg: *CodeGen, @"addrspace": std.lang.AddressSpace, derivation: Valu |
| 1739 | const as = nav.resolved.?.@"addrspace"; | 1749 | const as = nav.resolved.?.@"addrspace"; |
| 1740 | assert(as != .generic); | 1750 | assert(as != .generic); |
| 1741 | | 1751 | |
| 1742 | const storage_class = cg.storageClass(as); | | |
| 1743 | const var_id = try cg.resolveNav(nav_index); | 1752 | const var_id = try cg.resolveNav(nav_index); |
| 1744 | const nav_ty_id = try cg.resolveType(nav_ty, .indirect); | | |
| 1745 | const decl_ptr_ty_id = try cg.ptrType(nav_ty_id, storage_class); | | |
| 1746 | if (cg.needsLayout(as, nav_ty)) { | 1753 | if (cg.needsLayout(as, nav_ty)) { |
| 1747 | try cg.block_var_ids.put(gpa, var_id, {}); | 1754 | try cg.block_var_ids.put(gpa, var_id, {}); |
| 1748 | } | 1755 | } |
| 1749 | | | |
| 1750 | if (decl_ptr_ty_id == result_ty_id) return var_id; | | |
| 1751 | switch (target.os.tag) { | 1756 | switch (target.os.tag) { |
| 1752 | .vulkan, .opengl => return var_id, | 1757 | .vulkan, .opengl => return var_id, |
| 1753 | else => {}, | 1758 | else => {}, |
| 1754 | } | 1759 | } |
| 1755 | | 1760 | |
| | 1761 | const nav_ty_id = try cg.resolveType(nav_ty, .indirect); |
| | 1762 | const decl_ptr_ty_id = try cg.ptrType(nav_ty_id, cg.storageClass(as)); |
| | 1763 | const result_ty_id = try cg.derivedPtrType(@"addrspace", derivation); |
| | 1764 | if (decl_ptr_ty_id == result_ty_id) return var_id; |
| | 1765 | |
| 1756 | const casted_ptr_id = cg.allocId(); | 1766 | const casted_ptr_id = cg.allocId(); |
| 1757 | try cg.body.emit(gpa, .OpBitcast, .{ | 1767 | try cg.body.emit(gpa, .OpBitcast, .{ |
| 1758 | .id_result_type = result_ty_id, | 1768 | .id_result_type = result_ty_id, |
| ... | @@ -1772,7 +1782,7 @@ fn derivePtr(cg: *CodeGen, @"addrspace": std.lang.AddressSpace, derivation: Valu | ... | @@ -1772,7 +1782,7 @@ fn derivePtr(cg: *CodeGen, @"addrspace": std.lang.AddressSpace, derivation: Valu |
| 1772 | } | 1782 | } |
| 1773 | | 1783 | |
| 1774 | if (!uav_ty.hasRuntimeBits(zcu) and uav_ty.zigTypeTag(zcu) != .spirv) { | 1784 | if (!uav_ty.hasRuntimeBits(zcu) and uav_ty.zigTypeTag(zcu) != .spirv) { |
| 1775 | return cg.constUndef(result_ty_id); | 1785 | return cg.constUndef(try cg.derivedPtrType(@"addrspace", derivation)); |
| 1776 | } | 1786 | } |
| 1777 | | 1787 | |
| 1778 | if (cg.storageClass(@"addrspace") != .function) { | 1788 | if (cg.storageClass(@"addrspace") != .function) { |
| ... | @@ -1789,7 +1799,7 @@ fn derivePtr(cg: *CodeGen, @"addrspace": std.lang.AddressSpace, derivation: Valu | ... | @@ -1789,7 +1799,7 @@ fn derivePtr(cg: *CodeGen, @"addrspace": std.lang.AddressSpace, derivation: Valu |
| 1789 | .opt_payload => @panic("TODO"), | 1799 | .opt_payload => @panic("TODO"), |
| 1790 | .field => |derived| return cg.structFieldPtr( | 1800 | .field => |derived| return cg.structFieldPtr( |
| 1791 | @"addrspace", | 1801 | @"addrspace", |
| 1792 | result_ty_id, | 1802 | try cg.derivedPtrType(@"addrspace", derivation), |
| 1793 | derivation.elem_ty, | 1803 | derivation.elem_ty, |
| 1794 | derived.parent.elem_ty, | 1804 | derived.parent.elem_ty, |
| 1795 | try cg.derivePtr(@"addrspace", derived.parent.*), | 1805 | try cg.derivePtr(@"addrspace", derived.parent.*), |
| ... | @@ -1801,7 +1811,7 @@ fn derivePtr(cg: *CodeGen, @"addrspace": std.lang.AddressSpace, derivation: Valu | ... | @@ -1801,7 +1811,7 @@ fn derivePtr(cg: *CodeGen, @"addrspace": std.lang.AddressSpace, derivation: Valu |
| 1801 | .many => .many_ptr, | 1811 | .many => .many_ptr, |
| 1802 | }, | 1812 | }, |
| 1803 | @"addrspace", | 1813 | @"addrspace", |
| 1804 | derived.parent.elem_ty, | 1814 | derivation.elem_ty, |
| 1805 | try cg.derivePtr(@"addrspace", derived.parent.*), | 1815 | try cg.derivePtr(@"addrspace", derived.parent.*), |
| 1806 | try cg.constInt(.usize, derived.elem_index), | 1816 | try cg.constInt(.usize, derived.elem_index), |
| 1807 | ), | 1817 | ), |
| ... | @@ -1841,12 +1851,13 @@ fn derivePtr(cg: *CodeGen, @"addrspace": std.lang.AddressSpace, derivation: Valu | ... | @@ -1841,12 +1851,13 @@ fn derivePtr(cg: *CodeGen, @"addrspace": std.lang.AddressSpace, derivation: Valu |
| 1841 | const zero = try cg.constInt(.u32, 0); | 1851 | const zero = try cg.constInt(.u32, 0); |
| 1842 | const ids = try cg.id_scratch.addManyAsSlice(gpa, depth); | 1852 | const ids = try cg.id_scratch.addManyAsSlice(gpa, depth); |
| 1843 | @memset(ids, zero); | 1853 | @memset(ids, zero); |
| 1844 | return cg.accessChainId(result_ty_id, parent_ptr_id, ids); | 1854 | return cg.accessChainId(try cg.derivedPtrType(@"addrspace", derivation), parent_ptr_id, ids); |
| 1845 | } else { | 1855 | } else { |
| 1846 | return parent_ptr_id; | 1856 | return parent_ptr_id; |
| 1847 | } | 1857 | } |
| 1848 | } | 1858 | } |
| 1849 | if (target.os.tag == .opencl) { | 1859 | if (target.os.tag == .opencl) { |
| | 1860 | const result_ty_id = try cg.derivedPtrType(@"addrspace", derivation); |
| 1850 | const result_ptr_id = cg.allocId(); | 1861 | const result_ptr_id = cg.allocId(); |
| 1851 | try cg.body.emit(gpa, .OpBitcast, .{ | 1862 | try cg.body.emit(gpa, .OpBitcast, .{ |
| 1852 | .id_result_type = result_ty_id, | 1863 | .id_result_type = result_ty_id, |