authorgravatar for paul.verigo@gmail.comPavel Verigo <paul.verigo@gmail.com> 2026-08-08 12:05:32+02:00
committergravatar for paul.verigo@gmail.comPavel Verigo <paul.verigo@gmail.com> 2026-08-11 20:00:12+02:00
loge02750fc0bde5c37a14e0173804987030be0078d
treec78d1477b082972eec3d76c99bd28ac589ad709b
parentcce0b43270a57a884e7d7aeba25bc6953741156e

wasm: add __global_base/__wasm_first_page_end handling + init_funcs fix


2 files changed, 96 insertions(+), 88 deletions(-)

src/link/Wasm.zig+59-51
...@@ -1778,14 +1778,16 @@ pub const ObjectDataImport = extern struct {...@@ -1778,14 +1778,16 @@ pub const ObjectDataImport = extern struct {
1778 __zig_error_name_table,1778 __zig_error_name_table,
1779 __zig_tag_names,1779 __zig_tag_names,
1780 __zig_tag_name_table,1780 __zig_tag_name_table,
1781 __global_base,
1781 __heap_base,1782 __heap_base,
1782 __heap_end,1783 __heap_end,
1784 __wasm_first_page_end,
1783 /// Next, an `ObjectData.Index`.1785 /// Next, an `ObjectData.Index`.
1784 /// Next, index into `uavs_obj` or `uavs_exe` depending on whether emitting an object.1786 /// Next, index into `uavs_obj` or `uavs_exe` depending on whether emitting an object.
1785 /// Next, index into `navs_obj` or `navs_exe` depending on whether emitting an object.1787 /// Next, index into `navs_obj` or `navs_exe` depending on whether emitting an object.
1786 _,1788 _,
17871789
1788 const first_object = @backingInt(Resolution.__heap_end) + 1;1790 const first_object = @backingInt(Resolution.__wasm_first_page_end) + 1;
17891791
1790 pub const Unpacked = union(enum) {1792 pub const Unpacked = union(enum) {
1791 unresolved,1793 unresolved,
...@@ -1793,8 +1795,10 @@ pub const ObjectDataImport = extern struct {...@@ -1793,8 +1795,10 @@ pub const ObjectDataImport = extern struct {
1793 __zig_error_name_table,1795 __zig_error_name_table,
1794 __zig_tag_names,1796 __zig_tag_names,
1795 __zig_tag_name_table,1797 __zig_tag_name_table,
1798 __global_base,
1796 __heap_base,1799 __heap_base,
1797 __heap_end,1800 __heap_end,
1801 __wasm_first_page_end,
1798 object: ObjectData.Index,1802 object: ObjectData.Index,
1799 uav_exe: UavsExeIndex,1803 uav_exe: UavsExeIndex,
1800 uav_obj: UavsObjIndex,1804 uav_obj: UavsObjIndex,
...@@ -1809,8 +1813,10 @@ pub const ObjectDataImport = extern struct {...@@ -1809,8 +1813,10 @@ pub const ObjectDataImport = extern struct {
1809 .__zig_error_name_table => .__zig_error_name_table,1813 .__zig_error_name_table => .__zig_error_name_table,
1810 .__zig_tag_names => .__zig_tag_names,1814 .__zig_tag_names => .__zig_tag_names,
1811 .__zig_tag_name_table => .__zig_tag_name_table,1815 .__zig_tag_name_table => .__zig_tag_name_table,
1816 .__global_base => .__global_base,
1812 .__heap_base => .__heap_base,1817 .__heap_base => .__heap_base,
1813 .__heap_end => .__heap_end,1818 .__heap_end => .__heap_end,
1819 .__wasm_first_page_end => .__wasm_first_page_end,
1814 _ => {1820 _ => {
1815 const object_index = @backingInt(r) - first_object;1821 const object_index = @backingInt(r) - first_object;
18161822
...@@ -1847,8 +1853,10 @@ pub const ObjectDataImport = extern struct {...@@ -1847,8 +1853,10 @@ pub const ObjectDataImport = extern struct {
1847 .__zig_error_name_table => .__zig_error_name_table,1853 .__zig_error_name_table => .__zig_error_name_table,
1848 .__zig_tag_names => .__zig_tag_names,1854 .__zig_tag_names => .__zig_tag_names,
1849 .__zig_tag_name_table => .__zig_tag_name_table,1855 .__zig_tag_name_table => .__zig_tag_name_table,
1856 .__global_base => .__global_base,
1850 .__heap_base => .__heap_base,1857 .__heap_base => .__heap_base,
1851 .__heap_end => .__heap_end,1858 .__heap_end => .__heap_end,
1859 .__wasm_first_page_end => .__wasm_first_page_end,
1852 .object => |i| @fromBackingInt(@intCast(first_object + @backingInt(i))),1860 .object => |i| @fromBackingInt(@intCast(first_object + @backingInt(i))),
1853 inline .uav_exe, .uav_obj => |i| @fromBackingInt(@intCast(first_object + wasm.object_datas.items.len + @backingInt(i))),1861 inline .uav_exe, .uav_obj => |i| @fromBackingInt(@intCast(first_object + wasm.object_datas.items.len + @backingInt(i))),
1854 .nav_exe => |i| @fromBackingInt(@intCast(first_object + wasm.object_datas.items.len + wasm.uavs_exe.entries.len + @backingInt(i))),1862 .nav_exe => |i| @fromBackingInt(@intCast(first_object + wasm.object_datas.items.len + wasm.uavs_exe.entries.len + @backingInt(i))),
...@@ -1886,8 +1894,10 @@ pub const ObjectDataImport = extern struct {...@@ -1886,8 +1894,10 @@ pub const ObjectDataImport = extern struct {
1886 .__zig_error_name_table,1894 .__zig_error_name_table,
1887 .__zig_tag_names,1895 .__zig_tag_names,
1888 .__zig_tag_name_table,1896 .__zig_tag_name_table,
1897 .__global_base,
1889 .__heap_base,1898 .__heap_base,
1890 .__heap_end,1899 .__heap_end,
1900 .__wasm_first_page_end,
1891 .uav_exe,1901 .uav_exe,
1892 .uav_obj,1902 .uav_obj,
1893 .nav_exe,1903 .nav_exe,
...@@ -1910,8 +1920,11 @@ pub const ObjectDataImport = extern struct {...@@ -1910,8 +1920,11 @@ pub const ObjectDataImport = extern struct {
1910 .__zig_error_name_table => .{ .segment = .__zig_error_name_table, .offset = 0 },1920 .__zig_error_name_table => .{ .segment = .__zig_error_name_table, .offset = 0 },
1911 .__zig_tag_names => .{ .segment = .__zig_tag_names, .offset = 0 },1921 .__zig_tag_names => .{ .segment = .__zig_tag_names, .offset = 0 },
1912 .__zig_tag_name_table => .{ .segment = .__zig_tag_name_table, .offset = 0 },1922 .__zig_tag_name_table => .{ .segment = .__zig_tag_name_table, .offset = 0 },
1913 .__heap_base => .{ .segment = .__heap_base, .offset = 0 },1923 .__global_base,
1914 .__heap_end => .{ .segment = .__heap_end, .offset = 0 },1924 .__heap_base,
1925 .__heap_end,
1926 .__wasm_first_page_end,
1927 => unreachable,
1915 .uav_exe => |i| .{ .segment = .pack(wasm, .{ .uav_exe = i }), .offset = 0 },1928 .uav_exe => |i| .{ .segment = .pack(wasm, .{ .uav_exe = i }), .offset = 0 },
1916 .uav_obj => |i| .{ .segment = .pack(wasm, .{ .uav_obj = i }), .offset = 0 },1929 .uav_obj => |i| .{ .segment = .pack(wasm, .{ .uav_obj = i }), .offset = 0 },
1917 .nav_exe => |i| .{ .segment = .pack(wasm, .{ .nav_exe = i }), .offset = 0 },1930 .nav_exe => |i| .{ .segment = .pack(wasm, .{ .nav_exe = i }), .offset = 0 },
...@@ -1927,8 +1940,10 @@ pub const ObjectDataImport = extern struct {...@@ -1927,8 +1940,10 @@ pub const ObjectDataImport = extern struct {
1927 .__zig_tag_names,1940 .__zig_tag_names,
1928 .__zig_tag_name_table,1941 .__zig_tag_name_table,
1929 => .{ .binding = .local },1942 => .{ .binding = .local },
1943 .__global_base,
1930 .__heap_base,1944 .__heap_base,
1931 .__heap_end,1945 .__heap_end,
1946 .__wasm_first_page_end,
1932 => unreachable,1947 => unreachable,
1933 .object => |i| i.ptr(wasm).flags,1948 .object => |i| i.ptr(wasm).flags,
1934 inline .nav_exe, .nav_obj => |i| {1949 inline .nav_exe, .nav_obj => |i| {
...@@ -1976,8 +1991,10 @@ pub const ObjectDataImport = extern struct {...@@ -1976,8 +1991,10 @@ pub const ObjectDataImport = extern struct {
1976 .__zig_error_name_table => @tagName(.__zig_error_name_table),1991 .__zig_error_name_table => @tagName(.__zig_error_name_table),
1977 .__zig_tag_names => @tagName(.__zig_tag_names),1992 .__zig_tag_names => @tagName(.__zig_tag_names),
1978 .__zig_tag_name_table => @tagName(.__zig_tag_name_table),1993 .__zig_tag_name_table => @tagName(.__zig_tag_name_table),
1994 .__global_base => @tagName(.__global_base),
1979 .__heap_base => @tagName(.__heap_base),1995 .__heap_base => @tagName(.__heap_base),
1980 .__heap_end => @tagName(.__heap_end),1996 .__heap_end => @tagName(.__heap_end),
1997 .__wasm_first_page_end => @tagName(.__wasm_first_page_end),
1981 inline .uav_exe, .uav_obj => |i| std.fmt.bufPrint(1998 inline .uav_exe, .uav_obj => |i| std.fmt.bufPrint(
1982 buf,1999 buf,
1983 "__anon_{d}",2000 "__anon_{d}",
...@@ -2006,7 +2023,7 @@ pub const ObjectDataImport = extern struct {...@@ -2006,7 +2023,7 @@ pub const ObjectDataImport = extern struct {
2006 const elem_size = Zcu.Type.slice_const_u8_sentinel_0.abiSize(zcu);2023 const elem_size = Zcu.Type.slice_const_u8_sentinel_0.abiSize(zcu);
2007 return @intCast(table_len * elem_size);2024 return @intCast(table_len * elem_size);
2008 },2025 },
2009 .__heap_base, .__heap_end => wasm.pointerSize(),2026 .__global_base, .__heap_base, .__heap_end, .__wasm_first_page_end => 0,
2010 .object => |i| i.ptr(wasm).size,2027 .object => |i| i.ptr(wasm).size,
2011 inline .uav_exe, .uav_obj, .nav_exe, .nav_obj => |i| i.value(wasm).code.len,2028 inline .uav_exe, .uav_obj, .nav_exe, .nav_obj => |i| i.value(wasm).code.len,
2012 };2029 };
...@@ -2056,17 +2073,12 @@ pub const DataSegmentId = enum(u32) {...@@ -2056,17 +2073,12 @@ pub const DataSegmentId = enum(u32) {
2056 __zig_tag_names,2073 __zig_tag_names,
2057 /// All tag name slices for all `@tagName` implementations, concatenated together.2074 /// All tag name slices for all `@tagName` implementations, concatenated together.
2058 __zig_tag_name_table,2075 __zig_tag_name_table,
2059 /// This and `__heap_end` are better retrieved via a global, but there is
2060 /// some suboptimal code out there (wasi libc) that additionally needs them
2061 /// as data symbols.
2062 __heap_base,
2063 __heap_end,
2064 /// First, an `ObjectDataSegment.Index`.2076 /// First, an `ObjectDataSegment.Index`.
2065 /// Next, index into `uavs_obj` or `uavs_exe` depending on whether emitting an object.2077 /// Next, index into `uavs_obj` or `uavs_exe` depending on whether emitting an object.
2066 /// Next, index into `navs_obj` or `navs_exe` depending on whether emitting an object.2078 /// Next, index into `navs_obj` or `navs_exe` depending on whether emitting an object.
2067 _,2079 _,
20682080
2069 const first_object = @backingInt(DataSegmentId.__heap_end) + 1;2081 const first_object = @backingInt(DataSegmentId.__zig_tag_name_table) + 1;
20702082
2071 pub const Category = enum {2083 pub const Category = enum {
2072 /// Thread-local variables.2084 /// Thread-local variables.
...@@ -2083,8 +2095,6 @@ pub const DataSegmentId = enum(u32) {...@@ -2083,8 +2095,6 @@ pub const DataSegmentId = enum(u32) {
2083 __zig_error_name_table,2095 __zig_error_name_table,
2084 __zig_tag_names,2096 __zig_tag_names,
2085 __zig_tag_name_table,2097 __zig_tag_name_table,
2086 __heap_base,
2087 __heap_end,
2088 object: ObjectDataSegment.Index,2098 object: ObjectDataSegment.Index,
2089 uav_exe: UavsExeIndex,2099 uav_exe: UavsExeIndex,
2090 uav_obj: UavsObjIndex,2100 uav_obj: UavsObjIndex,
...@@ -2098,8 +2108,6 @@ pub const DataSegmentId = enum(u32) {...@@ -2098,8 +2108,6 @@ pub const DataSegmentId = enum(u32) {
2098 .__zig_error_name_table => .__zig_error_name_table,2108 .__zig_error_name_table => .__zig_error_name_table,
2099 .__zig_tag_names => .__zig_tag_names,2109 .__zig_tag_names => .__zig_tag_names,
2100 .__zig_tag_name_table => .__zig_tag_name_table,2110 .__zig_tag_name_table => .__zig_tag_name_table,
2101 .__heap_base => .__heap_base,
2102 .__heap_end => .__heap_end,
2103 .object => |i| @fromBackingInt(@intCast(first_object + @backingInt(i))),2111 .object => |i| @fromBackingInt(@intCast(first_object + @backingInt(i))),
2104 inline .uav_exe, .uav_obj => |i| @fromBackingInt(@intCast(first_object + wasm.object_data_segments.items.len + @backingInt(i))),2112 inline .uav_exe, .uav_obj => |i| @fromBackingInt(@intCast(first_object + wasm.object_data_segments.items.len + @backingInt(i))),
2105 .nav_exe => |i| @fromBackingInt(@intCast(first_object + wasm.object_data_segments.items.len + wasm.uavs_exe.entries.len + @backingInt(i))),2113 .nav_exe => |i| @fromBackingInt(@intCast(first_object + wasm.object_data_segments.items.len + wasm.uavs_exe.entries.len + @backingInt(i))),
...@@ -2113,8 +2121,6 @@ pub const DataSegmentId = enum(u32) {...@@ -2113,8 +2121,6 @@ pub const DataSegmentId = enum(u32) {
2113 .__zig_error_name_table => .__zig_error_name_table,2121 .__zig_error_name_table => .__zig_error_name_table,
2114 .__zig_tag_names => .__zig_tag_names,2122 .__zig_tag_names => .__zig_tag_names,
2115 .__zig_tag_name_table => .__zig_tag_name_table,2123 .__zig_tag_name_table => .__zig_tag_name_table,
2116 .__heap_base => .__heap_base,
2117 .__heap_end => .__heap_end,
2118 _ => {2124 _ => {
2119 const object_index = @backingInt(id) - first_object;2125 const object_index = @backingInt(id) - first_object;
21202126
...@@ -2164,8 +2170,6 @@ pub const DataSegmentId = enum(u32) {...@@ -2164,8 +2170,6 @@ pub const DataSegmentId = enum(u32) {
2164 .__zig_error_name_table,2170 .__zig_error_name_table,
2165 .__zig_tag_names,2171 .__zig_tag_names,
2166 .__zig_tag_name_table,2172 .__zig_tag_name_table,
2167 .__heap_base,
2168 .__heap_end,
2169 => .data,2173 => .data,
21702174
2171 .object => |i| {2175 .object => |i| {
...@@ -2192,8 +2196,6 @@ pub const DataSegmentId = enum(u32) {...@@ -2192,8 +2196,6 @@ pub const DataSegmentId = enum(u32) {
2192 .__zig_error_name_table,2196 .__zig_error_name_table,
2193 .__zig_tag_names,2197 .__zig_tag_names,
2194 .__zig_tag_name_table,2198 .__zig_tag_name_table,
2195 .__heap_base,
2196 .__heap_end,
2197 => false,2199 => false,
21982200
2199 .object => |i| i.ptr(wasm).flags.tls,2201 .object => |i| i.ptr(wasm).flags.tls,
...@@ -2213,8 +2215,6 @@ pub const DataSegmentId = enum(u32) {...@@ -2213,8 +2215,6 @@ pub const DataSegmentId = enum(u32) {
22132215
2214 .__zig_error_name_table,2216 .__zig_error_name_table,
2215 .__zig_tag_name_table,2217 .__zig_tag_name_table,
2216 .__heap_base,
2217 .__heap_end,
2218 => false,2218 => false,
22192219
2220 .object => |i| i.ptr(wasm).flags.strings,2220 .object => |i| i.ptr(wasm).flags.strings,
...@@ -2229,8 +2229,6 @@ pub const DataSegmentId = enum(u32) {...@@ -2229,8 +2229,6 @@ pub const DataSegmentId = enum(u32) {
2229 .__zig_error_name_table,2229 .__zig_error_name_table,
2230 .__zig_tag_names,2230 .__zig_tag_names,
2231 .__zig_tag_name_table,2231 .__zig_tag_name_table,
2232 .__heap_base,
2233 .__heap_end,
2234 => false,2232 => false,
22352233
2236 .object => |i| i.ptr(wasm).flags.retain,2234 .object => |i| i.ptr(wasm).flags.retain,
...@@ -2251,8 +2249,6 @@ pub const DataSegmentId = enum(u32) {...@@ -2251,8 +2249,6 @@ pub const DataSegmentId = enum(u32) {
2251 .__zig_tag_name_table,2249 .__zig_tag_name_table,
2252 .uav_exe,2250 .uav_exe,
2253 .uav_obj,2251 .uav_obj,
2254 .__heap_base,
2255 .__heap_end,
2256 => ".data",2252 => ".data",
22572253
2258 .object => |i| i.ptr(wasm).name.unwrap().?.slice(wasm),2254 .object => |i| i.ptr(wasm).name.unwrap().?.slice(wasm),
...@@ -2272,7 +2268,7 @@ pub const DataSegmentId = enum(u32) {...@@ -2272,7 +2268,7 @@ pub const DataSegmentId = enum(u32) {
2272 pub fn alignment(id: DataSegmentId, wasm: *const Wasm) Alignment {2268 pub fn alignment(id: DataSegmentId, wasm: *const Wasm) Alignment {
2273 return switch (unpack(id, wasm)) {2269 return switch (unpack(id, wasm)) {
2274 .__zig_error_names, .__zig_tag_names => .@"1",2270 .__zig_error_names, .__zig_tag_names => .@"1",
2275 .__zig_error_name_table, .__zig_tag_name_table, .__heap_base, .__heap_end => wasm.pointerAlignment(),2271 .__zig_error_name_table, .__zig_tag_name_table => wasm.pointerAlignment(),
2276 .object => |i| i.ptr(wasm).flags.alignment,2272 .object => |i| i.ptr(wasm).flags.alignment,
2277 inline .uav_exe, .uav_obj => |i| {2273 inline .uav_exe, .uav_obj => |i| {
2278 const zcu = wasm.base.comp.zcu.?;2274 const zcu = wasm.base.comp.zcu.?;
...@@ -2304,7 +2300,7 @@ pub const DataSegmentId = enum(u32) {...@@ -2304,7 +2300,7 @@ pub const DataSegmentId = enum(u32) {
2304 .__zig_error_name_table => wasm.error_name_table_ref_count,2300 .__zig_error_name_table => wasm.error_name_table_ref_count,
2305 .__zig_tag_names => @intCast(wasm.tag_name_offs.items.len),2301 .__zig_tag_names => @intCast(wasm.tag_name_offs.items.len),
2306 .__zig_tag_name_table => wasm.tag_name_table_ref_count,2302 .__zig_tag_name_table => wasm.tag_name_table_ref_count,
2307 .object, .uav_obj, .nav_obj, .__heap_base, .__heap_end => 0,2303 .object, .uav_obj, .nav_obj => 0,
2308 inline .uav_exe, .nav_exe => |i| i.value(wasm).count,2304 inline .uav_exe, .nav_exe => |i| i.value(wasm).count,
2309 };2305 };
2310 }2306 }
...@@ -2317,8 +2313,6 @@ pub const DataSegmentId = enum(u32) {...@@ -2317,8 +2313,6 @@ pub const DataSegmentId = enum(u32) {
2317 .__zig_error_name_table,2313 .__zig_error_name_table,
2318 .__zig_tag_names,2314 .__zig_tag_names,
2319 .__zig_tag_name_table,2315 .__zig_tag_name_table,
2320 .__heap_base,
2321 .__heap_end,
2322 => false,2316 => false,
23232317
2324 .object => |i| i.ptr(wasm).flags.is_passive,2318 .object => |i| i.ptr(wasm).flags.is_passive,
...@@ -2332,8 +2326,6 @@ pub const DataSegmentId = enum(u32) {...@@ -2332,8 +2326,6 @@ pub const DataSegmentId = enum(u32) {
2332 .__zig_error_name_table,2326 .__zig_error_name_table,
2333 .__zig_tag_names,2327 .__zig_tag_names,
2334 .__zig_tag_name_table,2328 .__zig_tag_name_table,
2335 .__heap_base,
2336 .__heap_end,
2337 => false,2329 => false,
23382330
2339 .object => |i| i.ptr(wasm).payload.off == .none,2331 .object => |i| i.ptr(wasm).payload.off == .none,
...@@ -2359,7 +2351,6 @@ pub const DataSegmentId = enum(u32) {...@@ -2359,7 +2351,6 @@ pub const DataSegmentId = enum(u32) {
2359 const elem_size = Zcu.Type.slice_const_u8_sentinel_0.abiSize(zcu);2351 const elem_size = Zcu.Type.slice_const_u8_sentinel_0.abiSize(zcu);
2360 return @intCast(table_len * elem_size);2352 return @intCast(table_len * elem_size);
2361 },2353 },
2362 .__heap_base, .__heap_end => wasm.pointerSize(),
2363 .object => |i| i.ptr(wasm).payload.len,2354 .object => |i| i.ptr(wasm).payload.len,
2364 inline .uav_exe, .uav_obj, .nav_exe, .nav_obj => |i| i.value(wasm).code.len,2355 inline .uav_exe, .uav_obj, .nav_exe, .nav_obj => |i| i.value(wasm).code.len,
2365 };2356 };
...@@ -2491,6 +2482,7 @@ pub const Func = extern struct {...@@ -2491,6 +2482,7 @@ pub const Func = extern struct {
2491/// Type reflection is used on the field names to autopopulate each field2482/// Type reflection is used on the field names to autopopulate each field
2492/// during initialization.2483/// during initialization.
2493const PreloadedStrings = struct {2484const PreloadedStrings = struct {
2485 __global_base: String,
2494 __heap_base: String,2486 __heap_base: String,
2495 __heap_end: String,2487 __heap_end: String,
2496 __indirect_function_table: String,2488 __indirect_function_table: String,
...@@ -2504,6 +2496,7 @@ const PreloadedStrings = struct {...@@ -2504,6 +2496,7 @@ const PreloadedStrings = struct {
2504 __wasm_init_memory: String,2496 __wasm_init_memory: String,
2505 __wasm_init_memory_flag: String,2497 __wasm_init_memory_flag: String,
2506 __wasm_init_tls: String,2498 __wasm_init_tls: String,
2499 __wasm_first_page_end: String,
2507 __zig_error_names: String,2500 __zig_error_names: String,
2508 __zig_error_name_table: String,2501 __zig_error_name_table: String,
2509 __zig_errors_len: String,2502 __zig_errors_len: String,
...@@ -3907,21 +3900,11 @@ pub fn prelink(wasm: *Wasm, prog_node: std.Progress.Node) link.Error!void {...@@ -3907,21 +3900,11 @@ pub fn prelink(wasm: *Wasm, prog_node: std.Progress.Node) link.Error!void {
3907 try markFunctionImport(wasm, name, import, @fromBackingInt(@intCast(i)));3900 try markFunctionImport(wasm, name, import, @fromBackingInt(@intCast(i)));
3908 }3901 }
3909 }3902 }
3910 // Also treat init functions as roots.
3911 for (wasm.object_init_funcs.items) |init_func| {
3912 const func = init_func.function_index.ptr(wasm);
3913 if (func.object_index.ptr(wasm).is_included) {
3914 try markFunction(wasm, init_func.function_index, false);
3915 }
3916 }
3917 wasm.functions_end_prelink = @intCast(wasm.functions.entries.len);
3918
3919 for (wasm.object_global_imports.keys(), wasm.object_global_imports.values(), 0..) |name, *import, i| {3903 for (wasm.object_global_imports.keys(), wasm.object_global_imports.values(), 0..) |name, *import, i| {
3920 if (import.flags.isIncluded(rdynamic, is_obj)) {3904 if (import.flags.isIncluded(rdynamic, is_obj)) {
3921 try markGlobalImport(wasm, name, import, @fromBackingInt(@intCast(i)));3905 try markGlobalImport(wasm, name, import, @fromBackingInt(@intCast(i)));
3922 }3906 }
3923 }3907 }
3924 wasm.globals_end_prelink = @intCast(wasm.globals.entries.len);
3925 wasm.global_exports_len = @intCast(wasm.global_exports.items.len);3908 wasm.global_exports_len = @intCast(wasm.global_exports.items.len);
39263909
3927 for (wasm.object_table_imports.keys(), wasm.object_table_imports.values(), 0..) |name, *import, i| {3910 for (wasm.object_table_imports.keys(), wasm.object_table_imports.values(), 0..) |name, *import, i| {
...@@ -3944,6 +3927,8 @@ pub fn prelink(wasm: *Wasm, prog_node: std.Progress.Node) link.Error!void {...@@ -3944,6 +3927,8 @@ pub fn prelink(wasm: *Wasm, prog_node: std.Progress.Node) link.Error!void {
3944 wasm.memories.limits.flags.has_max = wasm.memories.limits.flags.has_max or memory_import.limits_has_max;3927 wasm.memories.limits.flags.has_max = wasm.memories.limits.flags.has_max or memory_import.limits_has_max;
3945 }3928 }
39463929
3930 wasm.functions_end_prelink = @intCast(wasm.functions.entries.len);
3931 wasm.globals_end_prelink = @intCast(wasm.globals.entries.len);
3947 wasm.function_imports_len_prelink = @intCast(wasm.function_imports.entries.len);3932 wasm.function_imports_len_prelink = @intCast(wasm.function_imports.entries.len);
3948 wasm.data_imports_len_prelink = @intCast(wasm.data_imports.entries.len);3933 wasm.data_imports_len_prelink = @intCast(wasm.data_imports.entries.len);
3949}3934}
...@@ -3998,7 +3983,7 @@ fn markFunction(wasm: *Wasm, i: ObjectFunctionIndex, override_export: bool) link...@@ -3998,7 +3983,7 @@ fn markFunction(wasm: *Wasm, i: ObjectFunctionIndex, override_export: bool) link
3998 const rdynamic = comp.config.rdynamic;3983 const rdynamic = comp.config.rdynamic;
3999 const is_obj = comp.config.output_mode == .Obj;3984 const is_obj = comp.config.output_mode == .Obj;
4000 const function = i.ptr(wasm);3985 const function = i.ptr(wasm);
4001 markObject(wasm, function.object_index);3986 try markObject(wasm, function.object_index);
40023987
4003 if (!is_obj and (override_export or function.flags.isExported(rdynamic))) {3988 if (!is_obj and (override_export or function.flags.isExported(rdynamic))) {
4004 const symbol_name = function.name.unwrap().?;3989 const symbol_name = function.name.unwrap().?;
...@@ -4012,8 +3997,15 @@ fn markFunction(wasm: *Wasm, i: ObjectFunctionIndex, override_export: bool) link...@@ -4012,8 +3997,15 @@ fn markFunction(wasm: *Wasm, i: ObjectFunctionIndex, override_export: bool) link
4012 try wasm.markRelocations(function.relocations(wasm));3997 try wasm.markRelocations(function.relocations(wasm));
4013}3998}
40143999
4015fn markObject(wasm: *Wasm, i: ObjectIndex) void {4000fn markObject(wasm: *Wasm, i: ObjectIndex) link.Error!void {
4016 i.ptr(wasm).is_included = true;4001 const object = i.ptr(wasm);
4002 if (object.is_included) return;
4003 object.is_included = true;
4004
4005 const init_funcs = wasm.object_init_funcs.items[object.init_funcs.off..][0..object.init_funcs.len];
4006 for (init_funcs) |init_func| {
4007 try markFunction(wasm, init_func.function_index, false);
4008 }
4017}4009}
40184010
4019/// Recursively mark alive everything referenced by the global.4011/// Recursively mark alive everything referenced by the global.
...@@ -4076,6 +4068,7 @@ fn markGlobal(wasm: *Wasm, i: ObjectGlobalIndex, override_export: bool) link.Err...@@ -4076,6 +4068,7 @@ fn markGlobal(wasm: *Wasm, i: ObjectGlobalIndex, override_export: bool) link.Err
4076 const rdynamic = comp.config.rdynamic;4068 const rdynamic = comp.config.rdynamic;
4077 const is_obj = comp.config.output_mode == .Obj;4069 const is_obj = comp.config.output_mode == .Obj;
4078 const global = i.ptr(wasm);4070 const global = i.ptr(wasm);
4071 try markObject(wasm, global.object_index);
40794072
4080 if (!is_obj and (override_export or global.flags.isExported(rdynamic))) try wasm.global_exports.append(gpa, .{4073 if (!is_obj and (override_export or global.flags.isExported(rdynamic))) try wasm.global_exports.append(gpa, .{
4081 .name = global.name.unwrap().?,4074 .name = global.name.unwrap().?,
...@@ -4122,6 +4115,7 @@ fn markDataSegment(wasm: *Wasm, segment_index: ObjectDataSegment.Index) link.Err...@@ -4122,6 +4115,7 @@ fn markDataSegment(wasm: *Wasm, segment_index: ObjectDataSegment.Index) link.Err
4122 const segment = segment_index.ptr(wasm);4115 const segment = segment_index.ptr(wasm);
4123 if (segment.flags.alive) return;4116 if (segment.flags.alive) return;
4124 segment.flags.alive = true;4117 segment.flags.alive = true;
4118 try markObject(wasm, segment.object_index);
41254119
4126 wasm.any_passive_inits = wasm.any_passive_inits or segment.flags.is_passive or4120 wasm.any_passive_inits = wasm.any_passive_inits or segment.flags.is_passive or
4127 (comp.config.import_memory and !wasm.isBss(segment.name));4121 (comp.config.import_memory and !wasm.isBss(segment.name));
...@@ -4143,16 +4137,16 @@ pub fn markDataImport(...@@ -4143,16 +4137,16 @@ pub fn markDataImport(
4143 const gpa = comp.gpa;4137 const gpa = comp.gpa;
4144 const is_obj = comp.config.output_mode == .Obj;4138 const is_obj = comp.config.output_mode == .Obj;
41454139
4146 try wasm.data_segments.ensureUnusedCapacity(gpa, 1);
4147
4148 if (import.resolution == .unresolved) {4140 if (import.resolution == .unresolved) {
4149 if (!is_obj) {4141 if (!is_obj) {
4150 if (name == wasm.preloaded_strings.__heap_base) {4142 if (name == wasm.preloaded_strings.__global_base) {
4143 import.resolution = .__global_base;
4144 } else if (name == wasm.preloaded_strings.__heap_base) {
4151 import.resolution = .__heap_base;4145 import.resolution = .__heap_base;
4152 wasm.data_segments.putAssumeCapacity(.__heap_base, {});
4153 } else if (name == wasm.preloaded_strings.__heap_end) {4146 } else if (name == wasm.preloaded_strings.__heap_end) {
4154 import.resolution = .__heap_end;4147 import.resolution = .__heap_end;
4155 wasm.data_segments.putAssumeCapacity(.__heap_end, {});4148 } else if (name == wasm.preloaded_strings.__wasm_first_page_end) {
4149 import.resolution = .__wasm_first_page_end;
4156 } else {4150 } else {
4157 try wasm.data_imports.put(gpa, name, .fromObject(data_index, wasm));4151 try wasm.data_imports.put(gpa, name, .fromObject(data_index, wasm));
4158 }4152 }
...@@ -4857,6 +4851,17 @@ pub fn uavAddr(wasm: *const Wasm, ip_index: InternPool.Index) u32 {...@@ -4857,6 +4851,17 @@ pub fn uavAddr(wasm: *const Wasm, ip_index: InternPool.Index) u32 {
4857 return wasm.flush_buffer.data_segments.get(ds_id).?;4851 return wasm.flush_buffer.data_segments.get(ds_id).?;
4858}4852}
48594853
4854pub fn syntheticDataAddr(wasm: *const Wasm, resolution: ObjectDataImport.Resolution) ?u32 {
4855 const virtual_addrs = wasm.flush_buffer.virtual_addrs;
4856 return switch (resolution.unpack(wasm)) {
4857 .__global_base => virtual_addrs.global_base,
4858 .__heap_base => virtual_addrs.heap_base,
4859 .__heap_end => virtual_addrs.heap_end,
4860 .__wasm_first_page_end => virtual_addrs.wasm_first_page_end,
4861 else => null,
4862 };
4863}
4864
4860/// Asserts it is called after `Flush.data_segments` is fully populated and sorted.4865/// Asserts it is called after `Flush.data_segments` is fully populated and sorted.
4861pub fn navAddr(wasm: *const Wasm, nav_index: InternPool.Nav.Index) u32 {4866pub fn navAddr(wasm: *const Wasm, nav_index: InternPool.Nav.Index) u32 {
4862 assert(wasm.flush_buffer.memory_layout_finished);4867 assert(wasm.flush_buffer.memory_layout_finished);
...@@ -4881,8 +4886,11 @@ pub fn navAddr(wasm: *const Wasm, nav_index: InternPool.Nav.Index) u32 {...@@ -4881,8 +4886,11 @@ pub fn navAddr(wasm: *const Wasm, nav_index: InternPool.Nav.Index) u32 {
4881 const segment_base_addr = wasm.flush_buffer.data_segments.get(ds_id).?;4886 const segment_base_addr = wasm.flush_buffer.data_segments.get(ds_id).?;
4882 return segment_base_addr + object_data.offset;4887 return segment_base_addr + object_data.offset;
4883 },4888 },
4889 .__global_base,
4884 .__heap_base,4890 .__heap_base,
4885 .__heap_end,4891 .__heap_end,
4892 .__wasm_first_page_end,
4893 => return wasm.syntheticDataAddr(import.resolution).?,
4886 .uav_exe,4894 .uav_exe,
4887 .nav_exe,4895 .nav_exe,
4888 => {4896 => {
src/link/Wasm/Flush.zig+37-37
...@@ -41,6 +41,7 @@ data_imports: std.array_hash_map.Auto(String, Wasm.DataImportId) = .empty,...@@ -41,6 +41,7 @@ data_imports: std.array_hash_map.Auto(String, Wasm.DataImportId) = .empty,
41data_exports: std.array_hash_map.Auto(String, DataExportSymbol) = .empty,41data_exports: std.array_hash_map.Auto(String, DataExportSymbol) = .empty,
4242
43indirect_function_table: std.array_hash_map.Auto(Wasm.OutputFunctionIndex, void) = .empty,43indirect_function_table: std.array_hash_map.Auto(Wasm.OutputFunctionIndex, void) = .empty,
44sorted_init_funcs: std.ArrayList(Wasm.InitFunc) = .empty,
4445
45/// A subset of the full interned function type list created only during flush.46/// A subset of the full interned function type list created only during flush.
46func_types: std.array_hash_map.Auto(Wasm.FunctionType.Index, void) = .empty,47func_types: std.array_hash_map.Auto(Wasm.FunctionType.Index, void) = .empty,
...@@ -53,6 +54,8 @@ data_relocs: std.ArrayList(Relocation) = .empty,...@@ -53,6 +54,8 @@ data_relocs: std.ArrayList(Relocation) = .empty,
53/// For debug purposes only.54/// For debug purposes only.
54memory_layout_finished: bool = false,55memory_layout_finished: bool = false,
5556
57virtual_addrs: VirtualAddrs = undefined,
58
56/// Index into `func_types`.59/// Index into `func_types`.
57pub const FuncTypeIndex = enum(u32) {60pub const FuncTypeIndex = enum(u32) {
58 _,61 _,
...@@ -201,11 +204,13 @@ pub fn clear(f: *Flush) void {...@@ -201,11 +204,13 @@ pub fn clear(f: *Flush) void {
201 f.function_export_symbols.clearRetainingCapacity();204 f.function_export_symbols.clearRetainingCapacity();
202 f.data_exports.clearRetainingCapacity();205 f.data_exports.clearRetainingCapacity();
203 f.indirect_function_table.clearRetainingCapacity();206 f.indirect_function_table.clearRetainingCapacity();
207 f.sorted_init_funcs.clearRetainingCapacity();
204 f.func_types.clearRetainingCapacity();208 f.func_types.clearRetainingCapacity();
205 f.enum_tag_name_table.clearRetainingCapacity();209 f.enum_tag_name_table.clearRetainingCapacity();
206 f.code_relocs.clearRetainingCapacity();210 f.code_relocs.clearRetainingCapacity();
207 f.data_relocs.clearRetainingCapacity();211 f.data_relocs.clearRetainingCapacity();
208 f.memory_layout_finished = false;212 f.memory_layout_finished = false;
213 f.virtual_addrs = undefined;
209}214}
210215
211pub fn deinit(f: *Flush, gpa: Allocator) void {216pub fn deinit(f: *Flush, gpa: Allocator) void {
...@@ -220,6 +225,7 @@ pub fn deinit(f: *Flush, gpa: Allocator) void {...@@ -220,6 +225,7 @@ pub fn deinit(f: *Flush, gpa: Allocator) void {
220 f.data_imports.deinit(gpa);225 f.data_imports.deinit(gpa);
221 f.data_exports.deinit(gpa);226 f.data_exports.deinit(gpa);
222 f.indirect_function_table.deinit(gpa);227 f.indirect_function_table.deinit(gpa);
228 f.sorted_init_funcs.deinit(gpa);
223 f.func_types.deinit(gpa);229 f.func_types.deinit(gpa);
224 f.enum_tag_name_table.deinit(gpa);230 f.enum_tag_name_table.deinit(gpa);
225 f.code_relocs.deinit(gpa);231 f.code_relocs.deinit(gpa);
...@@ -542,9 +548,15 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -542,9 +548,15 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
542 for (wasm.object_indirect_function_set.keys()) |object_function_index|548 for (wasm.object_indirect_function_set.keys()) |object_function_index|
543 f.indirect_function_table.putAssumeCapacity(.fromObjectFunction(wasm, object_function_index), {});549 f.indirect_function_table.putAssumeCapacity(.fromObjectFunction(wasm, object_function_index), {});
544550
545 if (wasm.object_init_funcs.items.len > 0) {551 try f.sorted_init_funcs.ensureUnusedCapacity(gpa, wasm.object_init_funcs.items.len);
552 for (wasm.object_init_funcs.items) |init_func| {
553 const func = init_func.function_index.ptr(wasm);
554 if (!func.object_index.ptr(wasm).is_included) continue;
555 f.sorted_init_funcs.appendAssumeCapacity(init_func);
556 }
557 if (f.sorted_init_funcs.items.len > 0) {
546 // Zig has no constructors so these are only for object file inputs.558 // Zig has no constructors so these are only for object file inputs.
547 mem.sortUnstable(Wasm.InitFunc, wasm.object_init_funcs.items, {}, Wasm.InitFunc.lessThan);559 mem.sortUnstable(Wasm.InitFunc, f.sorted_init_funcs.items, {}, Wasm.InitFunc.lessThan);
548 if (!is_obj) try wasm.functions.put(gpa, .__wasm_call_ctors, {});560 if (!is_obj) try wasm.functions.put(gpa, .__wasm_call_ctors, {});
549 }561 }
550562
...@@ -703,10 +715,13 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -703,10 +715,13 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
703 // Always place the stack at the start by default unless the user specified the global-base flag.715 // Always place the stack at the start by default unless the user specified the global-base flag.
704 const place_stack_first, var memory_ptr: u64 = if (wasm.global_base) |base| .{ false, base } else .{ true, 0 };716 const place_stack_first, var memory_ptr: u64 = if (wasm.global_base) |base| .{ false, base } else .{ true, 0 };
705717
706 var virtual_addrs: VirtualAddrs = .{718 const virtual_addrs = &f.virtual_addrs;
719 virtual_addrs.* = .{
720 .global_base = undefined,
707 .stack_pointer = undefined,721 .stack_pointer = undefined,
708 .heap_base = undefined,722 .heap_base = undefined,
709 .heap_end = undefined,723 .heap_end = undefined,
724 .wasm_first_page_end = page_size,
710 .tls_base = null,725 .tls_base = null,
711 .tls_align = .none,726 .tls_align = .none,
712 .tls_size = null,727 .tls_size = null,
...@@ -719,10 +734,12 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -719,10 +734,12 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
719 virtual_addrs.stack_pointer = @intCast(memory_ptr);734 virtual_addrs.stack_pointer = @intCast(memory_ptr);
720 }735 }
721736
737 const data_vaddr: u32 = @intCast(memory_ptr);
738 virtual_addrs.global_base = data_vaddr;
739
722 const segment_ids = f.data_segments.keys();740 const segment_ids = f.data_segments.keys();
723 const segment_vaddrs = f.data_segments.values();741 const segment_vaddrs = f.data_segments.values();
724 assert(f.data_segment_groups.items.len == 0);742 assert(f.data_segment_groups.items.len == 0);
725 const data_vaddr: u32 = @intCast(memory_ptr);
726 if (segment_ids.len > 0) {743 if (segment_ids.len > 0) {
727 var seen_tls: enum { before, during, after } = .before;744 var seen_tls: enum { before, during, after } = .before;
728 var category: Wasm.DataSegmentId.Category = undefined;745 var category: Wasm.DataSegmentId.Category = undefined;
...@@ -1165,7 +1182,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -1165,7 +1182,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
1165 .__wasm_init_memory => {1182 .__wasm_init_memory => {
1166 const code_start = try reserveSize(gpa, binary_bytes);1183 const code_start = try reserveSize(gpa, binary_bytes);
1167 defer replaceSize(binary_bytes, code_start);1184 defer replaceSize(binary_bytes, code_start);
1168 try emitInitMemoryFunction(wasm, binary_bytes, &virtual_addrs);1185 try emitInitMemoryFunction(wasm, binary_bytes);
1169 },1186 },
1170 .__wasm_init_tls => {1187 .__wasm_init_tls => {
1171 const code_start = try reserveSize(gpa, binary_bytes);1188 const code_start = try reserveSize(gpa, binary_bytes);
...@@ -1327,14 +1344,6 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -1327,14 +1344,6 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
1327 const output_offset: u32 = @intCast(binary_bytes.items.len - section_offset);1344 const output_offset: u32 = @intCast(binary_bytes.items.len - section_offset);
1328 append: {1345 append: {
1329 const code = switch (segment_id.unpack(wasm)) {1346 const code = switch (segment_id.unpack(wasm)) {
1330 .__heap_base => {
1331 mem.writeInt(u32, try binary_bytes.addManyAsArray(gpa, 4), virtual_addrs.heap_base, .little);
1332 break :append;
1333 },
1334 .__heap_end => {
1335 mem.writeInt(u32, try binary_bytes.addManyAsArray(gpa, 4), virtual_addrs.heap_end, .little);
1336 break :append;
1337 },
1338 .__zig_error_names => {1347 .__zig_error_names => {
1339 try binary_bytes.appendSlice(gpa, wasm.error_name_bytes.items);1348 try binary_bytes.appendSlice(gpa, wasm.error_name_bytes.items);
1340 break :append;1349 break :append;
...@@ -1643,22 +1652,9 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -1643,22 +1652,9 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
1643 const sub_offset = try reserveCustomSectionHeader(gpa, binary_bytes);1652 const sub_offset = try reserveCustomSectionHeader(gpa, binary_bytes);
1644 defer replaceHeader(binary_bytes, sub_offset, @backingInt(Object.SubsectionType.init_funcs));1653 defer replaceHeader(binary_bytes, sub_offset, @backingInt(Object.SubsectionType.init_funcs));
16451654
1646 const init_funcs = wasm.object_init_funcs.items;1655 try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(f.sorted_init_funcs.items.len)));
1647 const total_functions: u32 = b: {
1648 var cnt: u32 = 0;
1649 for (init_funcs) |init_func| {
1650 const func = init_func.function_index.ptr(wasm);
1651 if (!func.object_index.ptr(wasm).is_included) continue;
1652 cnt += 1;
1653 }
1654 break :b cnt;
1655 };
1656 try appendLeb128(gpa, binary_bytes, total_functions);
1657
1658 for (init_funcs) |init_func| {
1659 const func = init_func.function_index.ptr(wasm);
1660 if (!func.object_index.ptr(wasm).is_included) continue;
16611656
1657 for (f.sorted_init_funcs.items) |init_func| {
1662 try appendLeb128(gpa, binary_bytes, init_func.priority);1658 try appendLeb128(gpa, binary_bytes, init_func.priority);
1663 const out_index: Wasm.OutputFunctionIndex = .fromObjectFunction(wasm, init_func.function_index);1659 const out_index: Wasm.OutputFunctionIndex = .fromObjectFunction(wasm, init_func.function_index);
1664 const symbol_index: u32 = symbol_table_offsets.function + @backingInt(out_index);1660 const symbol_index: u32 = symbol_table_offsets.function + @backingInt(out_index);
...@@ -1736,9 +1732,11 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -1736,9 +1732,11 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
1736}1732}
17371733
1738const VirtualAddrs = struct {1734const VirtualAddrs = struct {
1735 global_base: u32,
1739 stack_pointer: u32,1736 stack_pointer: u32,
1740 heap_base: u32,1737 heap_base: u32,
1741 heap_end: u32,1738 heap_end: u32,
1739 wasm_first_page_end: u32,
1742 tls_base: ?u32,1740 tls_base: ?u32,
1743 tls_align: Alignment,1741 tls_align: Alignment,
1744 tls_size: ?u32,1742 tls_size: ?u32,
...@@ -2587,6 +2585,9 @@ const RelocAddr = struct {...@@ -2587,6 +2585,9 @@ const RelocAddr = struct {
2587 const flush = &wasm.flush_buffer;2585 const flush = &wasm.flush_buffer;
2588 if (wasm.object_data_imports.getPtr(name)) |import| {2586 if (wasm.object_data_imports.getPtr(name)) |import| {
2589 if (import.resolution != .unresolved) {2587 if (import.resolution != .unresolved) {
2588 if (wasm.syntheticDataAddr(import.resolution)) |addr| {
2589 return fromAddr(addr, addend);
2590 }
2590 return fromDataLoc(flush, import.resolution.dataLoc(wasm), addend);2591 return fromDataLoc(flush, import.resolution.dataLoc(wasm), addend);
2591 }2592 }
2592 }2593 }
...@@ -2600,8 +2601,11 @@ const RelocAddr = struct {...@@ -2600,8 +2601,11 @@ const RelocAddr = struct {
2600 }2601 }
26012602
2602 fn fromDataLoc(flush: *const Flush, data_loc: Wasm.DataLoc, addend: i32) RelocAddr {2603 fn fromDataLoc(flush: *const Flush, data_loc: Wasm.DataLoc, addend: i32) RelocAddr {
2603 const base_addr: i64 = flush.data_segments.get(data_loc.segment).?;2604 return fromAddr(flush.data_segments.get(data_loc.segment).? + data_loc.offset, addend);
2604 return .{ .addr = @intCast(base_addr + data_loc.offset + addend) };2605 }
2606
2607 fn fromAddr(addr: u32, addend: i32) RelocAddr {
2608 return .{ .addr = @intCast(@as(i64, addr) + addend) };
2605 }2609 }
2606};2610};
26072611
...@@ -2643,9 +2647,8 @@ fn emitCallCtorsFunction(wasm: *const Wasm, binary_bytes: *ArrayList(u8)) Alloca...@@ -2643,9 +2647,8 @@ fn emitCallCtorsFunction(wasm: *const Wasm, binary_bytes: *ArrayList(u8)) Alloca
2643 try binary_bytes.ensureUnusedCapacity(gpa, 5 + 1);2647 try binary_bytes.ensureUnusedCapacity(gpa, 5 + 1);
2644 appendReservedUleb32(binary_bytes, 0); // no locals2648 appendReservedUleb32(binary_bytes, 0); // no locals
26452649
2646 for (wasm.object_init_funcs.items) |init_func| {2650 for (wasm.flush_buffer.sorted_init_funcs.items) |init_func| {
2647 const func = init_func.function_index.ptr(wasm);2651 const func = init_func.function_index.ptr(wasm);
2648 if (!func.object_index.ptr(wasm).is_included) continue;
2649 const ty = func.type_index.ptr(wasm);2652 const ty = func.type_index.ptr(wasm);
2650 const n_returns = ty.returns.slice(wasm).len;2653 const n_returns = ty.returns.slice(wasm).len;
26512654
...@@ -2662,14 +2665,11 @@ fn emitCallCtorsFunction(wasm: *const Wasm, binary_bytes: *ArrayList(u8)) Alloca...@@ -2662,14 +2665,11 @@ fn emitCallCtorsFunction(wasm: *const Wasm, binary_bytes: *ArrayList(u8)) Alloca
2662 binary_bytes.appendAssumeCapacity(@backingInt(std.wasm.Opcode.end)); // end function body2665 binary_bytes.appendAssumeCapacity(@backingInt(std.wasm.Opcode.end)); // end function body
2663}2666}
26642667
2665fn emitInitMemoryFunction(2668fn emitInitMemoryFunction(wasm: *const Wasm, binary_bytes: *ArrayList(u8)) Allocator.Error!void {
2666 wasm: *const Wasm,
2667 binary_bytes: *ArrayList(u8),
2668 virtual_addrs: *const VirtualAddrs,
2669) Allocator.Error!void {
2670 const comp = wasm.base.comp;2669 const comp = wasm.base.comp;
2671 const gpa = comp.gpa;2670 const gpa = comp.gpa;
2672 const shared_memory = comp.config.shared_memory;2671 const shared_memory = comp.config.shared_memory;
2672 const virtual_addrs = &wasm.flush_buffer.virtual_addrs;
26732673
2674 // Passive segments are used to avoid memory being reinitialized on each2674 // Passive segments are used to avoid memory being reinitialized on each
2675 // thread's instantiation. These passive segments are initialized and2675 // thread's instantiation. These passive segments are initialized and