Commit 2ac0ba03a6

Luuk de Gram <luuk@degram.dev>
2023-11-08 16:56:11
wasm-linker: ensure symbol fields are set for decls
Previously the symbol tag field would remain `undefined` until it was set during `flush`. However, the symbol's tag would be observed earlier than where it was being set. We now set it to the explicit tag `undefined` so this can be caught during debug. The symbol tag of a decl will now also be set right after `updateDecl` and `updateFunc`. Likewise, we now also set the `name` field during atom creation for decls, as well as set the other fields to the max(u32) to ensure we get a compiler crash during debug to ensure any misses will be caught.
1 parent 10a28bc
Changed files (2)
src
src/link/Wasm/Symbol.zig
@@ -34,6 +34,7 @@ pub const Tag = enum {
     /// synthetic kind used by the wasm linker during incremental compilation
     /// to notate a symbol has been freed, but still lives in the symbol list.
     dead,
+    undefined,
 
     /// From a given symbol tag, returns the `ExternalType`
     /// Asserts the given tag can be represented as an external type.
@@ -45,6 +46,7 @@ pub const Tag = enum {
             .section => unreachable, // Not an external type
             .event => unreachable, // Not an external type
             .dead => unreachable, // Dead symbols should not be referenced
+            .undefined => unreachable,
             .table => .table,
         };
     }
@@ -169,6 +171,7 @@ pub fn format(symbol: Symbol, comptime fmt: []const u8, options: std.fmt.FormatO
         .event => 'E',
         .table => 'T',
         .dead => '-',
+        .undefined => unreachable,
     };
     const visible: []const u8 = if (symbol.isVisible()) "yes" else "no";
     const binding: []const u8 = if (symbol.isLocal()) "local" else "global";
src/link/Wasm.zig
@@ -603,7 +603,14 @@ fn parseObjectFile(wasm: *Wasm, path: []const u8) !bool {
 pub fn getOrCreateAtomForDecl(wasm: *Wasm, decl_index: Module.Decl.Index) !Atom.Index {
     const gop = try wasm.decls.getOrPut(wasm.base.allocator, decl_index);
     if (!gop.found_existing) {
-        gop.value_ptr.* = try wasm.createAtom();
+        const atom_index = try wasm.createAtom();
+        gop.value_ptr.* = atom_index;
+        const atom = wasm.getAtom(atom_index);
+        const symbol = atom.symbolLoc().getSymbol(wasm);
+        const mod = wasm.base.options.module.?;
+        const decl = mod.declPtr(decl_index);
+        const full_name = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod));
+        symbol.name = try wasm.string_table.put(wasm.base.allocator, full_name);
     }
     return gop.value_ptr.*;
 }
@@ -1338,11 +1345,11 @@ pub fn deinit(wasm: *Wasm) void {
 pub fn allocateSymbol(wasm: *Wasm) !u32 {
     try wasm.symbols.ensureUnusedCapacity(wasm.base.allocator, 1);
     var symbol: Symbol = .{
-        .name = undefined, // will be set after updateDecl
+        .name = std.math.maxInt(u32), // will be set after updateDecl as well as during atom creation for decls
         .flags = @intFromEnum(Symbol.Flag.WASM_SYM_BINDING_LOCAL),
-        .tag = undefined, // will be set after updateDecl
-        .index = undefined, // will be set after updateDecl
-        .virtual_address = undefined, // will be set during atom allocation
+        .tag = .undefined, // will be set after updateDecl
+        .index = std.math.maxInt(u32), // will be set during atom parsing
+        .virtual_address = std.math.maxInt(u32), // will be set during atom allocation
     };
     if (wasm.symbols_free_list.popOrNull()) |index| {
         wasm.symbols.items[index] = symbol;
@@ -1414,7 +1421,7 @@ pub fn updateFunc(wasm: *Wasm, mod: *Module, func_index: InternPool.Index, air:
     //         &decl_state.?,
     //     );
     // }
-    return wasm.finishUpdateDecl(decl_index, code);
+    return wasm.finishUpdateDecl(decl_index, code, .function);
 }
 
 // Generate code for the Decl, storing it in memory to be later written to
@@ -1468,7 +1475,7 @@ pub fn updateDecl(wasm: *Wasm, mod: *Module, decl_index: Module.Decl.Index) !voi
         },
     };
 
-    return wasm.finishUpdateDecl(decl_index, code);
+    return wasm.finishUpdateDecl(decl_index, code, .data);
 }
 
 pub fn updateDeclLineNumber(wasm: *Wasm, mod: *Module, decl_index: Module.Decl.Index) !void {
@@ -1485,7 +1492,7 @@ pub fn updateDeclLineNumber(wasm: *Wasm, mod: *Module, decl_index: Module.Decl.I
     }
 }
 
-fn finishUpdateDecl(wasm: *Wasm, decl_index: Module.Decl.Index, code: []const u8) !void {
+fn finishUpdateDecl(wasm: *Wasm, decl_index: Module.Decl.Index, code: []const u8, symbol_tag: Symbol.Tag) !void {
     const mod = wasm.base.options.module.?;
     const decl = mod.declPtr(decl_index);
     const atom_index = wasm.decls.get(decl_index).?;
@@ -1493,6 +1500,7 @@ fn finishUpdateDecl(wasm: *Wasm, decl_index: Module.Decl.Index, code: []const u8
     const symbol = &wasm.symbols.items[atom.sym_index];
     const full_name = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod));
     symbol.name = try wasm.string_table.put(wasm.base.allocator, full_name);
+    symbol.tag = symbol_tag;
     try atom.code.appendSlice(wasm.base.allocator, code);
     try wasm.resolved_symbols.put(wasm.base.allocator, atom.symbolLoc(), {});