authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-12-18 22:11:20-08:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-01-15 15:11:36-08:00
log4f8a6b0888c8d1df87d254b68344bb99edcfe57c
tree2685575e3ef8de7a9134e8a35a9067a67d8d365c
parent5fac6f380ef77a7650047c65450aec0d3215da2d

wasm linker: implement data fixups

one hash table lookup per fixup

3 files changed, 53 insertions(+), 7 deletions(-)

src/codegen.zig+6-4
......@@ -674,8 +674,9 @@ fn lowerUavRef(
674674 .addend = @intCast(offset),
675675 });
676676 } else {
677 try wasm.uav_fixups.append(gpa, .{
678 .ip_index = uav.val,
677 try wasm.uav_fixups.ensureUnusedCapacity(gpa, 1);
678 wasm.uav_fixups.appendAssumeCapacity(.{
679 .uavs_exe_index = try wasm.refUavExe(pt, uav.val),
679680 .offset = @intCast(code.items.len),
680681 });
681682 }
......@@ -745,8 +746,9 @@ fn lowerNavRef(
745746 .addend = @intCast(offset),
746747 });
747748 } else {
748 try wasm.nav_fixups.append(gpa, .{
749 .nav_index = nav_index,
749 try wasm.nav_fixups.ensureUnusedCapacity(gpa, 1);
750 wasm.nav_fixups.appendAssumeCapacity(.{
751 .navs_exe_index = try wasm.refNavExe(nav_index),
750752 .offset = @intCast(code.items.len),
751753 });
752754 }
src/link/Wasm.zig+21-3
......@@ -259,13 +259,13 @@ params_scratch: std.ArrayListUnmanaged(std.wasm.Valtype) = .empty,
259259returns_scratch: std.ArrayListUnmanaged(std.wasm.Valtype) = .empty,
260260
261261pub const UavFixup = extern struct {
262 ip_index: InternPool.Index,
262 uavs_exe_index: UavsExeIndex,
263263 /// Index into `string_bytes`.
264264 offset: u32,
265265};
266266
267267pub const NavFixup = extern struct {
268 nav_index: InternPool.Nav.Index,
268 navs_exe_index: NavsExeIndex,
269269 /// Index into `string_bytes`.
270270 offset: u32,
271271};
......@@ -2379,7 +2379,7 @@ pub fn updateNav(wasm: *Wasm, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index
23792379 const gop = try wasm.navs_exe.getOrPut(gpa, nav_index);
23802380 gop.value_ptr.* = .{
23812381 .code = zcu_data.code,
2382 .count = 0,
2382 .count = if (gop.found_existing) gop.value_ptr.count else 0,
23832383 };
23842384 wasm.data_segments.putAssumeCapacity(.pack(wasm, .{ .nav_exe = @enumFromInt(gop.index) }), {});
23852385}
......@@ -3376,6 +3376,24 @@ pub fn refUavExe(wasm: *Wasm, pt: Zcu.PerThread, ip_index: InternPool.Index) !Ua
33763376 return uav_index;
33773377}
33783378
3379pub fn refNavExe(wasm: *Wasm, nav_index: InternPool.Nav.Index) !NavsExeIndex {
3380 const comp = wasm.base.comp;
3381 const gpa = comp.gpa;
3382 assert(comp.config.output_mode != .Obj);
3383 const gop = try wasm.navs_exe.getOrPut(gpa, nav_index);
3384 if (gop.found_existing) {
3385 gop.value_ptr.count += 1;
3386 } else {
3387 gop.value_ptr.* = .{
3388 .code = undefined,
3389 .count = 1,
3390 };
3391 }
3392 const navs_exe_index: NavsExeIndex = @enumFromInt(gop.index);
3393 try wasm.data_segments.put(gpa, .pack(wasm, .{ .nav_exe = navs_exe_index }), {});
3394 return navs_exe_index;
3395}
3396
33793397/// Asserts it is called after `Flush.data_segments` is fully populated and sorted.
33803398pub fn uavAddr(wasm: *Wasm, uav_index: UavsExeIndex) u32 {
33813399 assert(wasm.flush_buffer.memory_layout_finished);
src/link/Wasm/Flush.zig+26
......@@ -60,6 +60,11 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
6060 const import_memory = comp.config.import_memory;
6161 const export_memory = comp.config.export_memory;
6262 const target = &comp.root_mod.resolved_target.result;
63 const is64 = switch (target.cpu.arch) {
64 .wasm32 => false,
65 .wasm64 => true,
66 else => unreachable,
67 };
6368 const is_obj = comp.config.output_mode == .Obj;
6469 const allow_undefined = is_obj or wasm.import_symbols;
6570 const zcu = wasm.base.comp.zcu.?;
......@@ -650,6 +655,27 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
650655 section_index += 1;
651656 }
652657
658 if (!is_obj) {
659 for (wasm.uav_fixups.items) |uav_fixup| {
660 const ds_id: Wasm.DataSegment.Id = .pack(wasm, .{ .uav_exe = uav_fixup.uavs_exe_index });
661 const vaddr = f.data_segments.get(ds_id).?;
662 if (!is64) {
663 mem.writeInt(u32, wasm.string_bytes.items[uav_fixup.offset..][0..4], vaddr, .little);
664 } else {
665 mem.writeInt(u64, wasm.string_bytes.items[uav_fixup.offset..][0..8], vaddr, .little);
666 }
667 }
668 for (wasm.nav_fixups.items) |nav_fixup| {
669 const ds_id: Wasm.DataSegment.Id = .pack(wasm, .{ .nav_exe = nav_fixup.navs_exe_index });
670 const vaddr = f.data_segments.get(ds_id).?;
671 if (!is64) {
672 mem.writeInt(u32, wasm.string_bytes.items[nav_fixup.offset..][0..4], vaddr, .little);
673 } else {
674 mem.writeInt(u64, wasm.string_bytes.items[nav_fixup.offset..][0..8], vaddr, .little);
675 }
676 }
677 }
678
653679 // Data section.
654680 if (f.data_segment_groups.items.len != 0) {
655681 const header_offset = try reserveVecSectionHeader(gpa, binary_bytes);