authorgravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2023-11-08 16:56:11+01:00
committergravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2023-11-09 00:00:17+01:00
log2ac0ba03a60a133e7ffbab9ad6aaf3b54f6c747b
treebd220f17e27942eb4946faccc6cea891d8a8c78d
parent10a28bc4c48cd50882a7a5e5c57fee02b8c34731

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.

2 files changed, 19 insertions(+), 8 deletions(-)

src/link/Wasm.zig+16-8
...@@ -603,7 +603,14 @@ fn parseObjectFile(wasm: *Wasm, path: []const u8) !bool {...@@ -603,7 +603,14 @@ fn parseObjectFile(wasm: *Wasm, path: []const u8) !bool {
603pub fn getOrCreateAtomForDecl(wasm: *Wasm, decl_index: Module.Decl.Index) !Atom.Index {603pub fn getOrCreateAtomForDecl(wasm: *Wasm, decl_index: Module.Decl.Index) !Atom.Index {
604 const gop = try wasm.decls.getOrPut(wasm.base.allocator, decl_index);604 const gop = try wasm.decls.getOrPut(wasm.base.allocator, decl_index);
605 if (!gop.found_existing) {605 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);
607 }614 }
608 return gop.value_ptr.*;615 return gop.value_ptr.*;
609}616}
...@@ -1338,11 +1345,11 @@ pub fn deinit(wasm: *Wasm) void {...@@ -1338,11 +1345,11 @@ pub fn deinit(wasm: *Wasm) void {
1338pub fn allocateSymbol(wasm: *Wasm) !u32 {1345pub fn allocateSymbol(wasm: *Wasm) !u32 {
1339 try wasm.symbols.ensureUnusedCapacity(wasm.base.allocator, 1);1346 try wasm.symbols.ensureUnusedCapacity(wasm.base.allocator, 1);
1340 var symbol: Symbol = .{1347 var symbol: Symbol = .{
1341 .name = undefined, // will be set after updateDecl1348 .name = std.math.maxInt(u32), // will be set after updateDecl as well as during atom creation for decls
1342 .flags = @intFromEnum(Symbol.Flag.WASM_SYM_BINDING_LOCAL),1349 .flags = @intFromEnum(Symbol.Flag.WASM_SYM_BINDING_LOCAL),
1343 .tag = undefined, // will be set after updateDecl1350 .tag = .undefined, // will be set after updateDecl
1344 .index = undefined, // will be set after updateDecl1351 .index = std.math.maxInt(u32), // will be set during atom parsing
1345 .virtual_address = undefined, // will be set during atom allocation1352 .virtual_address = std.math.maxInt(u32), // will be set during atom allocation
1346 };1353 };
1347 if (wasm.symbols_free_list.popOrNull()) |index| {1354 if (wasm.symbols_free_list.popOrNull()) |index| {
1348 wasm.symbols.items[index] = symbol;1355 wasm.symbols.items[index] = symbol;
...@@ -1414,7 +1421,7 @@ pub fn updateFunc(wasm: *Wasm, mod: *Module, func_index: InternPool.Index, air:...@@ -1414,7 +1421,7 @@ pub fn updateFunc(wasm: *Wasm, mod: *Module, func_index: InternPool.Index, air:
1414 // &decl_state.?,1421 // &decl_state.?,
1415 // );1422 // );
1416 // }1423 // }
1417 return wasm.finishUpdateDecl(decl_index, code);1424 return wasm.finishUpdateDecl(decl_index, code, .function);
1418}1425}
14191426
1420// Generate code for the Decl, storing it in memory to be later written to1427// 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...@@ -1468,7 +1475,7 @@ pub fn updateDecl(wasm: *Wasm, mod: *Module, decl_index: Module.Decl.Index) !voi
1468 },1475 },
1469 };1476 };
14701477
1471 return wasm.finishUpdateDecl(decl_index, code);1478 return wasm.finishUpdateDecl(decl_index, code, .data);
1472}1479}
14731480
1474pub fn updateDeclLineNumber(wasm: *Wasm, mod: *Module, decl_index: Module.Decl.Index) !void {1481pub 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...@@ -1485,7 +1492,7 @@ pub fn updateDeclLineNumber(wasm: *Wasm, mod: *Module, decl_index: Module.Decl.I
1485 }1492 }
1486}1493}
14871494
1488fn finishUpdateDecl(wasm: *Wasm, decl_index: Module.Decl.Index, code: []const u8) !void {1495fn finishUpdateDecl(wasm: *Wasm, decl_index: Module.Decl.Index, code: []const u8, symbol_tag: Symbol.Tag) !void {
1489 const mod = wasm.base.options.module.?;1496 const mod = wasm.base.options.module.?;
1490 const decl = mod.declPtr(decl_index);1497 const decl = mod.declPtr(decl_index);
1491 const atom_index = wasm.decls.get(decl_index).?;1498 const atom_index = wasm.decls.get(decl_index).?;
...@@ -1493,6 +1500,7 @@ fn finishUpdateDecl(wasm: *Wasm, decl_index: Module.Decl.Index, code: []const u8...@@ -1493,6 +1500,7 @@ fn finishUpdateDecl(wasm: *Wasm, decl_index: Module.Decl.Index, code: []const u8
1493 const symbol = &wasm.symbols.items[atom.sym_index];1500 const symbol = &wasm.symbols.items[atom.sym_index];
1494 const full_name = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod));1501 const full_name = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod));
1495 symbol.name = try wasm.string_table.put(wasm.base.allocator, full_name);1502 symbol.name = try wasm.string_table.put(wasm.base.allocator, full_name);
1503 symbol.tag = symbol_tag;
1496 try atom.code.appendSlice(wasm.base.allocator, code);1504 try atom.code.appendSlice(wasm.base.allocator, code);
1497 try wasm.resolved_symbols.put(wasm.base.allocator, atom.symbolLoc(), {});1505 try wasm.resolved_symbols.put(wasm.base.allocator, atom.symbolLoc(), {});
14981506
src/link/Wasm/Symbol.zig+3
...@@ -34,6 +34,7 @@ pub const Tag = enum {...@@ -34,6 +34,7 @@ pub const Tag = enum {
34 /// synthetic kind used by the wasm linker during incremental compilation34 /// synthetic kind used by the wasm linker during incremental compilation
35 /// to notate a symbol has been freed, but still lives in the symbol list.35 /// to notate a symbol has been freed, but still lives in the symbol list.
36 dead,36 dead,
37 undefined,
3738
38 /// From a given symbol tag, returns the `ExternalType`39 /// From a given symbol tag, returns the `ExternalType`
39 /// Asserts the given tag can be represented as an external type.40 /// Asserts the given tag can be represented as an external type.
...@@ -45,6 +46,7 @@ pub const Tag = enum {...@@ -45,6 +46,7 @@ pub const Tag = enum {
45 .section => unreachable, // Not an external type46 .section => unreachable, // Not an external type
46 .event => unreachable, // Not an external type47 .event => unreachable, // Not an external type
47 .dead => unreachable, // Dead symbols should not be referenced48 .dead => unreachable, // Dead symbols should not be referenced
49 .undefined => unreachable,
48 .table => .table,50 .table => .table,
49 };51 };
50 }52 }
...@@ -169,6 +171,7 @@ pub fn format(symbol: Symbol, comptime fmt: []const u8, options: std.fmt.FormatO...@@ -169,6 +171,7 @@ pub fn format(symbol: Symbol, comptime fmt: []const u8, options: std.fmt.FormatO
169 .event => 'E',171 .event => 'E',
170 .table => 'T',172 .table => 'T',
171 .dead => '-',173 .dead => '-',
174 .undefined => unreachable,
172 };175 };
173 const visible: []const u8 = if (symbol.isVisible()) "yes" else "no";176 const visible: []const u8 = if (symbol.isVisible()) "yes" else "no";
174 const binding: []const u8 = if (symbol.isLocal()) "local" else "global";177 const binding: []const u8 = if (symbol.isLocal()) "local" else "global";