| ... | ... | @@ -46,7 +46,6 @@ const lldMain = @import("../main.zig").lldMain; |
| 46 | 46 | const trace = @import("../tracy.zig").trace; |
| 47 | 47 | const wasi_libc = @import("../wasi_libc.zig"); |
| 48 | 48 | const Value = @import("../Value.zig"); |
| 49 | | const ZcuType = @import("../Type.zig"); |
| 50 | 49 | |
| 51 | 50 | base: link.File, |
| 52 | 51 | /// Null-terminated strings, indexes have type String and string_table provides |
| ... | ... | @@ -190,6 +189,7 @@ navs_exe: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, ZcuDataExe) = .emp |
| 190 | 189 | uavs_obj: std.AutoArrayHashMapUnmanaged(InternPool.Index, ZcuDataObj) = .empty, |
| 191 | 190 | /// Tracks ref count to optimize LEB encodings for UAV references. |
| 192 | 191 | uavs_exe: std.AutoArrayHashMapUnmanaged(InternPool.Index, ZcuDataExe) = .empty, |
| 192 | /// When the key is an enum type, this represents a `@tagName` function. |
| 193 | 193 | zcu_funcs: std.AutoArrayHashMapUnmanaged(InternPool.Index, ZcuFunc) = .empty, |
| 194 | 194 | nav_exports: std.AutoArrayHashMapUnmanaged(NavExport, Zcu.Export.Index) = .empty, |
| 195 | 195 | uav_exports: std.AutoArrayHashMapUnmanaged(UavExport, Zcu.Export.Index) = .empty, |
| ... | ... | @@ -269,6 +269,7 @@ object_indirect_function_import_set: std.AutoArrayHashMapUnmanaged(String, void) |
| 269 | 269 | object_indirect_function_set: std.AutoArrayHashMapUnmanaged(ObjectFunctionIndex, void) = .empty, |
| 270 | 270 | |
| 271 | 271 | error_name_table_ref_count: u32 = 0, |
| 272 | tag_name_table_ref_count: u32 = 0, |
| 272 | 273 | |
| 273 | 274 | /// Set to true if any `GLOBAL_INDEX` relocation is encountered with |
| 274 | 275 | /// `SymbolFlags.tls` set to true. This is for objects only; final |
| ... | ... | @@ -294,6 +295,14 @@ error_name_bytes: std.ArrayListUnmanaged(u8) = .empty, |
| 294 | 295 | /// is stored. No need to serialize; trivially reconstructed. |
| 295 | 296 | error_name_offs: std.ArrayListUnmanaged(u32) = .empty, |
| 296 | 297 | |
| 298 | tag_name_bytes: std.ArrayListUnmanaged(u8) = .empty, |
| 299 | tag_name_offs: std.ArrayListUnmanaged(u32) = .empty, |
| 300 | |
| 301 | pub const TagNameOff = extern struct { |
| 302 | off: u32, |
| 303 | len: u32, |
| 304 | }; |
| 305 | |
| 297 | 306 | /// Index into `Wasm.zcu_indirect_function_set`. |
| 298 | 307 | pub const ZcuIndirectFunctionSetIndex = enum(u32) { |
| 299 | 308 | _, |
| ... | ... | @@ -857,8 +866,16 @@ const ZcuDataStarts = struct { |
| 857 | 866 | } |
| 858 | 867 | }; |
| 859 | 868 | |
| 860 | | pub const ZcuFunc = extern struct { |
| 869 | pub const ZcuFunc = union { |
| 861 | 870 | function: CodeGen.Function, |
| 871 | tag_name: TagName, |
| 872 | |
| 873 | pub const TagName = extern struct { |
| 874 | symbol_name: String, |
| 875 | type_index: FunctionType.Index, |
| 876 | /// Index into `Wasm.tag_name_offs`. |
| 877 | table_index: u32, |
| 878 | }; |
| 862 | 879 | |
| 863 | 880 | /// Index into `Wasm.zcu_funcs`. |
| 864 | 881 | /// Note that swapRemove is sometimes performed on `zcu_funcs`. |
| ... | ... | @@ -876,20 +893,35 @@ pub const ZcuFunc = extern struct { |
| 876 | 893 | pub fn name(i: @This(), wasm: *const Wasm) [:0]const u8 { |
| 877 | 894 | const zcu = wasm.base.comp.zcu.?; |
| 878 | 895 | const ip = &zcu.intern_pool; |
| 879 | | const func = ip.toFunc(i.key(wasm).*); |
| 880 | | const nav = ip.getNav(func.owner_nav); |
| 881 | | return nav.fqn.toSlice(ip); |
| 896 | const ip_index = i.key(wasm).*; |
| 897 | switch (ip.indexToKey(ip_index)) { |
| 898 | .func => |func| { |
| 899 | const nav = ip.getNav(func.owner_nav); |
| 900 | return nav.fqn.toSlice(ip); |
| 901 | }, |
| 902 | .enum_type => { |
| 903 | return i.value(wasm).tag_name.symbol_name.slice(wasm); |
| 904 | }, |
| 905 | else => unreachable, |
| 906 | } |
| 882 | 907 | } |
| 883 | 908 | |
| 884 | | pub fn typeIndex(i: @This(), wasm: *Wasm) ?FunctionType.Index { |
| 909 | pub fn typeIndex(i: @This(), wasm: *Wasm) FunctionType.Index { |
| 885 | 910 | const comp = wasm.base.comp; |
| 886 | 911 | const zcu = comp.zcu.?; |
| 887 | 912 | const target = &comp.root_mod.resolved_target.result; |
| 888 | 913 | const ip = &zcu.intern_pool; |
| 889 | | const func = ip.toFunc(i.key(wasm).*); |
| 890 | | const fn_ty = zcu.navValue(func.owner_nav).typeOf(zcu); |
| 891 | | const fn_info = zcu.typeToFunc(fn_ty).?; |
| 892 | | return wasm.getExistingFunctionType(fn_info.cc, fn_info.param_types.get(ip), .fromInterned(fn_info.return_type), target); |
| 914 | switch (ip.indexToKey(i.key(wasm).*)) { |
| 915 | .func => |func| { |
| 916 | const fn_ty = zcu.navValue(func.owner_nav).typeOf(zcu); |
| 917 | const fn_info = zcu.typeToFunc(fn_ty).?; |
| 918 | return wasm.getExistingFunctionType(fn_info.cc, fn_info.param_types.get(ip), .fromInterned(fn_info.return_type), target).?; |
| 919 | }, |
| 920 | .enum_type => { |
| 921 | return i.value(wasm).tag_name.type_index; |
| 922 | }, |
| 923 | else => unreachable, |
| 924 | } |
| 893 | 925 | } |
| 894 | 926 | }; |
| 895 | 927 | }; |
| ... | ... | @@ -988,8 +1020,12 @@ pub const FunctionImport = extern struct { |
| 988 | 1020 | return fromIpIndex(wasm, ip.getNav(nav_index).status.fully_resolved.val); |
| 989 | 1021 | } |
| 990 | 1022 | |
| 1023 | pub fn fromZcuFunc(wasm: *const Wasm, i: ZcuFunc.Index) Resolution { |
| 1024 | return pack(wasm, .{ .zcu_func = i }); |
| 1025 | } |
| 1026 | |
| 991 | 1027 | pub fn fromIpIndex(wasm: *const Wasm, ip_index: InternPool.Index) Resolution { |
| 992 | | return pack(wasm, .{ .zcu_func = @enumFromInt(wasm.zcu_funcs.getIndex(ip_index).?) }); |
| 1028 | return fromZcuFunc(wasm, @enumFromInt(wasm.zcu_funcs.getIndex(ip_index).?)); |
| 993 | 1029 | } |
| 994 | 1030 | |
| 995 | 1031 | pub fn fromObjectFunction(wasm: *const Wasm, object_function: ObjectFunctionIndex) Resolution { |
| ... | ... | @@ -1012,7 +1048,7 @@ pub const FunctionImport = extern struct { |
| 1012 | 1048 | => getExistingFuncType2(wasm, &.{}, &.{}), |
| 1013 | 1049 | .__wasm_init_tls => getExistingFuncType2(wasm, &.{.i32}, &.{}), |
| 1014 | 1050 | .object_function => |i| i.ptr(wasm).type_index, |
| 1015 | | .zcu_func => |i| i.typeIndex(wasm).?, |
| 1051 | .zcu_func => |i| i.typeIndex(wasm), |
| 1016 | 1052 | }; |
| 1017 | 1053 | } |
| 1018 | 1054 | |
| ... | ... | @@ -1717,6 +1753,10 @@ pub const DataPayload = extern struct { |
| 1717 | 1753 | pub const DataSegmentId = enum(u32) { |
| 1718 | 1754 | __zig_error_names, |
| 1719 | 1755 | __zig_error_name_table, |
| 1756 | /// All name string bytes for all `@tagName` implementations, concatenated together. |
| 1757 | __zig_tag_names, |
| 1758 | /// All tag name slices for all `@tagName` implementations, concatenated together. |
| 1759 | __zig_tag_name_table, |
| 1720 | 1760 | /// This and `__heap_end` are better retrieved via a global, but there is |
| 1721 | 1761 | /// some suboptimal code out there (wasi libc) that additionally needs them |
| 1722 | 1762 | /// as data symbols. |
| ... | ... | @@ -1742,6 +1782,8 @@ pub const DataSegmentId = enum(u32) { |
| 1742 | 1782 | pub const Unpacked = union(enum) { |
| 1743 | 1783 | __zig_error_names, |
| 1744 | 1784 | __zig_error_name_table, |
| 1785 | __zig_tag_names, |
| 1786 | __zig_tag_name_table, |
| 1745 | 1787 | __heap_base, |
| 1746 | 1788 | __heap_end, |
| 1747 | 1789 | object: ObjectDataSegment.Index, |
| ... | ... | @@ -1755,6 +1797,8 @@ pub const DataSegmentId = enum(u32) { |
| 1755 | 1797 | return switch (unpacked) { |
| 1756 | 1798 | .__zig_error_names => .__zig_error_names, |
| 1757 | 1799 | .__zig_error_name_table => .__zig_error_name_table, |
| 1800 | .__zig_tag_names => .__zig_tag_names, |
| 1801 | .__zig_tag_name_table => .__zig_tag_name_table, |
| 1758 | 1802 | .__heap_base => .__heap_base, |
| 1759 | 1803 | .__heap_end => .__heap_end, |
| 1760 | 1804 | .object => |i| @enumFromInt(first_object + @intFromEnum(i)), |
| ... | ... | @@ -1768,6 +1812,8 @@ pub const DataSegmentId = enum(u32) { |
| 1768 | 1812 | return switch (id) { |
| 1769 | 1813 | .__zig_error_names => .__zig_error_names, |
| 1770 | 1814 | .__zig_error_name_table => .__zig_error_name_table, |
| 1815 | .__zig_tag_names => .__zig_tag_names, |
| 1816 | .__zig_tag_name_table => .__zig_tag_name_table, |
| 1771 | 1817 | .__heap_base => .__heap_base, |
| 1772 | 1818 | .__heap_end => .__heap_end, |
| 1773 | 1819 | _ => { |
| ... | ... | @@ -1815,7 +1861,14 @@ pub const DataSegmentId = enum(u32) { |
| 1815 | 1861 | |
| 1816 | 1862 | pub fn category(id: DataSegmentId, wasm: *const Wasm) Category { |
| 1817 | 1863 | return switch (unpack(id, wasm)) { |
| 1818 | | .__zig_error_names, .__zig_error_name_table, .__heap_base, .__heap_end => .data, |
| 1864 | .__zig_error_names, |
| 1865 | .__zig_error_name_table, |
| 1866 | .__zig_tag_names, |
| 1867 | .__zig_tag_name_table, |
| 1868 | .__heap_base, |
| 1869 | .__heap_end, |
| 1870 | => .data, |
| 1871 | |
| 1819 | 1872 | .object => |i| { |
| 1820 | 1873 | const ptr = i.ptr(wasm); |
| 1821 | 1874 | if (ptr.flags.tls) return .tls; |
| ... | ... | @@ -1836,7 +1889,14 @@ pub const DataSegmentId = enum(u32) { |
| 1836 | 1889 | |
| 1837 | 1890 | pub fn isTls(id: DataSegmentId, wasm: *const Wasm) bool { |
| 1838 | 1891 | return switch (unpack(id, wasm)) { |
| 1839 | | .__zig_error_names, .__zig_error_name_table, .__heap_base, .__heap_end => false, |
| 1892 | .__zig_error_names, |
| 1893 | .__zig_error_name_table, |
| 1894 | .__zig_tag_names, |
| 1895 | .__zig_tag_name_table, |
| 1896 | .__heap_base, |
| 1897 | .__heap_end, |
| 1898 | => false, |
| 1899 | |
| 1840 | 1900 | .object => |i| i.ptr(wasm).flags.tls, |
| 1841 | 1901 | .uav_exe, .uav_obj => false, |
| 1842 | 1902 | inline .nav_exe, .nav_obj => |i| { |
| ... | ... | @@ -1854,7 +1914,16 @@ pub const DataSegmentId = enum(u32) { |
| 1854 | 1914 | |
| 1855 | 1915 | pub fn name(id: DataSegmentId, wasm: *const Wasm) []const u8 { |
| 1856 | 1916 | return switch (unpack(id, wasm)) { |
| 1857 | | .__zig_error_names, .__zig_error_name_table, .uav_exe, .uav_obj, .__heap_base, .__heap_end => ".data", |
| 1917 | .__zig_error_names, |
| 1918 | .__zig_error_name_table, |
| 1919 | .__zig_tag_names, |
| 1920 | .__zig_tag_name_table, |
| 1921 | .uav_exe, |
| 1922 | .uav_obj, |
| 1923 | .__heap_base, |
| 1924 | .__heap_end, |
| 1925 | => ".data", |
| 1926 | |
| 1858 | 1927 | .object => |i| i.ptr(wasm).name.unwrap().?.slice(wasm), |
| 1859 | 1928 | inline .nav_exe, .nav_obj => |i| { |
| 1860 | 1929 | const zcu = wasm.base.comp.zcu.?; |
| ... | ... | @@ -1867,14 +1936,14 @@ pub const DataSegmentId = enum(u32) { |
| 1867 | 1936 | |
| 1868 | 1937 | pub fn alignment(id: DataSegmentId, wasm: *const Wasm) Alignment { |
| 1869 | 1938 | return switch (unpack(id, wasm)) { |
| 1870 | | .__zig_error_names => .@"1", |
| 1871 | | .__zig_error_name_table, .__heap_base, .__heap_end => wasm.pointerAlignment(), |
| 1939 | .__zig_error_names, .__zig_tag_names => .@"1", |
| 1940 | .__zig_error_name_table, .__zig_tag_name_table, .__heap_base, .__heap_end => wasm.pointerAlignment(), |
| 1872 | 1941 | .object => |i| i.ptr(wasm).flags.alignment, |
| 1873 | 1942 | inline .uav_exe, .uav_obj => |i| { |
| 1874 | 1943 | const zcu = wasm.base.comp.zcu.?; |
| 1875 | 1944 | const ip = &zcu.intern_pool; |
| 1876 | 1945 | const ip_index = i.key(wasm).*; |
| 1877 | | const ty: ZcuType = .fromInterned(ip.typeOf(ip_index)); |
| 1946 | const ty: Zcu.Type = .fromInterned(ip.typeOf(ip_index)); |
| 1878 | 1947 | const result = ty.abiAlignment(zcu); |
| 1879 | 1948 | assert(result != .none); |
| 1880 | 1949 | return result; |
| ... | ... | @@ -1885,7 +1954,7 @@ pub const DataSegmentId = enum(u32) { |
| 1885 | 1954 | const nav = ip.getNav(i.key(wasm).*); |
| 1886 | 1955 | const explicit = nav.getAlignment(); |
| 1887 | 1956 | if (explicit != .none) return explicit; |
| 1888 | | const ty: ZcuType = .fromInterned(nav.typeOf(ip)); |
| 1957 | const ty: Zcu.Type = .fromInterned(nav.typeOf(ip)); |
| 1889 | 1958 | const result = ty.abiAlignment(zcu); |
| 1890 | 1959 | assert(result != .none); |
| 1891 | 1960 | return result; |
| ... | ... | @@ -1897,6 +1966,8 @@ pub const DataSegmentId = enum(u32) { |
| 1897 | 1966 | return switch (unpack(id, wasm)) { |
| 1898 | 1967 | .__zig_error_names => @intCast(wasm.error_name_offs.items.len), |
| 1899 | 1968 | .__zig_error_name_table => wasm.error_name_table_ref_count, |
| 1969 | .__zig_tag_names => @intCast(wasm.tag_name_offs.items.len), |
| 1970 | .__zig_tag_name_table => wasm.tag_name_table_ref_count, |
| 1900 | 1971 | .object, .uav_obj, .nav_obj, .__heap_base, .__heap_end => 0, |
| 1901 | 1972 | inline .uav_exe, .nav_exe => |i| i.value(wasm).count, |
| 1902 | 1973 | }; |
| ... | ... | @@ -1906,7 +1977,14 @@ pub const DataSegmentId = enum(u32) { |
| 1906 | 1977 | const comp = wasm.base.comp; |
| 1907 | 1978 | if (comp.config.import_memory and !id.isBss(wasm)) return true; |
| 1908 | 1979 | return switch (unpack(id, wasm)) { |
| 1909 | | .__zig_error_names, .__zig_error_name_table, .__heap_base, .__heap_end => false, |
| 1980 | .__zig_error_names, |
| 1981 | .__zig_error_name_table, |
| 1982 | .__zig_tag_names, |
| 1983 | .__zig_tag_name_table, |
| 1984 | .__heap_base, |
| 1985 | .__heap_end, |
| 1986 | => false, |
| 1987 | |
| 1910 | 1988 | .object => |i| i.ptr(wasm).flags.is_passive, |
| 1911 | 1989 | .uav_exe, .uav_obj, .nav_exe, .nav_obj => false, |
| 1912 | 1990 | }; |
| ... | ... | @@ -1914,7 +1992,14 @@ pub const DataSegmentId = enum(u32) { |
| 1914 | 1992 | |
| 1915 | 1993 | pub fn isEmpty(id: DataSegmentId, wasm: *const Wasm) bool { |
| 1916 | 1994 | return switch (unpack(id, wasm)) { |
| 1917 | | .__zig_error_names, .__zig_error_name_table, .__heap_base, .__heap_end => false, |
| 1995 | .__zig_error_names, |
| 1996 | .__zig_error_name_table, |
| 1997 | .__zig_tag_names, |
| 1998 | .__zig_tag_name_table, |
| 1999 | .__heap_base, |
| 2000 | .__heap_end, |
| 2001 | => false, |
| 2002 | |
| 1918 | 2003 | .object => |i| i.ptr(wasm).payload.off == .none, |
| 1919 | 2004 | inline .uav_exe, .uav_obj, .nav_exe, .nav_obj => |i| i.value(wasm).code.off == .none, |
| 1920 | 2005 | }; |
| ... | ... | @@ -1927,9 +2012,17 @@ pub const DataSegmentId = enum(u32) { |
| 1927 | 2012 | const comp = wasm.base.comp; |
| 1928 | 2013 | const zcu = comp.zcu.?; |
| 1929 | 2014 | const errors_len = wasm.error_name_offs.items.len; |
| 1930 | | const elem_size = ZcuType.slice_const_u8_sentinel_0.abiSize(zcu); |
| 2015 | const elem_size = Zcu.Type.slice_const_u8_sentinel_0.abiSize(zcu); |
| 1931 | 2016 | return @intCast(errors_len * elem_size); |
| 1932 | 2017 | }, |
| 2018 | .__zig_tag_names => @intCast(wasm.tag_name_bytes.items.len), |
| 2019 | .__zig_tag_name_table => { |
| 2020 | const comp = wasm.base.comp; |
| 2021 | const zcu = comp.zcu.?; |
| 2022 | const table_len = wasm.tag_name_offs.items.len; |
| 2023 | const elem_size = Zcu.Type.slice_const_u8_sentinel_0.abiSize(zcu); |
| 2024 | return @intCast(table_len * elem_size); |
| 2025 | }, |
| 1933 | 2026 | .__heap_base, .__heap_end => wasm.pointerSize(), |
| 1934 | 2027 | .object => |i| i.ptr(wasm).payload.len, |
| 1935 | 2028 | inline .uav_exe, .uav_obj, .nav_exe, .nav_obj => |i| i.value(wasm).code.len, |
| ... | ... | @@ -3052,6 +3145,8 @@ pub fn deinit(wasm: *Wasm) void { |
| 3052 | 3145 | |
| 3053 | 3146 | wasm.error_name_bytes.deinit(gpa); |
| 3054 | 3147 | wasm.error_name_offs.deinit(gpa); |
| 3148 | wasm.tag_name_bytes.deinit(gpa); |
| 3149 | wasm.tag_name_offs.deinit(gpa); |
| 3055 | 3150 | |
| 3056 | 3151 | wasm.missing_exports.deinit(gpa); |
| 3057 | 3152 | } |
| ... | ... | @@ -4197,7 +4292,7 @@ pub fn internFunctionType( |
| 4197 | 4292 | wasm: *Wasm, |
| 4198 | 4293 | cc: std.builtin.CallingConvention, |
| 4199 | 4294 | params: []const InternPool.Index, |
| 4200 | | return_type: ZcuType, |
| 4295 | return_type: Zcu.Type, |
| 4201 | 4296 | target: *const std.Target, |
| 4202 | 4297 | ) Allocator.Error!FunctionType.Index { |
| 4203 | 4298 | try convertZcuFnType(wasm.base.comp, cc, params, return_type, target, &wasm.params_scratch, &wasm.returns_scratch); |
| ... | ... | @@ -4211,7 +4306,7 @@ pub fn getExistingFunctionType( |
| 4211 | 4306 | wasm: *Wasm, |
| 4212 | 4307 | cc: std.builtin.CallingConvention, |
| 4213 | 4308 | params: []const InternPool.Index, |
| 4214 | | return_type: ZcuType, |
| 4309 | return_type: Zcu.Type, |
| 4215 | 4310 | target: *const std.Target, |
| 4216 | 4311 | ) ?FunctionType.Index { |
| 4217 | 4312 | convertZcuFnType(wasm.base.comp, cc, params, return_type, target, &wasm.params_scratch, &wasm.returns_scratch) catch |err| switch (err) { |
| ... | ... | @@ -4395,7 +4490,7 @@ fn convertZcuFnType( |
| 4395 | 4490 | comp: *Compilation, |
| 4396 | 4491 | cc: std.builtin.CallingConvention, |
| 4397 | 4492 | params: []const InternPool.Index, |
| 4398 | | return_type: ZcuType, |
| 4493 | return_type: Zcu.Type, |
| 4399 | 4494 | target: *const std.Target, |
| 4400 | 4495 | params_buffer: *std.ArrayListUnmanaged(std.wasm.Valtype), |
| 4401 | 4496 | returns_buffer: *std.ArrayListUnmanaged(std.wasm.Valtype), |
| ... | ... | @@ -4423,7 +4518,7 @@ fn convertZcuFnType( |
| 4423 | 4518 | |
| 4424 | 4519 | // param types |
| 4425 | 4520 | for (params) |param_type_ip| { |
| 4426 | | const param_type = ZcuType.fromInterned(param_type_ip); |
| 4521 | const param_type = Zcu.Type.fromInterned(param_type_ip); |
| 4427 | 4522 | if (!param_type.hasRuntimeBitsIgnoreComptime(zcu)) continue; |
| 4428 | 4523 | |
| 4429 | 4524 | switch (cc) { |