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...@@ -107,7 +107,7 @@ object_table_imports: std.AutoArrayHashMapUnmanaged(String, TableImport) = .empt
107object_tables: std.ArrayListUnmanaged(Table) = .empty,107object_tables: std.ArrayListUnmanaged(Table) = .empty,
108108
109/// All memory imports for all objects.109/// All memory imports for all objects.
110object_memory_imports: std.ArrayListUnmanaged(MemoryImport) = .empty,110object_memory_imports: std.AutoArrayHashMapUnmanaged(String, MemoryImport) = .empty,
111/// All parsed memory sections for all objects.111/// All parsed memory sections for all objects.
112object_memories: std.ArrayListUnmanaged(ObjectMemory) = .empty,112object_memories: std.ArrayListUnmanaged(ObjectMemory) = .empty,
113113
...@@ -2596,9 +2596,9 @@ pub const ObjectRelocation = struct {...@@ -2596,9 +2596,9 @@ pub const ObjectRelocation = struct {
25962596
2597pub const MemoryImport = extern struct {2597pub const MemoryImport = extern struct {
2598 module_name: String,2598 module_name: String,
2599 name: String,
2600 limits_min: u32,2599 limits_min: u32,
2601 limits_max: u32,2600 limits_max: u32,
2601 source_location: SourceLocation,
2602 limits_has_max: bool,2602 limits_has_max: bool,
2603 limits_is_shared: bool,2603 limits_is_shared: bool,
2604 padding: [2]u8 = .{ 0, 0 },2604 padding: [2]u8 = .{ 0, 0 },
src/link/Wasm/Flush.zig+7-5
...@@ -484,18 +484,19 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -484,18 +484,19 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
484 }484 }
485 total_imports += wasm.table_imports.entries.len;485 total_imports += wasm.table_imports.entries.len;
486486
487 for (wasm.object_memory_imports.items) |*memory_import| {487 for (wasm.object_memory_imports.keys(), wasm.object_memory_imports.values()) |name, *memory_import| {
488 try emitMemoryImport(wasm, binary_bytes, memory_import);488 try emitMemoryImport(wasm, binary_bytes, name, memory_import);
489 total_imports += 1;489 total_imports += 1;
490 } else if (import_memory) {490 } 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, &.{
492 // TODO the import_memory option needs to specify from which module493 // TODO the import_memory option needs to specify from which module
493 .module_name = wasm.object_host_name.unwrap().?,494 .module_name = wasm.object_host_name.unwrap().?,
494 .name = if (is_obj) wasm.preloaded_strings.__linear_memory else wasm.preloaded_strings.memory,
495 .limits_min = wasm.memories.limits.min,495 .limits_min = wasm.memories.limits.min,
496 .limits_max = wasm.memories.limits.max,496 .limits_max = wasm.memories.limits.max,
497 .limits_has_max = wasm.memories.limits.flags.has_max,497 .limits_has_max = wasm.memories.limits.flags.has_max,
498 .limits_is_shared = wasm.memories.limits.flags.is_shared,498 .limits_is_shared = wasm.memories.limits.flags.is_shared,
499 .source_location = .none,
499 });500 });
500 total_imports += 1;501 total_imports += 1;
501 }502 }
...@@ -1249,6 +1250,7 @@ fn emitLimits(...@@ -1249,6 +1250,7 @@ fn emitLimits(
1249fn emitMemoryImport(1250fn emitMemoryImport(
1250 wasm: *Wasm,1251 wasm: *Wasm,
1251 binary_bytes: *std.ArrayListUnmanaged(u8),1252 binary_bytes: *std.ArrayListUnmanaged(u8),
1253 name_index: String,
1252 memory_import: *const Wasm.MemoryImport,1254 memory_import: *const Wasm.MemoryImport,
1253) Allocator.Error!void {1255) Allocator.Error!void {
1254 const gpa = wasm.base.comp.gpa;1256 const gpa = wasm.base.comp.gpa;
...@@ -1256,7 +1258,7 @@ fn emitMemoryImport(...@@ -1256,7 +1258,7 @@ fn emitMemoryImport(
1256 try leb.writeUleb128(binary_bytes.writer(gpa), @as(u32, @intCast(module_name.len)));1258 try leb.writeUleb128(binary_bytes.writer(gpa), @as(u32, @intCast(module_name.len)));
1257 try binary_bytes.appendSlice(gpa, module_name);1259 try binary_bytes.appendSlice(gpa, module_name);
12581260
1259 const name = memory_import.name.slice(wasm);1261 const name = name_index.slice(wasm);
1260 try leb.writeUleb128(binary_bytes.writer(gpa), @as(u32, @intCast(name.len)));1262 try leb.writeUleb128(binary_bytes.writer(gpa), @as(u32, @intCast(name.len)));
1261 try binary_bytes.appendSlice(gpa, name);1263 try binary_bytes.appendSlice(gpa, name);
12621264
src/link/Wasm/Object.zig+23-8
...@@ -710,14 +710,29 @@ pub fn parse(...@@ -710,14 +710,29 @@ pub fn parse(
710 },710 },
711 .memory => {711 .memory => {
712 const limits, pos = readLimits(bytes, pos);712 const limits, pos = readLimits(bytes, pos);
713 try wasm.object_memory_imports.append(gpa, .{713 const gop = try wasm.object_memory_imports.getOrPut(gpa, interned_name);
714 .module_name = interned_module_name,714 if (gop.found_existing) {
715 .name = interned_name,715 if (gop.value_ptr.module_name != interned_module_name) {
716 .limits_min = limits.min,716 var err = try diags.addErrorWithNotes(2);
717 .limits_max = limits.max,717 try err.addMsg("memory '{s}' mismatching module names", .{name});
718 .limits_has_max = limits.flags.has_max,718 gop.value_ptr.source_location.addNote(&err, "module '{s}' here", .{
719 .limits_is_shared = limits.flags.is_shared,719 gop.value_ptr.module_name.slice(wasm),
720 });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 }
721 },736 },
722 .global => {737 .global => {
723 const valtype, pos = readEnum(std.wasm.Valtype, bytes, pos);738 const valtype, pos = readEnum(std.wasm.Valtype, bytes, pos);