authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-01-08 17:01:36-08:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-01-15 15:11:36-08:00
log21a28885615dd9ea168c003caa65ff80a145eab7
treedda19b3dabcfb3864d38e43abdb259a90dd34968
parent5186c6c4ee520f7f1c87134d45cd7a33f8b2aaea

wasm linker: don't assume nav callees are fully resolved

codegen can be called which contains calls to navs which have only their type resolved. this means the indirect function table needs to track nav indexes not ip indexes.

4 files changed, 8 insertions(+), 19 deletions(-)

src/Zcu.zig-11
......@@ -4120,14 +4120,3 @@ pub fn codegenFailTypeMsg(zcu: *Zcu, ty_index: InternPool.Index, msg: *ErrorMsg)
41204120 zcu.failed_types.putAssumeCapacityNoClobber(ty_index, msg);
41214121 return error.CodegenFail;
41224122}
4123
4124/// Check if nav is an alias to a function, in which case we want to lower the
4125/// actual nav, rather than the alias itself.
4126pub fn chaseNav(zcu: *const Zcu, nav: InternPool.Nav.Index) InternPool.Nav.Index {
4127 return switch (zcu.intern_pool.indexToKey(zcu.navValue(nav).toIntern())) {
4128 .func => |f| f.owner_nav,
4129 .variable => |variable| variable.owner_nav,
4130 .@"extern" => |@"extern"| @"extern".owner_nav,
4131 else => nav,
4132 };
4133}
src/arch/wasm/CodeGen.zig+5-5
......@@ -1025,10 +1025,9 @@ fn emitWValue(cg: *CodeGen, value: WValue) InnerError!void {
10251025 const comp = wasm.base.comp;
10261026 const zcu = comp.zcu.?;
10271027 const ip = &zcu.intern_pool;
1028 const ip_index = ip.getNav(nav_ref.nav_index).status.fully_resolved.val;
1029 if (ip.isFunctionType(ip.typeOf(ip_index))) {
1028 if (ip.getNav(nav_ref.nav_index).isExternOrFn(ip)) {
10301029 assert(nav_ref.offset == 0);
1031 const gop = try wasm.indirect_function_table.getOrPut(comp.gpa, ip_index);
1030 const gop = try wasm.indirect_function_table.getOrPut(comp.gpa, nav_ref.nav_index);
10321031 if (!gop.found_existing) gop.value_ptr.* = {};
10331032 try cg.addInst(.{
10341033 .tag = .func_ref,
......@@ -1056,7 +1055,8 @@ fn emitWValue(cg: *CodeGen, value: WValue) InnerError!void {
10561055 const ip = &zcu.intern_pool;
10571056 if (ip.isFunctionType(ip.typeOf(uav.ip_index))) {
10581057 assert(uav.offset == 0);
1059 const gop = try wasm.indirect_function_table.getOrPut(comp.gpa, uav.ip_index);
1058 const owner_nav = ip.toFunc(uav.ip_index).owner_nav;
1059 const gop = try wasm.indirect_function_table.getOrPut(comp.gpa, owner_nav);
10601060 if (!gop.found_existing) gop.value_ptr.* = {};
10611061 try cg.addInst(.{
10621062 .tag = .func_ref,
......@@ -3096,7 +3096,7 @@ fn lowerPtr(cg: *CodeGen, ptr_val: InternPool.Index, prev_offset: u64) InnerErro
30963096 const ptr = zcu.intern_pool.indexToKey(ptr_val).ptr;
30973097 const offset: u64 = prev_offset + ptr.byte_offset;
30983098 return switch (ptr.base_addr) {
3099 .nav => |nav| return .{ .nav_ref = .{ .nav_index = zcu.chaseNav(nav), .offset = @intCast(offset) } },
3099 .nav => |nav| return .{ .nav_ref = .{ .nav_index = nav, .offset = @intCast(offset) } },
31003100 .uav => |uav| return .{ .uav_ref = .{ .ip_index = uav.val, .offset = @intCast(offset) } },
31013101 .int => return cg.lowerConstant(try pt.intValue(Type.usize, offset), Type.usize),
31023102 .eu_payload => return cg.fail("Wasm TODO: lower error union payload pointer", .{}),
src/link/Wasm.zig+1-1
......@@ -260,7 +260,7 @@ table_imports: std.AutoArrayHashMapUnmanaged(String, TableImport.Index) = .empty
260260
261261/// All functions that have had their address taken and therefore might be
262262/// called via a `call_indirect` function.
263indirect_function_table: std.AutoArrayHashMapUnmanaged(InternPool.Index, void) = .empty,
263indirect_function_table: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, void) = .empty,
264264
265265error_name_table_ref_count: u32 = 0,
266266
src/link/Wasm/Flush.zig+2-2
......@@ -651,8 +651,8 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
651651 try leb.writeUleb128(binary_writer, @as(u8, 0)); // represents funcref
652652 }
653653 try leb.writeUleb128(binary_writer, @as(u32, @intCast(wasm.indirect_function_table.entries.len)));
654 for (wasm.indirect_function_table.keys()) |ip_index| {
655 const func_index: Wasm.OutputFunctionIndex = .fromIpIndex(wasm, ip_index);
654 for (wasm.indirect_function_table.keys()) |nav_index| {
655 const func_index: Wasm.OutputFunctionIndex = .fromIpNav(wasm, nav_index);
656656 try leb.writeUleb128(binary_writer, @intFromEnum(func_index));
657657 }
658658