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)...@@ -4120,14 +4120,3 @@ pub fn codegenFailTypeMsg(zcu: *Zcu, ty_index: InternPool.Index, msg: *ErrorMsg)
4120 zcu.failed_types.putAssumeCapacityNoClobber(ty_index, msg);4120 zcu.failed_types.putAssumeCapacityNoClobber(ty_index, msg);
4121 return error.CodegenFail;4121 return error.CodegenFail;
4122}4122}
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 {...@@ -1025,10 +1025,9 @@ fn emitWValue(cg: *CodeGen, value: WValue) InnerError!void {
1025 const comp = wasm.base.comp;1025 const comp = wasm.base.comp;
1026 const zcu = comp.zcu.?;1026 const zcu = comp.zcu.?;
1027 const ip = &zcu.intern_pool;1027 const ip = &zcu.intern_pool;
1028 const ip_index = ip.getNav(nav_ref.nav_index).status.fully_resolved.val;1028 if (ip.getNav(nav_ref.nav_index).isExternOrFn(ip)) {
1029 if (ip.isFunctionType(ip.typeOf(ip_index))) {
1030 assert(nav_ref.offset == 0);1029 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);
1032 if (!gop.found_existing) gop.value_ptr.* = {};1031 if (!gop.found_existing) gop.value_ptr.* = {};
1033 try cg.addInst(.{1032 try cg.addInst(.{
1034 .tag = .func_ref,1033 .tag = .func_ref,
...@@ -1056,7 +1055,8 @@ fn emitWValue(cg: *CodeGen, value: WValue) InnerError!void {...@@ -1056,7 +1055,8 @@ fn emitWValue(cg: *CodeGen, value: WValue) InnerError!void {
1056 const ip = &zcu.intern_pool;1055 const ip = &zcu.intern_pool;
1057 if (ip.isFunctionType(ip.typeOf(uav.ip_index))) {1056 if (ip.isFunctionType(ip.typeOf(uav.ip_index))) {
1058 assert(uav.offset == 0);1057 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);
1060 if (!gop.found_existing) gop.value_ptr.* = {};1060 if (!gop.found_existing) gop.value_ptr.* = {};
1061 try cg.addInst(.{1061 try cg.addInst(.{
1062 .tag = .func_ref,1062 .tag = .func_ref,
...@@ -3096,7 +3096,7 @@ fn lowerPtr(cg: *CodeGen, ptr_val: InternPool.Index, prev_offset: u64) InnerErro...@@ -3096,7 +3096,7 @@ fn lowerPtr(cg: *CodeGen, ptr_val: InternPool.Index, prev_offset: u64) InnerErro
3096 const ptr = zcu.intern_pool.indexToKey(ptr_val).ptr;3096 const ptr = zcu.intern_pool.indexToKey(ptr_val).ptr;
3097 const offset: u64 = prev_offset + ptr.byte_offset;3097 const offset: u64 = prev_offset + ptr.byte_offset;
3098 return switch (ptr.base_addr) {3098 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) } },
3100 .uav => |uav| return .{ .uav_ref = .{ .ip_index = uav.val, .offset = @intCast(offset) } },3100 .uav => |uav| return .{ .uav_ref = .{ .ip_index = uav.val, .offset = @intCast(offset) } },
3101 .int => return cg.lowerConstant(try pt.intValue(Type.usize, offset), Type.usize),3101 .int => return cg.lowerConstant(try pt.intValue(Type.usize, offset), Type.usize),
3102 .eu_payload => return cg.fail("Wasm TODO: lower error union payload pointer", .{}),3102 .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...@@ -260,7 +260,7 @@ table_imports: std.AutoArrayHashMapUnmanaged(String, TableImport.Index) = .empty
260260
261/// All functions that have had their address taken and therefore might be261/// All functions that have had their address taken and therefore might be
262/// called via a `call_indirect` function.262/// 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
265error_name_table_ref_count: u32 = 0,265error_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 {...@@ -651,8 +651,8 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
651 try leb.writeUleb128(binary_writer, @as(u8, 0)); // represents funcref651 try leb.writeUleb128(binary_writer, @as(u8, 0)); // represents funcref
652 }652 }
653 try leb.writeUleb128(binary_writer, @as(u32, @intCast(wasm.indirect_function_table.entries.len)));653 try leb.writeUleb128(binary_writer, @as(u32, @intCast(wasm.indirect_function_table.entries.len)));
654 for (wasm.indirect_function_table.keys()) |ip_index| {654 for (wasm.indirect_function_table.keys()) |nav_index| {
655 const func_index: Wasm.OutputFunctionIndex = .fromIpIndex(wasm, ip_index);655 const func_index: Wasm.OutputFunctionIndex = .fromIpNav(wasm, nav_index);
656 try leb.writeUleb128(binary_writer, @intFromEnum(func_index));656 try leb.writeUleb128(binary_writer, @intFromEnum(func_index));
657 }657 }
658658