diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2024-12-19 16:01:18 -0800 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2025-01-15 15:11:36 -0800 |
| commit | 5e0d33f00fea077b362f468d89a979aee270df0b (patch) | |
| tree | 189b5a32eb1ce645ff876a928267dc620ff142ef /src | |
| parent | 389b29fd8c13707891486dfed64ed2b9df3f1a39 (diff) | |
| download | zig-5e0d33f00fea077b362f468d89a979aee270df0b.tar.gz zig-5e0d33f00fea077b362f468d89a979aee270df0b.zip | |
wasm linker: also call lowerZcuData in updateFunc
codegen can generate zcu data dependencies that need to be populated
Diffstat (limited to 'src')
| -rw-r--r-- | src/link/Wasm.zig | 129 | ||||
| -rw-r--r-- | src/link/Wasm/Flush.zig | 3 |
2 files changed, 91 insertions, 41 deletions
diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig index 71a2c05bd4..ae5bc18c6a 100644 --- a/src/link/Wasm.zig +++ b/src/link/Wasm.zig @@ -675,6 +675,88 @@ pub const ZcuDataExe = extern struct { count: u32, }; +/// An abstraction for calling `lowerZcuData` repeatedly until all data entries +/// are populated. +const ZcuDataStarts = struct { + uavs_i: u32, + navs_i: u32, + + fn init(wasm: *const Wasm) ZcuDataStarts { + const comp = wasm.base.comp; + const is_obj = comp.config.output_mode == .Obj; + return if (is_obj) initObj(wasm) else initExe(wasm); + } + + fn initObj(wasm: *const Wasm) ZcuDataStarts { + return .{ + .uavs_i = @intCast(wasm.uavs_obj.entries.len), + .navs_i = @intCast(wasm.navs_obj.entries.len), + }; + } + + fn initExe(wasm: *const Wasm) ZcuDataStarts { + return .{ + .uavs_i = @intCast(wasm.uavs_exe.entries.len), + .navs_i = @intCast(wasm.navs_exe.entries.len), + }; + } + + fn finish(zds: ZcuDataStarts, wasm: *Wasm, pt: Zcu.PerThread) !void { + const comp = wasm.base.comp; + const is_obj = comp.config.output_mode == .Obj; + return if (is_obj) finishObj(zds, wasm, pt) else finishExe(zds, wasm, pt); + } + + fn finishObj(zds: ZcuDataStarts, wasm: *Wasm, pt: Zcu.PerThread) !void { + const zcu = wasm.base.comp.zcu.?; + const ip = &zcu.intern_pool; + var uavs_i = zds.uavs_i; + var navs_i = zds.navs_i; + while (true) { + while (navs_i < wasm.navs_obj.entries.len) : (navs_i += 1) { + const elem_nav = ip.getNav(wasm.navs_obj.keys()[navs_i]); + const elem_nav_init = switch (ip.indexToKey(elem_nav.status.resolved.val)) { + .variable => |variable| variable.init, + else => elem_nav.status.resolved.val, + }; + // Call to `lowerZcuData` here possibly creates more entries in these tables. + wasm.navs_obj.values()[navs_i] = try lowerZcuData(wasm, pt, elem_nav_init); + } + while (uavs_i < wasm.uavs_obj.entries.len) : (uavs_i += 1) { + // Call to `lowerZcuData` here possibly creates more entries in these tables. + wasm.uavs_obj.values()[uavs_i] = try lowerZcuData(wasm, pt, wasm.uavs_obj.keys()[uavs_i]); + } + if (navs_i >= wasm.navs_obj.entries.len) break; + } + } + + fn finishExe(zds: ZcuDataStarts, wasm: *Wasm, pt: Zcu.PerThread) !void { + const zcu = wasm.base.comp.zcu.?; + const ip = &zcu.intern_pool; + var uavs_i = zds.uavs_i; + var navs_i = zds.navs_i; + while (true) { + while (navs_i < wasm.navs_exe.entries.len) : (navs_i += 1) { + const elem_nav = ip.getNav(wasm.navs_exe.keys()[navs_i]); + const elem_nav_init = switch (ip.indexToKey(elem_nav.status.resolved.val)) { + .variable => |variable| variable.init, + else => elem_nav.status.resolved.val, + }; + // Call to `lowerZcuData` here possibly creates more entries in these tables. + const zcu_data = try lowerZcuData(wasm, pt, elem_nav_init); + assert(zcu_data.relocs.len == 0); + wasm.navs_exe.values()[navs_i].code = zcu_data.code; + } + while (uavs_i < wasm.uavs_exe.entries.len) : (uavs_i += 1) { + // Call to `lowerZcuData` here possibly creates more entries in these tables. + const zcu_data = try lowerZcuData(wasm, pt, wasm.uavs_exe.keys()[uavs_i]); + wasm.uavs_exe.values()[uavs_i].code = zcu_data.code; + } + if (navs_i >= wasm.navs_exe.entries.len) break; + } + } +}; + pub const ZcuFunc = extern struct { function: CodeGen.Function, @@ -2306,6 +2388,8 @@ pub fn updateFunc(wasm: *Wasm, pt: Zcu.PerThread, func_index: InternPool.Index, try wasm.functions.ensureUnusedCapacity(gpa, 1); try wasm.zcu_funcs.ensureUnusedCapacity(gpa, 1); + const zds: ZcuDataStarts = .init(wasm); + // This converts AIR to MIR but does not yet lower to wasm code. // That lowering happens during `flush`, after garbage collection, which // can affect function and global indexes, which affects the LEB integer @@ -2314,6 +2398,8 @@ pub fn updateFunc(wasm: *Wasm, pt: Zcu.PerThread, func_index: InternPool.Index, .function = try CodeGen.function(wasm, pt, func_index, air, liveness), }); wasm.functions.putAssumeCapacity(.pack(wasm, .{ .zcu_func = @enumFromInt(wasm.zcu_funcs.entries.len - 1) }), {}); + + try zds.finish(wasm, pt); } // Generate code for the "Nav", storing it in memory to be later written to @@ -2365,48 +2451,13 @@ pub fn updateNav(wasm: *Wasm, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index } if (is_obj) { - var uavs_i = wasm.uavs_obj.entries.len; - var navs_i = wasm.navs_obj.entries.len; + const zcu_data_starts: ZcuDataStarts = .initObj(wasm); _ = try refNavObj(wasm, nav_index); // Possibly creates an entry in `Wasm.navs_obj`. - while (true) { - while (navs_i < wasm.navs_obj.entries.len) : (navs_i += 1) { - const elem_nav = ip.getNav(wasm.navs_obj.keys()[navs_i]); - const elem_nav_init = switch (ip.indexToKey(elem_nav.status.resolved.val)) { - .variable => |variable| variable.init, - else => elem_nav.status.resolved.val, - }; - // Call to `lowerZcuData` here possibly creates more entries in these tables. - wasm.navs_obj.values()[navs_i] = try lowerZcuData(wasm, pt, elem_nav_init); - } - while (uavs_i < wasm.uavs_obj.entries.len) : (uavs_i += 1) { - // Call to `lowerZcuData` here possibly creates more entries in these tables. - wasm.uavs_obj.values()[uavs_i] = try lowerZcuData(wasm, pt, wasm.uavs_obj.keys()[uavs_i]); - } - if (navs_i >= wasm.navs_obj.entries.len) break; - } + try zcu_data_starts.finishObj(wasm, pt); } else { - var uavs_i = wasm.uavs_exe.entries.len; - var navs_i = wasm.navs_exe.entries.len; + const zcu_data_starts: ZcuDataStarts = .initExe(wasm); _ = try refNavExe(wasm, nav_index); // Possibly creates an entry in `Wasm.navs_exe`. - while (true) { - while (navs_i < wasm.navs_exe.entries.len) : (navs_i += 1) { - const elem_nav = ip.getNav(wasm.navs_exe.keys()[navs_i]); - const elem_nav_init = switch (ip.indexToKey(elem_nav.status.resolved.val)) { - .variable => |variable| variable.init, - else => elem_nav.status.resolved.val, - }; - // Call to `lowerZcuData` here possibly creates more entries in these tables. - const zcu_data = try lowerZcuData(wasm, pt, elem_nav_init); - assert(zcu_data.relocs.len == 0); - wasm.navs_exe.values()[navs_i].code = zcu_data.code; - } - while (uavs_i < wasm.uavs_exe.entries.len) : (uavs_i += 1) { - // Call to `lowerZcuData` here possibly creates more entries in these tables. - const zcu_data = try lowerZcuData(wasm, pt, wasm.uavs_exe.keys()[uavs_i]); - wasm.uavs_exe.values()[uavs_i].code = zcu_data.code; - } - if (navs_i >= wasm.navs_exe.entries.len) break; - } + try zcu_data_starts.finishExe(wasm, pt); } } diff --git a/src/link/Wasm/Flush.zig b/src/link/Wasm/Flush.zig index 45a4773ec2..7df0a0f128 100644 --- a/src/link/Wasm/Flush.zig +++ b/src/link/Wasm/Flush.zig @@ -644,8 +644,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { const code_start = try reserveSize(gpa, binary_bytes); defer replaceSize(binary_bytes, code_start); - const function = &i.value(wasm).function; - try function.lower(wasm, binary_bytes); + try i.value(wasm).function.lower(wasm, binary_bytes); }, }; |
