diff --git a/src/arch/wasm/Emit.zig b/src/arch/wasm/Emit.zig index 322b84134f..cb9fbd2ef0 100644 --- a/src/arch/wasm/Emit.zig +++ b/src/arch/wasm/Emit.zig @@ -108,7 +108,7 @@ pub fn lowerToCode(emit: *Emit) Error!void { inst += 1; continue :loop tags[inst]; } else { - const addr = try wasm.errorNameTableAddr(); + const addr: u32 = wasm.errorNameTableAddr(); leb.writeIleb128(code.fixedWriter(), addr) catch unreachable; inst += 1; @@ -931,7 +931,7 @@ fn uavRefOffExe(wasm: *Wasm, code: *std.ArrayListUnmanaged(u8), data: Mir.UavRef try code.ensureUnusedCapacity(gpa, 11); code.appendAssumeCapacity(@intFromEnum(opcode)); - const addr = try wasm.uavAddr(data.uav_exe); + const addr = wasm.uavAddr(data.uav_exe); leb.writeUleb128(code.fixedWriter(), @as(u32, @intCast(@as(i64, addr) + data.offset))) catch unreachable; } @@ -957,8 +957,9 @@ fn navRefOff(wasm: *Wasm, code: *std.ArrayListUnmanaged(u8), data: Mir.NavRefOff }); code.appendNTimesAssumeCapacity(0, 5); } else { - const addr = try wasm.navAddr(data.nav_index); - leb.writeUleb128(code.fixedWriter(), @as(u32, @intCast(@as(i64, addr) + data.offset))) catch unreachable; + const function_imports_len: u32 = @intCast(wasm.function_imports.entries.len); + const func_index = Wasm.FunctionIndex.fromIpNav(wasm, data.nav_index).?; + leb.writeUleb128(code.fixedWriter(), function_imports_len + @intFromEnum(func_index)) catch unreachable; } } else { const opcode: std.wasm.Opcode = if (is_wasm32) .i32_const else .i64_const; @@ -972,7 +973,7 @@ fn navRefOff(wasm: *Wasm, code: *std.ArrayListUnmanaged(u8), data: Mir.NavRefOff }); code.appendNTimesAssumeCapacity(0, if (is_wasm32) 5 else 10); } else { - const addr = try wasm.navAddr(data.nav_index); + const addr = wasm.navAddr(data.nav_index); leb.writeUleb128(code.fixedWriter(), @as(u32, @intCast(@as(i64, addr) + data.offset))) catch unreachable; } } diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig index 3150375230..39f8fab20d 100644 --- a/src/link/Wasm.zig +++ b/src/link/Wasm.zig @@ -3331,21 +3331,27 @@ pub fn refUavExe(wasm: *Wasm, pt: Zcu.PerThread, ip_index: InternPool.Index) !Ua return uav_index; } -pub fn uavAddr(wasm: *Wasm, uav_index: UavsExeIndex) Allocator.Error!u32 { +/// Asserts it is called after `Wasm.data_segments` is fully populated and sorted. +pub fn uavAddr(wasm: *Wasm, uav_index: UavsExeIndex) u32 { + assert(wasm.flush_buffer.memory_layout_finished); const comp = wasm.base.comp; assert(comp.config.output_mode != .Obj); const ds_id: DataSegment.Id = .pack(wasm, .{ .uav_exe = uav_index }); return wasm.data_segments.get(ds_id).?; } -pub fn navAddr(wasm: *Wasm, nav_index: InternPool.Nav.Index) Allocator.Error!u32 { +/// Asserts it is called after `Wasm.data_segments` is fully populated and sorted. +pub fn navAddr(wasm: *Wasm, nav_index: InternPool.Nav.Index) u32 { + assert(wasm.flush_buffer.memory_layout_finished); const comp = wasm.base.comp; assert(comp.config.output_mode != .Obj); const ds_id: DataSegment.Id = .pack(wasm, .{ .nav_exe = @enumFromInt(wasm.navs_exe.getIndex(nav_index).?) }); return wasm.data_segments.get(ds_id).?; } -pub fn errorNameTableAddr(wasm: *Wasm) Allocator.Error!u32 { +/// Asserts it is called after `Wasm.data_segments` is fully populated and sorted. +pub fn errorNameTableAddr(wasm: *Wasm) u32 { + assert(wasm.flush_buffer.memory_layout_finished); const comp = wasm.base.comp; assert(comp.config.output_mode != .Obj); return wasm.data_segments.get(.__zig_error_name_table).?; diff --git a/src/link/Wasm/Flush.zig b/src/link/Wasm/Flush.zig index 89ff2add58..7369d031c9 100644 --- a/src/link/Wasm/Flush.zig +++ b/src/link/Wasm/Flush.zig @@ -28,10 +28,14 @@ missing_exports: std.AutoArrayHashMapUnmanaged(String, void) = .empty, indirect_function_table: std.AutoArrayHashMapUnmanaged(Wasm.OutputFunctionIndex, u32) = .empty, +/// For debug purposes only. +memory_layout_finished: bool = false, + pub fn clear(f: *Flush) void { f.binary_bytes.clearRetainingCapacity(); f.data_segment_groups.clearRetainingCapacity(); f.indirect_function_table.clearRetainingCapacity(); + f.memory_layout_finished = false; } pub fn deinit(f: *Flush, gpa: Allocator) void { @@ -348,6 +352,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { if (shared_memory) wasm.memories.limits.flags.is_shared = true; log.debug("maximum memory pages: {?d}", .{wasm.memories.limits.max}); } + f.memory_layout_finished = true; var section_index: u32 = 0; // Index of the code section. Used to tell relocation table where the section lives.