wasm linker: fix not merging object memories

This commit is contained in:
Andrew Kelley 2025-01-06 17:14:39 -08:00
parent e6a5fe7c55
commit 3474057e5e
3 changed files with 32 additions and 15 deletions

View File

@ -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 },

View File

@ -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);

View File

@ -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);