authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-01-06 17:14:39-08:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-01-15 15:11:36-08:00
log3474057e5e5002c950758a8416e786d6195f058c
treeb5b392cae11a60f767063ac5c393df05c3993eaa
parente6a5fe7c5566007d9299c75f41455fa48c64db40

wasm linker: fix not merging object memories


3 files changed, 32 insertions(+), 15 deletions(-)

src/link/Wasm.zig+2-2
......@@ -107,7 +107,7 @@ object_table_imports: std.AutoArrayHashMapUnmanaged(String, TableImport) = .empt
107107object_tables: std.ArrayListUnmanaged(Table) = .empty,
108108
109109/// All memory imports for all objects.
110object_memory_imports: std.ArrayListUnmanaged(MemoryImport) = .empty,
110object_memory_imports: std.AutoArrayHashMapUnmanaged(String, MemoryImport) = .empty,
111111/// All parsed memory sections for all objects.
112112object_memories: std.ArrayListUnmanaged(ObjectMemory) = .empty,
113113
......@@ -2596,9 +2596,9 @@ pub const ObjectRelocation = struct {
25962596
25972597pub const MemoryImport = extern struct {
25982598 module_name: String,
2599 name: String,
26002599 limits_min: u32,
26012600 limits_max: u32,
2601 source_location: SourceLocation,
26022602 limits_has_max: bool,
26032603 limits_is_shared: bool,
26042604 padding: [2]u8 = .{ 0, 0 },
src/link/Wasm/Flush.zig+7-5
......@@ -484,18 +484,19 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
484484 }
485485 total_imports += wasm.table_imports.entries.len;
486486
487 for (wasm.object_memory_imports.items) |*memory_import| {
488 try emitMemoryImport(wasm, binary_bytes, memory_import);
487 for (wasm.object_memory_imports.keys(), wasm.object_memory_imports.values()) |name, *memory_import| {
488 try emitMemoryImport(wasm, binary_bytes, name, memory_import);
489489 total_imports += 1;
490490 } else if (import_memory) {
491 try emitMemoryImport(wasm, binary_bytes, &.{
491 const name = if (is_obj) wasm.preloaded_strings.__linear_memory else wasm.preloaded_strings.memory;
492 try emitMemoryImport(wasm, binary_bytes, name, &.{
492493 // TODO the import_memory option needs to specify from which module
493494 .module_name = wasm.object_host_name.unwrap().?,
494 .name = if (is_obj) wasm.preloaded_strings.__linear_memory else wasm.preloaded_strings.memory,
495495 .limits_min = wasm.memories.limits.min,
496496 .limits_max = wasm.memories.limits.max,
497497 .limits_has_max = wasm.memories.limits.flags.has_max,
498498 .limits_is_shared = wasm.memories.limits.flags.is_shared,
499 .source_location = .none,
499500 });
500501 total_imports += 1;
501502 }
......@@ -1249,6 +1250,7 @@ fn emitLimits(
12491250fn emitMemoryImport(
12501251 wasm: *Wasm,
12511252 binary_bytes: *std.ArrayListUnmanaged(u8),
1253 name_index: String,
12521254 memory_import: *const Wasm.MemoryImport,
12531255) Allocator.Error!void {
12541256 const gpa = wasm.base.comp.gpa;
......@@ -1256,7 +1258,7 @@ fn emitMemoryImport(
12561258 try leb.writeUleb128(binary_bytes.writer(gpa), @as(u32, @intCast(module_name.len)));
12571259 try binary_bytes.appendSlice(gpa, module_name);
12581260
1259 const name = memory_import.name.slice(wasm);
1261 const name = name_index.slice(wasm);
12601262 try leb.writeUleb128(binary_bytes.writer(gpa), @as(u32, @intCast(name.len)));
12611263 try binary_bytes.appendSlice(gpa, name);
12621264
src/link/Wasm/Object.zig+23-8
......@@ -710,14 +710,29 @@ pub fn parse(
710710 },
711711 .memory => {
712712 const limits, pos = readLimits(bytes, pos);
713 try wasm.object_memory_imports.append(gpa, .{
714 .module_name = interned_module_name,
715 .name = interned_name,
716 .limits_min = limits.min,
717 .limits_max = limits.max,
718 .limits_has_max = limits.flags.has_max,
719 .limits_is_shared = limits.flags.is_shared,
720 });
713 const gop = try wasm.object_memory_imports.getOrPut(gpa, interned_name);
714 if (gop.found_existing) {
715 if (gop.value_ptr.module_name != interned_module_name) {
716 var err = try diags.addErrorWithNotes(2);
717 try err.addMsg("memory '{s}' mismatching module names", .{name});
718 gop.value_ptr.source_location.addNote(&err, "module '{s}' here", .{
719 gop.value_ptr.module_name.slice(wasm),
720 });
721 source_location.addNote(&err, "module '{s}' here", .{module_name});
722 }
723 // TODO error for mismatching flags
724 gop.value_ptr.limits_min = @min(gop.value_ptr.limits_min, limits.min);
725 gop.value_ptr.limits_max = @max(gop.value_ptr.limits_max, limits.max);
726 } else {
727 gop.value_ptr.* = .{
728 .module_name = interned_module_name,
729 .limits_min = limits.min,
730 .limits_max = limits.max,
731 .limits_has_max = limits.flags.has_max,
732 .limits_is_shared = limits.flags.is_shared,
733 .source_location = source_location,
734 };
735 }
721736 },
722737 .global => {
723738 const valtype, pos = readEnum(std.wasm.Valtype, bytes, pos);