Commit 21a2888561

Andrew Kelley <andrew@ziglang.org>
2025-01-09 02:01:36
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.
1 parent 5186c6c
Changed files (4)
src
src/arch/wasm/CodeGen.zig
@@ -1025,10 +1025,9 @@ fn emitWValue(cg: *CodeGen, value: WValue) InnerError!void {
             const comp = wasm.base.comp;
             const zcu = comp.zcu.?;
             const ip = &zcu.intern_pool;
-            const ip_index = ip.getNav(nav_ref.nav_index).status.fully_resolved.val;
-            if (ip.isFunctionType(ip.typeOf(ip_index))) {
+            if (ip.getNav(nav_ref.nav_index).isExternOrFn(ip)) {
                 assert(nav_ref.offset == 0);
-                const gop = try wasm.indirect_function_table.getOrPut(comp.gpa, ip_index);
+                const gop = try wasm.indirect_function_table.getOrPut(comp.gpa, nav_ref.nav_index);
                 if (!gop.found_existing) gop.value_ptr.* = {};
                 try cg.addInst(.{
                     .tag = .func_ref,
@@ -1056,7 +1055,8 @@ fn emitWValue(cg: *CodeGen, value: WValue) InnerError!void {
             const ip = &zcu.intern_pool;
             if (ip.isFunctionType(ip.typeOf(uav.ip_index))) {
                 assert(uav.offset == 0);
-                const gop = try wasm.indirect_function_table.getOrPut(comp.gpa, uav.ip_index);
+                const owner_nav = ip.toFunc(uav.ip_index).owner_nav;
+                const gop = try wasm.indirect_function_table.getOrPut(comp.gpa, owner_nav);
                 if (!gop.found_existing) gop.value_ptr.* = {};
                 try cg.addInst(.{
                     .tag = .func_ref,
@@ -3096,7 +3096,7 @@ fn lowerPtr(cg: *CodeGen, ptr_val: InternPool.Index, prev_offset: u64) InnerErro
     const ptr = zcu.intern_pool.indexToKey(ptr_val).ptr;
     const offset: u64 = prev_offset + ptr.byte_offset;
     return switch (ptr.base_addr) {
-        .nav => |nav| return .{ .nav_ref = .{ .nav_index = zcu.chaseNav(nav), .offset = @intCast(offset) } },
+        .nav => |nav| return .{ .nav_ref = .{ .nav_index = nav, .offset = @intCast(offset) } },
         .uav => |uav| return .{ .uav_ref = .{ .ip_index = uav.val, .offset = @intCast(offset) } },
         .int => return cg.lowerConstant(try pt.intValue(Type.usize, offset), Type.usize),
         .eu_payload => return cg.fail("Wasm TODO: lower error union payload pointer", .{}),
src/link/Wasm/Flush.zig
@@ -651,8 +651,8 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
             try leb.writeUleb128(binary_writer, @as(u8, 0)); // represents funcref
         }
         try leb.writeUleb128(binary_writer, @as(u32, @intCast(wasm.indirect_function_table.entries.len)));
-        for (wasm.indirect_function_table.keys()) |ip_index| {
-            const func_index: Wasm.OutputFunctionIndex = .fromIpIndex(wasm, ip_index);
+        for (wasm.indirect_function_table.keys()) |nav_index| {
+            const func_index: Wasm.OutputFunctionIndex = .fromIpNav(wasm, nav_index);
             try leb.writeUleb128(binary_writer, @intFromEnum(func_index));
         }
 
src/link/Wasm.zig
@@ -260,7 +260,7 @@ table_imports: std.AutoArrayHashMapUnmanaged(String, TableImport.Index) = .empty
 
 /// All functions that have had their address taken and therefore might be
 /// called via a `call_indirect` function.
-indirect_function_table: std.AutoArrayHashMapUnmanaged(InternPool.Index, void) = .empty,
+indirect_function_table: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, void) = .empty,
 
 error_name_table_ref_count: u32 = 0,
 
src/Zcu.zig
@@ -4120,14 +4120,3 @@ pub fn codegenFailTypeMsg(zcu: *Zcu, ty_index: InternPool.Index, msg: *ErrorMsg)
     zcu.failed_types.putAssumeCapacityNoClobber(ty_index, msg);
     return error.CodegenFail;
 }
-
-/// Check if nav is an alias to a function, in which case we want to lower the
-/// actual nav, rather than the alias itself.
-pub fn chaseNav(zcu: *const Zcu, nav: InternPool.Nav.Index) InternPool.Nav.Index {
-    return switch (zcu.intern_pool.indexToKey(zcu.navValue(nav).toIntern())) {
-        .func => |f| f.owner_nav,
-        .variable => |variable| variable.owner_nav,
-        .@"extern" => |@"extern"| @"extern".owner_nav,
-        else => nav,
-    };
-}