authorgravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2024-01-29 06:52:50+01:00
committergravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2024-02-29 15:23:04+01:00
logc153f94c892fc3b718d29ba4ae3234e99d4baba4
tree436ba6d7aaa2daa8860dc9b4096b23f336d46f3c
parentfde8c2f41a76f6bc56d733a8cb6aae90f8e3f41b
signaturelock-open Commit is signed but in an unrecognized format.

wasm: ensure unique function indexes

We cannot keep function indexes as maxInt(u32) due to functions being dedupliated when they point to the same function. For this reason we now use a regular arraylist which will have new functions appended to, and when deleted, its index is appended to the free list, allowing us to re-use slots in the function list.

3 files changed, 28 insertions(+), 25 deletions(-)

src/link/Wasm.zig+1-1
......@@ -819,7 +819,7 @@ fn resolveSymbolsInObject(wasm: *Wasm, file_index: File.Index) !void {
819819 }
820820
821821 if (symbol.tag != existing_sym.tag) {
822 log.err("symbol '{s}' mismatching type '{s}", .{ sym_name, @tagName(symbol.tag) });
822 log.err("symbol '{s}' mismatching types '{s}' and '{s}'", .{ sym_name, @tagName(symbol.tag), @tagName(existing_sym.tag) });
823823 log.err(" first definition in '{s}'", .{existing_file_path});
824824 log.err(" next definition in '{s}'", .{obj_file.path()});
825825 return error.SymbolMismatchingType;
src/link/Wasm/ZigObject.zig+23-23
......@@ -13,7 +13,9 @@ decls_map: std.AutoHashMapUnmanaged(InternPool.DeclIndex, DeclInfo) = .{},
1313func_types: std.ArrayListUnmanaged(std.wasm.Type) = .{},
1414/// List of `std.wasm.Func`. Each entry contains the function signature,
1515/// rather than the actual body.
16functions: std.AutoHashMapUnmanaged(u32, std.wasm.Func) = .{},
16functions: std.ArrayListUnmanaged(std.wasm.Func) = .{},
17/// List of indexes pointing to an entry within the `functions` list which has been removed.
18functions_free_list: std.ArrayListUnmanaged(u32) = .{},
1719/// Map of symbol locations, represented by its `types.Import`.
1820imports: std.AutoHashMapUnmanaged(u32, types.Import) = .{},
1921/// List of WebAssembly globals.
......@@ -320,11 +322,7 @@ fn finishUpdateDecl(
320322
321323 switch (decl.ty.zigTypeTag(mod)) {
322324 .Fn => {
323 try zig_object.functions.put(
324 gpa,
325 atom.sym_index,
326 .{ .type_index = zig_object.atom_types.get(atom_index).? },
327 );
325 sym.index = try zig_object.appendFunction(gpa, .{ .type_index = zig_object.atom_types.get(atom_index).? });
328326 sym.tag = .function;
329327 },
330328 else => {
......@@ -689,6 +687,9 @@ pub fn addOrUpdateImport(
689687 };
690688 zig_object.imported_functions_count += 1;
691689 }
690 sym.tag = .function;
691 } else {
692 sym.tag = .data;
692693 }
693694}
694695
......@@ -821,10 +822,6 @@ pub fn deleteDeclExport(
821822 std.debug.assert(zig_object.global_syms.remove(sym.name));
822823 std.debug.assert(wasm_file.symbol_atom.remove(.{ .file = zig_object.index, .index = sym_index }));
823824 zig_object.symbols_free_list.append(wasm_file.base.comp.gpa, sym_index) catch {};
824
825 if (sym.tag == .function) {
826 std.debug.assert(zig_object.functions.remove(sym_index));
827 }
828825 sym.tag = .dead;
829826 }
830827}
......@@ -867,17 +864,6 @@ pub fn updateExports(
867864 else index: {
868865 const sym_index = try zig_object.allocateSymbol(gpa);
869866 try decl_info.appendExport(gpa, sym_index);
870
871 // For functions, we also need to put the alias in the function section.
872 // We simply copy the aliased function.
873 // The final linakge will deduplicate these functions.
874 if (decl.ty.zigTypeTag(mod) == .Fn) {
875 try zig_object.functions.putNoClobber(
876 gpa,
877 sym_index,
878 zig_object.functions.get(atom.sym_index).?,
879 );
880 }
881867 break :index sym_index;
882868 };
883869
......@@ -969,7 +955,7 @@ pub fn freeDecl(zig_object: *ZigObject, wasm_file: *Wasm, decl_index: InternPool
969955 }
970956 switch (decl.ty.zigTypeTag(mod)) {
971957 .Fn => {
972 std.debug.assert(zig_object.functions.remove(atom.sym_index));
958 zig_object.functions_free_list.append(gpa, sym.index) catch {};
973959 std.debug.assert(zig_object.atom_types.remove(atom_index));
974960 },
975961 else => {
......@@ -1221,7 +1207,7 @@ pub fn createFunction(
12211207 sym.tag = .function;
12221208 sym.name = try zig_object.string_table.insert(gpa, symbol_name);
12231209 const type_index = try zig_object.putOrGetFuncType(gpa, func_ty);
1224 try zig_object.functions.putNoClobber(gpa, sym_index, .{ .type_index = type_index });
1210 sym.index = try zig_object.appendFunction(gpa, .{ .type_index = type_index });
12251211
12261212 const atom_index = try wasm_file.createAtom(sym_index, zig_object.index);
12271213 const atom = wasm_file.getAtomPtr(atom_index);
......@@ -1232,6 +1218,20 @@ pub fn createFunction(
12321218 return sym_index;
12331219}
12341220
1221/// Appends a new `std.wasm.Func` to the list of functions and returns its index.
1222fn appendFunction(zig_object: *ZigObject, gpa: std.mem.Allocator, func: std.wasm.Func) !u32 {
1223 const index: u32 = if (zig_object.functions_free_list.popOrNull()) |idx|
1224 idx
1225 else idx: {
1226 const len: u32 = @intCast(zig_object.functions.items.len);
1227 _ = try zig_object.functions.addOne(gpa);
1228 break :idx len;
1229 };
1230 zig_object.functions.items[index] = func;
1231
1232 return index;
1233}
1234
12351235const build_options = @import("build_options");
12361236const builtin = @import("builtin");
12371237const codegen = @import("../../codegen.zig");
src/link/Wasm/file.zig+4-1
......@@ -91,7 +91,10 @@ pub const File = union(enum) {
9191
9292 pub fn function(file: File, sym_index: u32) std.wasm.Func {
9393 switch (file) {
94 .zig_object => |obj| return obj.functions.get(sym_index).?,
94 .zig_object => |obj| {
95 const sym = obj.symbols.items[sym_index];
96 return obj.functions.items[sym.index];
97 },
9598 .object => |obj| {
9699 const sym = obj.symtable[sym_index];
97100 return obj.functions[sym.index - obj.imported_functions_count];