Skip to content

Commit 2ac0ba0

Browse files
committed
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 commit 2ac0ba0

File tree

2 files changed

+19
-8
lines changed

2 files changed

+19
-8
lines changed

src/link/Wasm.zig

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -603,7 +603,14 @@ fn parseObjectFile(wasm: *Wasm, path: []const u8) !bool {
603603
pub fn getOrCreateAtomForDecl(wasm: *Wasm, decl_index: Module.Decl.Index) !Atom.Index {
604604
const gop = try wasm.decls.getOrPut(wasm.base.allocator, decl_index);
605605
if (!gop.found_existing) {
606-
gop.value_ptr.* = try wasm.createAtom();
606+
const atom_index = try wasm.createAtom();
607+
gop.value_ptr.* = atom_index;
608+
const atom = wasm.getAtom(atom_index);
609+
const symbol = atom.symbolLoc().getSymbol(wasm);
610+
const mod = wasm.base.options.module.?;
611+
const decl = mod.declPtr(decl_index);
612+
const full_name = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod));
613+
symbol.name = try wasm.string_table.put(wasm.base.allocator, full_name);
607614
}
608615
return gop.value_ptr.*;
609616
}
@@ -1338,11 +1345,11 @@ pub fn deinit(wasm: *Wasm) void {
13381345
pub fn allocateSymbol(wasm: *Wasm) !u32 {
13391346
try wasm.symbols.ensureUnusedCapacity(wasm.base.allocator, 1);
13401347
var symbol: Symbol = .{
1341-
.name = undefined, // will be set after updateDecl
1348+
.name = std.math.maxInt(u32), // will be set after updateDecl as well as during atom creation for decls
13421349
.flags = @intFromEnum(Symbol.Flag.WASM_SYM_BINDING_LOCAL),
1343-
.tag = undefined, // will be set after updateDecl
1344-
.index = undefined, // will be set after updateDecl
1345-
.virtual_address = undefined, // will be set during atom allocation
1350+
.tag = .undefined, // will be set after updateDecl
1351+
.index = std.math.maxInt(u32), // will be set during atom parsing
1352+
.virtual_address = std.math.maxInt(u32), // will be set during atom allocation
13461353
};
13471354
if (wasm.symbols_free_list.popOrNull()) |index| {
13481355
wasm.symbols.items[index] = symbol;
@@ -1414,7 +1421,7 @@ pub fn updateFunc(wasm: *Wasm, mod: *Module, func_index: InternPool.Index, air:
14141421
// &decl_state.?,
14151422
// );
14161423
// }
1417-
return wasm.finishUpdateDecl(decl_index, code);
1424+
return wasm.finishUpdateDecl(decl_index, code, .function);
14181425
}
14191426

14201427
// 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
14681475
},
14691476
};
14701477

1471-
return wasm.finishUpdateDecl(decl_index, code);
1478+
return wasm.finishUpdateDecl(decl_index, code, .data);
14721479
}
14731480

14741481
pub fn updateDeclLineNumber(wasm: *Wasm, mod: *Module, decl_index: Module.Decl.Index) !void {
@@ -1485,14 +1492,15 @@ pub fn updateDeclLineNumber(wasm: *Wasm, mod: *Module, decl_index: Module.Decl.I
14851492
}
14861493
}
14871494

1488-
fn finishUpdateDecl(wasm: *Wasm, decl_index: Module.Decl.Index, code: []const u8) !void {
1495+
fn finishUpdateDecl(wasm: *Wasm, decl_index: Module.Decl.Index, code: []const u8, symbol_tag: Symbol.Tag) !void {
14891496
const mod = wasm.base.options.module.?;
14901497
const decl = mod.declPtr(decl_index);
14911498
const atom_index = wasm.decls.get(decl_index).?;
14921499
const atom = wasm.getAtomPtr(atom_index);
14931500
const symbol = &wasm.symbols.items[atom.sym_index];
14941501
const full_name = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod));
14951502
symbol.name = try wasm.string_table.put(wasm.base.allocator, full_name);
1503+
symbol.tag = symbol_tag;
14961504
try atom.code.appendSlice(wasm.base.allocator, code);
14971505
try wasm.resolved_symbols.put(wasm.base.allocator, atom.symbolLoc(), {});
14981506

src/link/Wasm/Symbol.zig

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ pub const Tag = enum {
3434
/// synthetic kind used by the wasm linker during incremental compilation
3535
/// to notate a symbol has been freed, but still lives in the symbol list.
3636
dead,
37+
undefined,
3738

3839
/// From a given symbol tag, returns the `ExternalType`
3940
/// Asserts the given tag can be represented as an external type.
@@ -45,6 +46,7 @@ pub const Tag = enum {
4546
.section => unreachable, // Not an external type
4647
.event => unreachable, // Not an external type
4748
.dead => unreachable, // Dead symbols should not be referenced
49+
.undefined => unreachable,
4850
.table => .table,
4951
};
5052
}
@@ -169,6 +171,7 @@ pub fn format(symbol: Symbol, comptime fmt: []const u8, options: std.fmt.FormatO
169171
.event => 'E',
170172
.table => 'T',
171173
.dead => '-',
174+
.undefined => unreachable,
172175
};
173176
const visible: []const u8 = if (symbol.isVisible()) "yes" else "no";
174177
const binding: []const u8 = if (symbol.isLocal()) "local" else "global";

0 commit comments

Comments
 (0)