authorgravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2022-03-26 17:14:56+01:00
committergravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2022-03-26 21:20:29+01:00
log97448e4d5f6a4c1f9eb7ed11d8b147c0883168c2
tree495b5cc0474e3fa7e0f4819d899b2ac436596961
parentaf844931b2600e50e586436dee0d607d67ed9ff2

wasm: Only generate import when referenced

Rather than creating an import for externs on updateDecl, we now generate them when they're referenced. This is required so using @TypeOf(extern_fn()) will not emit the import into the binary (causing an incorrect function type index as it won't be fully analyzed).

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

src/arch/wasm/CodeGen.zig+6-1
...@@ -64,7 +64,7 @@ const WValue = union(enum) {...@@ -64,7 +64,7 @@ const WValue = union(enum) {
64 /// loads and stores without requiring checks everywhere.64 /// loads and stores without requiring checks everywhere.
65 fn offset(self: WValue) u32 {65 fn offset(self: WValue) u32 {
66 switch (self) {66 switch (self) {
67 .stack_offset => |offset| return offset,67 .stack_offset => |stack_offset| return stack_offset,
68 else => return 0,68 else => return 0,
69 }69 }
70 }70 }
...@@ -1549,6 +1549,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions....@@ -1549,6 +1549,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions.
1549 var func_type = try genFunctype(self.gpa, ext_decl.ty, self.target);1549 var func_type = try genFunctype(self.gpa, ext_decl.ty, self.target);
1550 defer func_type.deinit(self.gpa);1550 defer func_type.deinit(self.gpa);
1551 ext_decl.fn_link.wasm.type_index = try self.bin_file.putOrGetFuncType(func_type);1551 ext_decl.fn_link.wasm.type_index = try self.bin_file.putOrGetFuncType(func_type);
1552 try self.bin_file.addOrUpdateImport(ext_decl);
1552 break :blk ext_decl;1553 break :blk ext_decl;
1553 } else if (func_val.castTag(.decl_ref)) |decl_ref| {1554 } else if (func_val.castTag(.decl_ref)) |decl_ref| {
1554 break :blk decl_ref.data;1555 break :blk decl_ref.data;
...@@ -1939,6 +1940,10 @@ fn lowerConstant(self: *Self, val: Value, ty: Type) InnerError!WValue {...@@ -1939,6 +1940,10 @@ fn lowerConstant(self: *Self, val: Value, ty: Type) InnerError!WValue {
1939 const decl = decl_ref.data;1940 const decl = decl_ref.data;
1940 return self.lowerDeclRefValue(.{ .ty = ty, .val = val }, decl);1941 return self.lowerDeclRefValue(.{ .ty = ty, .val = val }, decl);
1941 }1942 }
1943 if (val.castTag(.decl_ref_mut)) |decl_ref| {
1944 const decl = decl_ref.data.decl;
1945 return self.lowerDeclRefValue(.{ .ty = ty, .val = val }, decl);
1946 }
19421947
1943 const target = self.target;1948 const target = self.target;
19441949
src/link/Wasm.zig+13-17
...@@ -496,8 +496,6 @@ pub fn allocateDeclIndexes(self: *Wasm, decl: *Module.Decl) !void {...@@ -496,8 +496,6 @@ pub fn allocateDeclIndexes(self: *Wasm, decl: *Module.Decl) !void {
496 atom.sym_index = @intCast(u32, self.symbols.items.len);496 atom.sym_index = @intCast(u32, self.symbols.items.len);
497 self.symbols.appendAssumeCapacity(symbol);497 self.symbols.appendAssumeCapacity(symbol);
498 }498 }
499
500 try self.resolved_symbols.putNoClobber(self.base.allocator, atom.symbolLoc(), {});
501 try self.symbol_atom.putNoClobber(self.base.allocator, atom.symbolLoc(), atom);499 try self.symbol_atom.putNoClobber(self.base.allocator, atom.symbolLoc(), atom);
502}500}
503501
...@@ -552,7 +550,7 @@ pub fn updateDecl(self: *Wasm, module: *Module, decl: *Module.Decl) !void {...@@ -552,7 +550,7 @@ pub fn updateDecl(self: *Wasm, module: *Module, decl: *Module.Decl) !void {
552 decl.link.wasm.clear();550 decl.link.wasm.clear();
553551
554 if (decl.isExtern()) {552 if (decl.isExtern()) {
555 return self.addOrUpdateImport(decl);553 return;
556 }554 }
557555
558 if (decl.val.castTag(.function)) |_| {556 if (decl.val.castTag(.function)) |_| {
...@@ -588,10 +586,6 @@ pub fn updateDecl(self: *Wasm, module: *Module, decl: *Module.Decl) !void {...@@ -588,10 +586,6 @@ pub fn updateDecl(self: *Wasm, module: *Module, decl: *Module.Decl) !void {
588}586}
589587
590fn finishUpdateDecl(self: *Wasm, decl: *Module.Decl, code: []const u8) !void {588fn finishUpdateDecl(self: *Wasm, decl: *Module.Decl, code: []const u8) !void {
591 if (decl.isExtern()) {
592 return self.addOrUpdateImport(decl);
593 }
594
595 if (code.len == 0) return;589 if (code.len == 0) return;
596 const atom: *Atom = &decl.link.wasm;590 const atom: *Atom = &decl.link.wasm;
597 atom.size = @intCast(u32, code.len);591 atom.size = @intCast(u32, code.len);
...@@ -602,6 +596,8 @@ fn finishUpdateDecl(self: *Wasm, decl: *Module.Decl, code: []const u8) !void {...@@ -602,6 +596,8 @@ fn finishUpdateDecl(self: *Wasm, decl: *Module.Decl, code: []const u8) !void {
602 defer self.base.allocator.free(full_name);596 defer self.base.allocator.free(full_name);
603 symbol.name = try self.string_table.put(self.base.allocator, full_name);597 symbol.name = try self.string_table.put(self.base.allocator, full_name);
604 try atom.code.appendSlice(self.base.allocator, code);598 try atom.code.appendSlice(self.base.allocator, code);
599
600 try self.resolved_symbols.put(self.base.allocator, atom.symbolLoc(), {});
605}601}
606602
607/// Lowers a constant typed value to a local symbol and atom.603/// Lowers a constant typed value to a local symbol and atom.
...@@ -831,10 +827,10 @@ pub fn freeDecl(self: *Wasm, decl: *Module.Decl) void {...@@ -831,10 +827,10 @@ pub fn freeDecl(self: *Wasm, decl: *Module.Decl) void {
831 }827 }
832828
833 if (decl.isExtern()) {829 if (decl.isExtern()) {
834 assert(self.imports.remove(atom.symbolLoc()));830 _ = self.imports.remove(atom.symbolLoc());
835 }831 }
836 assert(self.resolved_symbols.swapRemove(atom.symbolLoc()));832 _ = self.resolved_symbols.swapRemove(atom.symbolLoc());
837 _ = self.symbol_atom.remove(atom.symbolLoc()); // not all decl's exist in symbol_atom833 _ = self.symbol_atom.remove(atom.symbolLoc());
838 atom.deinit(self.base.allocator);834 atom.deinit(self.base.allocator);
839}835}
840836
...@@ -855,19 +851,19 @@ fn mapFunctionTable(self: *Wasm) void {...@@ -855,19 +851,19 @@ fn mapFunctionTable(self: *Wasm) void {
855 }851 }
856}852}
857853
858fn addOrUpdateImport(self: *Wasm, decl: *Module.Decl) !void {854pub fn addOrUpdateImport(self: *Wasm, decl: *Module.Decl) !void {
859 // For the import name itself, we use the decl's name, rather than the fully qualified name855 // For the import name itself, we use the decl's name, rather than the fully qualified name
860 const decl_name_index = try self.string_table.put(self.base.allocator, mem.sliceTo(decl.name, 0));856 const decl_name_index = try self.string_table.put(self.base.allocator, mem.sliceTo(decl.name, 0));
861 const symbol_index = decl.link.wasm.sym_index;857 const symbol_index = decl.link.wasm.sym_index;
862 const symbol: *Symbol = &self.symbols.items[symbol_index];858 const symbol: *Symbol = &self.symbols.items[symbol_index];
863 symbol.setUndefined(true);859 symbol.setUndefined(true);
864 symbol.setGlobal(true);860 symbol.setGlobal(true);
865 try self.globals.putNoClobber(861 const global_gop = try self.globals.getOrPut(self.base.allocator, decl_name_index);
866 self.base.allocator,862 if (!global_gop.found_existing) {
867 decl_name_index,863 const loc: SymbolLoc = .{ .file = null, .index = symbol_index };
868 .{ .file = null, .index = symbol_index },864 global_gop.value_ptr.* = loc;
869 );865 try self.resolved_symbols.put(self.base.allocator, loc, {});
870 try self.resolved_symbols.put(self.base.allocator, .{ .file = null, .index = symbol_index }, {});866 }
871867
872 switch (decl.ty.zigTypeTag()) {868 switch (decl.ty.zigTypeTag()) {
873 .Fn => {869 .Fn => {