authorgravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2024-01-24 17:24:58+01:00
committergravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2024-02-29 15:23:04+01:00
logfde8c2f41a76f6bc56d733a8cb6aae90f8e3f41b
tree742d36a6ee82580107b0e1f7f8e5fa9fbe225863
parent8f96e7eec1b2af005e17bf21f91fc91add92d7dd
signaturelock-open Commit is signed but in an unrecognized format.

wasm: reimplement `deleteDeclExport`

Removes the symbol from the decl's list of exports, marks it as dead, as well as appends it to the symbol free list. Also removes it from the list of global symbols as all exports are global. In the future we should perhaps use a map for the export list to prevent linear lookups. But this requires a benchmark as having more than 1 export for the same decl is very rare.

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

src/link/Wasm.zig+1-2
...@@ -1534,9 +1534,8 @@ pub fn deleteDeclExport(...@@ -1534,9 +1534,8 @@ pub fn deleteDeclExport(
1534 decl_index: InternPool.DeclIndex,1534 decl_index: InternPool.DeclIndex,
1535 name: InternPool.NullTerminatedString,1535 name: InternPool.NullTerminatedString,
1536) void {1536) void {
1537 _ = name;
1538 if (wasm.llvm_object) |_| return;1537 if (wasm.llvm_object) |_| return;
1539 return wasm.zigObjectPtr().?.deleteDeclExport(wasm, decl_index);1538 return wasm.zigObjectPtr().?.deleteDeclExport(wasm, decl_index, name);
1540}1539}
15411540
1542pub fn updateExports(1541pub fn updateExports(
src/link/Wasm/ZigObject.zig+39-6
...@@ -98,6 +98,16 @@ const DeclInfo = struct {...@@ -98,6 +98,16 @@ const DeclInfo = struct {
98 fn appendExport(di: *DeclInfo, gpa: std.mem.Allocator, sym_index: u32) !void {98 fn appendExport(di: *DeclInfo, gpa: std.mem.Allocator, sym_index: u32) !void {
99 return di.exports.append(gpa, sym_index);99 return di.exports.append(gpa, sym_index);
100 }100 }
101
102 fn deleteExport(di: *DeclInfo, sym_index: u32) void {
103 for (di.exports.items, 0..) |idx, index| {
104 if (idx == sym_index) {
105 _ = di.exports.swapRemove(index);
106 return;
107 }
108 }
109 unreachable; // invalid sym_index
110 }
101};111};
102112
103/// Initializes the `ZigObject` with initial symbols.113/// Initializes the `ZigObject` with initial symbols.
...@@ -800,12 +810,23 @@ pub fn deleteDeclExport(...@@ -800,12 +810,23 @@ pub fn deleteDeclExport(
800 zig_object: *ZigObject,810 zig_object: *ZigObject,
801 wasm_file: *Wasm,811 wasm_file: *Wasm,
802 decl_index: InternPool.DeclIndex,812 decl_index: InternPool.DeclIndex,
813 name: InternPool.NullTerminatedString,
803) void {814) void {
804 const decl_info = zig_object.decls_map.get(decl_index) orelse return;815 const mod = wasm_file.base.comp.module.?;
805 const sym_index = wasm_file.getAtom(decl_info.atom).sym_index;816 const decl_info = zig_object.decls_map.getPtr(decl_index) orelse return;
806 const loc: Wasm.SymbolLoc = .{ .file = zig_object.index, .index = sym_index };817 const export_name = mod.intern_pool.stringToSlice(name);
807 const sym = loc.getSymbol(wasm_file);818 if (decl_info.@"export"(zig_object, export_name)) |sym_index| {
808 std.debug.assert(zig_object.global_syms.remove(sym.name));819 const sym = zig_object.symbol(sym_index);
820 decl_info.deleteExport(sym_index);
821 std.debug.assert(zig_object.global_syms.remove(sym.name));
822 std.debug.assert(wasm_file.symbol_atom.remove(.{ .file = zig_object.index, .index = sym_index }));
823 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 }
828 sym.tag = .dead;
829 }
809}830}
810831
811pub fn updateExports(832pub fn updateExports(
...@@ -846,6 +867,17 @@ pub fn updateExports(...@@ -846,6 +867,17 @@ pub fn updateExports(
846 else index: {867 else index: {
847 const sym_index = try zig_object.allocateSymbol(gpa);868 const sym_index = try zig_object.allocateSymbol(gpa);
848 try decl_info.appendExport(gpa, sym_index);869 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 }
849 break :index sym_index;881 break :index sym_index;
850 };882 };
851883
...@@ -879,6 +911,7 @@ pub fn updateExports(...@@ -879,6 +911,7 @@ pub fn updateExports(
879 sym.setFlag(.WASM_SYM_VISIBILITY_HIDDEN);911 sym.setFlag(.WASM_SYM_VISIBILITY_HIDDEN);
880 }912 }
881 try zig_object.global_syms.put(gpa, export_name, sym_index);913 try zig_object.global_syms.put(gpa, export_name, sym_index);
914 try wasm_file.symbol_atom.put(gpa, .{ .file = zig_object.index, .index = sym_index }, atom_index);
882 }915 }
883}916}
884917
...@@ -1145,8 +1178,8 @@ pub fn storeDeclType(zig_object: *ZigObject, gpa: std.mem.Allocator, decl_index:...@@ -1145,8 +1178,8 @@ pub fn storeDeclType(zig_object: *ZigObject, gpa: std.mem.Allocator, decl_index:
1145pub fn parseSymbolIntoAtom(zig_object: *ZigObject, wasm_file: *Wasm, index: u32) !Atom.Index {1178pub fn parseSymbolIntoAtom(zig_object: *ZigObject, wasm_file: *Wasm, index: u32) !Atom.Index {
1146 const gpa = wasm_file.base.comp.gpa;1179 const gpa = wasm_file.base.comp.gpa;
1147 const loc: Wasm.SymbolLoc = .{ .file = zig_object.index, .index = index };1180 const loc: Wasm.SymbolLoc = .{ .file = zig_object.index, .index = index };
1148 const final_index = try wasm_file.getMatchingSegment(zig_object.index, index);
1149 const atom_index = wasm_file.symbol_atom.get(loc).?;1181 const atom_index = wasm_file.symbol_atom.get(loc).?;
1182 const final_index = try wasm_file.getMatchingSegment(zig_object.index, index);
1150 try wasm_file.appendAtomAtIndex(final_index, atom_index);1183 try wasm_file.appendAtomAtIndex(final_index, atom_index);
1151 const atom = wasm_file.getAtom(atom_index);1184 const atom = wasm_file.getAtom(atom_index);
1152 for (atom.relocs.items) |reloc| {1185 for (atom.relocs.items) |reloc| {