diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig index ffe6fd4e8ae5708dbecc3ebc3d565de2cd775e6e..8dc5fbcc14160160dc0c1b9d0c66d3a3ef3cc4de 100644 --- a/src/link/Wasm.zig +++ b/src/link/Wasm.zig @@ -1778,14 +1778,16 @@ pub const ObjectDataImport = extern struct { __zig_error_name_table, __zig_tag_names, __zig_tag_name_table, + __global_base, __heap_base, __heap_end, + __wasm_first_page_end, /// Next, an `ObjectData.Index`. /// Next, index into `uavs_obj` or `uavs_exe` depending on whether emitting an object. /// Next, index into `navs_obj` or `navs_exe` depending on whether emitting an object. _, - const first_object = @backingInt(Resolution.__heap_end) + 1; + const first_object = @backingInt(Resolution.__wasm_first_page_end) + 1; pub const Unpacked = union(enum) { unresolved, @@ -1793,8 +1795,10 @@ pub const ObjectDataImport = extern struct { __zig_error_name_table, __zig_tag_names, __zig_tag_name_table, + __global_base, __heap_base, __heap_end, + __wasm_first_page_end, object: ObjectData.Index, uav_exe: UavsExeIndex, uav_obj: UavsObjIndex, @@ -1809,8 +1813,10 @@ pub const ObjectDataImport = extern struct { .__zig_error_name_table => .__zig_error_name_table, .__zig_tag_names => .__zig_tag_names, .__zig_tag_name_table => .__zig_tag_name_table, + .__global_base => .__global_base, .__heap_base => .__heap_base, .__heap_end => .__heap_end, + .__wasm_first_page_end => .__wasm_first_page_end, _ => { const object_index = @backingInt(r) - first_object; @@ -1847,8 +1853,10 @@ pub const ObjectDataImport = extern struct { .__zig_error_name_table => .__zig_error_name_table, .__zig_tag_names => .__zig_tag_names, .__zig_tag_name_table => .__zig_tag_name_table, + .__global_base => .__global_base, .__heap_base => .__heap_base, .__heap_end => .__heap_end, + .__wasm_first_page_end => .__wasm_first_page_end, .object => |i| @fromBackingInt(@intCast(first_object + @backingInt(i))), inline .uav_exe, .uav_obj => |i| @fromBackingInt(@intCast(first_object + wasm.object_datas.items.len + @backingInt(i))), .nav_exe => |i| @fromBackingInt(@intCast(first_object + wasm.object_datas.items.len + wasm.uavs_exe.entries.len + @backingInt(i))), @@ -1886,8 +1894,10 @@ pub const ObjectDataImport = extern struct { .__zig_error_name_table, .__zig_tag_names, .__zig_tag_name_table, + .__global_base, .__heap_base, .__heap_end, + .__wasm_first_page_end, .uav_exe, .uav_obj, .nav_exe, @@ -1910,8 +1920,11 @@ pub const ObjectDataImport = extern struct { .__zig_error_name_table => .{ .segment = .__zig_error_name_table, .offset = 0 }, .__zig_tag_names => .{ .segment = .__zig_tag_names, .offset = 0 }, .__zig_tag_name_table => .{ .segment = .__zig_tag_name_table, .offset = 0 }, - .__heap_base => .{ .segment = .__heap_base, .offset = 0 }, - .__heap_end => .{ .segment = .__heap_end, .offset = 0 }, + .__global_base, + .__heap_base, + .__heap_end, + .__wasm_first_page_end, + => unreachable, .uav_exe => |i| .{ .segment = .pack(wasm, .{ .uav_exe = i }), .offset = 0 }, .uav_obj => |i| .{ .segment = .pack(wasm, .{ .uav_obj = i }), .offset = 0 }, .nav_exe => |i| .{ .segment = .pack(wasm, .{ .nav_exe = i }), .offset = 0 }, @@ -1927,8 +1940,10 @@ pub const ObjectDataImport = extern struct { .__zig_tag_names, .__zig_tag_name_table, => .{ .binding = .local }, + .__global_base, .__heap_base, .__heap_end, + .__wasm_first_page_end, => unreachable, .object => |i| i.ptr(wasm).flags, inline .nav_exe, .nav_obj => |i| { @@ -1976,8 +1991,10 @@ pub const ObjectDataImport = extern struct { .__zig_error_name_table => @tagName(.__zig_error_name_table), .__zig_tag_names => @tagName(.__zig_tag_names), .__zig_tag_name_table => @tagName(.__zig_tag_name_table), + .__global_base => @tagName(.__global_base), .__heap_base => @tagName(.__heap_base), .__heap_end => @tagName(.__heap_end), + .__wasm_first_page_end => @tagName(.__wasm_first_page_end), inline .uav_exe, .uav_obj => |i| std.fmt.bufPrint( buf, "__anon_{d}", @@ -2006,7 +2023,7 @@ pub const ObjectDataImport = extern struct { const elem_size = Zcu.Type.slice_const_u8_sentinel_0.abiSize(zcu); return @intCast(table_len * elem_size); }, - .__heap_base, .__heap_end => wasm.pointerSize(), + .__global_base, .__heap_base, .__heap_end, .__wasm_first_page_end => 0, .object => |i| i.ptr(wasm).size, inline .uav_exe, .uav_obj, .nav_exe, .nav_obj => |i| i.value(wasm).code.len, }; @@ -2056,17 +2073,12 @@ pub const DataSegmentId = enum(u32) { __zig_tag_names, /// All tag name slices for all `@tagName` implementations, concatenated together. __zig_tag_name_table, - /// This and `__heap_end` are better retrieved via a global, but there is - /// some suboptimal code out there (wasi libc) that additionally needs them - /// as data symbols. - __heap_base, - __heap_end, /// First, an `ObjectDataSegment.Index`. /// Next, index into `uavs_obj` or `uavs_exe` depending on whether emitting an object. /// Next, index into `navs_obj` or `navs_exe` depending on whether emitting an object. _, - const first_object = @backingInt(DataSegmentId.__heap_end) + 1; + const first_object = @backingInt(DataSegmentId.__zig_tag_name_table) + 1; pub const Category = enum { /// Thread-local variables. @@ -2083,8 +2095,6 @@ pub const DataSegmentId = enum(u32) { __zig_error_name_table, __zig_tag_names, __zig_tag_name_table, - __heap_base, - __heap_end, object: ObjectDataSegment.Index, uav_exe: UavsExeIndex, uav_obj: UavsObjIndex, @@ -2098,8 +2108,6 @@ pub const DataSegmentId = enum(u32) { .__zig_error_name_table => .__zig_error_name_table, .__zig_tag_names => .__zig_tag_names, .__zig_tag_name_table => .__zig_tag_name_table, - .__heap_base => .__heap_base, - .__heap_end => .__heap_end, .object => |i| @fromBackingInt(@intCast(first_object + @backingInt(i))), inline .uav_exe, .uav_obj => |i| @fromBackingInt(@intCast(first_object + wasm.object_data_segments.items.len + @backingInt(i))), .nav_exe => |i| @fromBackingInt(@intCast(first_object + wasm.object_data_segments.items.len + wasm.uavs_exe.entries.len + @backingInt(i))), @@ -2113,8 +2121,6 @@ pub const DataSegmentId = enum(u32) { .__zig_error_name_table => .__zig_error_name_table, .__zig_tag_names => .__zig_tag_names, .__zig_tag_name_table => .__zig_tag_name_table, - .__heap_base => .__heap_base, - .__heap_end => .__heap_end, _ => { const object_index = @backingInt(id) - first_object; @@ -2164,8 +2170,6 @@ pub const DataSegmentId = enum(u32) { .__zig_error_name_table, .__zig_tag_names, .__zig_tag_name_table, - .__heap_base, - .__heap_end, => .data, .object => |i| { @@ -2192,8 +2196,6 @@ pub const DataSegmentId = enum(u32) { .__zig_error_name_table, .__zig_tag_names, .__zig_tag_name_table, - .__heap_base, - .__heap_end, => false, .object => |i| i.ptr(wasm).flags.tls, @@ -2213,8 +2215,6 @@ pub const DataSegmentId = enum(u32) { .__zig_error_name_table, .__zig_tag_name_table, - .__heap_base, - .__heap_end, => false, .object => |i| i.ptr(wasm).flags.strings, @@ -2229,8 +2229,6 @@ pub const DataSegmentId = enum(u32) { .__zig_error_name_table, .__zig_tag_names, .__zig_tag_name_table, - .__heap_base, - .__heap_end, => false, .object => |i| i.ptr(wasm).flags.retain, @@ -2251,8 +2249,6 @@ pub const DataSegmentId = enum(u32) { .__zig_tag_name_table, .uav_exe, .uav_obj, - .__heap_base, - .__heap_end, => ".data", .object => |i| i.ptr(wasm).name.unwrap().?.slice(wasm), @@ -2272,7 +2268,7 @@ pub const DataSegmentId = enum(u32) { pub fn alignment(id: DataSegmentId, wasm: *const Wasm) Alignment { return switch (unpack(id, wasm)) { .__zig_error_names, .__zig_tag_names => .@"1", - .__zig_error_name_table, .__zig_tag_name_table, .__heap_base, .__heap_end => wasm.pointerAlignment(), + .__zig_error_name_table, .__zig_tag_name_table => wasm.pointerAlignment(), .object => |i| i.ptr(wasm).flags.alignment, inline .uav_exe, .uav_obj => |i| { const zcu = wasm.base.comp.zcu.?; @@ -2304,7 +2300,7 @@ pub const DataSegmentId = enum(u32) { .__zig_error_name_table => wasm.error_name_table_ref_count, .__zig_tag_names => @intCast(wasm.tag_name_offs.items.len), .__zig_tag_name_table => wasm.tag_name_table_ref_count, - .object, .uav_obj, .nav_obj, .__heap_base, .__heap_end => 0, + .object, .uav_obj, .nav_obj => 0, inline .uav_exe, .nav_exe => |i| i.value(wasm).count, }; } @@ -2317,8 +2313,6 @@ pub const DataSegmentId = enum(u32) { .__zig_error_name_table, .__zig_tag_names, .__zig_tag_name_table, - .__heap_base, - .__heap_end, => false, .object => |i| i.ptr(wasm).flags.is_passive, @@ -2332,8 +2326,6 @@ pub const DataSegmentId = enum(u32) { .__zig_error_name_table, .__zig_tag_names, .__zig_tag_name_table, - .__heap_base, - .__heap_end, => false, .object => |i| i.ptr(wasm).payload.off == .none, @@ -2359,7 +2351,6 @@ pub const DataSegmentId = enum(u32) { const elem_size = Zcu.Type.slice_const_u8_sentinel_0.abiSize(zcu); return @intCast(table_len * elem_size); }, - .__heap_base, .__heap_end => wasm.pointerSize(), .object => |i| i.ptr(wasm).payload.len, inline .uav_exe, .uav_obj, .nav_exe, .nav_obj => |i| i.value(wasm).code.len, }; @@ -2491,6 +2482,7 @@ pub const Func = extern struct { /// Type reflection is used on the field names to autopopulate each field /// during initialization. const PreloadedStrings = struct { + __global_base: String, __heap_base: String, __heap_end: String, __indirect_function_table: String, @@ -2504,6 +2496,7 @@ const PreloadedStrings = struct { __wasm_init_memory: String, __wasm_init_memory_flag: String, __wasm_init_tls: String, + __wasm_first_page_end: String, __zig_error_names: String, __zig_error_name_table: String, __zig_errors_len: String, @@ -3907,21 +3900,11 @@ pub fn prelink(wasm: *Wasm, prog_node: std.Progress.Node) link.Error!void { try markFunctionImport(wasm, name, import, @fromBackingInt(@intCast(i))); } } - // Also treat init functions as roots. - for (wasm.object_init_funcs.items) |init_func| { - const func = init_func.function_index.ptr(wasm); - if (func.object_index.ptr(wasm).is_included) { - try markFunction(wasm, init_func.function_index, false); - } - } - wasm.functions_end_prelink = @intCast(wasm.functions.entries.len); - for (wasm.object_global_imports.keys(), wasm.object_global_imports.values(), 0..) |name, *import, i| { if (import.flags.isIncluded(rdynamic, is_obj)) { try markGlobalImport(wasm, name, import, @fromBackingInt(@intCast(i))); } } - wasm.globals_end_prelink = @intCast(wasm.globals.entries.len); wasm.global_exports_len = @intCast(wasm.global_exports.items.len); for (wasm.object_table_imports.keys(), wasm.object_table_imports.values(), 0..) |name, *import, i| { @@ -3944,6 +3927,8 @@ pub fn prelink(wasm: *Wasm, prog_node: std.Progress.Node) link.Error!void { wasm.memories.limits.flags.has_max = wasm.memories.limits.flags.has_max or memory_import.limits_has_max; } + wasm.functions_end_prelink = @intCast(wasm.functions.entries.len); + wasm.globals_end_prelink = @intCast(wasm.globals.entries.len); wasm.function_imports_len_prelink = @intCast(wasm.function_imports.entries.len); wasm.data_imports_len_prelink = @intCast(wasm.data_imports.entries.len); } @@ -3998,7 +3983,7 @@ fn markFunction(wasm: *Wasm, i: ObjectFunctionIndex, override_export: bool) link const rdynamic = comp.config.rdynamic; const is_obj = comp.config.output_mode == .Obj; const function = i.ptr(wasm); - markObject(wasm, function.object_index); + try markObject(wasm, function.object_index); if (!is_obj and (override_export or function.flags.isExported(rdynamic))) { const symbol_name = function.name.unwrap().?; @@ -4012,8 +3997,15 @@ fn markFunction(wasm: *Wasm, i: ObjectFunctionIndex, override_export: bool) link try wasm.markRelocations(function.relocations(wasm)); } -fn markObject(wasm: *Wasm, i: ObjectIndex) void { - i.ptr(wasm).is_included = true; +fn markObject(wasm: *Wasm, i: ObjectIndex) link.Error!void { + const object = i.ptr(wasm); + if (object.is_included) return; + object.is_included = true; + + const init_funcs = wasm.object_init_funcs.items[object.init_funcs.off..][0..object.init_funcs.len]; + for (init_funcs) |init_func| { + try markFunction(wasm, init_func.function_index, false); + } } /// Recursively mark alive everything referenced by the global. @@ -4076,6 +4068,7 @@ fn markGlobal(wasm: *Wasm, i: ObjectGlobalIndex, override_export: bool) link.Err const rdynamic = comp.config.rdynamic; const is_obj = comp.config.output_mode == .Obj; const global = i.ptr(wasm); + try markObject(wasm, global.object_index); if (!is_obj and (override_export or global.flags.isExported(rdynamic))) try wasm.global_exports.append(gpa, .{ .name = global.name.unwrap().?, @@ -4122,6 +4115,7 @@ fn markDataSegment(wasm: *Wasm, segment_index: ObjectDataSegment.Index) link.Err const segment = segment_index.ptr(wasm); if (segment.flags.alive) return; segment.flags.alive = true; + try markObject(wasm, segment.object_index); wasm.any_passive_inits = wasm.any_passive_inits or segment.flags.is_passive or (comp.config.import_memory and !wasm.isBss(segment.name)); @@ -4143,16 +4137,16 @@ pub fn markDataImport( const gpa = comp.gpa; const is_obj = comp.config.output_mode == .Obj; - try wasm.data_segments.ensureUnusedCapacity(gpa, 1); - if (import.resolution == .unresolved) { if (!is_obj) { - if (name == wasm.preloaded_strings.__heap_base) { + if (name == wasm.preloaded_strings.__global_base) { + import.resolution = .__global_base; + } else if (name == wasm.preloaded_strings.__heap_base) { import.resolution = .__heap_base; - wasm.data_segments.putAssumeCapacity(.__heap_base, {}); } else if (name == wasm.preloaded_strings.__heap_end) { import.resolution = .__heap_end; - wasm.data_segments.putAssumeCapacity(.__heap_end, {}); + } else if (name == wasm.preloaded_strings.__wasm_first_page_end) { + import.resolution = .__wasm_first_page_end; } else { try wasm.data_imports.put(gpa, name, .fromObject(data_index, wasm)); } @@ -4857,6 +4851,17 @@ pub fn uavAddr(wasm: *const Wasm, ip_index: InternPool.Index) u32 { return wasm.flush_buffer.data_segments.get(ds_id).?; } +pub fn syntheticDataAddr(wasm: *const Wasm, resolution: ObjectDataImport.Resolution) ?u32 { + const virtual_addrs = wasm.flush_buffer.virtual_addrs; + return switch (resolution.unpack(wasm)) { + .__global_base => virtual_addrs.global_base, + .__heap_base => virtual_addrs.heap_base, + .__heap_end => virtual_addrs.heap_end, + .__wasm_first_page_end => virtual_addrs.wasm_first_page_end, + else => null, + }; +} + /// Asserts it is called after `Flush.data_segments` is fully populated and sorted. pub fn navAddr(wasm: *const Wasm, nav_index: InternPool.Nav.Index) u32 { assert(wasm.flush_buffer.memory_layout_finished); @@ -4881,8 +4886,11 @@ pub fn navAddr(wasm: *const Wasm, nav_index: InternPool.Nav.Index) u32 { const segment_base_addr = wasm.flush_buffer.data_segments.get(ds_id).?; return segment_base_addr + object_data.offset; }, + .__global_base, .__heap_base, .__heap_end, + .__wasm_first_page_end, + => return wasm.syntheticDataAddr(import.resolution).?, .uav_exe, .nav_exe, => { diff --git a/src/link/Wasm/Flush.zig b/src/link/Wasm/Flush.zig index 5420c8758d551801cd740bee80dda14e45f1a7a8..0c259d404407d396e80ceaf329bf69a0abf055cf 100644 --- a/src/link/Wasm/Flush.zig +++ b/src/link/Wasm/Flush.zig @@ -41,6 +41,7 @@ data_imports: std.array_hash_map.Auto(String, Wasm.DataImportId) = .empty, data_exports: std.array_hash_map.Auto(String, DataExportSymbol) = .empty, indirect_function_table: std.array_hash_map.Auto(Wasm.OutputFunctionIndex, void) = .empty, +sorted_init_funcs: std.ArrayList(Wasm.InitFunc) = .empty, /// A subset of the full interned function type list created only during flush. func_types: std.array_hash_map.Auto(Wasm.FunctionType.Index, void) = .empty, @@ -53,6 +54,8 @@ data_relocs: std.ArrayList(Relocation) = .empty, /// For debug purposes only. memory_layout_finished: bool = false, +virtual_addrs: VirtualAddrs = undefined, + /// Index into `func_types`. pub const FuncTypeIndex = enum(u32) { _, @@ -201,11 +204,13 @@ pub fn clear(f: *Flush) void { f.function_export_symbols.clearRetainingCapacity(); f.data_exports.clearRetainingCapacity(); f.indirect_function_table.clearRetainingCapacity(); + f.sorted_init_funcs.clearRetainingCapacity(); f.func_types.clearRetainingCapacity(); f.enum_tag_name_table.clearRetainingCapacity(); f.code_relocs.clearRetainingCapacity(); f.data_relocs.clearRetainingCapacity(); f.memory_layout_finished = false; + f.virtual_addrs = undefined; } pub fn deinit(f: *Flush, gpa: Allocator) void { @@ -220,6 +225,7 @@ pub fn deinit(f: *Flush, gpa: Allocator) void { f.data_imports.deinit(gpa); f.data_exports.deinit(gpa); f.indirect_function_table.deinit(gpa); + f.sorted_init_funcs.deinit(gpa); f.func_types.deinit(gpa); f.enum_tag_name_table.deinit(gpa); f.code_relocs.deinit(gpa); @@ -542,9 +548,15 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { for (wasm.object_indirect_function_set.keys()) |object_function_index| f.indirect_function_table.putAssumeCapacity(.fromObjectFunction(wasm, object_function_index), {}); - if (wasm.object_init_funcs.items.len > 0) { + try f.sorted_init_funcs.ensureUnusedCapacity(gpa, wasm.object_init_funcs.items.len); + for (wasm.object_init_funcs.items) |init_func| { + const func = init_func.function_index.ptr(wasm); + if (!func.object_index.ptr(wasm).is_included) continue; + f.sorted_init_funcs.appendAssumeCapacity(init_func); + } + if (f.sorted_init_funcs.items.len > 0) { // Zig has no constructors so these are only for object file inputs. - mem.sortUnstable(Wasm.InitFunc, wasm.object_init_funcs.items, {}, Wasm.InitFunc.lessThan); + mem.sortUnstable(Wasm.InitFunc, f.sorted_init_funcs.items, {}, Wasm.InitFunc.lessThan); if (!is_obj) try wasm.functions.put(gpa, .__wasm_call_ctors, {}); } @@ -703,10 +715,13 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { // Always place the stack at the start by default unless the user specified the global-base flag. const place_stack_first, var memory_ptr: u64 = if (wasm.global_base) |base| .{ false, base } else .{ true, 0 }; - var virtual_addrs: VirtualAddrs = .{ + const virtual_addrs = &f.virtual_addrs; + virtual_addrs.* = .{ + .global_base = undefined, .stack_pointer = undefined, .heap_base = undefined, .heap_end = undefined, + .wasm_first_page_end = page_size, .tls_base = null, .tls_align = .none, .tls_size = null, @@ -719,10 +734,12 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { virtual_addrs.stack_pointer = @intCast(memory_ptr); } + const data_vaddr: u32 = @intCast(memory_ptr); + virtual_addrs.global_base = data_vaddr; + const segment_ids = f.data_segments.keys(); const segment_vaddrs = f.data_segments.values(); assert(f.data_segment_groups.items.len == 0); - const data_vaddr: u32 = @intCast(memory_ptr); if (segment_ids.len > 0) { var seen_tls: enum { before, during, after } = .before; var category: Wasm.DataSegmentId.Category = undefined; @@ -1165,7 +1182,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { .__wasm_init_memory => { const code_start = try reserveSize(gpa, binary_bytes); defer replaceSize(binary_bytes, code_start); - try emitInitMemoryFunction(wasm, binary_bytes, &virtual_addrs); + try emitInitMemoryFunction(wasm, binary_bytes); }, .__wasm_init_tls => { const code_start = try reserveSize(gpa, binary_bytes); @@ -1327,14 +1344,6 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { const output_offset: u32 = @intCast(binary_bytes.items.len - section_offset); append: { const code = switch (segment_id.unpack(wasm)) { - .__heap_base => { - mem.writeInt(u32, try binary_bytes.addManyAsArray(gpa, 4), virtual_addrs.heap_base, .little); - break :append; - }, - .__heap_end => { - mem.writeInt(u32, try binary_bytes.addManyAsArray(gpa, 4), virtual_addrs.heap_end, .little); - break :append; - }, .__zig_error_names => { try binary_bytes.appendSlice(gpa, wasm.error_name_bytes.items); break :append; @@ -1643,22 +1652,9 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { const sub_offset = try reserveCustomSectionHeader(gpa, binary_bytes); defer replaceHeader(binary_bytes, sub_offset, @backingInt(Object.SubsectionType.init_funcs)); - const init_funcs = wasm.object_init_funcs.items; - const total_functions: u32 = b: { - var cnt: u32 = 0; - for (init_funcs) |init_func| { - const func = init_func.function_index.ptr(wasm); - if (!func.object_index.ptr(wasm).is_included) continue; - cnt += 1; - } - break :b cnt; - }; - try appendLeb128(gpa, binary_bytes, total_functions); - - for (init_funcs) |init_func| { - const func = init_func.function_index.ptr(wasm); - if (!func.object_index.ptr(wasm).is_included) continue; + try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(f.sorted_init_funcs.items.len))); + for (f.sorted_init_funcs.items) |init_func| { try appendLeb128(gpa, binary_bytes, init_func.priority); const out_index: Wasm.OutputFunctionIndex = .fromObjectFunction(wasm, init_func.function_index); const symbol_index: u32 = symbol_table_offsets.function + @backingInt(out_index); @@ -1736,9 +1732,11 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { } const VirtualAddrs = struct { + global_base: u32, stack_pointer: u32, heap_base: u32, heap_end: u32, + wasm_first_page_end: u32, tls_base: ?u32, tls_align: Alignment, tls_size: ?u32, @@ -2587,6 +2585,9 @@ const RelocAddr = struct { const flush = &wasm.flush_buffer; if (wasm.object_data_imports.getPtr(name)) |import| { if (import.resolution != .unresolved) { + if (wasm.syntheticDataAddr(import.resolution)) |addr| { + return fromAddr(addr, addend); + } return fromDataLoc(flush, import.resolution.dataLoc(wasm), addend); } } @@ -2600,8 +2601,11 @@ const RelocAddr = struct { } fn fromDataLoc(flush: *const Flush, data_loc: Wasm.DataLoc, addend: i32) RelocAddr { - const base_addr: i64 = flush.data_segments.get(data_loc.segment).?; - return .{ .addr = @intCast(base_addr + data_loc.offset + addend) }; + return fromAddr(flush.data_segments.get(data_loc.segment).? + data_loc.offset, addend); + } + + fn fromAddr(addr: u32, addend: i32) RelocAddr { + return .{ .addr = @intCast(@as(i64, addr) + addend) }; } }; @@ -2643,9 +2647,8 @@ fn emitCallCtorsFunction(wasm: *const Wasm, binary_bytes: *ArrayList(u8)) Alloca try binary_bytes.ensureUnusedCapacity(gpa, 5 + 1); appendReservedUleb32(binary_bytes, 0); // no locals - for (wasm.object_init_funcs.items) |init_func| { + for (wasm.flush_buffer.sorted_init_funcs.items) |init_func| { const func = init_func.function_index.ptr(wasm); - if (!func.object_index.ptr(wasm).is_included) continue; const ty = func.type_index.ptr(wasm); const n_returns = ty.returns.slice(wasm).len; @@ -2662,14 +2665,11 @@ fn emitCallCtorsFunction(wasm: *const Wasm, binary_bytes: *ArrayList(u8)) Alloca binary_bytes.appendAssumeCapacity(@backingInt(std.wasm.Opcode.end)); // end function body } -fn emitInitMemoryFunction( - wasm: *const Wasm, - binary_bytes: *ArrayList(u8), - virtual_addrs: *const VirtualAddrs, -) Allocator.Error!void { +fn emitInitMemoryFunction(wasm: *const Wasm, binary_bytes: *ArrayList(u8)) Allocator.Error!void { const comp = wasm.base.comp; const gpa = comp.gpa; const shared_memory = comp.config.shared_memory; + const virtual_addrs = &wasm.flush_buffer.virtual_addrs; // Passive segments are used to avoid memory being reinitialized on each // thread's instantiation. These passive segments are initialized and