authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-01-08 16:25:00-08:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-01-15 15:11:36-08:00
log5186c6c4ee520f7f1c87134d45cd7a33f8b2aaea
tree690966b310aac635845e518884d06124ddeb2123
parent3474057e5e5002c950758a8416e786d6195f058c

wasm linker: distinguish symbol name vs import name, and implement weak


3 files changed, 115 insertions(+), 30 deletions(-)

src/link/Wasm.zig+76-11
...@@ -91,6 +91,7 @@ objects: std.ArrayListUnmanaged(Object) = .{},...@@ -91,6 +91,7 @@ objects: std.ArrayListUnmanaged(Object) = .{},
91func_types: std.AutoArrayHashMapUnmanaged(FunctionType, void) = .empty,91func_types: std.AutoArrayHashMapUnmanaged(FunctionType, void) = .empty,
92/// Provides a mapping of both imports and provided functions to symbol name.92/// Provides a mapping of both imports and provided functions to symbol name.
93/// Local functions may be unnamed.93/// Local functions may be unnamed.
94/// Key is symbol name, however the `FunctionImport` may have an name override for the import name.
94object_function_imports: std.AutoArrayHashMapUnmanaged(String, FunctionImport) = .empty,95object_function_imports: std.AutoArrayHashMapUnmanaged(String, FunctionImport) = .empty,
95/// All functions for all objects.96/// All functions for all objects.
96object_functions: std.ArrayListUnmanaged(ObjectFunction) = .empty,97object_functions: std.ArrayListUnmanaged(ObjectFunction) = .empty,
...@@ -164,7 +165,7 @@ object_host_name: OptionalString,...@@ -164,7 +165,7 @@ object_host_name: OptionalString,
164/// Memory section165/// Memory section
165memories: std.wasm.Memory = .{ .limits = .{166memories: std.wasm.Memory = .{ .limits = .{
166 .min = 0,167 .min = 0,
167 .max = undefined,168 .max = 0,
168 .flags = .{ .has_max = false, .is_shared = false },169 .flags = .{ .has_max = false, .is_shared = false },
169} },170} },
170171
...@@ -371,6 +372,17 @@ pub const OutputFunctionIndex = enum(u32) {...@@ -371,6 +372,17 @@ pub const OutputFunctionIndex = enum(u32) {
371 return fromResolution(wasm, .fromObjectFunction(wasm, index)).?;372 return fromResolution(wasm, .fromObjectFunction(wasm, index)).?;
372 }373 }
373374
375 pub fn fromObjectFunctionHandlingWeak(wasm: *const Wasm, index: ObjectFunctionIndex) OutputFunctionIndex {
376 const ptr = index.ptr(wasm);
377 if (ptr.flags.binding == .weak) {
378 const name = ptr.name.unwrap().?;
379 const import = wasm.object_function_imports.getPtr(name).?;
380 assert(import.resolution != .unresolved);
381 return fromResolution(wasm, import.resolution).?;
382 }
383 return fromResolution(wasm, .fromObjectFunction(wasm, index)).?;
384 }
385
374 pub fn fromIpIndex(wasm: *const Wasm, ip_index: InternPool.Index) OutputFunctionIndex {386 pub fn fromIpIndex(wasm: *const Wasm, ip_index: InternPool.Index) OutputFunctionIndex {
375 const zcu = wasm.base.comp.zcu.?;387 const zcu = wasm.base.comp.zcu.?;
376 const ip = &zcu.intern_pool;388 const ip = &zcu.intern_pool;
...@@ -923,6 +935,8 @@ const DebugSection = struct {};...@@ -923,6 +935,8 @@ const DebugSection = struct {};
923pub const FunctionImport = extern struct {935pub const FunctionImport = extern struct {
924 flags: SymbolFlags,936 flags: SymbolFlags,
925 module_name: OptionalString,937 module_name: OptionalString,
938 /// May be different than the key which is a symbol name.
939 name: String,
926 source_location: SourceLocation,940 source_location: SourceLocation,
927 resolution: Resolution,941 resolution: Resolution,
928 type: FunctionType.Index,942 type: FunctionType.Index,
...@@ -1042,10 +1056,14 @@ pub const FunctionImport = extern struct {...@@ -1042,10 +1056,14 @@ pub const FunctionImport = extern struct {
1042 return &wasm.object_function_imports.values()[@intFromEnum(index)];1056 return &wasm.object_function_imports.values()[@intFromEnum(index)];
1043 }1057 }
10441058
1045 pub fn name(index: Index, wasm: *const Wasm) String {1059 pub fn symbolName(index: Index, wasm: *const Wasm) String {
1046 return index.key(wasm).*;1060 return index.key(wasm).*;
1047 }1061 }
10481062
1063 pub fn importName(index: Index, wasm: *const Wasm) String {
1064 return index.value(wasm).name;
1065 }
1066
1049 pub fn moduleName(index: Index, wasm: *const Wasm) OptionalString {1067 pub fn moduleName(index: Index, wasm: *const Wasm) OptionalString {
1050 return index.value(wasm).module_name;1068 return index.value(wasm).module_name;
1051 }1069 }
...@@ -1079,6 +1097,8 @@ pub const ObjectFunction = extern struct {...@@ -1079,6 +1097,8 @@ pub const ObjectFunction = extern struct {
1079pub const GlobalImport = extern struct {1097pub const GlobalImport = extern struct {
1080 flags: SymbolFlags,1098 flags: SymbolFlags,
1081 module_name: OptionalString,1099 module_name: OptionalString,
1100 /// May be different than the key which is a symbol name.
1101 name: String,
1082 source_location: SourceLocation,1102 source_location: SourceLocation,
1083 resolution: Resolution,1103 resolution: Resolution,
10841104
...@@ -1194,10 +1214,14 @@ pub const GlobalImport = extern struct {...@@ -1194,10 +1214,14 @@ pub const GlobalImport = extern struct {
1194 return &wasm.object_global_imports.values()[@intFromEnum(index)];1214 return &wasm.object_global_imports.values()[@intFromEnum(index)];
1195 }1215 }
11961216
1197 pub fn name(index: Index, wasm: *const Wasm) String {1217 pub fn symbolName(index: Index, wasm: *const Wasm) String {
1198 return index.key(wasm).*;1218 return index.key(wasm).*;
1199 }1219 }
12001220
1221 pub fn importName(index: Index, wasm: *const Wasm) String {
1222 return index.value(wasm).name;
1223 }
1224
1201 pub fn moduleName(index: Index, wasm: *const Wasm) OptionalString {1225 pub fn moduleName(index: Index, wasm: *const Wasm) OptionalString {
1202 return index.value(wasm).module_name;1226 return index.value(wasm).module_name;
1203 }1227 }
...@@ -1260,6 +1284,8 @@ pub const RefType1 = enum(u1) {...@@ -1260,6 +1284,8 @@ pub const RefType1 = enum(u1) {
1260pub const TableImport = extern struct {1284pub const TableImport = extern struct {
1261 flags: SymbolFlags,1285 flags: SymbolFlags,
1262 module_name: String,1286 module_name: String,
1287 /// May be different than the key which is a symbol name.
1288 name: String,
1263 source_location: SourceLocation,1289 source_location: SourceLocation,
1264 resolution: Resolution,1290 resolution: Resolution,
1265 limits_min: u32,1291 limits_min: u32,
...@@ -1387,6 +1413,15 @@ pub const ObjectTableIndex = enum(u32) {...@@ -1387,6 +1413,15 @@ pub const ObjectTableIndex = enum(u32) {
1387 pub fn ptr(index: ObjectTableIndex, wasm: *const Wasm) *Table {1413 pub fn ptr(index: ObjectTableIndex, wasm: *const Wasm) *Table {
1388 return &wasm.object_tables.items[@intFromEnum(index)];1414 return &wasm.object_tables.items[@intFromEnum(index)];
1389 }1415 }
1416
1417 pub fn chaseWeak(i: ObjectTableIndex, wasm: *const Wasm) ObjectTableIndex {
1418 const table = ptr(i, wasm);
1419 if (table.flags.binding != .weak) return i;
1420 const name = table.name.unwrap().?;
1421 const import = wasm.object_table_imports.getPtr(name).?;
1422 assert(import.resolution != .unresolved); // otherwise it should resolve to this one.
1423 return import.resolution.unpack().object_table;
1424 }
1390};1425};
13911426
1392/// Index into `Wasm.object_globals`.1427/// Index into `Wasm.object_globals`.
...@@ -1400,6 +1435,15 @@ pub const ObjectGlobalIndex = enum(u32) {...@@ -1400,6 +1435,15 @@ pub const ObjectGlobalIndex = enum(u32) {
1400 pub fn name(index: ObjectGlobalIndex, wasm: *const Wasm) OptionalString {1435 pub fn name(index: ObjectGlobalIndex, wasm: *const Wasm) OptionalString {
1401 return index.ptr(wasm).name;1436 return index.ptr(wasm).name;
1402 }1437 }
1438
1439 pub fn chaseWeak(i: ObjectGlobalIndex, wasm: *const Wasm) ObjectGlobalIndex {
1440 const global = ptr(i, wasm);
1441 if (global.flags.binding != .weak) return i;
1442 const import_name = global.name.unwrap().?;
1443 const import = wasm.object_global_imports.getPtr(import_name).?;
1444 assert(import.resolution != .unresolved); // otherwise it should resolve to this one.
1445 return import.resolution.unpack(wasm).object_global;
1446 }
1403};1447};
14041448
1405pub const ObjectMemory = extern struct {1449pub const ObjectMemory = extern struct {
...@@ -1442,6 +1486,15 @@ pub const ObjectFunctionIndex = enum(u32) {...@@ -1442,6 +1486,15 @@ pub const ObjectFunctionIndex = enum(u32) {
1442 assert(result != .none);1486 assert(result != .none);
1443 return result;1487 return result;
1444 }1488 }
1489
1490 pub fn chaseWeak(i: ObjectFunctionIndex, wasm: *const Wasm) ObjectFunctionIndex {
1491 const func = ptr(i, wasm);
1492 if (func.flags.binding != .weak) return i;
1493 const name = func.name.unwrap().?;
1494 const import = wasm.object_function_imports.getPtr(name).?;
1495 assert(import.resolution != .unresolved); // otherwise it should resolve to this one.
1496 return import.resolution.unpack(wasm).object_function;
1497 }
1445};1498};
14461499
1447/// Index into `object_functions`, or null.1500/// Index into `object_functions`, or null.
...@@ -2131,7 +2184,7 @@ pub const ZcuImportIndex = enum(u32) {...@@ -2131,7 +2184,7 @@ pub const ZcuImportIndex = enum(u32) {
2131 return &wasm.imports.keys()[@intFromEnum(index)];2184 return &wasm.imports.keys()[@intFromEnum(index)];
2132 }2185 }
21332186
2134 pub fn name(index: ZcuImportIndex, wasm: *const Wasm) String {2187 pub fn importName(index: ZcuImportIndex, wasm: *const Wasm) String {
2135 const zcu = wasm.base.comp.zcu.?;2188 const zcu = wasm.base.comp.zcu.?;
2136 const ip = &zcu.intern_pool;2189 const ip = &zcu.intern_pool;
2137 const nav_index = index.ptr(wasm).*;2190 const nav_index = index.ptr(wasm).*;
...@@ -2217,9 +2270,9 @@ pub const FunctionImportId = enum(u32) {...@@ -2217,9 +2270,9 @@ pub const FunctionImportId = enum(u32) {
2217 }2270 }
2218 }2271 }
22192272
2220 pub fn name(id: FunctionImportId, wasm: *const Wasm) String {2273 pub fn importName(id: FunctionImportId, wasm: *const Wasm) String {
2221 return switch (unpack(id, wasm)) {2274 return switch (unpack(id, wasm)) {
2222 inline .object_function_import, .zcu_import => |i| i.name(wasm),2275 inline .object_function_import, .zcu_import => |i| i.importName(wasm),
2223 };2276 };
2224 }2277 }
22252278
...@@ -2300,9 +2353,9 @@ pub const GlobalImportId = enum(u32) {...@@ -2300,9 +2353,9 @@ pub const GlobalImportId = enum(u32) {
2300 }2353 }
2301 }2354 }
23022355
2303 pub fn name(id: GlobalImportId, wasm: *const Wasm) String {2356 pub fn importName(id: GlobalImportId, wasm: *const Wasm) String {
2304 return switch (unpack(id, wasm)) {2357 return switch (unpack(id, wasm)) {
2305 inline .object_global_import, .zcu_import => |i| i.name(wasm),2358 inline .object_global_import, .zcu_import => |i| i.importName(wasm),
2306 };2359 };
2307 }2360 }
23082361
...@@ -3297,6 +3350,14 @@ pub fn prelink(wasm: *Wasm, prog_node: std.Progress.Node) link.File.FlushError!v...@@ -3297,6 +3350,14 @@ pub fn prelink(wasm: *Wasm, prog_node: std.Progress.Node) link.File.FlushError!v
3297 try markDataImport(wasm, name, import, @enumFromInt(i));3350 try markDataImport(wasm, name, import, @enumFromInt(i));
3298 }3351 }
3299 }3352 }
3353
3354 // This is a wild ass guess at how to merge memories, haven't checked yet
3355 // what the proper way to do this is.
3356 for (wasm.object_memory_imports.values()) |*memory_import| {
3357 wasm.memories.limits.min = @min(wasm.memories.limits.min, memory_import.limits_min);
3358 wasm.memories.limits.max = @max(wasm.memories.limits.max, memory_import.limits_max);
3359 wasm.memories.limits.flags.has_max = wasm.memories.limits.flags.has_max or memory_import.limits_has_max;
3360 }
3300}3361}
33013362
3302fn markFunctionImport(3363fn markFunctionImport(
...@@ -3532,12 +3593,12 @@ fn markRelocations(wasm: *Wasm, relocs: ObjectRelocation.IterableSlice) link.Fil...@@ -3532,12 +3593,12 @@ fn markRelocations(wasm: *Wasm, relocs: ObjectRelocation.IterableSlice) link.Fil
3532 .table_index_i64,3593 .table_index_i64,
3533 .table_index_rel_sleb,3594 .table_index_rel_sleb,
3534 .table_index_rel_sleb64,3595 .table_index_rel_sleb64,
3535 => try markFunction(wasm, pointee.function),3596 => try markFunction(wasm, pointee.function.chaseWeak(wasm)),
3536 .global_index_leb,3597 .global_index_leb,
3537 .global_index_i32,3598 .global_index_i32,
3538 => try markGlobal(wasm, pointee.global),3599 => try markGlobal(wasm, pointee.global.chaseWeak(wasm)),
3539 .table_number_leb,3600 .table_number_leb,
3540 => try wasm.tables.put(wasm.base.comp.gpa, .fromObjectTable(pointee.table), {}),3601 => try markTable(wasm, pointee.table.chaseWeak(wasm)),
35413602
3542 .section_offset_i32 => {3603 .section_offset_i32 => {
3543 log.warn("TODO: ensure section {d} is included in output", .{pointee.section});3604 log.warn("TODO: ensure section {d} is included in output", .{pointee.section});
...@@ -3561,6 +3622,10 @@ fn markRelocations(wasm: *Wasm, relocs: ObjectRelocation.IterableSlice) link.Fil...@@ -3561,6 +3622,10 @@ fn markRelocations(wasm: *Wasm, relocs: ObjectRelocation.IterableSlice) link.Fil
3561 }3622 }
3562}3623}
35633624
3625fn markTable(wasm: *Wasm, i: ObjectTableIndex) link.File.FlushError!void {
3626 try wasm.tables.put(wasm.base.comp.gpa, .fromObjectTable(i), {});
3627}
3628
3564pub fn flushModule(3629pub fn flushModule(
3565 wasm: *Wasm,3630 wasm: *Wasm,
3566 arena: Allocator,3631 arena: Allocator,
src/link/Wasm/Flush.zig+6-9
...@@ -459,7 +459,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -459,7 +459,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
459 try leb.writeUleb128(binary_writer, @as(u32, @intCast(module_name.len)));459 try leb.writeUleb128(binary_writer, @as(u32, @intCast(module_name.len)));
460 try binary_writer.writeAll(module_name);460 try binary_writer.writeAll(module_name);
461461
462 const name = id.name(wasm).slice(wasm);462 const name = id.importName(wasm).slice(wasm);
463 try leb.writeUleb128(binary_writer, @as(u32, @intCast(name.len)));463 try leb.writeUleb128(binary_writer, @as(u32, @intCast(name.len)));
464 try binary_writer.writeAll(name);464 try binary_writer.writeAll(name);
465465
...@@ -474,7 +474,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -474,7 +474,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
474 try leb.writeUleb128(binary_writer, @as(u32, @intCast(module_name.len)));474 try leb.writeUleb128(binary_writer, @as(u32, @intCast(module_name.len)));
475 try binary_writer.writeAll(module_name);475 try binary_writer.writeAll(module_name);
476476
477 const name = id.key(wasm).slice(wasm);477 const name = table_import.name.slice(wasm);
478 try leb.writeUleb128(binary_writer, @as(u32, @intCast(name.len)));478 try leb.writeUleb128(binary_writer, @as(u32, @intCast(name.len)));
479 try binary_writer.writeAll(name);479 try binary_writer.writeAll(name);
480480
...@@ -484,10 +484,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -484,10 +484,7 @@ 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.keys(), wasm.object_memory_imports.values()) |name, *memory_import| {487 if (import_memory) {
488 try emitMemoryImport(wasm, binary_bytes, name, memory_import);
489 total_imports += 1;
490 } else if (import_memory) {
491 const name = if (is_obj) wasm.preloaded_strings.__linear_memory else wasm.preloaded_strings.memory;488 const name = if (is_obj) wasm.preloaded_strings.__linear_memory else wasm.preloaded_strings.memory;
492 try emitMemoryImport(wasm, binary_bytes, name, &.{489 try emitMemoryImport(wasm, binary_bytes, name, &.{
493 // TODO the import_memory option needs to specify from which module490 // TODO the import_memory option needs to specify from which module
...@@ -506,7 +503,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {...@@ -506,7 +503,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
506 try leb.writeUleb128(binary_writer, @as(u32, @intCast(module_name.len)));503 try leb.writeUleb128(binary_writer, @as(u32, @intCast(module_name.len)));
507 try binary_writer.writeAll(module_name);504 try binary_writer.writeAll(module_name);
508505
509 const name = id.name(wasm).slice(wasm);506 const name = id.importName(wasm).slice(wasm);
510 try leb.writeUleb128(binary_writer, @as(u32, @intCast(name.len)));507 try leb.writeUleb128(binary_writer, @as(u32, @intCast(name.len)));
511 try binary_writer.writeAll(name);508 try binary_writer.writeAll(name);
512509
...@@ -1458,8 +1455,8 @@ fn applyRelocs(code: []u8, code_offset: u32, relocs: Wasm.ObjectRelocation.Itera...@@ -1458,8 +1455,8 @@ fn applyRelocs(code: []u8, code_offset: u32, relocs: Wasm.ObjectRelocation.Itera
1458 if (offset >= relocs.end) break;1455 if (offset >= relocs.end) break;
1459 const sliced_code = code[offset - code_offset ..];1456 const sliced_code = code[offset - code_offset ..];
1460 switch (tag) {1457 switch (tag) {
1461 .function_index_i32 => reloc_u32_function(sliced_code, .fromObjectFunction(wasm, pointee.function)),1458 .function_index_i32 => reloc_u32_function(sliced_code, .fromObjectFunctionHandlingWeak(wasm, pointee.function)),
1462 .function_index_leb => reloc_leb_function(sliced_code, .fromObjectFunction(wasm, pointee.function)),1459 .function_index_leb => reloc_leb_function(sliced_code, .fromObjectFunctionHandlingWeak(wasm, pointee.function)),
1463 .function_offset_i32 => @panic("TODO this value is not known yet"),1460 .function_offset_i32 => @panic("TODO this value is not known yet"),
1464 .function_offset_i64 => @panic("TODO this value is not known yet"),1461 .function_offset_i64 => @panic("TODO this value is not known yet"),
1465 .table_index_i32 => @panic("TODO indirect function table needs to support object functions too"),1462 .table_index_i32 => @panic("TODO indirect function table needs to support object functions too"),
src/link/Wasm/Object.zig+33-10
...@@ -972,7 +972,7 @@ pub fn parse(...@@ -972,7 +972,7 @@ pub fn parse(
972 for (ss.symbol_table.items) |symbol| switch (symbol.pointee) {972 for (ss.symbol_table.items) |symbol| switch (symbol.pointee) {
973 .function_import => |index| {973 .function_import => |index| {
974 const ptr = index.ptr(ss);974 const ptr = index.ptr(ss);
975 const name = symbol.name.unwrap().?;975 const name = symbol.name.unwrap() orelse ptr.name;
976 if (symbol.flags.binding == .local) {976 if (symbol.flags.binding == .local) {
977 diags.addParseError(path, "local symbol '{s}' references import", .{name.slice(wasm)});977 diags.addParseError(path, "local symbol '{s}' references import", .{name.slice(wasm)});
978 continue;978 continue;
...@@ -1000,10 +1000,18 @@ pub fn parse(...@@ -1000,10 +1000,18 @@ pub fn parse(
1000 source_location.addNote(&err, "module '{s}' here", .{ptr.module_name.slice(wasm)});1000 source_location.addNote(&err, "module '{s}' here", .{ptr.module_name.slice(wasm)});
1001 continue;1001 continue;
1002 }1002 }
1003 if (gop.value_ptr.name != ptr.name) {
1004 var err = try diags.addErrorWithNotes(2);
1005 try err.addMsg("symbol '{s}' mismatching import names", .{name.slice(wasm)});
1006 gop.value_ptr.source_location.addNote(&err, "imported as '{s}' here", .{gop.value_ptr.name.slice(wasm)});
1007 source_location.addNote(&err, "imported as '{s}' here", .{ptr.name.slice(wasm)});
1008 continue;
1009 }
1003 } else {1010 } else {
1004 gop.value_ptr.* = .{1011 gop.value_ptr.* = .{
1005 .flags = symbol.flags,1012 .flags = symbol.flags,
1006 .module_name = ptr.module_name.toOptional(),1013 .module_name = ptr.module_name.toOptional(),
1014 .name = ptr.name,
1007 .source_location = source_location,1015 .source_location = source_location,
1008 .resolution = .unresolved,1016 .resolution = .unresolved,
1009 .type = fn_ty_index,1017 .type = fn_ty_index,
...@@ -1012,7 +1020,7 @@ pub fn parse(...@@ -1012,7 +1020,7 @@ pub fn parse(
1012 },1020 },
1013 .global_import => |index| {1021 .global_import => |index| {
1014 const ptr = index.ptr(ss);1022 const ptr = index.ptr(ss);
1015 const name = symbol.name.unwrap().?;1023 const name = symbol.name.unwrap() orelse ptr.name;
1016 if (symbol.flags.binding == .local) {1024 if (symbol.flags.binding == .local) {
1017 diags.addParseError(path, "local symbol '{s}' references import", .{name.slice(wasm)});1025 diags.addParseError(path, "local symbol '{s}' references import", .{name.slice(wasm)});
1018 continue;1026 continue;
...@@ -1049,10 +1057,18 @@ pub fn parse(...@@ -1049,10 +1057,18 @@ pub fn parse(
1049 source_location.addNote(&err, "module '{s}' here", .{ptr.module_name.slice(wasm)});1057 source_location.addNote(&err, "module '{s}' here", .{ptr.module_name.slice(wasm)});
1050 continue;1058 continue;
1051 }1059 }
1060 if (gop.value_ptr.name != ptr.name) {
1061 var err = try diags.addErrorWithNotes(2);
1062 try err.addMsg("symbol '{s}' mismatching import names", .{name.slice(wasm)});
1063 gop.value_ptr.source_location.addNote(&err, "imported as '{s}' here", .{gop.value_ptr.name.slice(wasm)});
1064 source_location.addNote(&err, "imported as '{s}' here", .{ptr.name.slice(wasm)});
1065 continue;
1066 }
1052 } else {1067 } else {
1053 gop.value_ptr.* = .{1068 gop.value_ptr.* = .{
1054 .flags = symbol.flags,1069 .flags = symbol.flags,
1055 .module_name = ptr.module_name.toOptional(),1070 .module_name = ptr.module_name.toOptional(),
1071 .name = ptr.name,
1056 .source_location = source_location,1072 .source_location = source_location,
1057 .resolution = .unresolved,1073 .resolution = .unresolved,
1058 };1074 };
...@@ -1064,7 +1080,7 @@ pub fn parse(...@@ -1064,7 +1080,7 @@ pub fn parse(
1064 },1080 },
1065 .table_import => |index| {1081 .table_import => |index| {
1066 const ptr = index.ptr(ss);1082 const ptr = index.ptr(ss);
1067 const name = symbol.name.unwrap().?;1083 const name = symbol.name.unwrap() orelse ptr.name;
1068 if (symbol.flags.binding == .local) {1084 if (symbol.flags.binding == .local) {
1069 diags.addParseError(path, "local symbol '{s}' references import", .{name.slice(wasm)});1085 diags.addParseError(path, "local symbol '{s}' references import", .{name.slice(wasm)});
1070 continue;1086 continue;
...@@ -1088,6 +1104,13 @@ pub fn parse(...@@ -1088,6 +1104,13 @@ pub fn parse(
1088 source_location.addNote(&err, "module '{s}' here", .{ptr.module_name.slice(wasm)});1104 source_location.addNote(&err, "module '{s}' here", .{ptr.module_name.slice(wasm)});
1089 continue;1105 continue;
1090 }1106 }
1107 if (gop.value_ptr.name != ptr.name) {
1108 var err = try diags.addErrorWithNotes(2);
1109 try err.addMsg("symbol '{s}' mismatching import names", .{name.slice(wasm)});
1110 gop.value_ptr.source_location.addNote(&err, "imported as '{s}' here", .{gop.value_ptr.name.slice(wasm)});
1111 source_location.addNote(&err, "imported as '{s}' here", .{ptr.name.slice(wasm)});
1112 continue;
1113 }
1091 if (symbol.flags.binding == .strong) gop.value_ptr.flags.binding = .strong;1114 if (symbol.flags.binding == .strong) gop.value_ptr.flags.binding = .strong;
1092 if (!symbol.flags.visibility_hidden) gop.value_ptr.flags.visibility_hidden = false;1115 if (!symbol.flags.visibility_hidden) gop.value_ptr.flags.visibility_hidden = false;
1093 if (symbol.flags.no_strip) gop.value_ptr.flags.no_strip = true;1116 if (symbol.flags.no_strip) gop.value_ptr.flags.no_strip = true;
...@@ -1095,6 +1118,7 @@ pub fn parse(...@@ -1095,6 +1118,7 @@ pub fn parse(
1095 gop.value_ptr.* = .{1118 gop.value_ptr.* = .{
1096 .flags = symbol.flags,1119 .flags = symbol.flags,
1097 .module_name = ptr.module_name,1120 .module_name = ptr.module_name,
1121 .name = ptr.name,
1098 .source_location = source_location,1122 .source_location = source_location,
1099 .resolution = .unresolved,1123 .resolution = .unresolved,
1100 .limits_min = ptr.limits_min,1124 .limits_min = ptr.limits_min,
...@@ -1158,6 +1182,7 @@ pub fn parse(...@@ -1158,6 +1182,7 @@ pub fn parse(
1158 gop.value_ptr.* = .{1182 gop.value_ptr.* = .{
1159 .flags = symbol.flags,1183 .flags = symbol.flags,
1160 .module_name = host_name,1184 .module_name = host_name,
1185 .name = name,
1161 .source_location = source_location,1186 .source_location = source_location,
1162 .resolution = .fromObjectFunction(wasm, index),1187 .resolution = .fromObjectFunction(wasm, index),
1163 .type = ptr.type_index,1188 .type = ptr.type_index,
...@@ -1214,8 +1239,9 @@ pub fn parse(...@@ -1214,8 +1239,9 @@ pub fn parse(
1214 gop.value_ptr.* = .{1239 gop.value_ptr.* = .{
1215 .flags = symbol.flags,1240 .flags = symbol.flags,
1216 .module_name = .none,1241 .module_name = .none,
1242 .name = name,
1217 .source_location = source_location,1243 .source_location = source_location,
1218 .resolution = .unresolved,1244 .resolution = .fromObjectGlobal(wasm, index),
1219 };1245 };
1220 gop.value_ptr.flags.global_type = .{1246 gop.value_ptr.flags.global_type = .{
1221 .valtype = .from(new_ty.valtype),1247 .valtype = .from(new_ty.valtype),
...@@ -1258,7 +1284,7 @@ pub fn parse(...@@ -1258,7 +1284,7 @@ pub fn parse(
1258 gop.value_ptr.* = .{1284 gop.value_ptr.* = .{
1259 .flags = symbol.flags,1285 .flags = symbol.flags,
1260 .source_location = source_location,1286 .source_location = source_location,
1261 .resolution = .unresolved,1287 .resolution = .fromObjectDataIndex(wasm, index),
1262 };1288 };
1263 }1289 }
1264 },1290 },
...@@ -1280,11 +1306,8 @@ pub fn parse(...@@ -1280,11 +1306,8 @@ pub fn parse(
1280 switch (exp.pointee) {1306 switch (exp.pointee) {
1281 inline .function, .table, .memory, .global => |index| {1307 inline .function, .table, .memory, .global => |index| {
1282 const ptr = index.ptr(wasm);1308 const ptr = index.ptr(wasm);
1283 if (ptr.name == .none) {1309 ptr.name = exp.name.toOptional();
1284 // Missing symbol table entry; use defaults for exported things.1310 ptr.flags.exported = true;
1285 ptr.name = exp.name.toOptional();
1286 ptr.flags.exported = true;
1287 }
1288 },1311 },
1289 }1312 }
1290 }1313 }