| ... | @@ -468,6 +468,7 @@ fn createSyntheticSymbol(wasm: *Wasm, name: []const u8, tag: Symbol.Tag) !Symbol | ... | @@ -468,6 +468,7 @@ fn createSyntheticSymbol(wasm: *Wasm, name: []const u8, tag: Symbol.Tag) !Symbol |
| 468 | .flags = 0, | 468 | .flags = 0, |
| 469 | .tag = tag, | 469 | .tag = tag, |
| 470 | .index = undefined, | 470 | .index = undefined, |
| | 471 | .virtual_address = undefined, |
| 471 | }); | 472 | }); |
| 472 | try wasm.resolved_symbols.putNoClobber(wasm.base.allocator, loc, {}); | 473 | try wasm.resolved_symbols.putNoClobber(wasm.base.allocator, loc, {}); |
| 473 | try wasm.globals.put(wasm.base.allocator, name_offset, loc); | 474 | try wasm.globals.put(wasm.base.allocator, name_offset, loc); |
| ... | @@ -1011,6 +1012,7 @@ pub fn allocateSymbol(wasm: *Wasm) !u32 { | ... | @@ -1011,6 +1012,7 @@ pub fn allocateSymbol(wasm: *Wasm) !u32 { |
| 1011 | .flags = @enumToInt(Symbol.Flag.WASM_SYM_BINDING_LOCAL), | 1012 | .flags = @enumToInt(Symbol.Flag.WASM_SYM_BINDING_LOCAL), |
| 1012 | .tag = undefined, // will be set after updateDecl | 1013 | .tag = undefined, // will be set after updateDecl |
| 1013 | .index = undefined, // will be set after updateDecl | 1014 | .index = undefined, // will be set after updateDecl |
| | 1015 | .virtual_address = undefined, // will be set during atom allocation |
| 1014 | }; | 1016 | }; |
| 1015 | if (wasm.symbols_free_list.popOrNull()) |index| { | 1017 | if (wasm.symbols_free_list.popOrNull()) |index| { |
| 1016 | wasm.symbols.items[index] = symbol; | 1018 | wasm.symbols.items[index] = symbol; |
| ... | @@ -1246,6 +1248,7 @@ pub fn lowerUnnamedConst(wasm: *Wasm, tv: TypedValue, decl_index: Module.Decl.In | ... | @@ -1246,6 +1248,7 @@ pub fn lowerUnnamedConst(wasm: *Wasm, tv: TypedValue, decl_index: Module.Decl.In |
| 1246 | .flags = @enumToInt(Symbol.Flag.WASM_SYM_BINDING_LOCAL), | 1248 | .flags = @enumToInt(Symbol.Flag.WASM_SYM_BINDING_LOCAL), |
| 1247 | .tag = .data, | 1249 | .tag = .data, |
| 1248 | .index = undefined, | 1250 | .index = undefined, |
| | 1251 | .virtual_address = undefined, |
| 1249 | }; | 1252 | }; |
| 1250 | try wasm.resolved_symbols.putNoClobber(wasm.base.allocator, atom.symbolLoc(), {}); | 1253 | try wasm.resolved_symbols.putNoClobber(wasm.base.allocator, atom.symbolLoc(), {}); |
| 1251 | | 1254 | |
| ... | @@ -1292,6 +1295,7 @@ pub fn getGlobalSymbol(wasm: *Wasm, name: []const u8) !u32 { | ... | @@ -1292,6 +1295,7 @@ pub fn getGlobalSymbol(wasm: *Wasm, name: []const u8) !u32 { |
| 1292 | .flags = 0, | 1295 | .flags = 0, |
| 1293 | .index = undefined, // index to type will be set after merging function symbols | 1296 | .index = undefined, // index to type will be set after merging function symbols |
| 1294 | .tag = .function, | 1297 | .tag = .function, |
| | 1298 | .virtual_address = undefined, |
| 1295 | }; | 1299 | }; |
| 1296 | symbol.setGlobal(true); | 1300 | symbol.setGlobal(true); |
| 1297 | symbol.setUndefined(true); | 1301 | symbol.setUndefined(true); |
| ... | @@ -1788,6 +1792,30 @@ fn allocateAtoms(wasm: *Wasm) !void { | ... | @@ -1788,6 +1792,30 @@ fn allocateAtoms(wasm: *Wasm) !void { |
| 1788 | } | 1792 | } |
| 1789 | } | 1793 | } |
| 1790 | | 1794 | |
| | 1795 | /// For each data symbol, sets the virtual address. |
| | 1796 | fn allocateVirtualAddresses(wasm: *Wasm) void { |
| | 1797 | for (wasm.resolved_symbols.keys()) |loc| { |
| | 1798 | const symbol = loc.getSymbol(wasm); |
| | 1799 | if (symbol.tag != .data) { |
| | 1800 | continue; // only data symbols have virtual addresses |
| | 1801 | } |
| | 1802 | const atom_index = wasm.symbol_atom.get(loc) orelse { |
| | 1803 | // synthetic symbol that does not contain an atom |
| | 1804 | continue; |
| | 1805 | }; |
| | 1806 | |
| | 1807 | const atom = wasm.getAtom(atom_index); |
| | 1808 | const merge_segment = wasm.base.options.output_mode != .Obj; |
| | 1809 | const segment_info = if (atom.file) |object_index| blk: { |
| | 1810 | break :blk wasm.objects.items[object_index].segment_info; |
| | 1811 | } else wasm.segment_info.values(); |
| | 1812 | const segment_name = segment_info[symbol.index].outputName(merge_segment); |
| | 1813 | const segment_index = wasm.data_segments.get(segment_name).?; |
| | 1814 | const segment = wasm.segments.items[segment_index]; |
| | 1815 | symbol.virtual_address = atom.offset + segment.offset; |
| | 1816 | } |
| | 1817 | } |
| | 1818 | |
| 1791 | fn sortDataSegments(wasm: *Wasm) !void { | 1819 | fn sortDataSegments(wasm: *Wasm) !void { |
| 1792 | var new_mapping: std.StringArrayHashMapUnmanaged(u32) = .{}; | 1820 | var new_mapping: std.StringArrayHashMapUnmanaged(u32) = .{}; |
| 1793 | try new_mapping.ensureUnusedCapacity(wasm.base.allocator, wasm.data_segments.count()); | 1821 | try new_mapping.ensureUnusedCapacity(wasm.base.allocator, wasm.data_segments.count()); |
| ... | @@ -2137,13 +2165,10 @@ fn setupExports(wasm: *Wasm) !void { | ... | @@ -2137,13 +2165,10 @@ fn setupExports(wasm: *Wasm) !void { |
| 2137 | break :blk try wasm.string_table.put(wasm.base.allocator, sym_name); | 2165 | break :blk try wasm.string_table.put(wasm.base.allocator, sym_name); |
| 2138 | }; | 2166 | }; |
| 2139 | const exp: types.Export = if (symbol.tag == .data) exp: { | 2167 | const exp: types.Export = if (symbol.tag == .data) exp: { |
| 2140 | const atom_index = wasm.symbol_atom.get(sym_loc).?; | | |
| 2141 | const atom = wasm.getAtom(atom_index); | | |
| 2142 | const va = atom.getVA(wasm, symbol); | | |
| 2143 | const global_index = @intCast(u32, wasm.imported_globals_count + wasm.wasm_globals.items.len); | 2168 | const global_index = @intCast(u32, wasm.imported_globals_count + wasm.wasm_globals.items.len); |
| 2144 | try wasm.wasm_globals.append(wasm.base.allocator, .{ | 2169 | try wasm.wasm_globals.append(wasm.base.allocator, .{ |
| 2145 | .global_type = .{ .valtype = .i32, .mutable = false }, | 2170 | .global_type = .{ .valtype = .i32, .mutable = false }, |
| 2146 | .init = .{ .i32_const = @intCast(i32, va) }, | 2171 | .init = .{ .i32_const = @intCast(i32, symbol.virtual_address) }, |
| 2147 | }); | 2172 | }); |
| 2148 | break :exp .{ | 2173 | break :exp .{ |
| 2149 | .name = export_name, | 2174 | .name = export_name, |
| ... | @@ -2240,12 +2265,8 @@ fn setupMemory(wasm: *Wasm) !void { | ... | @@ -2240,12 +2265,8 @@ fn setupMemory(wasm: *Wasm) !void { |
| 2240 | // One of the linked object files has a reference to the __heap_base symbol. | 2265 | // One of the linked object files has a reference to the __heap_base symbol. |
| 2241 | // We must set its virtual address so it can be used in relocations. | 2266 | // We must set its virtual address so it can be used in relocations. |
| 2242 | if (wasm.findGlobalSymbol("__heap_base")) |loc| { | 2267 | if (wasm.findGlobalSymbol("__heap_base")) |loc| { |
| 2243 | const segment_index = wasm.data_segments.get(".synthetic").?; | 2268 | const symbol = loc.getSymbol(wasm); |
| 2244 | const segment = &wasm.segments.items[segment_index]; | 2269 | symbol.virtual_address = @intCast(u32, mem.alignForwardGeneric(u64, memory_ptr, heap_alignment)); |
| 2245 | segment.offset = 0; // for simplicity we store the entire VA into atom's offset. | | |
| 2246 | const atom_index = wasm.symbol_atom.get(loc).?; | | |
| 2247 | const atom = wasm.getAtomPtr(atom_index); | | |
| 2248 | atom.offset = @intCast(u32, mem.alignForwardGeneric(u64, memory_ptr, heap_alignment)); | | |
| 2249 | } | 2270 | } |
| 2250 | | 2271 | |
| 2251 | // Setup the max amount of pages | 2272 | // Setup the max amount of pages |
| ... | @@ -2274,12 +2295,8 @@ fn setupMemory(wasm: *Wasm) !void { | ... | @@ -2274,12 +2295,8 @@ fn setupMemory(wasm: *Wasm) !void { |
| 2274 | log.debug("Total memory pages: {d}", .{wasm.memories.limits.min}); | 2295 | log.debug("Total memory pages: {d}", .{wasm.memories.limits.min}); |
| 2275 | | 2296 | |
| 2276 | if (wasm.findGlobalSymbol("__heap_end")) |loc| { | 2297 | if (wasm.findGlobalSymbol("__heap_end")) |loc| { |
| 2277 | const segment_index = wasm.data_segments.get(".synthetic").?; | 2298 | const symbol = loc.getSymbol(wasm); |
| 2278 | const segment = &wasm.segments.items[segment_index]; | 2299 | symbol.virtual_address = @intCast(u32, memory_ptr); |
| 2279 | segment.offset = 0; | | |
| 2280 | const atom_index = wasm.symbol_atom.get(loc).?; | | |
| 2281 | const atom = wasm.getAtomPtr(atom_index); | | |
| 2282 | atom.offset = @intCast(u32, memory_ptr); | | |
| 2283 | } | 2300 | } |
| 2284 | | 2301 | |
| 2285 | if (wasm.base.options.max_memory) |max_memory| { | 2302 | if (wasm.base.options.max_memory) |max_memory| { |
| ... | @@ -2417,6 +2434,7 @@ pub fn getErrorTableSymbol(wasm: *Wasm) !u32 { | ... | @@ -2417,6 +2434,7 @@ pub fn getErrorTableSymbol(wasm: *Wasm) !u32 { |
| 2417 | .tag = .data, | 2434 | .tag = .data, |
| 2418 | .flags = 0, | 2435 | .flags = 0, |
| 2419 | .index = 0, | 2436 | .index = 0, |
| | 2437 | .virtual_address = undefined, |
| 2420 | }; | 2438 | }; |
| 2421 | symbol.setFlag(.WASM_SYM_VISIBILITY_HIDDEN); | 2439 | symbol.setFlag(.WASM_SYM_VISIBILITY_HIDDEN); |
| 2422 | | 2440 | |
| ... | @@ -2449,6 +2467,7 @@ fn populateErrorNameTable(wasm: *Wasm) !void { | ... | @@ -2449,6 +2467,7 @@ fn populateErrorNameTable(wasm: *Wasm) !void { |
| 2449 | .tag = .data, | 2467 | .tag = .data, |
| 2450 | .flags = 0, | 2468 | .flags = 0, |
| 2451 | .index = 0, | 2469 | .index = 0, |
| | 2470 | .virtual_address = undefined, |
| 2452 | }; | 2471 | }; |
| 2453 | names_symbol.setFlag(.WASM_SYM_VISIBILITY_HIDDEN); | 2472 | names_symbol.setFlag(.WASM_SYM_VISIBILITY_HIDDEN); |
| 2454 | | 2473 | |
| ... | @@ -2748,6 +2767,7 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l | ... | @@ -2748,6 +2767,7 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l |
| 2748 | | 2767 | |
| 2749 | try wasm.allocateAtoms(); | 2768 | try wasm.allocateAtoms(); |
| 2750 | try wasm.setupMemory(); | 2769 | try wasm.setupMemory(); |
| | 2770 | wasm.allocateVirtualAddresses(); |
| 2751 | wasm.mapFunctionTable(); | 2771 | wasm.mapFunctionTable(); |
| 2752 | try wasm.mergeSections(); | 2772 | try wasm.mergeSections(); |
| 2753 | try wasm.mergeTypes(); | 2773 | try wasm.mergeTypes(); |
| ... | @@ -2866,6 +2886,7 @@ pub fn flushModule(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod | ... | @@ -2866,6 +2886,7 @@ pub fn flushModule(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod |
| 2866 | | 2886 | |
| 2867 | try wasm.allocateAtoms(); | 2887 | try wasm.allocateAtoms(); |
| 2868 | try wasm.setupMemory(); | 2888 | try wasm.setupMemory(); |
| | 2889 | wasm.allocateVirtualAddresses(); |
| 2869 | wasm.mapFunctionTable(); | 2890 | wasm.mapFunctionTable(); |
| 2870 | try wasm.mergeSections(); | 2891 | try wasm.mergeSections(); |
| 2871 | try wasm.mergeTypes(); | 2892 | try wasm.mergeTypes(); |