| ... | @@ -475,7 +475,7 @@ fn createSyntheticSymbol(wasm: *Wasm, name: []const u8, tag: Symbol.Tag) !Symbol | ... | @@ -475,7 +475,7 @@ fn createSyntheticSymbol(wasm: *Wasm, name: []const u8, tag: Symbol.Tag) !Symbol |
| 475 | .index = undefined, | 475 | .index = undefined, |
| 476 | }); | 476 | }); |
| 477 | try wasm.resolved_symbols.putNoClobber(wasm.base.allocator, loc, {}); | 477 | try wasm.resolved_symbols.putNoClobber(wasm.base.allocator, loc, {}); |
| 478 | try wasm.globals.putNoClobber(wasm.base.allocator, name_offset, loc); | 478 | try wasm.globals.put(wasm.base.allocator, name_offset, loc); |
| 479 | return loc; | 479 | return loc; |
| 480 | } | 480 | } |
| 481 | /// Initializes symbols and atoms for the debug sections | 481 | /// Initializes symbols and atoms for the debug sections |
| ... | @@ -851,6 +851,35 @@ fn validateFeatures( | ... | @@ -851,6 +851,35 @@ fn validateFeatures( |
| 851 | to_emit.* = allowed; | 851 | to_emit.* = allowed; |
| 852 | } | 852 | } |
| 853 | | 853 | |
| | 854 | /// Creates synthetic linker-symbols, but only if they are being referenced from |
| | 855 | /// any object file. For instance, the `__heap_base` symbol will only be created, |
| | 856 | /// if one or multiple undefined references exist. When none exist, the symbol will |
| | 857 | /// not be created, ensuring we don't unneccesarily emit unreferenced symbols. |
| | 858 | fn resolveLazySymbols(wasm: *Wasm) !void { |
| | 859 | if (wasm.undefs.fetchSwapRemove("__heap_base")) |kv| { |
| | 860 | const loc = try wasm.createSyntheticSymbol("__heap_base", .data); |
| | 861 | try wasm.discarded.putNoClobber(wasm.base.allocator, kv.value, loc); |
| | 862 | _ = wasm.resolved_symbols.swapRemove(loc); // we don't want to emit this symbol, only use it for relocations. |
| | 863 | |
| | 864 | const atom = try wasm.base.allocator.create(Atom); |
| | 865 | errdefer wasm.base.allocator.destroy(atom); |
| | 866 | try wasm.managed_atoms.append(wasm.base.allocator, atom); |
| | 867 | atom.* = Atom.empty; |
| | 868 | atom.sym_index = loc.index; |
| | 869 | atom.alignment = 1; |
| | 870 | |
| | 871 | try wasm.parseAtom(atom, .{ .data = .synthetic }); |
| | 872 | try wasm.symbol_atom.putNoClobber(wasm.base.allocator, loc, atom); |
| | 873 | } |
| | 874 | } |
| | 875 | |
| | 876 | // Tries to find a global symbol by its name. Returns null when not found, |
| | 877 | /// and its location when it is found. |
| | 878 | fn findGlobalSymbol(wasm: *Wasm, name: []const u8) ?SymbolLoc { |
| | 879 | const offset = wasm.string_table.getOffset(name) orelse return null; |
| | 880 | return wasm.globals.get(offset); |
| | 881 | } |
| | 882 | |
| 854 | fn checkUndefinedSymbols(wasm: *const Wasm) !void { | 883 | fn checkUndefinedSymbols(wasm: *const Wasm) !void { |
| 855 | if (wasm.base.options.output_mode == .Obj) return; | 884 | if (wasm.base.options.output_mode == .Obj) return; |
| 856 | if (wasm.base.options.import_symbols) return; | 885 | if (wasm.base.options.import_symbols) return; |
| ... | @@ -1458,14 +1487,13 @@ fn mapFunctionTable(wasm: *Wasm) void { | ... | @@ -1458,14 +1487,13 @@ fn mapFunctionTable(wasm: *Wasm) void { |
| 1458 | } | 1487 | } |
| 1459 | | 1488 | |
| 1460 | if (wasm.base.options.import_table or wasm.base.options.output_mode == .Obj) { | 1489 | if (wasm.base.options.import_table or wasm.base.options.output_mode == .Obj) { |
| 1461 | const sym_loc = wasm.globals.get(wasm.string_table.getOffset("__indirect_function_table").?).?; | 1490 | const sym_loc = wasm.findGlobalSymbol("__indirect_function_table").?; |
| 1462 | const import = wasm.imports.getPtr(sym_loc).?; | 1491 | const import = wasm.imports.getPtr(sym_loc).?; |
| 1463 | import.kind.table.limits.min = index - 1; // we start at index 1. | 1492 | import.kind.table.limits.min = index - 1; // we start at index 1. |
| 1464 | } else if (index > 1) { | 1493 | } else if (index > 1) { |
| 1465 | log.debug("Appending indirect function table", .{}); | 1494 | log.debug("Appending indirect function table", .{}); |
| 1466 | const offset = wasm.string_table.getOffset("__indirect_function_table").?; | 1495 | const sym_loc = wasm.findGlobalSymbol("__indirect_function_table").?; |
| 1467 | const sym_with_loc = wasm.globals.get(offset).?; | 1496 | const symbol = sym_loc.getSymbol(wasm); |
| 1468 | const symbol = sym_with_loc.getSymbol(wasm); | | |
| 1469 | const table = &wasm.tables.items[symbol.index - wasm.imported_tables_count]; | 1497 | const table = &wasm.tables.items[symbol.index - wasm.imported_tables_count]; |
| 1470 | table.limits = .{ .min = index, .max = index }; | 1498 | table.limits = .{ .min = index, .max = index }; |
| 1471 | } | 1499 | } |
| ... | @@ -1544,6 +1572,7 @@ const Kind = union(enum) { | ... | @@ -1544,6 +1572,7 @@ const Kind = union(enum) { |
| 1544 | read_only, | 1572 | read_only, |
| 1545 | uninitialized, | 1573 | uninitialized, |
| 1546 | initialized, | 1574 | initialized, |
| | 1575 | synthetic, |
| 1547 | }, | 1576 | }, |
| 1548 | function: FnData, | 1577 | function: FnData, |
| 1549 | | 1578 | |
| ... | @@ -1554,6 +1583,7 @@ const Kind = union(enum) { | ... | @@ -1554,6 +1583,7 @@ const Kind = union(enum) { |
| 1554 | .read_only => return ".rodata.", | 1583 | .read_only => return ".rodata.", |
| 1555 | .uninitialized => return ".bss.", | 1584 | .uninitialized => return ".bss.", |
| 1556 | .initialized => return ".data.", | 1585 | .initialized => return ".data.", |
| | 1586 | .synthetic => return ".synthetic", |
| 1557 | } | 1587 | } |
| 1558 | } | 1588 | } |
| 1559 | }; | 1589 | }; |
| ... | @@ -1690,9 +1720,14 @@ fn allocateAtoms(wasm: *Wasm) !void { | ... | @@ -1690,9 +1720,14 @@ fn allocateAtoms(wasm: *Wasm) !void { |
| 1690 | var offset: u32 = 0; | 1720 | var offset: u32 = 0; |
| 1691 | while (true) { | 1721 | while (true) { |
| 1692 | const symbol_loc = atom.symbolLoc(); | 1722 | const symbol_loc = atom.symbolLoc(); |
| 1693 | if (!wasm.resolved_symbols.contains(symbol_loc)) { | 1723 | if (wasm.code_section_index) |index| { |
| 1694 | atom = atom.next orelse break; | 1724 | if (index == entry.key_ptr.*) { |
| 1695 | continue; | 1725 | if (!wasm.resolved_symbols.contains(symbol_loc)) { |
| | 1726 | // only allocate resolved function body's. |
| | 1727 | atom = atom.next orelse break; |
| | 1728 | continue; |
| | 1729 | } |
| | 1730 | } |
| 1696 | } | 1731 | } |
| 1697 | offset = std.mem.alignForwardGeneric(u32, offset, atom.alignment); | 1732 | offset = std.mem.alignForwardGeneric(u32, offset, atom.alignment); |
| 1698 | atom.offset = offset; | 1733 | atom.offset = offset; |
| ... | @@ -1727,6 +1762,7 @@ fn sortDataSegments(wasm: *Wasm) !void { | ... | @@ -1727,6 +1762,7 @@ fn sortDataSegments(wasm: *Wasm) !void { |
| 1727 | if (mem.startsWith(u8, name, ".rodata")) return 0; | 1762 | if (mem.startsWith(u8, name, ".rodata")) return 0; |
| 1728 | if (mem.startsWith(u8, name, ".data")) return 1; | 1763 | if (mem.startsWith(u8, name, ".data")) return 1; |
| 1729 | if (mem.startsWith(u8, name, ".text")) return 2; | 1764 | if (mem.startsWith(u8, name, ".text")) return 2; |
| | 1765 | if (mem.startsWith(u8, name, ".synthetic")) return 100; // always at end |
| 1730 | return 3; | 1766 | return 3; |
| 1731 | } | 1767 | } |
| 1732 | }; | 1768 | }; |
| ... | @@ -1789,7 +1825,7 @@ fn initializeCallCtorsFunction(wasm: *Wasm) !void { | ... | @@ -1789,7 +1825,7 @@ fn initializeCallCtorsFunction(wasm: *Wasm) !void { |
| 1789 | if (wasm.code_section_index == null) { | 1825 | if (wasm.code_section_index == null) { |
| 1790 | // Make sure to remove it from the resolved symbols so we do not emit | 1826 | // Make sure to remove it from the resolved symbols so we do not emit |
| 1791 | // it within any section. TODO: Remove this once we implement garbage collection. | 1827 | // it within any section. TODO: Remove this once we implement garbage collection. |
| 1792 | const loc = wasm.globals.get(wasm.string_table.getOffset("__wasm_call_ctors").?).?; | 1828 | const loc = wasm.findGlobalSymbol("__wasm_call_ctors").?; |
| 1793 | std.debug.assert(wasm.resolved_symbols.swapRemove(loc)); | 1829 | std.debug.assert(wasm.resolved_symbols.swapRemove(loc)); |
| 1794 | return; | 1830 | return; |
| 1795 | } | 1831 | } |
| ... | @@ -1806,11 +1842,6 @@ fn initializeCallCtorsFunction(wasm: *Wasm) !void { | ... | @@ -1806,11 +1842,6 @@ fn initializeCallCtorsFunction(wasm: *Wasm) !void { |
| 1806 | // call constructors | 1842 | // call constructors |
| 1807 | for (wasm.init_funcs.items) |init_func_loc| { | 1843 | for (wasm.init_funcs.items) |init_func_loc| { |
| 1808 | const symbol = init_func_loc.getSymbol(wasm); | 1844 | const symbol = init_func_loc.getSymbol(wasm); |
| 1809 | if (symbol.isUndefined()) { | | |
| 1810 | std.debug.print("Undefined symbol '{s}'\n", .{wasm.string_table.get(symbol.name)}); | | |
| 1811 | } | | |
| 1812 | std.debug.print("Symbol: {s}\n", .{init_func_loc.getSymbolLoc().getName(wasm)}); | | |
| 1813 | std.debug.assert(wasm.resolved_symbols.contains(init_func_loc.getSymbolLoc().finalLoc(wasm))); | | |
| 1814 | const func = wasm.functions.values()[symbol.index - wasm.imported_functions_count]; | 1845 | const func = wasm.functions.values()[symbol.index - wasm.imported_functions_count]; |
| 1815 | const ty = wasm.func_types.items[func.type_index]; | 1846 | const ty = wasm.func_types.items[func.type_index]; |
| 1816 | | 1847 | |
| ... | @@ -1828,7 +1859,7 @@ fn initializeCallCtorsFunction(wasm: *Wasm) !void { | ... | @@ -1828,7 +1859,7 @@ fn initializeCallCtorsFunction(wasm: *Wasm) !void { |
| 1828 | try writer.writeByte(std.wasm.opcode(.end)); | 1859 | try writer.writeByte(std.wasm.opcode(.end)); |
| 1829 | } | 1860 | } |
| 1830 | | 1861 | |
| 1831 | const loc = wasm.globals.get(wasm.string_table.getOffset("__wasm_call_ctors").?).?; | 1862 | const loc = wasm.findGlobalSymbol("__wasm_call_ctors").?; |
| 1832 | const symbol = loc.getSymbol(wasm); | 1863 | const symbol = loc.getSymbol(wasm); |
| 1833 | // create type (() -> nil) as we do not have any parameters or return value. | 1864 | // create type (() -> nil) as we do not have any parameters or return value. |
| 1834 | const ty_index = try wasm.putOrGetFuncType(.{ .params = &[_]std.wasm.Valtype{}, .returns = &[_]std.wasm.Valtype{} }); | 1865 | const ty_index = try wasm.putOrGetFuncType(.{ .params = &[_]std.wasm.Valtype{}, .returns = &[_]std.wasm.Valtype{} }); |
| ... | @@ -2039,12 +2070,7 @@ fn setupExports(wasm: *Wasm) !void { | ... | @@ -2039,12 +2070,7 @@ fn setupExports(wasm: *Wasm) !void { |
| 2039 | var failed_exports = false; | 2070 | var failed_exports = false; |
| 2040 | | 2071 | |
| 2041 | for (force_exp_names) |exp_name| { | 2072 | for (force_exp_names) |exp_name| { |
| 2042 | const name_index = wasm.string_table.getOffset(exp_name) orelse { | 2073 | const loc = wasm.findGlobalSymbol(exp_name) orelse { |
| 2043 | log.err("could not export '{s}', symbol not found", .{exp_name}); | | |
| 2044 | failed_exports = true; | | |
| 2045 | continue; | | |
| 2046 | }; | | |
| 2047 | const loc = wasm.globals.get(name_index) orelse { | | |
| 2048 | log.err("could not export '{s}', symbol not found", .{exp_name}); | 2074 | log.err("could not export '{s}', symbol not found", .{exp_name}); |
| 2049 | failed_exports = true; | 2075 | failed_exports = true; |
| 2050 | continue; | 2076 | continue; |
| ... | @@ -2100,7 +2126,7 @@ fn setupExports(wasm: *Wasm) !void { | ... | @@ -2100,7 +2126,7 @@ fn setupExports(wasm: *Wasm) !void { |
| 2100 | fn setupStart(wasm: *Wasm) !void { | 2126 | fn setupStart(wasm: *Wasm) !void { |
| 2101 | const entry_name = wasm.base.options.entry orelse "_start"; | 2127 | const entry_name = wasm.base.options.entry orelse "_start"; |
| 2102 | | 2128 | |
| 2103 | const symbol_name_offset = wasm.string_table.getOffset(entry_name) orelse { | 2129 | const symbol_loc = wasm.findGlobalSymbol(entry_name) orelse { |
| 2104 | if (wasm.base.options.output_mode == .Exe) { | 2130 | if (wasm.base.options.output_mode == .Exe) { |
| 2105 | if (wasm.base.options.wasi_exec_model == .reactor) return; // Not required for reactors | 2131 | if (wasm.base.options.wasi_exec_model == .reactor) return; // Not required for reactors |
| 2106 | } else { | 2132 | } else { |
| ... | @@ -2110,10 +2136,6 @@ fn setupStart(wasm: *Wasm) !void { | ... | @@ -2110,10 +2136,6 @@ fn setupStart(wasm: *Wasm) !void { |
| 2110 | return error.MissingSymbol; | 2136 | return error.MissingSymbol; |
| 2111 | }; | 2137 | }; |
| 2112 | | 2138 | |
| 2113 | const symbol_loc = wasm.globals.get(symbol_name_offset) orelse { | | |
| 2114 | log.err("Entry symbol '{s}' not found", .{entry_name}); | | |
| 2115 | return error.MissingSymbol; | | |
| 2116 | }; | | |
| 2117 | const symbol = symbol_loc.getSymbol(wasm); | 2139 | const symbol = symbol_loc.getSymbol(wasm); |
| 2118 | if (symbol.tag != .function) { | 2140 | if (symbol.tag != .function) { |
| 2119 | log.err("Entry symbol '{s}' is not a function", .{entry_name}); | 2141 | log.err("Entry symbol '{s}' is not a function", .{entry_name}); |
| ... | @@ -2133,6 +2155,8 @@ fn setupMemory(wasm: *Wasm) !void { | ... | @@ -2133,6 +2155,8 @@ fn setupMemory(wasm: *Wasm) !void { |
| 2133 | // Use the user-provided stack size or else we use 1MB by default | 2155 | // Use the user-provided stack size or else we use 1MB by default |
| 2134 | const stack_size = wasm.base.options.stack_size_override orelse page_size * 16; | 2156 | const stack_size = wasm.base.options.stack_size_override orelse page_size * 16; |
| 2135 | const stack_alignment = 16; // wasm's stack alignment as specified by tool-convention | 2157 | const stack_alignment = 16; // wasm's stack alignment as specified by tool-convention |
| | 2158 | const heap_alignment = 16; // wasm's heap alignment as specified by tool-convention |
| | 2159 | |
| 2136 | // Always place the stack at the start by default | 2160 | // Always place the stack at the start by default |
| 2137 | // unless the user specified the global-base flag | 2161 | // unless the user specified the global-base flag |
| 2138 | var place_stack_first = true; | 2162 | var place_stack_first = true; |
| ... | @@ -2151,8 +2175,13 @@ fn setupMemory(wasm: *Wasm) !void { | ... | @@ -2151,8 +2175,13 @@ fn setupMemory(wasm: *Wasm) !void { |
| 2151 | } | 2175 | } |
| 2152 | | 2176 | |
| 2153 | var offset: u32 = @intCast(u32, memory_ptr); | 2177 | var offset: u32 = @intCast(u32, memory_ptr); |
| 2154 | for (wasm.data_segments.values()) |segment_index| { | 2178 | var data_seg_it = wasm.data_segments.iterator(); |
| 2155 | const segment = &wasm.segments.items[segment_index]; | 2179 | while (data_seg_it.next()) |entry| { |
| | 2180 | if (mem.eql(u8, entry.key_ptr.*, ".synthetic")) { |
| | 2181 | // do not update synthetic segments as they are not part of the output |
| | 2182 | continue; |
| | 2183 | } |
| | 2184 | const segment = &wasm.segments.items[entry.value_ptr.*]; |
| 2156 | memory_ptr = std.mem.alignForwardGeneric(u64, memory_ptr, segment.alignment); | 2185 | memory_ptr = std.mem.alignForwardGeneric(u64, memory_ptr, segment.alignment); |
| 2157 | memory_ptr += segment.size; | 2186 | memory_ptr += segment.size; |
| 2158 | segment.offset = offset; | 2187 | segment.offset = offset; |
| ... | @@ -2165,6 +2194,16 @@ fn setupMemory(wasm: *Wasm) !void { | ... | @@ -2165,6 +2194,16 @@ fn setupMemory(wasm: *Wasm) !void { |
| 2165 | wasm.wasm_globals.items[0].init.i32_const = @bitCast(i32, @intCast(u32, memory_ptr)); | 2194 | wasm.wasm_globals.items[0].init.i32_const = @bitCast(i32, @intCast(u32, memory_ptr)); |
| 2166 | } | 2195 | } |
| 2167 | | 2196 | |
| | 2197 | // One of the linked object files has a reference to the __heap_base symbol. |
| | 2198 | // We must set its virtual address so it can be used in relocations. |
| | 2199 | if (wasm.findGlobalSymbol("__heap_base")) |loc| { |
| | 2200 | const segment_index = wasm.data_segments.get(".synthetic").?; |
| | 2201 | const segment = &wasm.segments.items[segment_index]; |
| | 2202 | segment.offset = 0; // for simplicity we store the entire VA into atom's offset. |
| | 2203 | const atom = wasm.symbol_atom.get(loc).?; |
| | 2204 | atom.offset = @intCast(u32, mem.alignForwardGeneric(u64, memory_ptr, heap_alignment)); |
| | 2205 | } |
| | 2206 | |
| 2168 | // Setup the max amount of pages | 2207 | // Setup the max amount of pages |
| 2169 | // For now we only support wasm32 by setting the maximum allowed memory size 2^32-1 | 2208 | // For now we only support wasm32 by setting the maximum allowed memory size 2^32-1 |
| 2170 | const max_memory_allowed: u64 = (1 << 32) - 1; | 2209 | const max_memory_allowed: u64 = (1 << 32) - 1; |
| ... | @@ -2666,6 +2705,7 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l | ... | @@ -2666,6 +2705,7 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l |
| 2666 | var enabled_features: [@typeInfo(types.Feature.Tag).Enum.fields.len]bool = undefined; | 2705 | var enabled_features: [@typeInfo(types.Feature.Tag).Enum.fields.len]bool = undefined; |
| 2667 | try wasm.validateFeatures(&enabled_features, &emit_features_count); | 2706 | try wasm.validateFeatures(&enabled_features, &emit_features_count); |
| 2668 | try wasm.resolveSymbolsInArchives(); | 2707 | try wasm.resolveSymbolsInArchives(); |
| | 2708 | try wasm.resolveLazySymbols(); |
| 2669 | try wasm.checkUndefinedSymbols(); | 2709 | try wasm.checkUndefinedSymbols(); |
| 2670 | | 2710 | |
| 2671 | try wasm.setupInitFunctions(); | 2711 | try wasm.setupInitFunctions(); |
| ... | @@ -2749,6 +2789,7 @@ pub fn flushModule(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod | ... | @@ -2749,6 +2789,7 @@ pub fn flushModule(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod |
| 2749 | var enabled_features: [@typeInfo(types.Feature.Tag).Enum.fields.len]bool = undefined; | 2789 | var enabled_features: [@typeInfo(types.Feature.Tag).Enum.fields.len]bool = undefined; |
| 2750 | try wasm.validateFeatures(&enabled_features, &emit_features_count); | 2790 | try wasm.validateFeatures(&enabled_features, &emit_features_count); |
| 2751 | try wasm.resolveSymbolsInArchives(); | 2791 | try wasm.resolveSymbolsInArchives(); |
| | 2792 | try wasm.resolveLazySymbols(); |
| 2752 | try wasm.checkUndefinedSymbols(); | 2793 | try wasm.checkUndefinedSymbols(); |
| 2753 | | 2794 | |
| 2754 | // When we finish/error we reset the state of the linker | 2795 | // When we finish/error we reset the state of the linker |
| ... | @@ -2992,7 +3033,7 @@ fn writeToFile( | ... | @@ -2992,7 +3033,7 @@ fn writeToFile( |
| 2992 | if (wasm.function_table.count() > 0) { | 3033 | if (wasm.function_table.count() > 0) { |
| 2993 | const header_offset = try reserveVecSectionHeader(&binary_bytes); | 3034 | const header_offset = try reserveVecSectionHeader(&binary_bytes); |
| 2994 | | 3035 | |
| 2995 | const table_loc = wasm.globals.get(wasm.string_table.getOffset("__indirect_function_table").?).?; | 3036 | const table_loc = wasm.findGlobalSymbol("__indirect_function_table").?; |
| 2996 | const table_sym = table_loc.getSymbol(wasm); | 3037 | const table_sym = table_loc.getSymbol(wasm); |
| 2997 | | 3038 | |
| 2998 | var flags: u32 = if (table_sym.index == 0) 0x0 else 0x02; // passive with implicit 0-index table or set table index manually | 3039 | var flags: u32 = if (table_sym.index == 0) 0x0 else 0x02; // passive with implicit 0-index table or set table index manually |
| ... | @@ -3031,10 +3072,12 @@ fn writeToFile( | ... | @@ -3031,10 +3072,12 @@ fn writeToFile( |
| 3031 | defer sorted_atoms.deinit(); | 3072 | defer sorted_atoms.deinit(); |
| 3032 | | 3073 | |
| 3033 | while (true) { | 3074 | while (true) { |
| 3034 | if (!is_obj) { | 3075 | if (wasm.resolved_symbols.contains(atom.symbolLoc())) { |
| 3035 | atom.resolveRelocs(wasm); | 3076 | if (!is_obj) { |
| | 3077 | atom.resolveRelocs(wasm); |
| | 3078 | } |
| | 3079 | sorted_atoms.appendAssumeCapacity(atom); |
| 3036 | } | 3080 | } |
| 3037 | sorted_atoms.appendAssumeCapacity(atom); | | |
| 3038 | atom = atom.next orelse break; | 3081 | atom = atom.next orelse break; |
| 3039 | } | 3082 | } |
| 3040 | | 3083 | |
| ... | @@ -3075,10 +3118,11 @@ fn writeToFile( | ... | @@ -3075,10 +3118,11 @@ fn writeToFile( |
| 3075 | // do not output 'bss' section unless we import memory and therefore | 3118 | // do not output 'bss' section unless we import memory and therefore |
| 3076 | // want to guarantee the data is zero initialized | 3119 | // want to guarantee the data is zero initialized |
| 3077 | if (!import_memory and std.mem.eql(u8, entry.key_ptr.*, ".bss")) continue; | 3120 | if (!import_memory and std.mem.eql(u8, entry.key_ptr.*, ".bss")) continue; |
| 3078 | segment_count += 1; | | |
| 3079 | const atom_index = entry.value_ptr.*; | 3121 | const atom_index = entry.value_ptr.*; |
| 3080 | var atom: *Atom = wasm.atoms.getPtr(atom_index).?.*.getFirst(); | | |
| 3081 | const segment = wasm.segments.items[atom_index]; | 3122 | const segment = wasm.segments.items[atom_index]; |
| | 3123 | if (segment.size == 0) continue; // do not emit empty segments |
| | 3124 | segment_count += 1; |
| | 3125 | var atom: *Atom = wasm.atoms.getPtr(atom_index).?.*.getFirst(); |
| 3082 | | 3126 | |
| 3083 | // flag and index to memory section (currently, there can only be 1 memory section in wasm) | 3127 | // flag and index to memory section (currently, there can only be 1 memory section in wasm) |
| 3084 | try leb.writeULEB128(binary_writer, @as(u32, 0)); | 3128 | try leb.writeULEB128(binary_writer, @as(u32, 0)); |