Commit 4d14374a66

Luuk de Gram <luuk@degram.dev>
2024-01-21 15:20:24
wasm: Move `createFunction` to `ZigObject`
This function was previously only called by the backend which generates a synthetical function that is not represented by any AIR or Zig code. For this reason, the ownership is moved to the zig-object and stored there so it can be linked with the other object files without the driver having to specialize it.
1 parent 0a030d6
Changed files (3)
src/link/Wasm/file.zig
@@ -89,11 +89,14 @@ pub const File = union(enum) {
         };
     }
 
-    pub fn functions(file: File) []const std.wasm.Func {
-        return switch (file) {
-            .zig_object => |obj| obj.functions.items,
-            .object => |obj| obj.functions,
-        };
+    pub fn function(file: File, sym_index: u32) std.wasm.Func {
+        switch (file) {
+            .zig_object => |obj| return obj.functions.get(sym_index).?,
+            .object => |obj| {
+                const sym = obj.symtable[sym_index];
+                return obj.functions[sym.index - obj.imported_functions_count];
+            },
+        }
     }
 
     pub fn globals(file: File) []const std.wasm.Global {
src/link/Wasm/ZigObject.zig
@@ -13,7 +13,7 @@ decls: std.AutoHashMapUnmanaged(InternPool.DeclIndex, Atom.Index) = .{},
 func_types: std.ArrayListUnmanaged(std.wasm.Type) = .{},
 /// List of `std.wasm.Func`. Each entry contains the function signature,
 /// rather than the actual body.
-functions: std.ArrayListUnmanaged(std.wasm.Func) = .{},
+functions: std.AutoHashMapUnmanaged(u32, std.wasm.Func) = .{},
 /// Map of symbol locations, represented by its `types.Import`.
 imports: std.AutoHashMapUnmanaged(u32, types.Import) = .{},
 /// List of WebAssembly globals.
@@ -1189,6 +1189,33 @@ pub fn parseSymbolIntoAtom(zig_object: *ZigObject, wasm_file: *Wasm, index: u32)
     return atom_index;
 }
 
+/// Creates a new Wasm function with a given symbol name and body.
+/// Returns the symbol index of the new function.
+pub fn createFunction(
+    zig_object: *ZigObject,
+    wasm_file: *Wasm,
+    symbol_name: []const u8,
+    func_ty: std.wasm.Type,
+    function_body: *std.ArrayList(u8),
+    relocations: *std.ArrayList(types.Relocation),
+) !u32 {
+    const gpa = wasm_file.base.comp.gpa;
+    const sym_index = try zig_object.allocateSymbol(gpa);
+    const sym = &zig_object.symbols.items[sym_index];
+    sym.tag = .function;
+    sym.name = try zig_object.string_table.insert(gpa, symbol_name);
+    const type_index = try zig_object.putOrGetFuncType(gpa, func_ty);
+    try zig_object.functions.putNoClobber(gpa, sym_index, .{ .type_index = type_index });
+
+    const atom_index = try wasm_file.createAtom(sym_index, zig_object.index);
+    const atom = wasm_file.getAtomPtr(atom_index);
+    atom.size = @intCast(function_body.items.len);
+    atom.code = function_body.moveToUnmanaged();
+    atom.relocs = relocations.moveToUnmanaged();
+
+    return sym_index;
+}
+
 const build_options = @import("build_options");
 const builtin = @import("builtin");
 const codegen = @import("../../codegen.zig");
src/link/Wasm.zig
@@ -1481,7 +1481,7 @@ fn getFunctionSignature(wasm: *const Wasm, loc: SymbolLoc) std.wasm.Type {
             const ty_index = obj_file.import(loc.index).kind.function;
             return obj_file.funcTypes()[ty_index];
         }
-        const type_index = obj_file.functions()[symbol.index - obj_file.importedFunctions()].type_index;
+        const type_index = obj_file.function(loc.index).type_index;
         return obj_file.funcTypes()[type_index];
     }
     if (is_undefined) {
@@ -1850,9 +1850,7 @@ fn createSyntheticFunction(
 }
 
 /// Unlike `createSyntheticFunction` this function is to be called by
-/// the codegeneration backend. This will not allocate the created Atom yet,
-/// but will instead be appended to `synthetic_functions` list and will be
-/// parsed at the end of code generation.
+/// the codegeneration backend. This will not allocate the created Atom yet.
 /// Returns the index of the symbol.
 pub fn createFunction(
     wasm: *Wasm,
@@ -1861,31 +1859,7 @@ pub fn createFunction(
     function_body: *std.ArrayList(u8),
     relocations: *std.ArrayList(Relocation),
 ) !u32 {
-    const gpa = wasm.base.comp.gpa;
-    const loc = try wasm.createSyntheticSymbol(symbol_name, .function);
-
-    const atom_index = try wasm.createAtom(loc.index, wasm.zig_object_index);
-    const atom = wasm.getAtomPtr(atom_index);
-    atom.code = function_body.moveToUnmanaged();
-    atom.relocs = relocations.moveToUnmanaged();
-    atom.size = @intCast(function_body.items.len);
-    const symbol = loc.getSymbol(wasm);
-    symbol.setFlag(.WASM_SYM_VISIBILITY_HIDDEN); // ensure function does not get exported
-
-    const section_index = wasm.code_section_index orelse idx: {
-        const index = @as(u32, @intCast(wasm.segments.items.len));
-        try wasm.appendDummySegment();
-        break :idx index;
-    };
-    try wasm.appendAtomAtIndex(section_index, atom_index);
-    try wasm.zigObjectPtr().?.atom_types.put(
-        gpa,
-        atom_index,
-        try wasm.zigObjectPtr().?.putOrGetFuncType(gpa, func_ty),
-    );
-    try wasm.synthetic_functions.append(gpa, atom_index);
-
-    return loc.index;
+    return wasm.zigObjectPtr().?.createFunction(wasm, symbol_name, func_ty, function_body, relocations);
 }
 
 /// If required, sets the function index in the `start` section.
@@ -2050,7 +2024,6 @@ fn mergeSections(wasm: *Wasm) !void {
 
         switch (symbol.tag) {
             .function => {
-                const index = symbol.index - obj_file.importedFunctions();
                 const gop = try wasm.functions.getOrPut(
                     gpa,
                     .{ .file = sym_loc.file, .index = symbol.index },
@@ -2068,7 +2041,7 @@ fn mergeSections(wasm: *Wasm) !void {
                     try removed_duplicates.append(sym_loc);
                     continue;
                 }
-                gop.value_ptr.* = .{ .func = obj_file.functions()[index], .sym_index = sym_loc.index };
+                gop.value_ptr.* = .{ .func = obj_file.function(sym_loc.index), .sym_index = sym_loc.index };
                 symbol.index = @as(u32, @intCast(gop.index)) + wasm.imported_functions_count;
             },
             .global => {