From 3474057e5e5002c950758a8416e786d6195f058c Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 6 Jan 2025 17:14:39 -0800 Subject: [PATCH] wasm linker: fix not merging object memories --- src/link/Wasm.zig | 4 ++-- src/link/Wasm/Flush.zig | 12 +++++++----- src/link/Wasm/Object.zig | 31 +++++++++++++++++++++++-------- 3 files changed, 32 insertions(+), 15 deletions(-) diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig index d9d1fecf54..1f0ba70b58 100644 --- a/src/link/Wasm.zig +++ b/src/link/Wasm.zig @@ -107,7 +107,7 @@ object_table_imports: std.AutoArrayHashMapUnmanaged(String, TableImport) = .empt object_tables: std.ArrayListUnmanaged(Table) = .empty, /// All memory imports for all objects. -object_memory_imports: std.ArrayListUnmanaged(MemoryImport) = .empty, +object_memory_imports: std.AutoArrayHashMapUnmanaged(String, MemoryImport) = .empty, /// All parsed memory sections for all objects. object_memories: std.ArrayListUnmanaged(ObjectMemory) = .empty, @@ -2596,9 +2596,9 @@ pub const ObjectRelocation = struct { pub const MemoryImport = extern struct { module_name: String, - name: String, limits_min: u32, limits_max: u32, + source_location: SourceLocation, limits_has_max: bool, limits_is_shared: bool, padding: [2]u8 = .{ 0, 0 }, diff --git a/src/link/Wasm/Flush.zig b/src/link/Wasm/Flush.zig index dde69db260..23b590696b 100644 --- a/src/link/Wasm/Flush.zig +++ b/src/link/Wasm/Flush.zig @@ -484,18 +484,19 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { } total_imports += wasm.table_imports.entries.len; - for (wasm.object_memory_imports.items) |*memory_import| { - try emitMemoryImport(wasm, binary_bytes, memory_import); + for (wasm.object_memory_imports.keys(), wasm.object_memory_imports.values()) |name, *memory_import| { + try emitMemoryImport(wasm, binary_bytes, name, memory_import); total_imports += 1; } else if (import_memory) { - try emitMemoryImport(wasm, binary_bytes, &.{ + const name = if (is_obj) wasm.preloaded_strings.__linear_memory else wasm.preloaded_strings.memory; + try emitMemoryImport(wasm, binary_bytes, name, &.{ // TODO the import_memory option needs to specify from which module .module_name = wasm.object_host_name.unwrap().?, - .name = if (is_obj) wasm.preloaded_strings.__linear_memory else wasm.preloaded_strings.memory, .limits_min = wasm.memories.limits.min, .limits_max = wasm.memories.limits.max, .limits_has_max = wasm.memories.limits.flags.has_max, .limits_is_shared = wasm.memories.limits.flags.is_shared, + .source_location = .none, }); total_imports += 1; } @@ -1249,6 +1250,7 @@ fn emitLimits( fn emitMemoryImport( wasm: *Wasm, binary_bytes: *std.ArrayListUnmanaged(u8), + name_index: String, memory_import: *const Wasm.MemoryImport, ) Allocator.Error!void { const gpa = wasm.base.comp.gpa; @@ -1256,7 +1258,7 @@ fn emitMemoryImport( try leb.writeUleb128(binary_bytes.writer(gpa), @as(u32, @intCast(module_name.len))); try binary_bytes.appendSlice(gpa, module_name); - const name = memory_import.name.slice(wasm); + const name = name_index.slice(wasm); try leb.writeUleb128(binary_bytes.writer(gpa), @as(u32, @intCast(name.len))); try binary_bytes.appendSlice(gpa, name); diff --git a/src/link/Wasm/Object.zig b/src/link/Wasm/Object.zig index 12c51be88e..9f877a0a05 100644 --- a/src/link/Wasm/Object.zig +++ b/src/link/Wasm/Object.zig @@ -710,14 +710,29 @@ pub fn parse( }, .memory => { const limits, pos = readLimits(bytes, pos); - try wasm.object_memory_imports.append(gpa, .{ - .module_name = interned_module_name, - .name = interned_name, - .limits_min = limits.min, - .limits_max = limits.max, - .limits_has_max = limits.flags.has_max, - .limits_is_shared = limits.flags.is_shared, - }); + const gop = try wasm.object_memory_imports.getOrPut(gpa, interned_name); + if (gop.found_existing) { + if (gop.value_ptr.module_name != interned_module_name) { + var err = try diags.addErrorWithNotes(2); + try err.addMsg("memory '{s}' mismatching module names", .{name}); + gop.value_ptr.source_location.addNote(&err, "module '{s}' here", .{ + gop.value_ptr.module_name.slice(wasm), + }); + source_location.addNote(&err, "module '{s}' here", .{module_name}); + } + // TODO error for mismatching flags + gop.value_ptr.limits_min = @min(gop.value_ptr.limits_min, limits.min); + gop.value_ptr.limits_max = @max(gop.value_ptr.limits_max, limits.max); + } else { + gop.value_ptr.* = .{ + .module_name = interned_module_name, + .limits_min = limits.min, + .limits_max = limits.max, + .limits_has_max = limits.flags.has_max, + .limits_is_shared = limits.flags.is_shared, + .source_location = source_location, + }; + } }, .global => { const valtype, pos = readEnum(std.wasm.Valtype, bytes, pos);