| ... | @@ -149,7 +149,8 @@ discarded: std.AutoHashMapUnmanaged(SymbolLoc, SymbolLoc) = .{}, | ... | @@ -149,7 +149,8 @@ discarded: std.AutoHashMapUnmanaged(SymbolLoc, SymbolLoc) = .{}, |
| 149 | /// into the final binary. | 149 | /// into the final binary. |
| 150 | resolved_symbols: std.AutoArrayHashMapUnmanaged(SymbolLoc, void) = .{}, | 150 | resolved_symbols: std.AutoArrayHashMapUnmanaged(SymbolLoc, void) = .{}, |
| 151 | /// Symbols that remain undefined after symbol resolution. | 151 | /// Symbols that remain undefined after symbol resolution. |
| 152 | undefs: std.StringArrayHashMapUnmanaged(SymbolLoc) = .{}, | 152 | /// Note: The key represents an offset into the string table, rather than the actual string. |
| | 153 | undefs: std.AutoArrayHashMapUnmanaged(u32, SymbolLoc) = .{}, |
| 153 | /// Maps a symbol's location to an atom. This can be used to find meta | 154 | /// Maps a symbol's location to an atom. This can be used to find meta |
| 154 | /// data of a symbol, such as its size, or its offset to perform a relocation. | 155 | /// data of a symbol, such as its size, or its offset to perform a relocation. |
| 155 | /// Undefined (and synthetic) symbols do not have an Atom and therefore cannot be mapped. | 156 | /// Undefined (and synthetic) symbols do not have an Atom and therefore cannot be mapped. |
| ... | @@ -514,6 +515,10 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*Wasm { | ... | @@ -514,6 +515,10 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*Wasm { |
| 514 | /// Leaves index undefined and the default flags (0). | 515 | /// Leaves index undefined and the default flags (0). |
| 515 | fn createSyntheticSymbol(wasm: *Wasm, name: []const u8, tag: Symbol.Tag) !SymbolLoc { | 516 | fn createSyntheticSymbol(wasm: *Wasm, name: []const u8, tag: Symbol.Tag) !SymbolLoc { |
| 516 | const name_offset = try wasm.string_table.put(wasm.base.allocator, name); | 517 | const name_offset = try wasm.string_table.put(wasm.base.allocator, name); |
| | 518 | return wasm.createSyntheticSymbolOffset(name_offset, tag); |
| | 519 | } |
| | 520 | |
| | 521 | fn createSyntheticSymbolOffset(wasm: *Wasm, name_offset: u32, tag: Symbol.Tag) !SymbolLoc { |
| 517 | const sym_index = @intCast(u32, wasm.symbols.items.len); | 522 | const sym_index = @intCast(u32, wasm.symbols.items.len); |
| 518 | const loc: SymbolLoc = .{ .index = sym_index, .file = null }; | 523 | const loc: SymbolLoc = .{ .index = sym_index, .file = null }; |
| 519 | try wasm.symbols.append(wasm.base.allocator, .{ | 524 | try wasm.symbols.append(wasm.base.allocator, .{ |
| ... | @@ -691,7 +696,7 @@ fn resolveSymbolsInObject(wasm: *Wasm, object_index: u16) !void { | ... | @@ -691,7 +696,7 @@ fn resolveSymbolsInObject(wasm: *Wasm, object_index: u16) !void { |
| 691 | try wasm.resolved_symbols.putNoClobber(wasm.base.allocator, location, {}); | 696 | try wasm.resolved_symbols.putNoClobber(wasm.base.allocator, location, {}); |
| 692 | | 697 | |
| 693 | if (symbol.isUndefined()) { | 698 | if (symbol.isUndefined()) { |
| 694 | try wasm.undefs.putNoClobber(wasm.base.allocator, sym_name, location); | 699 | try wasm.undefs.putNoClobber(wasm.base.allocator, sym_name_index, location); |
| 695 | } | 700 | } |
| 696 | continue; | 701 | continue; |
| 697 | } | 702 | } |
| ... | @@ -801,7 +806,7 @@ fn resolveSymbolsInObject(wasm: *Wasm, object_index: u16) !void { | ... | @@ -801,7 +806,7 @@ fn resolveSymbolsInObject(wasm: *Wasm, object_index: u16) !void { |
| 801 | try wasm.resolved_symbols.put(wasm.base.allocator, location, {}); | 806 | try wasm.resolved_symbols.put(wasm.base.allocator, location, {}); |
| 802 | assert(wasm.resolved_symbols.swapRemove(existing_loc)); | 807 | assert(wasm.resolved_symbols.swapRemove(existing_loc)); |
| 803 | if (existing_sym.isUndefined()) { | 808 | if (existing_sym.isUndefined()) { |
| 804 | _ = wasm.undefs.swapRemove(sym_name); | 809 | _ = wasm.undefs.swapRemove(sym_name_index); |
| 805 | } | 810 | } |
| 806 | } | 811 | } |
| 807 | } | 812 | } |
| ... | @@ -812,15 +817,16 @@ fn resolveSymbolsInArchives(wasm: *Wasm) !void { | ... | @@ -812,15 +817,16 @@ fn resolveSymbolsInArchives(wasm: *Wasm) !void { |
| 812 | log.debug("Resolving symbols in archives", .{}); | 817 | log.debug("Resolving symbols in archives", .{}); |
| 813 | var index: u32 = 0; | 818 | var index: u32 = 0; |
| 814 | undef_loop: while (index < wasm.undefs.count()) { | 819 | undef_loop: while (index < wasm.undefs.count()) { |
| 815 | const sym_name = wasm.undefs.keys()[index]; | 820 | const sym_name_index = wasm.undefs.keys()[index]; |
| 816 | | 821 | |
| 817 | for (wasm.archives.items) |archive| { | 822 | for (wasm.archives.items) |archive| { |
| | 823 | const sym_name = wasm.string_table.get(sym_name_index); |
| | 824 | log.debug("Detected symbol '{s}' in archive '{s}', parsing objects..", .{ sym_name, archive.name }); |
| 818 | const offset = archive.toc.get(sym_name) orelse { | 825 | const offset = archive.toc.get(sym_name) orelse { |
| 819 | // symbol does not exist in this archive | 826 | // symbol does not exist in this archive |
| 820 | continue; | 827 | continue; |
| 821 | }; | 828 | }; |
| 822 | | 829 | |
| 823 | log.debug("Detected symbol '{s}' in archive '{s}', parsing objects..", .{ sym_name, archive.name }); | | |
| 824 | // Symbol is found in unparsed object file within current archive. | 830 | // Symbol is found in unparsed object file within current archive. |
| 825 | // Parse object and and resolve symbols again before we check remaining | 831 | // Parse object and and resolve symbols again before we check remaining |
| 826 | // undefined symbols. | 832 | // undefined symbols. |
| ... | @@ -1191,28 +1197,36 @@ fn validateFeatures( | ... | @@ -1191,28 +1197,36 @@ fn validateFeatures( |
| 1191 | /// if one or multiple undefined references exist. When none exist, the symbol will | 1197 | /// if one or multiple undefined references exist. When none exist, the symbol will |
| 1192 | /// not be created, ensuring we don't unneccesarily emit unreferenced symbols. | 1198 | /// not be created, ensuring we don't unneccesarily emit unreferenced symbols. |
| 1193 | fn resolveLazySymbols(wasm: *Wasm) !void { | 1199 | fn resolveLazySymbols(wasm: *Wasm) !void { |
| 1194 | if (wasm.undefs.fetchSwapRemove("__heap_base")) |kv| { | 1200 | if (wasm.string_table.getOffset("__heap_base")) |name_offset| { |
| 1195 | const loc = try wasm.createSyntheticSymbol("__heap_base", .data); | 1201 | if (wasm.undefs.fetchSwapRemove(name_offset)) |kv| { |
| 1196 | try wasm.discarded.putNoClobber(wasm.base.allocator, kv.value, loc); | 1202 | const loc = try wasm.createSyntheticSymbolOffset(name_offset, .data); |
| 1197 | _ = wasm.resolved_symbols.swapRemove(loc); // we don't want to emit this symbol, only use it for relocations. | 1203 | try wasm.discarded.putNoClobber(wasm.base.allocator, kv.value, loc); |
| | 1204 | _ = wasm.resolved_symbols.swapRemove(loc); // we don't want to emit this symbol, only use it for relocations. |
| | 1205 | } |
| 1198 | } | 1206 | } |
| 1199 | | 1207 | |
| 1200 | if (wasm.undefs.fetchSwapRemove("__heap_end")) |kv| { | 1208 | if (wasm.string_table.getOffset("__heap_end")) |name_offset| { |
| 1201 | const loc = try wasm.createSyntheticSymbol("__heap_end", .data); | 1209 | if (wasm.undefs.fetchSwapRemove(name_offset)) |kv| { |
| 1202 | try wasm.discarded.putNoClobber(wasm.base.allocator, kv.value, loc); | 1210 | const loc = try wasm.createSyntheticSymbolOffset(name_offset, .data); |
| 1203 | _ = wasm.resolved_symbols.swapRemove(loc); | 1211 | try wasm.discarded.putNoClobber(wasm.base.allocator, kv.value, loc); |
| | 1212 | _ = wasm.resolved_symbols.swapRemove(loc); |
| | 1213 | } |
| 1204 | } | 1214 | } |
| 1205 | | 1215 | |
| 1206 | if (!wasm.base.options.shared_memory) { | 1216 | if (!wasm.base.options.shared_memory) { |
| 1207 | if (wasm.undefs.fetchSwapRemove("__tls_base")) |kv| { | 1217 | if (wasm.string_table.getOffset("__tls_base")) |name_offset| { |
| 1208 | const loc = try wasm.createSyntheticSymbol("__tls_base", .global); | 1218 | if (wasm.undefs.fetchSwapRemove(name_offset)) |kv| { |
| 1209 | try wasm.discarded.putNoClobber(wasm.base.allocator, kv.value, loc); | 1219 | const loc = try wasm.createSyntheticSymbolOffset(name_offset, .global); |
| | 1220 | try wasm.discarded.putNoClobber(wasm.base.allocator, kv.value, loc); |
| | 1221 | } |
| 1210 | } | 1222 | } |
| 1211 | } | 1223 | } |
| 1212 | if (wasm.undefs.fetchSwapRemove("__zig_errors_len")) |kv| { | 1224 | if (wasm.string_table.getOffset("__zig_errors_len")) |name_offset| { |
| 1213 | const loc = try wasm.createSyntheticSymbol("__zig_errors_len", .data); | 1225 | if (wasm.undefs.fetchSwapRemove(name_offset)) |kv| { |
| 1214 | try wasm.discarded.putNoClobber(wasm.base.allocator, kv.value, loc); | 1226 | const loc = try wasm.createSyntheticSymbolOffset(name_offset, .data); |
| 1215 | _ = wasm.resolved_symbols.swapRemove(kv.value); | 1227 | try wasm.discarded.putNoClobber(wasm.base.allocator, kv.value, loc); |
| | 1228 | _ = wasm.resolved_symbols.swapRemove(kv.value); |
| | 1229 | } |
| 1216 | } | 1230 | } |
| 1217 | } | 1231 | } |
| 1218 | | 1232 | |
| ... | @@ -1611,7 +1625,7 @@ pub fn getGlobalSymbol(wasm: *Wasm, name: []const u8, lib_name: ?[]const u8) !u3 | ... | @@ -1611,7 +1625,7 @@ pub fn getGlobalSymbol(wasm: *Wasm, name: []const u8, lib_name: ?[]const u8) !u3 |
| 1611 | wasm.symbols.items[sym_index] = symbol; | 1625 | wasm.symbols.items[sym_index] = symbol; |
| 1612 | gop.value_ptr.* = .{ .index = sym_index, .file = null }; | 1626 | gop.value_ptr.* = .{ .index = sym_index, .file = null }; |
| 1613 | try wasm.resolved_symbols.put(wasm.base.allocator, gop.value_ptr.*, {}); | 1627 | try wasm.resolved_symbols.put(wasm.base.allocator, gop.value_ptr.*, {}); |
| 1614 | try wasm.undefs.putNoClobber(wasm.base.allocator, name, gop.value_ptr.*); | 1628 | try wasm.undefs.putNoClobber(wasm.base.allocator, name_index, gop.value_ptr.*); |
| 1615 | return sym_index; | 1629 | return sym_index; |
| 1616 | } | 1630 | } |
| 1617 | | 1631 | |
| ... | @@ -1769,7 +1783,7 @@ pub fn updateDeclExports( | ... | @@ -1769,7 +1783,7 @@ pub fn updateDeclExports( |
| 1769 | | 1783 | |
| 1770 | // if the symbol was previously undefined, remove it as an import | 1784 | // if the symbol was previously undefined, remove it as an import |
| 1771 | _ = wasm.imports.remove(sym_loc); | 1785 | _ = wasm.imports.remove(sym_loc); |
| 1772 | _ = wasm.undefs.swapRemove(mod.intern_pool.stringToSlice(exp.name)); | 1786 | _ = wasm.undefs.swapRemove(export_name); |
| 1773 | } | 1787 | } |
| 1774 | } | 1788 | } |
| 1775 | | 1789 | |
| ... | @@ -1885,7 +1899,7 @@ pub fn addOrUpdateImport( | ... | @@ -1885,7 +1899,7 @@ pub fn addOrUpdateImport( |
| 1885 | const loc: SymbolLoc = .{ .file = null, .index = symbol_index }; | 1899 | const loc: SymbolLoc = .{ .file = null, .index = symbol_index }; |
| 1886 | global_gop.value_ptr.* = loc; | 1900 | global_gop.value_ptr.* = loc; |
| 1887 | try wasm.resolved_symbols.put(wasm.base.allocator, loc, {}); | 1901 | try wasm.resolved_symbols.put(wasm.base.allocator, loc, {}); |
| 1888 | try wasm.undefs.putNoClobber(wasm.base.allocator, full_name, loc); | 1902 | try wasm.undefs.putNoClobber(wasm.base.allocator, decl_name_index, loc); |
| 1889 | } | 1903 | } |
| 1890 | | 1904 | |
| 1891 | if (type_index) |ty_index| { | 1905 | if (type_index) |ty_index| { |