Commit 4f8a6b0888

Andrew Kelley <andrew@ziglang.org>
2024-12-19 07:11:20
wasm linker: implement data fixups
one hash table lookup per fixup
1 parent 5fac6f3
Changed files (3)
src/link/Wasm/Flush.zig
@@ -60,6 +60,11 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
     const import_memory = comp.config.import_memory;
     const export_memory = comp.config.export_memory;
     const target = &comp.root_mod.resolved_target.result;
+    const is64 = switch (target.cpu.arch) {
+        .wasm32 => false,
+        .wasm64 => true,
+        else => unreachable,
+    };
     const is_obj = comp.config.output_mode == .Obj;
     const allow_undefined = is_obj or wasm.import_symbols;
     const zcu = wasm.base.comp.zcu.?;
@@ -650,6 +655,27 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
         section_index += 1;
     }
 
+    if (!is_obj) {
+        for (wasm.uav_fixups.items) |uav_fixup| {
+            const ds_id: Wasm.DataSegment.Id = .pack(wasm, .{ .uav_exe = uav_fixup.uavs_exe_index });
+            const vaddr = f.data_segments.get(ds_id).?;
+            if (!is64) {
+                mem.writeInt(u32, wasm.string_bytes.items[uav_fixup.offset..][0..4], vaddr, .little);
+            } else {
+                mem.writeInt(u64, wasm.string_bytes.items[uav_fixup.offset..][0..8], vaddr, .little);
+            }
+        }
+        for (wasm.nav_fixups.items) |nav_fixup| {
+            const ds_id: Wasm.DataSegment.Id = .pack(wasm, .{ .nav_exe = nav_fixup.navs_exe_index });
+            const vaddr = f.data_segments.get(ds_id).?;
+            if (!is64) {
+                mem.writeInt(u32, wasm.string_bytes.items[nav_fixup.offset..][0..4], vaddr, .little);
+            } else {
+                mem.writeInt(u64, wasm.string_bytes.items[nav_fixup.offset..][0..8], vaddr, .little);
+            }
+        }
+    }
+
     // Data section.
     if (f.data_segment_groups.items.len != 0) {
         const header_offset = try reserveVecSectionHeader(gpa, binary_bytes);
src/link/Wasm.zig
@@ -259,13 +259,13 @@ params_scratch: std.ArrayListUnmanaged(std.wasm.Valtype) = .empty,
 returns_scratch: std.ArrayListUnmanaged(std.wasm.Valtype) = .empty,
 
 pub const UavFixup = extern struct {
-    ip_index: InternPool.Index,
+    uavs_exe_index: UavsExeIndex,
     /// Index into `string_bytes`.
     offset: u32,
 };
 
 pub const NavFixup = extern struct {
-    nav_index: InternPool.Nav.Index,
+    navs_exe_index: NavsExeIndex,
     /// Index into `string_bytes`.
     offset: u32,
 };
@@ -2379,7 +2379,7 @@ pub fn updateNav(wasm: *Wasm, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index
     const gop = try wasm.navs_exe.getOrPut(gpa, nav_index);
     gop.value_ptr.* = .{
         .code = zcu_data.code,
-        .count = 0,
+        .count = if (gop.found_existing) gop.value_ptr.count else 0,
     };
     wasm.data_segments.putAssumeCapacity(.pack(wasm, .{ .nav_exe = @enumFromInt(gop.index) }), {});
 }
@@ -3376,6 +3376,24 @@ pub fn refUavExe(wasm: *Wasm, pt: Zcu.PerThread, ip_index: InternPool.Index) !Ua
     return uav_index;
 }
 
+pub fn refNavExe(wasm: *Wasm, nav_index: InternPool.Nav.Index) !NavsExeIndex {
+    const comp = wasm.base.comp;
+    const gpa = comp.gpa;
+    assert(comp.config.output_mode != .Obj);
+    const gop = try wasm.navs_exe.getOrPut(gpa, nav_index);
+    if (gop.found_existing) {
+        gop.value_ptr.count += 1;
+    } else {
+        gop.value_ptr.* = .{
+            .code = undefined,
+            .count = 1,
+        };
+    }
+    const navs_exe_index: NavsExeIndex = @enumFromInt(gop.index);
+    try wasm.data_segments.put(gpa, .pack(wasm, .{ .nav_exe = navs_exe_index }), {});
+    return navs_exe_index;
+}
+
 /// Asserts it is called after `Flush.data_segments` is fully populated and sorted.
 pub fn uavAddr(wasm: *Wasm, uav_index: UavsExeIndex) u32 {
     assert(wasm.flush_buffer.memory_layout_finished);
src/codegen.zig
@@ -674,8 +674,9 @@ fn lowerUavRef(
                     .addend = @intCast(offset),
                 });
             } else {
-                try wasm.uav_fixups.append(gpa, .{
-                    .ip_index = uav.val,
+                try wasm.uav_fixups.ensureUnusedCapacity(gpa, 1);
+                wasm.uav_fixups.appendAssumeCapacity(.{
+                    .uavs_exe_index = try wasm.refUavExe(pt, uav.val),
                     .offset = @intCast(code.items.len),
                 });
             }
@@ -745,8 +746,9 @@ fn lowerNavRef(
                     .addend = @intCast(offset),
                 });
             } else {
-                try wasm.nav_fixups.append(gpa, .{
-                    .nav_index = nav_index,
+                try wasm.nav_fixups.ensureUnusedCapacity(gpa, 1);
+                wasm.nav_fixups.appendAssumeCapacity(.{
+                    .navs_exe_index = try wasm.refNavExe(nav_index),
                     .offset = @intCast(code.items.len),
                 });
             }