| ... | ... | @@ -125,7 +125,10 @@ func_types: std.ArrayListUnmanaged(std.wasm.Type) = .{}, |
| 125 | 125 | /// Output function section where the key is the original |
| 126 | 126 | /// function index and the value is function. |
| 127 | 127 | /// This allows us to map multiple symbols to the same function. |
| 128 | | functions: std.AutoArrayHashMapUnmanaged(struct { file: ?u16, index: u32 }, struct { func: std.wasm.Func, sym_index: u32 }) = .{}, |
| 128 | functions: std.AutoArrayHashMapUnmanaged( |
| 129 | struct { file: File.Index, index: u32 }, |
| 130 | struct { func: std.wasm.Func, sym_index: u32 }, |
| 131 | ) = .{}, |
| 129 | 132 | /// Output global section |
| 130 | 133 | wasm_globals: std.ArrayListUnmanaged(std.wasm.Global) = .{}, |
| 131 | 134 | /// Memory section |
| ... | ... | @@ -217,16 +220,14 @@ pub const SymbolLoc = struct { |
| 217 | 220 | /// The index of the symbol within the specified file |
| 218 | 221 | index: u32, |
| 219 | 222 | /// The index of the object file where the symbol resides. |
| 220 | | /// When this is `null` the symbol comes from a non-object file. |
| 221 | | file: ?u16, |
| 223 | file: File.Index, |
| 222 | 224 | |
| 223 | 225 | /// From a given location, returns the corresponding symbol in the wasm binary |
| 224 | 226 | pub fn getSymbol(loc: SymbolLoc, wasm_file: *const Wasm) *Symbol { |
| 225 | 227 | if (wasm_file.discarded.get(loc)) |new_loc| { |
| 226 | 228 | return new_loc.getSymbol(wasm_file); |
| 227 | 229 | } |
| 228 | | if (loc.file) |object_index| { |
| 229 | | const obj_file = wasm_file.file(@enumFromInt(object_index)).?; |
| 230 | if (wasm_file.file(loc.file)) |obj_file| { |
| 230 | 231 | return obj_file.symbol(loc.index); |
| 231 | 232 | } |
| 232 | 233 | return &wasm_file.synthetic_symbols.items[loc.index]; |
| ... | ... | @@ -237,8 +238,7 @@ pub const SymbolLoc = struct { |
| 237 | 238 | if (wasm_file.discarded.get(loc)) |new_loc| { |
| 238 | 239 | return new_loc.getName(wasm_file); |
| 239 | 240 | } |
| 240 | | if (loc.file) |object_index| { |
| 241 | | const obj_file = wasm_file.file(@enumFromInt(object_index)).?; |
| 241 | if (wasm_file.file(loc.file)) |obj_file| { |
| 242 | 242 | return obj_file.symbolName(loc.index); |
| 243 | 243 | } |
| 244 | 244 | return wasm_file.string_table.get(wasm_file.synthetic_symbols.items[loc.index].name); |
| ... | ... | @@ -263,7 +263,7 @@ pub const InitFuncLoc = struct { |
| 263 | 263 | /// object file index in the list of objects. |
| 264 | 264 | /// Unlike `SymbolLoc` this cannot be `null` as we never define |
| 265 | 265 | /// our own ctors. |
| 266 | | file: u16, |
| 266 | file: File.Index, |
| 267 | 267 | /// Symbol index within the corresponding object file. |
| 268 | 268 | index: u32, |
| 269 | 269 | /// The priority in which the constructor must be called. |
| ... | ... | @@ -633,7 +633,7 @@ fn createSyntheticSymbol(wasm: *Wasm, name: []const u8, tag: Symbol.Tag) !Symbol |
| 633 | 633 | |
| 634 | 634 | fn createSyntheticSymbolOffset(wasm: *Wasm, name_offset: u32, tag: Symbol.Tag) !SymbolLoc { |
| 635 | 635 | const sym_index = @as(u32, @intCast(wasm.synthetic_symbols.items.len)); |
| 636 | | const loc: SymbolLoc = .{ .index = sym_index, .file = null }; |
| 636 | const loc: SymbolLoc = .{ .index = sym_index, .file = .null }; |
| 637 | 637 | const gpa = wasm.base.comp.gpa; |
| 638 | 638 | try wasm.synthetic_symbols.append(gpa, .{ |
| 639 | 639 | .name = name_offset, |
| ... | ... | @@ -680,7 +680,7 @@ pub fn createAtom(wasm: *Wasm, sym_index: u32, file_index: File.Index) !Atom.Ind |
| 680 | 680 | const index: Atom.Index = @intCast(wasm.managed_atoms.items.len); |
| 681 | 681 | const atom = try wasm.managed_atoms.addOne(gpa); |
| 682 | 682 | atom.* = .{ .file = file_index, .sym_index = sym_index }; |
| 683 | | try wasm.symbol_atom.putNoClobber(gpa, .{ .file = null, .index = sym_index }, index); |
| 683 | try wasm.symbol_atom.putNoClobber(gpa, atom.symbolLoc(), index); |
| 684 | 684 | |
| 685 | 685 | return index; |
| 686 | 686 | } |
| ... | ... | @@ -763,10 +763,7 @@ fn resolveSymbolsInObject(wasm: *Wasm, file_index: File.Index) !void { |
| 763 | 763 | |
| 764 | 764 | for (obj_file.symbols(), 0..) |symbol, i| { |
| 765 | 765 | const sym_index: u32 = @intCast(i); |
| 766 | | const location: SymbolLoc = .{ |
| 767 | | .file = @intFromEnum(file_index), |
| 768 | | .index = sym_index, |
| 769 | | }; |
| 766 | const location: SymbolLoc = .{ .file = file_index, .index = sym_index }; |
| 770 | 767 | const sym_name = obj_file.string(symbol.name); |
| 771 | 768 | if (mem.eql(u8, sym_name, "__indirect_function_table")) { |
| 772 | 769 | continue; |
| ... | ... | @@ -796,9 +793,10 @@ fn resolveSymbolsInObject(wasm: *Wasm, file_index: File.Index) !void { |
| 796 | 793 | |
| 797 | 794 | const existing_loc = maybe_existing.value_ptr.*; |
| 798 | 795 | const existing_sym: *Symbol = existing_loc.getSymbol(wasm); |
| 796 | const existing_file = wasm.file(existing_loc.file); |
| 799 | 797 | |
| 800 | | const existing_file_path = if (existing_loc.file) |existing_file_index| |
| 801 | | wasm.file(@enumFromInt(existing_file_index)).?.path() |
| 798 | const existing_file_path = if (existing_file) |existing_obj_file| |
| 799 | existing_obj_file.path() |
| 802 | 800 | else |
| 803 | 801 | wasm.name; |
| 804 | 802 | |
| ... | ... | @@ -831,8 +829,7 @@ fn resolveSymbolsInObject(wasm: *Wasm, file_index: File.Index) !void { |
| 831 | 829 | if (existing_sym.isUndefined() and symbol.isUndefined()) { |
| 832 | 830 | // only verify module/import name for function symbols |
| 833 | 831 | if (symbol.tag == .function) { |
| 834 | | const existing_name = if (existing_loc.file) |existing_file_index| blk: { |
| 835 | | const existing_obj = wasm.file(@enumFromInt(existing_file_index)).?; |
| 832 | const existing_name = if (existing_file) |existing_obj| blk: { |
| 836 | 833 | const imp = existing_obj.import(existing_loc.index); |
| 837 | 834 | break :blk existing_obj.string(imp.module_name); |
| 838 | 835 | } else blk: { |
| ... | ... | @@ -1363,8 +1360,8 @@ fn checkUndefinedSymbols(wasm: *const Wasm) !void { |
| 1363 | 1360 | const symbol = undef.getSymbol(wasm); |
| 1364 | 1361 | if (symbol.tag == .data) { |
| 1365 | 1362 | found_undefined_symbols = true; |
| 1366 | | const file_name = if (undef.file) |file_index| |
| 1367 | | wasm.file(@enumFromInt(file_index)).?.path() |
| 1363 | const file_name = if (wasm.file(undef.file)) |obj_file| |
| 1364 | obj_file.path() |
| 1368 | 1365 | else |
| 1369 | 1366 | wasm.name; |
| 1370 | 1367 | const symbol_name = undef.getName(wasm); |
| ... | ... | @@ -1461,8 +1458,7 @@ fn getGlobalType(wasm: *const Wasm, loc: SymbolLoc) std.wasm.GlobalType { |
| 1461 | 1458 | const symbol = loc.getSymbol(wasm); |
| 1462 | 1459 | assert(symbol.tag == .global); |
| 1463 | 1460 | const is_undefined = symbol.isUndefined(); |
| 1464 | | if (loc.file) |file_index| { |
| 1465 | | const obj_file = wasm.file(@enumFromInt(file_index)).?; |
| 1461 | if (wasm.file(loc.file)) |obj_file| { |
| 1466 | 1462 | if (is_undefined) { |
| 1467 | 1463 | return obj_file.import(loc.index).kind.global; |
| 1468 | 1464 | } |
| ... | ... | @@ -1480,8 +1476,7 @@ fn getFunctionSignature(wasm: *const Wasm, loc: SymbolLoc) std.wasm.Type { |
| 1480 | 1476 | const symbol = loc.getSymbol(wasm); |
| 1481 | 1477 | assert(symbol.tag == .function); |
| 1482 | 1478 | const is_undefined = symbol.isUndefined(); |
| 1483 | | if (loc.file) |file_index| { |
| 1484 | | const obj_file = wasm.file(@enumFromInt(file_index)).?; |
| 1479 | if (wasm.file(loc.file)) |obj_file| { |
| 1485 | 1480 | if (is_undefined) { |
| 1486 | 1481 | const ty_index = obj_file.import(loc.index).kind.function; |
| 1487 | 1482 | return obj_file.funcTypes()[ty_index]; |
| ... | ... | @@ -1625,8 +1620,8 @@ fn allocateAtoms(wasm: *Wasm) !void { |
| 1625 | 1620 | // Ensure we get the original symbol, so we verify the correct symbol on whether |
| 1626 | 1621 | // it is dead or not and ensure an atom is removed when dead. |
| 1627 | 1622 | // This is required as we may have parsed aliases into atoms. |
| 1628 | | const sym = if (symbol_loc.file) |file_index| |
| 1629 | | wasm.file(@enumFromInt(file_index)).?.symbol(symbol_loc.index).* |
| 1623 | const sym = if (wasm.file(symbol_loc.file)) |obj_file| |
| 1624 | obj_file.symbol(symbol_loc.index).* |
| 1630 | 1625 | else |
| 1631 | 1626 | wasm.synthetic_symbols.items[symbol_loc.index]; |
| 1632 | 1627 | |
| ... | ... | @@ -1754,10 +1749,10 @@ fn setupInitFunctions(wasm: *Wasm) !void { |
| 1754 | 1749 | log.debug("appended init func '{s}'\n", .{object.string_table.get(symbol.name)}); |
| 1755 | 1750 | wasm.init_funcs.appendAssumeCapacity(.{ |
| 1756 | 1751 | .index = init_func.symbol_index, |
| 1757 | | .file = @intFromEnum(file_index), |
| 1752 | .file = file_index, |
| 1758 | 1753 | .priority = init_func.priority, |
| 1759 | 1754 | }); |
| 1760 | | try wasm.mark(.{ .index = init_func.symbol_index, .file = @intFromEnum(file_index) }); |
| 1755 | try wasm.mark(.{ .index = init_func.symbol_index, .file = file_index }); |
| 1761 | 1756 | } |
| 1762 | 1757 | } |
| 1763 | 1758 | |
| ... | ... | @@ -1841,7 +1836,7 @@ fn createSyntheticFunction( |
| 1841 | 1836 | const func_index = wasm.imported_functions_count + @as(u32, @intCast(wasm.functions.count())); |
| 1842 | 1837 | try wasm.functions.putNoClobber( |
| 1843 | 1838 | gpa, |
| 1844 | | .{ .file = null, .index = func_index }, |
| 1839 | .{ .file = .null, .index = func_index }, |
| 1845 | 1840 | .{ .func = .{ .type_index = ty_index }, .sym_index = loc.index }, |
| 1846 | 1841 | ); |
| 1847 | 1842 | symbol.index = func_index; |
| ... | ... | @@ -1849,8 +1844,8 @@ fn createSyntheticFunction( |
| 1849 | 1844 | // create the atom that will be output into the final binary |
| 1850 | 1845 | const atom_index = try wasm.createAtom(loc.index, .null); |
| 1851 | 1846 | const atom = wasm.getAtomPtr(atom_index); |
| 1852 | | atom.code = function_body.moveToUnmanaged(); |
| 1853 | 1847 | atom.size = @intCast(function_body.items.len); |
| 1848 | atom.code = function_body.moveToUnmanaged(); |
| 1854 | 1849 | try wasm.appendAtomAtIndex(wasm.code_section_index.?, atom_index); |
| 1855 | 1850 | } |
| 1856 | 1851 | |
| ... | ... | @@ -1969,20 +1964,8 @@ fn initializeTLSFunction(wasm: *Wasm) !void { |
| 1969 | 1964 | fn setupImports(wasm: *Wasm) !void { |
| 1970 | 1965 | const gpa = wasm.base.comp.gpa; |
| 1971 | 1966 | log.debug("Merging imports", .{}); |
| 1972 | | var discarded_it = wasm.discarded.keyIterator(); |
| 1973 | | while (discarded_it.next()) |discarded| { |
| 1974 | | if (discarded.file == null) { |
| 1975 | | // remove an import if it was resolved |
| 1976 | | if (wasm.imports.remove(discarded.*)) { |
| 1977 | | log.debug("Removed symbol '{s}' as an import", .{ |
| 1978 | | discarded.getName(wasm), |
| 1979 | | }); |
| 1980 | | } |
| 1981 | | } |
| 1982 | | } |
| 1983 | | |
| 1984 | 1967 | for (wasm.resolved_symbols.keys()) |symbol_loc| { |
| 1985 | | const file_index = symbol_loc.file orelse { |
| 1968 | const obj_file = wasm.file(symbol_loc.file) orelse { |
| 1986 | 1969 | // Synthetic symbols will already exist in the `import` section |
| 1987 | 1970 | continue; |
| 1988 | 1971 | }; |
| ... | ... | @@ -1996,7 +1979,6 @@ fn setupImports(wasm: *Wasm) !void { |
| 1996 | 1979 | } |
| 1997 | 1980 | |
| 1998 | 1981 | log.debug("Symbol '{s}' will be imported from the host", .{symbol_loc.getName(wasm)}); |
| 1999 | | const obj_file = wasm.file(@enumFromInt(file_index)).?; |
| 2000 | 1982 | const import = obj_file.import(symbol_loc.index); |
| 2001 | 1983 | |
| 2002 | 1984 | // We copy the import to a new import to ensure the names contain references |
| ... | ... | @@ -2054,15 +2036,13 @@ fn mergeSections(wasm: *Wasm) !void { |
| 2054 | 2036 | defer removed_duplicates.deinit(); |
| 2055 | 2037 | |
| 2056 | 2038 | for (wasm.resolved_symbols.keys()) |sym_loc| { |
| 2057 | | const file_index = sym_loc.file orelse { |
| 2039 | const obj_file = wasm.file(sym_loc.file) orelse { |
| 2058 | 2040 | // Zig code-generated symbols are already within the sections and do not |
| 2059 | 2041 | // require to be merged |
| 2060 | 2042 | continue; |
| 2061 | 2043 | }; |
| 2062 | 2044 | |
| 2063 | | const obj_file = wasm.file(@enumFromInt(file_index)).?; |
| 2064 | 2045 | const symbol = obj_file.symbol(sym_loc.index); |
| 2065 | | |
| 2066 | 2046 | if (symbol.isDead() or symbol.isUndefined()) { |
| 2067 | 2047 | // Skip undefined symbols as they go in the `import` section |
| 2068 | 2048 | continue; |
| ... | ... | @@ -2105,7 +2085,7 @@ fn mergeSections(wasm: *Wasm) !void { |
| 2105 | 2085 | symbol.index = @as(u32, @intCast(wasm.tables.items.len)) + wasm.imported_tables_count; |
| 2106 | 2086 | try wasm.tables.append(gpa, original_table); |
| 2107 | 2087 | }, |
| 2108 | | else => continue, |
| 2088 | else => {}, |
| 2109 | 2089 | } |
| 2110 | 2090 | } |
| 2111 | 2091 | |
| ... | ... | @@ -2132,12 +2112,11 @@ fn mergeTypes(wasm: *Wasm) !void { |
| 2132 | 2112 | defer dirty.deinit(); |
| 2133 | 2113 | |
| 2134 | 2114 | for (wasm.resolved_symbols.keys()) |sym_loc| { |
| 2135 | | const file_index = sym_loc.file orelse { |
| 2115 | const obj_file = wasm.file(sym_loc.file) orelse { |
| 2136 | 2116 | // zig code-generated symbols are already present in final type section |
| 2137 | 2117 | continue; |
| 2138 | 2118 | }; |
| 2139 | 2119 | |
| 2140 | | const obj_file = wasm.file(@enumFromInt(file_index)).?; |
| 2141 | 2120 | const symbol = obj_file.symbol(sym_loc.index); |
| 2142 | 2121 | if (symbol.tag != .function or symbol.isDead()) { |
| 2143 | 2122 | // Only functions have types. Only retrieve the type of referenced functions. |
| ... | ... | @@ -2191,7 +2170,7 @@ fn setupExports(wasm: *Wasm) !void { |
| 2191 | 2170 | |
| 2192 | 2171 | const sym_name = sym_loc.getName(wasm); |
| 2193 | 2172 | const export_name = if (wasm.export_names.get(sym_loc)) |name| name else blk: { |
| 2194 | | if (sym_loc.file == null) break :blk symbol.name; |
| 2173 | if (sym_loc.file == .null) break :blk symbol.name; |
| 2195 | 2174 | break :blk try wasm.string_table.put(gpa, sym_name); |
| 2196 | 2175 | }; |
| 2197 | 2176 | const exp: types.Export = if (symbol.tag == .data) exp: { |
| ... | ... | @@ -2425,7 +2404,7 @@ pub fn getMatchingSegment(wasm: *Wasm, file_index: File.Index, symbol_index: u32 |
| 2425 | 2404 | break :blk index; |
| 2426 | 2405 | }, |
| 2427 | 2406 | .section => { |
| 2428 | | const section_name = obj_file.symbolName(symbol.index); |
| 2407 | const section_name = obj_file.symbolName(symbol_index); |
| 2429 | 2408 | if (mem.eql(u8, section_name, ".debug_info")) { |
| 2430 | 2409 | return wasm.debug_info_index orelse blk: { |
| 2431 | 2410 | wasm.debug_info_index = index; |
| ... | ... | @@ -2475,7 +2454,7 @@ pub fn getMatchingSegment(wasm: *Wasm, file_index: File.Index, symbol_index: u32 |
| 2475 | 2454 | break :blk index; |
| 2476 | 2455 | }; |
| 2477 | 2456 | } else { |
| 2478 | | log.warn("found unknown section '{s}'", .{section_name}); |
| 2457 | log.err("found unknown section '{s}'", .{section_name}); |
| 2479 | 2458 | return error.UnexpectedValue; |
| 2480 | 2459 | } |
| 2481 | 2460 | }, |
| ... | ... | @@ -4221,10 +4200,7 @@ fn emitDataRelocations( |
| 4221 | 4200 | size_offset += getULEB128Size(atom.size); |
| 4222 | 4201 | for (atom.relocs.items) |relocation| { |
| 4223 | 4202 | count += 1; |
| 4224 | | const sym_loc: SymbolLoc = .{ |
| 4225 | | .file = atom.file, |
| 4226 | | .index = relocation.index, |
| 4227 | | }; |
| 4203 | const sym_loc: SymbolLoc = .{ .file = atom.file, .index = relocation.index }; |
| 4228 | 4204 | const symbol_index = symbol_table.get(sym_loc).?; |
| 4229 | 4205 | try leb.writeULEB128(writer, @intFromEnum(relocation.relocation_type)); |
| 4230 | 4206 | const offset = atom.offset + relocation.offset + size_offset; |
| ... | ... | @@ -4322,8 +4298,7 @@ fn markReferences(wasm: *Wasm) !void { |
| 4322 | 4298 | // Debug sections may require to be parsed and marked when it contains |
| 4323 | 4299 | // relocations to alive symbols. |
| 4324 | 4300 | if (sym.tag == .section and comp.config.debug_format != .strip) { |
| 4325 | | const file_index = sym_loc.file orelse continue; // Incremental debug info is done independently |
| 4326 | | const obj_file = wasm.file(@enumFromInt(file_index)).?; |
| 4301 | const obj_file = wasm.file(sym_loc.file) orelse continue; // Incremental debug info is done independently |
| 4327 | 4302 | _ = try obj_file.parseSymbolIntoAtom(wasm, sym_loc.index); |
| 4328 | 4303 | sym.mark(); |
| 4329 | 4304 | } |
| ... | ... | @@ -4347,10 +4322,10 @@ fn mark(wasm: *Wasm, loc: SymbolLoc) !void { |
| 4347 | 4322 | return; |
| 4348 | 4323 | } |
| 4349 | 4324 | |
| 4350 | | const atom_index = if (loc.file) |file_index| idx: { |
| 4351 | | const obj_file = wasm.file(@enumFromInt(file_index)).?; |
| 4352 | | break :idx try obj_file.parseSymbolIntoAtom(wasm, loc.index); |
| 4353 | | } else wasm.symbol_atom.get(loc) orelse return; |
| 4325 | const atom_index = if (wasm.file(loc.file)) |obj_file| |
| 4326 | try obj_file.parseSymbolIntoAtom(wasm, loc.index) |
| 4327 | else |
| 4328 | wasm.symbol_atom.get(loc) orelse return; |
| 4354 | 4329 | |
| 4355 | 4330 | const atom = wasm.getAtom(atom_index); |
| 4356 | 4331 | for (atom.relocs.items) |reloc| { |