| ... | @@ -2134,10 +2134,14 @@ const Kind = union(enum) { | ... | @@ -2134,10 +2134,14 @@ const Kind = union(enum) { |
| 2134 | fn parseAtom(wasm: *Wasm, atom_index: Atom.Index, kind: Kind) !void { | 2134 | fn parseAtom(wasm: *Wasm, atom_index: Atom.Index, kind: Kind) !void { |
| 2135 | const atom = wasm.getAtomPtr(atom_index); | 2135 | const atom = wasm.getAtomPtr(atom_index); |
| 2136 | const symbol = (SymbolLoc{ .file = null, .index = atom.sym_index }).getSymbol(wasm); | 2136 | const symbol = (SymbolLoc{ .file = null, .index = atom.sym_index }).getSymbol(wasm); |
| 2137 | if (symbol.isDead()) { | 2137 | const do_garbage_collect = wasm.base.options.gc_sections orelse |
| | 2138 | (wasm.base.options.output_mode != .Obj); |
| | 2139 | |
| | 2140 | if (symbol.isDead() and do_garbage_collect) { |
| 2138 | // Prevent unreferenced symbols from being parsed. | 2141 | // Prevent unreferenced symbols from being parsed. |
| 2139 | return; | 2142 | return; |
| 2140 | } | 2143 | } |
| | 2144 | |
| 2141 | const final_index: u32 = switch (kind) { | 2145 | const final_index: u32 = switch (kind) { |
| 2142 | .function => result: { | 2146 | .function => result: { |
| 2143 | const index: u32 = @intCast(wasm.functions.count() + wasm.imported_functions_count); | 2147 | const index: u32 = @intCast(wasm.functions.count() + wasm.imported_functions_count); |
| ... | @@ -2289,16 +2293,23 @@ fn allocateAtoms(wasm: *Wasm) !void { | ... | @@ -2289,16 +2293,23 @@ fn allocateAtoms(wasm: *Wasm) !void { |
| 2289 | if (sym.isDead()) { | 2293 | if (sym.isDead()) { |
| 2290 | // Dead symbols must be unlinked from the linked-list to prevent them | 2294 | // Dead symbols must be unlinked from the linked-list to prevent them |
| 2291 | // from being emit into the binary. | 2295 | // from being emit into the binary. |
| 2292 | if (atom.prev) |prev_index| { | 2296 | if (atom.next) |next_index| { |
| 2293 | const prev = wasm.getAtomPtr(prev_index); | 2297 | const next = wasm.getAtomPtr(next_index); |
| 2294 | prev.next = atom.next; | 2298 | next.prev = atom.prev; |
| | 2299 | } else if (entry.value_ptr.* == atom_index) { |
| | 2300 | // When the atom is dead and is also the first atom retrieved from wasm.atoms(index) we update |
| | 2301 | // the entry to point it to the previous atom to ensure we do not start with a dead symbol that |
| | 2302 | // was removed and therefore do not emit any code at all. |
| | 2303 | if (atom.prev) |prev| { |
| | 2304 | entry.value_ptr.* = prev; |
| | 2305 | } |
| 2295 | } | 2306 | } |
| 2296 | atom_index = atom.next orelse { | 2307 | atom_index = atom.prev orelse { |
| 2297 | atom.prev = null; | 2308 | atom.next = null; |
| 2298 | break; | 2309 | break; |
| 2299 | }; | 2310 | }; |
| 2300 | const next = wasm.getAtomPtr(atom_index); | 2311 | const prev = wasm.getAtomPtr(atom_index); |
| 2301 | next.prev = atom.prev; | 2312 | prev.next = atom.next; |
| 2302 | atom.prev = null; | 2313 | atom.prev = null; |
| 2303 | atom.next = null; | 2314 | atom.next = null; |
| 2304 | continue; | 2315 | continue; |
| ... | @@ -2787,6 +2798,7 @@ fn mergeSections(wasm: *Wasm) !void { | ... | @@ -2787,6 +2798,7 @@ fn mergeSections(wasm: *Wasm) !void { |
| 2787 | // We found an alias to the same function, discard this symbol in favor of | 2798 | // We found an alias to the same function, discard this symbol in favor of |
| 2788 | // the original symbol and point the discard function to it. This ensures | 2799 | // the original symbol and point the discard function to it. This ensures |
| 2789 | // we only emit a single function, instead of duplicates. | 2800 | // we only emit a single function, instead of duplicates. |
| | 2801 | symbol.unmark(); |
| 2790 | try wasm.discarded.putNoClobber( | 2802 | try wasm.discarded.putNoClobber( |
| 2791 | wasm.base.allocator, | 2803 | wasm.base.allocator, |
| 2792 | sym_loc, | 2804 | sym_loc, |
| ... | @@ -2815,7 +2827,6 @@ fn mergeSections(wasm: *Wasm) !void { | ... | @@ -2815,7 +2827,6 @@ fn mergeSections(wasm: *Wasm) !void { |
| 2815 | // For any removed duplicates, remove them from the resolved symbols list | 2827 | // For any removed duplicates, remove them from the resolved symbols list |
| 2816 | for (removed_duplicates.items) |sym_loc| { | 2828 | for (removed_duplicates.items) |sym_loc| { |
| 2817 | assert(wasm.resolved_symbols.swapRemove(sym_loc)); | 2829 | assert(wasm.resolved_symbols.swapRemove(sym_loc)); |
| 2818 | sym_loc.getSymbol(wasm).unmark(); | | |
| 2819 | } | 2830 | } |
| 2820 | | 2831 | |
| 2821 | log.debug("Merged ({d}) functions", .{wasm.functions.count()}); | 2832 | log.debug("Merged ({d}) functions", .{wasm.functions.count()}); |
| ... | @@ -3741,8 +3752,8 @@ fn writeToFile( | ... | @@ -3741,8 +3752,8 @@ fn writeToFile( |
| 3741 | binary_bytes.items, | 3752 | binary_bytes.items, |
| 3742 | header_offset, | 3753 | header_offset, |
| 3743 | .type, | 3754 | .type, |
| 3744 | @as(u32, @intCast(binary_bytes.items.len - header_offset - header_size)), | 3755 | @intCast(binary_bytes.items.len - header_offset - header_size), |
| 3745 | @as(u32, @intCast(wasm.func_types.items.len)), | 3756 | @intCast(wasm.func_types.items.len), |
| 3746 | ); | 3757 | ); |
| 3747 | section_count += 1; | 3758 | section_count += 1; |
| 3748 | } | 3759 | } |
| ... | @@ -3774,8 +3785,8 @@ fn writeToFile( | ... | @@ -3774,8 +3785,8 @@ fn writeToFile( |
| 3774 | binary_bytes.items, | 3785 | binary_bytes.items, |
| 3775 | header_offset, | 3786 | header_offset, |
| 3776 | .import, | 3787 | .import, |
| 3777 | @as(u32, @intCast(binary_bytes.items.len - header_offset - header_size)), | 3788 | @intCast(binary_bytes.items.len - header_offset - header_size), |
| 3778 | @as(u32, @intCast(wasm.imports.count() + @intFromBool(import_memory))), | 3789 | @intCast(wasm.imports.count() + @intFromBool(import_memory)), |
| 3779 | ); | 3790 | ); |
| 3780 | section_count += 1; | 3791 | section_count += 1; |
| 3781 | } | 3792 | } |
| ... | @@ -3791,8 +3802,8 @@ fn writeToFile( | ... | @@ -3791,8 +3802,8 @@ fn writeToFile( |
| 3791 | binary_bytes.items, | 3802 | binary_bytes.items, |
| 3792 | header_offset, | 3803 | header_offset, |
| 3793 | .function, | 3804 | .function, |
| 3794 | @as(u32, @intCast(binary_bytes.items.len - header_offset - header_size)), | 3805 | @intCast(binary_bytes.items.len - header_offset - header_size), |
| 3795 | @as(u32, @intCast(wasm.functions.count())), | 3806 | @intCast(wasm.functions.count()), |
| 3796 | ); | 3807 | ); |
| 3797 | section_count += 1; | 3808 | section_count += 1; |
| 3798 | } | 3809 | } |
| ... | @@ -3810,8 +3821,8 @@ fn writeToFile( | ... | @@ -3810,8 +3821,8 @@ fn writeToFile( |
| 3810 | binary_bytes.items, | 3821 | binary_bytes.items, |
| 3811 | header_offset, | 3822 | header_offset, |
| 3812 | .table, | 3823 | .table, |
| 3813 | @as(u32, @intCast(binary_bytes.items.len - header_offset - header_size)), | 3824 | @intCast(binary_bytes.items.len - header_offset - header_size), |
| 3814 | @as(u32, @intCast(wasm.tables.items.len)), | 3825 | @intCast(wasm.tables.items.len), |
| 3815 | ); | 3826 | ); |
| 3816 | section_count += 1; | 3827 | section_count += 1; |
| 3817 | } | 3828 | } |
| ... | @@ -3825,8 +3836,8 @@ fn writeToFile( | ... | @@ -3825,8 +3836,8 @@ fn writeToFile( |
| 3825 | binary_bytes.items, | 3836 | binary_bytes.items, |
| 3826 | header_offset, | 3837 | header_offset, |
| 3827 | .memory, | 3838 | .memory, |
| 3828 | @as(u32, @intCast(binary_bytes.items.len - header_offset - header_size)), | 3839 | @intCast(binary_bytes.items.len - header_offset - header_size), |
| 3829 | @as(u32, 1), // wasm currently only supports 1 linear memory segment | 3840 | 1, // wasm currently only supports 1 linear memory segment |
| 3830 | ); | 3841 | ); |
| 3831 | section_count += 1; | 3842 | section_count += 1; |
| 3832 | } | 3843 | } |
| ... | @@ -3845,8 +3856,8 @@ fn writeToFile( | ... | @@ -3845,8 +3856,8 @@ fn writeToFile( |
| 3845 | binary_bytes.items, | 3856 | binary_bytes.items, |
| 3846 | header_offset, | 3857 | header_offset, |
| 3847 | .global, | 3858 | .global, |
| 3848 | @as(u32, @intCast(binary_bytes.items.len - header_offset - header_size)), | 3859 | @intCast(binary_bytes.items.len - header_offset - header_size), |
| 3849 | @as(u32, @intCast(wasm.wasm_globals.items.len)), | 3860 | @intCast(wasm.wasm_globals.items.len), |
| 3850 | ); | 3861 | ); |
| 3851 | section_count += 1; | 3862 | section_count += 1; |
| 3852 | } | 3863 | } |
| ... | @@ -3874,8 +3885,8 @@ fn writeToFile( | ... | @@ -3874,8 +3885,8 @@ fn writeToFile( |
| 3874 | binary_bytes.items, | 3885 | binary_bytes.items, |
| 3875 | header_offset, | 3886 | header_offset, |
| 3876 | .@"export", | 3887 | .@"export", |
| 3877 | @as(u32, @intCast(binary_bytes.items.len - header_offset - header_size)), | 3888 | @intCast(binary_bytes.items.len - header_offset - header_size), |
| 3878 | @as(u32, @intCast(wasm.exports.items.len)) + @intFromBool(export_memory), | 3889 | @intCast(wasm.exports.items.len + @intFromBool(export_memory)), |
| 3879 | ); | 3890 | ); |
| 3880 | section_count += 1; | 3891 | section_count += 1; |
| 3881 | } | 3892 | } |
| ... | @@ -3918,8 +3929,8 @@ fn writeToFile( | ... | @@ -3918,8 +3929,8 @@ fn writeToFile( |
| 3918 | binary_bytes.items, | 3929 | binary_bytes.items, |
| 3919 | header_offset, | 3930 | header_offset, |
| 3920 | .element, | 3931 | .element, |
| 3921 | @as(u32, @intCast(binary_bytes.items.len - header_offset - header_size)), | 3932 | @intCast(binary_bytes.items.len - header_offset - header_size), |
| 3922 | @as(u32, 1), | 3933 | 1, |
| 3923 | ); | 3934 | ); |
| 3924 | section_count += 1; | 3935 | section_count += 1; |
| 3925 | } | 3936 | } |
| ... | @@ -3932,8 +3943,8 @@ fn writeToFile( | ... | @@ -3932,8 +3943,8 @@ fn writeToFile( |
| 3932 | binary_bytes.items, | 3943 | binary_bytes.items, |
| 3933 | header_offset, | 3944 | header_offset, |
| 3934 | .data_count, | 3945 | .data_count, |
| 3935 | @as(u32, @intCast(binary_bytes.items.len - header_offset - header_size)), | 3946 | @intCast(binary_bytes.items.len - header_offset - header_size), |
| 3936 | @as(u32, @intCast(data_segments_count)), | 3947 | @intCast(data_segments_count), |
| 3937 | ); | 3948 | ); |
| 3938 | } | 3949 | } |
| 3939 | | 3950 | |
| ... | @@ -3978,7 +3989,7 @@ fn writeToFile( | ... | @@ -3978,7 +3989,7 @@ fn writeToFile( |
| 3978 | header_offset, | 3989 | header_offset, |
| 3979 | .code, | 3990 | .code, |
| 3980 | code_section_size, | 3991 | code_section_size, |
| 3981 | @as(u32, @intCast(wasm.functions.count())), | 3992 | @intCast(wasm.functions.count()), |
| 3982 | ); | 3993 | ); |
| 3983 | code_section_index = section_count; | 3994 | code_section_index = section_count; |
| 3984 | section_count += 1; | 3995 | section_count += 1; |
| ... | @@ -4049,8 +4060,8 @@ fn writeToFile( | ... | @@ -4049,8 +4060,8 @@ fn writeToFile( |
| 4049 | binary_bytes.items, | 4060 | binary_bytes.items, |
| 4050 | header_offset, | 4061 | header_offset, |
| 4051 | .data, | 4062 | .data, |
| 4052 | @as(u32, @intCast(binary_bytes.items.len - header_offset - header_size)), | 4063 | @intCast(binary_bytes.items.len - header_offset - header_size), |
| 4053 | @as(u32, @intCast(segment_count)), | 4064 | @intCast(segment_count), |
| 4054 | ); | 4065 | ); |
| 4055 | data_section_index = section_count; | 4066 | data_section_index = section_count; |
| 4056 | section_count += 1; | 4067 | section_count += 1; |
| ... | @@ -4597,6 +4608,14 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) ! | ... | @@ -4597,6 +4608,14 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) ! |
| 4597 | try argv.append("--export-table"); | 4608 | try argv.append("--export-table"); |
| 4598 | } | 4609 | } |
| 4599 | | 4610 | |
| | 4611 | if (wasm.base.options.gc_sections) |gc| { |
| | 4612 | // For wasm-ld we only need to specify '--no-gc-sections' when the user explicitly |
| | 4613 | // specified it as garbage collection is enabled by default. |
| | 4614 | if (!gc) { |
| | 4615 | try argv.append("--no-gc-sections"); |
| | 4616 | } |
| | 4617 | } |
| | 4618 | |
| 4600 | if (wasm.base.options.strip) { | 4619 | if (wasm.base.options.strip) { |
| 4601 | try argv.append("-s"); | 4620 | try argv.append("-s"); |
| 4602 | } | 4621 | } |
| ... | @@ -4882,7 +4901,7 @@ fn emitLinkSection(wasm: *Wasm, binary_bytes: *std.ArrayList(u8), symbol_table: | ... | @@ -4882,7 +4901,7 @@ fn emitLinkSection(wasm: *Wasm, binary_bytes: *std.ArrayList(u8), symbol_table: |
| 4882 | try wasm.emitSymbolTable(binary_bytes, symbol_table); | 4901 | try wasm.emitSymbolTable(binary_bytes, symbol_table); |
| 4883 | try wasm.emitSegmentInfo(binary_bytes); | 4902 | try wasm.emitSegmentInfo(binary_bytes); |
| 4884 | | 4903 | |
| 4885 | const size = @as(u32, @intCast(binary_bytes.items.len - offset - 6)); | 4904 | const size: u32 = @intCast(binary_bytes.items.len - offset - 6); |
| 4886 | try writeCustomSectionHeader(binary_bytes.items, offset, size); | 4905 | try writeCustomSectionHeader(binary_bytes.items, offset, size); |
| 4887 | } | 4906 | } |
| 4888 | | 4907 | |
| ... | @@ -4930,7 +4949,7 @@ fn emitSymbolTable(wasm: *Wasm, binary_bytes: *std.ArrayList(u8), symbol_table: | ... | @@ -4930,7 +4949,7 @@ fn emitSymbolTable(wasm: *Wasm, binary_bytes: *std.ArrayList(u8), symbol_table: |
| 4930 | } | 4949 | } |
| 4931 | | 4950 | |
| 4932 | var buf: [10]u8 = undefined; | 4951 | var buf: [10]u8 = undefined; |
| 4933 | leb.writeUnsignedFixed(5, buf[0..5], @as(u32, @intCast(binary_bytes.items.len - table_offset + 5))); | 4952 | leb.writeUnsignedFixed(5, buf[0..5], @intCast(binary_bytes.items.len - table_offset + 5)); |
| 4934 | leb.writeUnsignedFixed(5, buf[5..], symbol_count); | 4953 | leb.writeUnsignedFixed(5, buf[5..], symbol_count); |
| 4935 | try binary_bytes.insertSlice(table_offset, &buf); | 4954 | try binary_bytes.insertSlice(table_offset, &buf); |
| 4936 | } | 4955 | } |
| ... | @@ -5013,7 +5032,7 @@ fn emitCodeRelocations( | ... | @@ -5013,7 +5032,7 @@ fn emitCodeRelocations( |
| 5013 | var buf: [5]u8 = undefined; | 5032 | var buf: [5]u8 = undefined; |
| 5014 | leb.writeUnsignedFixed(5, &buf, count); | 5033 | leb.writeUnsignedFixed(5, &buf, count); |
| 5015 | try binary_bytes.insertSlice(reloc_start, &buf); | 5034 | try binary_bytes.insertSlice(reloc_start, &buf); |
| 5016 | const size = @as(u32, @intCast(binary_bytes.items.len - header_offset - 6)); | 5035 | const size: u32 = @intCast(binary_bytes.items.len - header_offset - 6); |
| 5017 | try writeCustomSectionHeader(binary_bytes.items, header_offset, size); | 5036 | try writeCustomSectionHeader(binary_bytes.items, header_offset, size); |
| 5018 | } | 5037 | } |
| 5019 | | 5038 | |
| ... | @@ -5123,10 +5142,14 @@ pub fn storeDeclType(wasm: *Wasm, decl_index: InternPool.DeclIndex, func_type: s | ... | @@ -5123,10 +5142,14 @@ pub fn storeDeclType(wasm: *Wasm, decl_index: InternPool.DeclIndex, func_type: s |
| 5123 | fn markReferences(wasm: *Wasm) !void { | 5142 | fn markReferences(wasm: *Wasm) !void { |
| 5124 | const tracy = trace(@src()); | 5143 | const tracy = trace(@src()); |
| 5125 | defer tracy.end(); | 5144 | defer tracy.end(); |
| | 5145 | const do_garbage_collect = wasm.base.options.gc_sections orelse |
| | 5146 | (wasm.base.options.output_mode != .Obj); |
| | 5147 | |
| 5126 | for (wasm.resolved_symbols.keys()) |sym_loc| { | 5148 | for (wasm.resolved_symbols.keys()) |sym_loc| { |
| 5127 | const sym = sym_loc.getSymbol(wasm); | 5149 | const sym = sym_loc.getSymbol(wasm); |
| 5128 | if (sym.isExported(wasm.base.options.rdynamic) or sym.isNoStrip()) { | 5150 | if (sym.isExported(wasm.base.options.rdynamic) or sym.isNoStrip() or !do_garbage_collect) { |
| 5129 | try wasm.mark(sym_loc); | 5151 | try wasm.mark(sym_loc); |
| | 5152 | continue; |
| 5130 | } | 5153 | } |
| 5131 | | 5154 | |
| 5132 | // Debug sections may require to be parsed and marked when it contains | 5155 | // Debug sections may require to be parsed and marked when it contains |
| ... | @@ -5139,7 +5162,7 @@ fn markReferences(wasm: *Wasm) !void { | ... | @@ -5139,7 +5162,7 @@ fn markReferences(wasm: *Wasm) !void { |
| 5139 | for (atom.relocs.items) |reloc| { | 5162 | for (atom.relocs.items) |reloc| { |
| 5140 | const target_loc: SymbolLoc = .{ .index = reloc.index, .file = atom.file }; | 5163 | const target_loc: SymbolLoc = .{ .index = reloc.index, .file = atom.file }; |
| 5141 | const target_sym = target_loc.getSymbol(wasm); | 5164 | const target_sym = target_loc.getSymbol(wasm); |
| 5142 | if (target_sym.isAlive()) { | 5165 | if (target_sym.isAlive() or !do_garbage_collect) { |
| 5143 | sym.mark(); | 5166 | sym.mark(); |
| 5144 | continue; // Skip all other relocations as this debug atom is already marked now | 5167 | continue; // Skip all other relocations as this debug atom is already marked now |
| 5145 | } | 5168 | } |