| author | |
| committer | |
| log | a327d238f1fa6c79ac8254785082b8ffb54945f0 |
| tree | da521e3f1e3cce70072f0bf6fc07eefa2d474d84 |
| parent | d999a8e33b75a6ddd477cc71d8f682fe703496eb |
3 files changed, 52 insertions(+), 15 deletions(-)
src/codegen.zig+25-12| ... | ... | @@ -738,19 +738,32 @@ fn lowerNavRef( |
| 738 | 738 | dev.check(link.File.Tag.wasm.devFeature()); |
| 739 | 739 | const wasm = lf.cast(.wasm).?; |
| 740 | 740 | assert(reloc_parent == .none); |
| 741 | if (is_obj) { | |
| 742 | try wasm.out_relocs.append(gpa, .{ | |
| 743 | .offset = @intCast(code.items.len), | |
| 744 | .pointee = .{ .symbol_index = try wasm.navSymbolIndex(nav_index) }, | |
| 745 | .tag = if (ptr_width_bytes == 4) .memory_addr_i32 else .memory_addr_i64, | |
| 746 | .addend = @intCast(offset), | |
| 747 | }); | |
| 741 | if (is_fn_body) { | |
| 742 | const gop = try wasm.zcu_indirect_function_set.getOrPut(gpa, nav_index); | |
| 743 | if (!gop.found_existing) gop.value_ptr.* = {}; | |
| 744 | if (is_obj) { | |
| 745 | @panic("TODO add out_reloc for this"); | |
| 746 | } else { | |
| 747 | try wasm.func_table_fixups.append(gpa, .{ | |
| 748 | .table_index = @enumFromInt(gop.index), | |
| 749 | .offset = @intCast(code.items.len), | |
| 750 | }); | |
| 751 | } | |
| 748 | 752 | } else { |
| 749 | try wasm.nav_fixups.ensureUnusedCapacity(gpa, 1); | |
| 750 | wasm.nav_fixups.appendAssumeCapacity(.{ | |
| 751 | .navs_exe_index = try wasm.refNavExe(nav_index), | |
| 752 | .offset = @intCast(code.items.len), | |
| 753 | }); | |
| 753 | if (is_obj) { | |
| 754 | try wasm.out_relocs.append(gpa, .{ | |
| 755 | .offset = @intCast(code.items.len), | |
| 756 | .pointee = .{ .symbol_index = try wasm.navSymbolIndex(nav_index) }, | |
| 757 | .tag = if (ptr_width_bytes == 4) .memory_addr_i32 else .memory_addr_i64, | |
| 758 | .addend = @intCast(offset), | |
| 759 | }); | |
| 760 | } else { | |
| 761 | try wasm.nav_fixups.ensureUnusedCapacity(gpa, 1); | |
| 762 | wasm.nav_fixups.appendAssumeCapacity(.{ | |
| 763 | .navs_exe_index = try wasm.refNavExe(nav_index), | |
| 764 | .offset = @intCast(code.items.len), | |
| 765 | }); | |
| 766 | } | |
| 754 | 767 | } |
| 755 | 768 | code.appendNTimesAssumeCapacity(0, ptr_width_bytes); |
| 756 | 769 | return; |
src/link/Wasm.zig+14-3| ... | ... | @@ -151,7 +151,11 @@ uav_fixups: std.ArrayListUnmanaged(UavFixup) = .empty, |
| 151 | 151 | /// List of locations within `string_bytes` that must be patched with the virtual |
| 152 | 152 | /// memory address of a Nav during `flush`. |
| 153 | 153 | /// When emitting an object file, `out_relocs` is used instead. |
| 154 | /// No functions here only global variables. | |
| 154 | 155 | nav_fixups: std.ArrayListUnmanaged(NavFixup) = .empty, |
| 156 | /// When a nav reference is a function pointer, this tracks the required function | |
| 157 | /// table entry index that needs to overwrite the code in the final output. | |
| 158 | func_table_fixups: std.ArrayListUnmanaged(FuncTableFixup) = .empty, | |
| 155 | 159 | /// Symbols to be emitted into an object file. Remains empty when not emitting |
| 156 | 160 | /// an object file. |
| 157 | 161 | symbol_table: std.AutoArrayHashMapUnmanaged(String, void) = .empty, |
| ... | ... | @@ -307,6 +311,12 @@ pub const NavFixup = extern struct { |
| 307 | 311 | offset: u32, |
| 308 | 312 | }; |
| 309 | 313 | |
| 314 | pub const FuncTableFixup = extern struct { | |
| 315 | table_index: ZcuIndirectFunctionSetIndex, | |
| 316 | /// Index into `string_bytes`. | |
| 317 | offset: u32, | |
| 318 | }; | |
| 319 | ||
| 310 | 320 | /// Index into `objects`. |
| 311 | 321 | pub const ObjectIndex = enum(u32) { |
| 312 | 322 | _, |
| ... | ... | @@ -2208,7 +2218,7 @@ pub const FunctionImportId = enum(u32) { |
| 2208 | 2218 | pub fn pack(unpacked: Unpacked, wasm: *const Wasm) FunctionImportId { |
| 2209 | 2219 | return switch (unpacked) { |
| 2210 | 2220 | .object_function_import => |i| @enumFromInt(@intFromEnum(i)), |
| 2211 | .zcu_import => |i| @enumFromInt(@intFromEnum(i) - wasm.object_function_imports.entries.len), | |
| 2221 | .zcu_import => |i| @enumFromInt(@intFromEnum(i) + wasm.object_function_imports.entries.len), | |
| 2212 | 2222 | }; |
| 2213 | 2223 | } |
| 2214 | 2224 | |
| ... | ... | @@ -2295,7 +2305,7 @@ pub const GlobalImportId = enum(u32) { |
| 2295 | 2305 | pub fn pack(unpacked: Unpacked, wasm: *const Wasm) GlobalImportId { |
| 2296 | 2306 | return switch (unpacked) { |
| 2297 | 2307 | .object_global_import => |i| @enumFromInt(@intFromEnum(i)), |
| 2298 | .zcu_import => |i| @enumFromInt(@intFromEnum(i) - wasm.object_global_imports.entries.len), | |
| 2308 | .zcu_import => |i| @enumFromInt(@intFromEnum(i) + wasm.object_global_imports.entries.len), | |
| 2299 | 2309 | }; |
| 2300 | 2310 | } |
| 2301 | 2311 | |
| ... | ... | @@ -2360,7 +2370,7 @@ pub const DataImportId = enum(u32) { |
| 2360 | 2370 | pub fn pack(unpacked: Unpacked, wasm: *const Wasm) DataImportId { |
| 2361 | 2371 | return switch (unpacked) { |
| 2362 | 2372 | .object_data_import => |i| @enumFromInt(@intFromEnum(i)), |
| 2363 | .zcu_import => |i| @enumFromInt(@intFromEnum(i) - wasm.object_data_imports.entries.len), | |
| 2373 | .zcu_import => |i| @enumFromInt(@intFromEnum(i) + wasm.object_data_imports.entries.len), | |
| 2364 | 2374 | }; |
| 2365 | 2375 | } |
| 2366 | 2376 | |
| ... | ... | @@ -3027,6 +3037,7 @@ pub fn deinit(wasm: *Wasm) void { |
| 3027 | 3037 | wasm.out_relocs.deinit(gpa); |
| 3028 | 3038 | wasm.uav_fixups.deinit(gpa); |
| 3029 | 3039 | wasm.nav_fixups.deinit(gpa); |
| 3040 | wasm.func_table_fixups.deinit(gpa); | |
| 3030 | 3041 | |
| 3031 | 3042 | wasm.zcu_indirect_function_set.deinit(gpa); |
| 3032 | 3043 | wasm.object_indirect_function_import_set.deinit(gpa); |
src/link/Wasm/Flush.zig+13| ... | ... | @@ -54,6 +54,11 @@ const IndirectFunctionTableIndex = enum(u32) { |
| 54 | 54 | fn fromOutputFunctionIndex(f: *const Flush, i: Wasm.OutputFunctionIndex) IndirectFunctionTableIndex { |
| 55 | 55 | return @enumFromInt(f.indirect_function_table.getIndex(i).?); |
| 56 | 56 | } |
| 57 | ||
| 58 | fn fromZcuIndirectFunctionSetIndex(i: Wasm.ZcuIndirectFunctionSetIndex) IndirectFunctionTableIndex { | |
| 59 | // These are the same since those are added to the table first. | |
| 60 | return @enumFromInt(@intFromEnum(i)); | |
| 61 | } | |
| 57 | 62 | }; |
| 58 | 63 | |
| 59 | 64 | const DataSegmentGroup = struct { |
| ... | ... | @@ -755,6 +760,14 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { |
| 755 | 760 | mem.writeInt(u64, wasm.string_bytes.items[nav_fixup.offset..][0..8], vaddr, .little); |
| 756 | 761 | } |
| 757 | 762 | } |
| 763 | for (wasm.func_table_fixups.items) |fixup| { | |
| 764 | const table_index: IndirectFunctionTableIndex = .fromZcuIndirectFunctionSetIndex(fixup.table_index); | |
| 765 | if (!is64) { | |
| 766 | mem.writeInt(u32, wasm.string_bytes.items[fixup.offset..][0..4], @intFromEnum(table_index), .little); | |
| 767 | } else { | |
| 768 | mem.writeInt(u64, wasm.string_bytes.items[fixup.offset..][0..8], @intFromEnum(table_index), .little); | |
| 769 | } | |
| 770 | } | |
| 758 | 771 | } |
| 759 | 772 | |
| 760 | 773 | // Data section. |