diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig index 0ed32caf4c..663d9d4a4d 100644 --- a/src/link/Wasm.zig +++ b/src/link/Wasm.zig @@ -1333,6 +1333,10 @@ pub fn deinit(wasm: *Wasm) void { atom.deinit(gpa); } } + for (wasm.synthetic_functions.items) |atom_index| { + const atom = wasm.getAtomPtr(atom_index); + atom.deinit(gpa); + } wasm.decls.deinit(gpa); wasm.anon_decls.deinit(gpa); @@ -1364,10 +1368,6 @@ pub fn deinit(wasm: *Wasm) void { wasm.exports.deinit(gpa); wasm.string_table.deinit(gpa); - for (wasm.synthetic_functions.items) |atom_index| { - const atom = wasm.getAtomPtr(atom_index); - atom.deinit(gpa); - } wasm.synthetic_functions.deinit(gpa); if (wasm.dwarf) |*dwarf| { @@ -2134,9 +2134,13 @@ const Kind = union(enum) { fn parseAtom(wasm: *Wasm, atom_index: Atom.Index, kind: Kind) !void { const atom = wasm.getAtomPtr(atom_index); const symbol = (SymbolLoc{ .file = null, .index = atom.sym_index }).getSymbol(wasm); + if (symbol.isDead()) { + // Prevent unreferenced symbols from being parsed. + return; + } const final_index: u32 = switch (kind) { .function => result: { - const index = @as(u32, @intCast(wasm.functions.count() + wasm.imported_functions_count)); + const index: u32 = @intCast(wasm.functions.count() + wasm.imported_functions_count); const type_index = wasm.atom_types.get(atom_index).?; try wasm.functions.putNoClobber( wasm.base.allocator, @@ -2147,7 +2151,7 @@ fn parseAtom(wasm: *Wasm, atom_index: Atom.Index, kind: Kind) !void { symbol.index = index; if (wasm.code_section_index == null) { - wasm.code_section_index = @as(u32, @intCast(wasm.segments.items.len)); + wasm.code_section_index = @intCast(wasm.segments.items.len); try wasm.segments.append(wasm.base.allocator, .{ .alignment = atom.alignment, .size = atom.size, @@ -2185,12 +2189,12 @@ fn parseAtom(wasm: *Wasm, atom_index: Atom.Index, kind: Kind) !void { const index = gop.value_ptr.*; wasm.segments.items[index].size += atom.size; - symbol.index = @as(u32, @intCast(wasm.segment_info.getIndex(index).?)); + symbol.index = @intCast(wasm.segment_info.getIndex(index).?); // segment info already exists, so free its memory wasm.base.allocator.free(segment_name); break :result index; } else { - const index = @as(u32, @intCast(wasm.segments.items.len)); + const index: u32 = @intCast(wasm.segments.items.len); var flags: u32 = 0; if (wasm.base.options.shared_memory) { flags |= @intFromEnum(Segment.Flag.WASM_DATA_SEGMENT_IS_PASSIVE); @@ -2203,7 +2207,7 @@ fn parseAtom(wasm: *Wasm, atom_index: Atom.Index, kind: Kind) !void { }); gop.value_ptr.* = index; - const info_index = @as(u32, @intCast(wasm.segment_info.count())); + const info_index: u32 = @intCast(wasm.segment_info.count()); try wasm.segment_info.put(wasm.base.allocator, index, segment_info); symbol.index = info_index; break :result index; @@ -2318,8 +2322,10 @@ fn allocateAtoms(wasm: *Wasm) !void { fn allocateVirtualAddresses(wasm: *Wasm) void { for (wasm.resolved_symbols.keys()) |loc| { const symbol = loc.getSymbol(wasm); - if (symbol.tag != .data) { - continue; // only data symbols have virtual addresses + if (symbol.tag != .data or symbol.isDead()) { + // Only data symbols have virtual addresses. + // Dead symbols do not get allocated, so we don't need to set their virtual address either. + continue; } const atom_index = wasm.symbol_atom.get(loc) orelse { // synthetic symbol that does not contain an atom @@ -2681,10 +2687,10 @@ fn setupImports(wasm: *Wasm) !void { } for (wasm.resolved_symbols.keys()) |symbol_loc| { - if (symbol_loc.file == null) { + const file_index = symbol_loc.file orelse { // imports generated by Zig code are already in the `import` section continue; - } + }; const symbol = symbol_loc.getSymbol(wasm); if (symbol.isDead() or @@ -2695,7 +2701,7 @@ fn setupImports(wasm: *Wasm) !void { } log.debug("Symbol '{s}' will be imported from the host", .{symbol_loc.getName(wasm)}); - const object = wasm.objects.items[symbol_loc.file.?]; + const object = wasm.objects.items[file_index]; const import = object.findImport(symbol.tag.externalType(), symbol.index); // We copy the import to a new import to ensure the names contain references @@ -3092,6 +3098,11 @@ pub fn getMatchingSegment(wasm: *Wasm, object_index: u16, symbol_index: u32) !u3 .offset = 0, .flags = flags, }); + try wasm.segment_info.putNoClobber(wasm.base.allocator, index, .{ + .name = try wasm.base.allocator.dupe(u8, segment_info.name), + .alignment = segment_info.alignment, + .flags = segment_info.flags, + }); return index; } else return result.value_ptr.*; }, @@ -3198,6 +3209,7 @@ pub fn getErrorTableSymbol(wasm: *Wasm) !u32 { .virtual_address = undefined, }; symbol.setFlag(.WASM_SYM_VISIBILITY_HIDDEN); + symbol.mark(); try wasm.resolved_symbols.put(wasm.base.allocator, atom.symbolLoc(), {}); @@ -3230,6 +3242,7 @@ fn populateErrorNameTable(wasm: *Wasm) !void { .virtual_address = undefined, }; names_symbol.setFlag(.WASM_SYM_VISIBILITY_HIDDEN); + names_symbol.mark(); log.debug("Populating error names", .{}); @@ -3606,9 +3619,9 @@ pub fn flushModule(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod // So we can rebuild the binary file on each incremental update defer wasm.resetState(); try wasm.setupInitFunctions(); - try wasm.setupErrorsLen(); try wasm.setupStart(); try wasm.markReferences(); + try wasm.setupErrorsLen(); try wasm.setupImports(); if (wasm.base.options.module) |mod| { var decl_it = wasm.decls.iterator(); @@ -5152,14 +5165,15 @@ fn mark(wasm: *Wasm, loc: SymbolLoc) !void { return; } - const file = loc.file orelse return; // Marking synthetic and Zig symbols is done seperately - const object = &wasm.objects.items[file]; - const atom_index = try Object.parseSymbolIntoAtom(object, file, loc.index, wasm); + const atom_index = if (loc.file) |file_index| idx: { + const object = &wasm.objects.items[file_index]; + const atom_index = try object.parseSymbolIntoAtom(file_index, loc.index, wasm); + break :idx atom_index; + } else wasm.symbol_atom.get(loc) orelse return; const atom = wasm.getAtom(atom_index); - const relocations: []const types.Relocation = atom.relocs.items; - for (relocations) |reloc| { - const target_loc: SymbolLoc = .{ .index = reloc.index, .file = file }; + for (atom.relocs.items) |reloc| { + const target_loc: SymbolLoc = .{ .index = reloc.index, .file = loc.file }; try wasm.mark(target_loc.finalLoc(wasm)); } }