From 2ac0ba03a60a133e7ffbab9ad6aaf3b54f6c747b Mon Sep 17 00:00:00 2001 From: Luuk de Gram Date: Wed, 8 Nov 2023 16:56:11 +0100 Subject: [PATCH] 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. --- src/link/Wasm.zig | 24 ++++++++++++++++-------- src/link/Wasm/Symbol.zig | 3 +++ 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig index baa10be603..2677184c12 100644 --- a/src/link/Wasm.zig +++ b/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(), {}); diff --git a/src/link/Wasm/Symbol.zig b/src/link/Wasm/Symbol.zig index 8dc10771ae..d15e86a666 100644 --- a/src/link/Wasm/Symbol.zig +++ b/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";