| ... | ... | @@ -69,8 +69,8 @@ imported_globals_count: u32 = 0, |
| 69 | 69 | /// The count of imported tables. This number will be appended |
| 70 | 70 | /// to the table indexes when sections are merged. |
| 71 | 71 | imported_tables_count: u32 = 0, |
| 72 | | /// Map of symbol locations, represented by its `wasm.Import` |
| 73 | | imports: std.AutoHashMapUnmanaged(SymbolLoc, wasm.Import) = .{}, |
| 72 | /// Map of symbol locations, represented by its `types.Import` |
| 73 | imports: std.AutoHashMapUnmanaged(SymbolLoc, types.Import) = .{}, |
| 74 | 74 | /// Represents non-synthetic section entries. |
| 75 | 75 | /// Used for code, data and custom sections. |
| 76 | 76 | segments: std.ArrayListUnmanaged(Segment) = .{}, |
| ... | ... | @@ -94,7 +94,7 @@ memories: wasm.Memory = .{ .limits = .{ .min = 0, .max = null } }, |
| 94 | 94 | /// Output table section |
| 95 | 95 | tables: std.ArrayListUnmanaged(wasm.Table) = .{}, |
| 96 | 96 | /// Output export section |
| 97 | | exports: std.ArrayListUnmanaged(wasm.Export) = .{}, |
| 97 | exports: std.ArrayListUnmanaged(types.Export) = .{}, |
| 98 | 98 | |
| 99 | 99 | /// Indirect function table, used to call function pointers |
| 100 | 100 | /// When this is non-zero, we must emit a table entry, |
| ... | ... | @@ -105,8 +105,8 @@ function_table: std.AutoHashMapUnmanaged(u32, u32) = .{}, |
| 105 | 105 | |
| 106 | 106 | /// All object files and their data which are linked into the final binary |
| 107 | 107 | objects: std.ArrayListUnmanaged(Object) = .{}, |
| 108 | | /// A map of global names to their symbol location |
| 109 | | globals: std.StringHashMapUnmanaged(SymbolLoc) = .{}, |
| 108 | /// A map of global names (read: offset into string table) to their symbol location |
| 109 | globals: std.AutoHashMapUnmanaged(u32, SymbolLoc) = .{}, |
| 110 | 110 | /// Maps discarded symbols and their positions to the location of the symbol |
| 111 | 111 | /// it was resolved to |
| 112 | 112 | discarded: std.AutoHashMapUnmanaged(SymbolLoc, SymbolLoc) = .{}, |
| ... | ... | @@ -119,7 +119,8 @@ resolved_symbols: std.AutoArrayHashMapUnmanaged(SymbolLoc, void) = .{}, |
| 119 | 119 | symbol_atom: std.AutoHashMapUnmanaged(SymbolLoc, *Atom) = .{}, |
| 120 | 120 | /// Maps a symbol's location to its export name, which may differ from the decl's name |
| 121 | 121 | /// which does the exporting. |
| 122 | | export_names: std.AutoHashMapUnmanaged(SymbolLoc, []const u8) = .{}, |
| 122 | /// Note: The value represents the offset into the string table, rather than the actual string. |
| 123 | export_names: std.AutoHashMapUnmanaged(SymbolLoc, u32) = .{}, |
| 123 | 124 | |
| 124 | 125 | pub const Segment = struct { |
| 125 | 126 | alignment: u32, |
| ... | ... | @@ -223,6 +224,15 @@ pub const StringTable = struct { |
| 223 | 224 | return mem.sliceTo(@ptrCast([*:0]const u8, self.string_data.items.ptr + off), 0); |
| 224 | 225 | } |
| 225 | 226 | |
| 227 | /// Returns the offset of a given string when it exists. |
| 228 | /// Will return null if the given string does not yet exist within the string table. |
| 229 | pub fn getOffset(self: *StringTable, string: []const u8) ?u32 { |
| 230 | return self.string_table.getKeyAdapted( |
| 231 | string, |
| 232 | std.hash_map.StringIndexAdapter{ .bytes = &self.string_data }, |
| 233 | ); |
| 234 | } |
| 235 | |
| 226 | 236 | /// Frees all resources of the string table. Any references pointing |
| 227 | 237 | /// to the strings will be invalid. |
| 228 | 238 | pub fn deinit(self: *StringTable, allocator: Allocator) void { |
| ... | ... | @@ -250,16 +260,17 @@ pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Option |
| 250 | 260 | try file.writeAll(&(wasm.magic ++ wasm.version)); |
| 251 | 261 | |
| 252 | 262 | // As sym_index '0' is reserved, we use it for our stack pointer symbol |
| 263 | const sym_name = try wasm_bin.string_table.put(allocator, "__stack_pointer"); |
| 253 | 264 | const symbol = try wasm_bin.symbols.addOne(allocator); |
| 254 | 265 | symbol.* = .{ |
| 255 | | .name = try wasm_bin.string_table.put(allocator, "__stack_pointer"), |
| 266 | .name = sym_name, |
| 256 | 267 | .tag = .global, |
| 257 | 268 | .flags = 0, |
| 258 | 269 | .index = 0, |
| 259 | 270 | }; |
| 260 | 271 | const loc: SymbolLoc = .{ .file = null, .index = 0 }; |
| 261 | 272 | try wasm_bin.resolved_symbols.putNoClobber(allocator, loc, {}); |
| 262 | | try wasm_bin.globals.putNoClobber(allocator, "__stack_pointer", loc); |
| 273 | try wasm_bin.globals.putNoClobber(allocator, sym_name, loc); |
| 263 | 274 | |
| 264 | 275 | // For object files we will import the stack pointer symbol |
| 265 | 276 | if (options.output_mode == .Obj) { |
| ... | ... | @@ -268,8 +279,8 @@ pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Option |
| 268 | 279 | allocator, |
| 269 | 280 | .{ .file = null, .index = 0 }, |
| 270 | 281 | .{ |
| 271 | | .module_name = wasm_bin.host_name, |
| 272 | | .name = "__stack_pointer", |
| 282 | .module_name = try wasm_bin.string_table.put(allocator, wasm_bin.host_name), |
| 283 | .name = sym_name, |
| 273 | 284 | .kind = .{ .global = .{ .valtype = .i32, .mutable = true } }, |
| 274 | 285 | }, |
| 275 | 286 | ); |
| ... | ... | @@ -344,6 +355,7 @@ fn resolveSymbolsInObject(self: *Wasm, object_index: u16) !void { |
| 344 | 355 | .index = sym_index, |
| 345 | 356 | }; |
| 346 | 357 | const sym_name = object.string_table.get(symbol.name); |
| 358 | const sym_name_index = try self.string_table.put(self.base.allocator, sym_name); |
| 347 | 359 | |
| 348 | 360 | if (symbol.isLocal()) { |
| 349 | 361 | if (symbol.isUndefined()) { |
| ... | ... | @@ -358,7 +370,7 @@ fn resolveSymbolsInObject(self: *Wasm, object_index: u16) !void { |
| 358 | 370 | // TODO: locals are allowed to have duplicate symbol names |
| 359 | 371 | // TODO: Store undefined symbols so we can verify at the end if they've all been found |
| 360 | 372 | // if not, emit an error (unless --allow-undefined is enabled). |
| 361 | | const maybe_existing = try self.globals.getOrPut(self.base.allocator, sym_name); |
| 373 | const maybe_existing = try self.globals.getOrPut(self.base.allocator, sym_name_index); |
| 362 | 374 | if (!maybe_existing.found_existing) { |
| 363 | 375 | maybe_existing.value_ptr.* = location; |
| 364 | 376 | try self.resolved_symbols.putNoClobber(self.base.allocator, location, {}); |
| ... | ... | @@ -383,13 +395,18 @@ fn resolveSymbolsInObject(self: *Wasm, object_index: u16) !void { |
| 383 | 395 | continue; // Do not overwrite defined symbols with undefined symbols |
| 384 | 396 | } |
| 385 | 397 | |
| 398 | // when both symbols are weak, we skip overwriting |
| 399 | if (existing_sym.isWeak() and symbol.isWeak()) { |
| 400 | continue; |
| 401 | } |
| 402 | |
| 386 | 403 | // simply overwrite with the new symbol |
| 387 | 404 | log.debug("Overwriting symbol '{s}'", .{sym_name}); |
| 388 | 405 | log.debug(" old definition in '{s}'", .{existing_file_path}); |
| 389 | 406 | log.debug(" new definition in '{s}'", .{object.name}); |
| 390 | 407 | try self.discarded.putNoClobber(self.base.allocator, maybe_existing.value_ptr.*, location); |
| 391 | 408 | maybe_existing.value_ptr.* = location; |
| 392 | | try self.globals.put(self.base.allocator, sym_name, location); |
| 409 | try self.globals.put(self.base.allocator, sym_name_index, location); |
| 393 | 410 | try self.resolved_symbols.put(self.base.allocator, location, {}); |
| 394 | 411 | assert(self.resolved_symbols.swapRemove(existing_loc)); |
| 395 | 412 | } |
| ... | ... | @@ -696,7 +713,7 @@ pub fn deleteExport(self: *Wasm, exp: Export) void { |
| 696 | 713 | if (self.export_names.fetchRemove(loc)) |kv| { |
| 697 | 714 | assert(self.globals.remove(kv.value)); |
| 698 | 715 | } else { |
| 699 | | assert(self.globals.remove(symbol_name)); |
| 716 | assert(self.globals.remove(symbol.name)); |
| 700 | 717 | } |
| 701 | 718 | } |
| 702 | 719 | |
| ... | ... | @@ -723,7 +740,9 @@ pub fn updateDeclExports( |
| 723 | 740 | )); |
| 724 | 741 | continue; |
| 725 | 742 | } |
| 726 | | if (self.globals.getPtr(exp.options.name)) |existing_loc| { |
| 743 | |
| 744 | const export_name = try self.string_table.put(self.base.allocator, exp.options.name); |
| 745 | if (self.globals.getPtr(export_name)) |existing_loc| { |
| 727 | 746 | if (existing_loc.index == decl.link.wasm.sym_index) continue; |
| 728 | 747 | const existing_sym: Symbol = existing_loc.getSymbol(self).*; |
| 729 | 748 | |
| ... | ... | @@ -775,13 +794,13 @@ pub fn updateDeclExports( |
| 775 | 794 | } |
| 776 | 795 | // Ensure the symbol will be exported using the given name |
| 777 | 796 | if (!mem.eql(u8, exp.options.name, sym_loc.getName(self))) { |
| 778 | | try self.export_names.put(self.base.allocator, sym_loc, exp.options.name); |
| 797 | try self.export_names.put(self.base.allocator, sym_loc, export_name); |
| 779 | 798 | } |
| 780 | 799 | |
| 781 | 800 | symbol.setGlobal(true); |
| 782 | 801 | try self.globals.put( |
| 783 | 802 | self.base.allocator, |
| 784 | | exp.options.name, |
| 803 | export_name, |
| 785 | 804 | sym_loc, |
| 786 | 805 | ); |
| 787 | 806 | |
| ... | ... | @@ -832,14 +851,14 @@ fn mapFunctionTable(self: *Wasm) void { |
| 832 | 851 | |
| 833 | 852 | fn addOrUpdateImport(self: *Wasm, decl: *Module.Decl) !void { |
| 834 | 853 | // For the import name itself, we use the decl's name, rather than the fully qualified name |
| 835 | | const decl_name = mem.sliceTo(decl.name, 0); |
| 854 | const decl_name_index = try self.string_table.put(self.base.allocator, mem.sliceTo(decl.name, 0)); |
| 836 | 855 | const symbol_index = decl.link.wasm.sym_index; |
| 837 | 856 | const symbol: *Symbol = &self.symbols.items[symbol_index]; |
| 838 | 857 | symbol.setUndefined(true); |
| 839 | 858 | symbol.setGlobal(true); |
| 840 | 859 | try self.globals.putNoClobber( |
| 841 | 860 | self.base.allocator, |
| 842 | | decl_name, |
| 861 | decl_name_index, |
| 843 | 862 | .{ .file = null, .index = symbol_index }, |
| 844 | 863 | ); |
| 845 | 864 | try self.resolved_symbols.put(self.base.allocator, .{ .file = null, .index = symbol_index }, {}); |
| ... | ... | @@ -852,8 +871,8 @@ fn addOrUpdateImport(self: *Wasm, decl: *Module.Decl) !void { |
| 852 | 871 | } else self.host_name; |
| 853 | 872 | if (!gop.found_existing) { |
| 854 | 873 | gop.value_ptr.* = .{ |
| 855 | | .module_name = module_name, |
| 856 | | .name = decl_name, |
| 874 | .module_name = try self.string_table.put(self.base.allocator, module_name), |
| 875 | .name = decl_name_index, |
| 857 | 876 | .kind = .{ .function = decl.fn_link.wasm.type_index }, |
| 858 | 877 | }; |
| 859 | 878 | } |
| ... | ... | @@ -1001,9 +1020,18 @@ fn setupImports(self: *Wasm) !void { |
| 1001 | 1020 | } |
| 1002 | 1021 | |
| 1003 | 1022 | log.debug("Symbol '{s}' will be imported from the host", .{symbol_loc.getName(self)}); |
| 1004 | | const import = self.objects.items[symbol_loc.file.?].findImport(symbol.tag.externalType(), symbol.index); |
| 1005 | | // TODO: De-duplicate imports |
| 1006 | | try self.imports.putNoClobber(self.base.allocator, symbol_loc, import); |
| 1023 | const object = self.objects.items[symbol_loc.file.?]; |
| 1024 | const import = object.findImport(symbol.tag.externalType(), symbol.index); |
| 1025 | |
| 1026 | // We copy the import to a new import to ensure the names contain references |
| 1027 | // to the internal string table, rather than of the object file. |
| 1028 | var new_imp: types.Import = .{ |
| 1029 | .module_name = try self.string_table.put(self.base.allocator, object.string_table.get(import.module_name)), |
| 1030 | .name = try self.string_table.put(self.base.allocator, object.string_table.get(import.name)), |
| 1031 | .kind = import.kind, |
| 1032 | }; |
| 1033 | // TODO: De-duplicate imports when they contain the same names and type |
| 1034 | try self.imports.putNoClobber(self.base.allocator, symbol_loc, new_imp); |
| 1007 | 1035 | } |
| 1008 | 1036 | |
| 1009 | 1037 | // Assign all indexes of the imports to their representing symbols |
| ... | ... | @@ -1013,7 +1041,7 @@ fn setupImports(self: *Wasm) !void { |
| 1013 | 1041 | var it = self.imports.iterator(); |
| 1014 | 1042 | while (it.next()) |entry| { |
| 1015 | 1043 | const symbol = entry.key_ptr.*.getSymbol(self); |
| 1016 | | const import: wasm.Import = entry.value_ptr.*; |
| 1044 | const import: types.Import = entry.value_ptr.*; |
| 1017 | 1045 | switch (import.kind) { |
| 1018 | 1046 | .function => { |
| 1019 | 1047 | symbol.index = function_index; |
| ... | ... | @@ -1045,7 +1073,8 @@ fn setupImports(self: *Wasm) !void { |
| 1045 | 1073 | /// and merges it into a single section for each. |
| 1046 | 1074 | fn mergeSections(self: *Wasm) !void { |
| 1047 | 1075 | // append the indirect function table if initialized |
| 1048 | | if (self.globals.get("__indirect_function_table")) |sym_loc| { |
| 1076 | if (self.string_table.getOffset("__indirect_function_table")) |offset| { |
| 1077 | const sym_loc = self.globals.get(offset).?; |
| 1049 | 1078 | const table: wasm.Table = .{ |
| 1050 | 1079 | .limits = .{ .min = @intCast(u32, self.function_table.count()), .max = null }, |
| 1051 | 1080 | .reftype = .funcref, |
| ... | ... | @@ -1114,7 +1143,7 @@ fn mergeTypes(self: *Wasm) !void { |
| 1114 | 1143 | |
| 1115 | 1144 | if (symbol.isUndefined()) { |
| 1116 | 1145 | log.debug("Adding type from extern function '{s}'", .{sym_loc.getName(self)}); |
| 1117 | | const import: *wasm.Import = self.imports.getPtr(sym_loc).?; |
| 1146 | const import: *types.Import = self.imports.getPtr(sym_loc).?; |
| 1118 | 1147 | const original_type = object.func_types[import.kind.function]; |
| 1119 | 1148 | import.kind.function = try self.putOrGetFuncType(original_type); |
| 1120 | 1149 | } else { |
| ... | ... | @@ -1135,13 +1164,13 @@ fn setupExports(self: *Wasm) !void { |
| 1135 | 1164 | if (!symbol.isExported()) continue; |
| 1136 | 1165 | |
| 1137 | 1166 | const sym_name = sym_loc.getName(self); |
| 1138 | | const export_name = if (self.export_names.get(sym_loc)) |name| name else sym_name; |
| 1139 | | const exp: wasm.Export = .{ |
| 1167 | const export_name = if (self.export_names.get(sym_loc)) |name| name else symbol.name; |
| 1168 | const exp: types.Export = .{ |
| 1140 | 1169 | .name = export_name, |
| 1141 | 1170 | .kind = symbol.tag.externalType(), |
| 1142 | 1171 | .index = symbol.index, |
| 1143 | 1172 | }; |
| 1144 | | log.debug("Exporting symbol '{s}' as '{s}' at index: ({d})", .{ sym_name, exp.name, exp.index }); |
| 1173 | log.debug("Exporting symbol '{s}' as '{s}' at index: ({d})", .{ sym_name, self.string_table.get(exp.name), exp.index }); |
| 1145 | 1174 | try self.exports.append(self.base.allocator, exp); |
| 1146 | 1175 | } |
| 1147 | 1176 | |
| ... | ... | @@ -1151,7 +1180,7 @@ fn setupExports(self: *Wasm) !void { |
| 1151 | 1180 | fn setupStart(self: *Wasm) !void { |
| 1152 | 1181 | const entry_name = self.base.options.entry orelse "_start"; |
| 1153 | 1182 | |
| 1154 | | const symbol_loc = self.globals.get(entry_name) orelse { |
| 1183 | const symbol_name_offset = self.string_table.getOffset(entry_name) orelse { |
| 1155 | 1184 | if (self.base.options.output_mode == .Exe) { |
| 1156 | 1185 | if (self.base.options.wasi_exec_model == .reactor) return; // Not required for reactors |
| 1157 | 1186 | } else { |
| ... | ... | @@ -1161,6 +1190,7 @@ fn setupStart(self: *Wasm) !void { |
| 1161 | 1190 | return error.MissingSymbol; |
| 1162 | 1191 | }; |
| 1163 | 1192 | |
| 1193 | const symbol_loc = self.globals.get(symbol_name_offset).?; |
| 1164 | 1194 | const symbol = symbol_loc.getSymbol(self); |
| 1165 | 1195 | if (symbol.tag != .function) { |
| 1166 | 1196 | log.err("Entry symbol '{s}' is not a function", .{entry_name}); |
| ... | ... | @@ -1443,9 +1473,9 @@ pub fn flushModule(self: *Wasm, comp: *Compilation) !void { |
| 1443 | 1473 | |
| 1444 | 1474 | // import table is always first table so emit that first |
| 1445 | 1475 | if (import_table) { |
| 1446 | | const table_imp: wasm.Import = .{ |
| 1447 | | .module_name = self.host_name, |
| 1448 | | .name = "__indirect_function_table", |
| 1476 | const table_imp: types.Import = .{ |
| 1477 | .module_name = try self.string_table.put(self.base.allocator, self.host_name), |
| 1478 | .name = try self.string_table.put(self.base.allocator, "__indirect_function_table"), |
| 1449 | 1479 | .kind = .{ |
| 1450 | 1480 | .table = .{ |
| 1451 | 1481 | .limits = .{ |
| ... | ... | @@ -1456,23 +1486,23 @@ pub fn flushModule(self: *Wasm, comp: *Compilation) !void { |
| 1456 | 1486 | }, |
| 1457 | 1487 | }, |
| 1458 | 1488 | }; |
| 1459 | | try emitImport(writer, table_imp); |
| 1489 | try self.emitImport(writer, table_imp); |
| 1460 | 1490 | } |
| 1461 | 1491 | |
| 1462 | 1492 | var it = self.imports.iterator(); |
| 1463 | 1493 | while (it.next()) |entry| { |
| 1464 | 1494 | assert(entry.key_ptr.*.getSymbol(self).isUndefined()); |
| 1465 | 1495 | const import = entry.value_ptr.*; |
| 1466 | | try emitImport(writer, import); |
| 1496 | try self.emitImport(writer, import); |
| 1467 | 1497 | } |
| 1468 | 1498 | |
| 1469 | 1499 | if (import_memory) { |
| 1470 | | const mem_imp: wasm.Import = .{ |
| 1471 | | .module_name = self.host_name, |
| 1472 | | .name = "__linear_memory", |
| 1500 | const mem_imp: types.Import = .{ |
| 1501 | .module_name = try self.string_table.put(self.base.allocator, self.host_name), |
| 1502 | .name = try self.string_table.put(self.base.allocator, "__linear_memory"), |
| 1473 | 1503 | .kind = .{ .memory = self.memories.limits }, |
| 1474 | 1504 | }; |
| 1475 | | try emitImport(writer, mem_imp); |
| 1505 | try self.emitImport(writer, mem_imp); |
| 1476 | 1506 | } |
| 1477 | 1507 | |
| 1478 | 1508 | try writeVecSectionHeader( |
| ... | ... | @@ -1567,8 +1597,9 @@ pub fn flushModule(self: *Wasm, comp: *Compilation) !void { |
| 1567 | 1597 | const header_offset = try reserveVecSectionHeader(file); |
| 1568 | 1598 | const writer = file.writer(); |
| 1569 | 1599 | for (self.exports.items) |exp| { |
| 1570 | | try leb.writeULEB128(writer, @intCast(u32, exp.name.len)); |
| 1571 | | try writer.writeAll(exp.name); |
| 1600 | const name = self.string_table.get(exp.name); |
| 1601 | try leb.writeULEB128(writer, @intCast(u32, name.len)); |
| 1602 | try writer.writeAll(name); |
| 1572 | 1603 | try leb.writeULEB128(writer, @enumToInt(exp.kind)); |
| 1573 | 1604 | try leb.writeULEB128(writer, exp.index); |
| 1574 | 1605 | } |
| ... | ... | @@ -1747,9 +1778,12 @@ fn emitNameSection(self: *Wasm, file: fs.File, arena: Allocator) !void { |
| 1747 | 1778 | |
| 1748 | 1779 | for (self.resolved_symbols.keys()) |sym_loc| { |
| 1749 | 1780 | const symbol = sym_loc.getSymbol(self).*; |
| 1781 | const name = if (symbol.isUndefined()) blk: { |
| 1782 | break :blk self.string_table.get(self.imports.get(sym_loc).?.name); |
| 1783 | } else sym_loc.getName(self); |
| 1750 | 1784 | switch (symbol.tag) { |
| 1751 | | .function => funcs.appendAssumeCapacity(.{ .index = symbol.index, .name = sym_loc.getName(self) }), |
| 1752 | | .global => globals.appendAssumeCapacity(.{ .index = symbol.index, .name = sym_loc.getName(self) }), |
| 1785 | .function => funcs.appendAssumeCapacity(.{ .index = symbol.index, .name = name }), |
| 1786 | .global => globals.appendAssumeCapacity(.{ .index = symbol.index, .name = name }), |
| 1753 | 1787 | else => {}, |
| 1754 | 1788 | } |
| 1755 | 1789 | } |
| ... | ... | @@ -1831,12 +1865,14 @@ fn emitInit(writer: anytype, init_expr: wasm.InitExpression) !void { |
| 1831 | 1865 | try writer.writeByte(wasm.opcode(.end)); |
| 1832 | 1866 | } |
| 1833 | 1867 | |
| 1834 | | fn emitImport(writer: anytype, import: wasm.Import) !void { |
| 1835 | | try leb.writeULEB128(writer, @intCast(u32, import.module_name.len)); |
| 1836 | | try writer.writeAll(import.module_name); |
| 1868 | fn emitImport(self: *Wasm, writer: anytype, import: types.Import) !void { |
| 1869 | const module_name = self.string_table.get(import.module_name); |
| 1870 | try leb.writeULEB128(writer, @intCast(u32, module_name.len)); |
| 1871 | try writer.writeAll(module_name); |
| 1837 | 1872 | |
| 1838 | | try leb.writeULEB128(writer, @intCast(u32, import.name.len)); |
| 1839 | | try writer.writeAll(import.name); |
| 1873 | const name = self.string_table.get(import.name); |
| 1874 | try leb.writeULEB128(writer, @intCast(u32, name.len)); |
| 1875 | try writer.writeAll(name); |
| 1840 | 1876 | |
| 1841 | 1877 | try writer.writeByte(@enumToInt(import.kind)); |
| 1842 | 1878 | switch (import.kind) { |
| ... | ... | @@ -2353,7 +2389,7 @@ fn emitSymbolTable(self: *Wasm, file: fs.File, arena: Allocator, symbol_table: * |
| 2353 | 2389 | try leb.writeULEB128(writer, @enumToInt(symbol.tag)); |
| 2354 | 2390 | try leb.writeULEB128(writer, symbol.flags); |
| 2355 | 2391 | |
| 2356 | | const sym_name = if (self.export_names.get(sym_loc)) |exp_name| exp_name else sym_loc.getName(self); |
| 2392 | const sym_name = if (self.export_names.get(sym_loc)) |exp_name| self.string_table.get(exp_name) else sym_loc.getName(self); |
| 2357 | 2393 | switch (symbol.tag) { |
| 2358 | 2394 | .data => { |
| 2359 | 2395 | try leb.writeULEB128(writer, @intCast(u32, sym_name.len)); |