diff --git a/src/codegen.zig b/src/codegen.zig index df88682466..3971d8f521 100644 --- a/src/codegen.zig +++ b/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), }); } diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig index e45555432d..acfb694cf2 100644 --- a/src/link/Wasm.zig +++ b/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); diff --git a/src/link/Wasm/Flush.zig b/src/link/Wasm/Flush.zig index 8da9d78a59..45a4773ec2 100644 --- a/src/link/Wasm/Flush.zig +++ b/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);