| ... | @@ -79,6 +79,8 @@ data_segments: std.StringArrayHashMapUnmanaged(u32) = .{}, | ... | @@ -79,6 +79,8 @@ data_segments: std.StringArrayHashMapUnmanaged(u32) = .{}, |
| 79 | /// A list of `types.Segment` which provide meta data | 79 | /// A list of `types.Segment` which provide meta data |
| 80 | /// about a data symbol such as its name | 80 | /// about a data symbol such as its name |
| 81 | segment_info: std.ArrayListUnmanaged(types.Segment) = .{}, | 81 | segment_info: std.ArrayListUnmanaged(types.Segment) = .{}, |
| | 82 | /// Deduplicated string table for strings used by symbols, imports and exports. |
| | 83 | string_table: StringTable = .{}, |
| 82 | | 84 | |
| 83 | // Output sections | 85 | // Output sections |
| 84 | /// Output type section | 86 | /// Output type section |
| ... | @@ -155,6 +157,79 @@ pub const SymbolLoc = struct { | ... | @@ -155,6 +157,79 @@ pub const SymbolLoc = struct { |
| 155 | } | 157 | } |
| 156 | return &wasm_bin.symbols.items[self.index]; | 158 | return &wasm_bin.symbols.items[self.index]; |
| 157 | } | 159 | } |
| | 160 | |
| | 161 | /// From a given location, returns the name of the symbol. |
| | 162 | pub fn getName(self: SymbolLoc, wasm_bin: *const Wasm) []const u8 { |
| | 163 | if (wasm_bin.discarded.get(self)) |new_loc| { |
| | 164 | return new_loc.getName(wasm_bin); |
| | 165 | } |
| | 166 | if (self.file) |object_index| { |
| | 167 | const object = wasm_bin.objects.items[object_index]; |
| | 168 | return object.string_table.get(object.symtable[self.index].name); |
| | 169 | } |
| | 170 | return wasm_bin.string_table.get(wasm_bin.symbols.items[self.index].name); |
| | 171 | } |
| | 172 | }; |
| | 173 | |
| | 174 | /// Generic string table that duplicates strings |
| | 175 | /// and converts them into offsets instead. |
| | 176 | pub const StringTable = struct { |
| | 177 | /// Table that maps string offsets, which is used to de-duplicate strings. |
| | 178 | /// Rather than having the offset map to the data, the `StringContext` holds all bytes of the string. |
| | 179 | /// The strings are stored as a contigious array where each string is zero-terminated. |
| | 180 | string_table: std.HashMapUnmanaged( |
| | 181 | u32, |
| | 182 | void, |
| | 183 | std.hash_map.StringIndexContext, |
| | 184 | std.hash_map.default_max_load_percentage, |
| | 185 | ) = .{}, |
| | 186 | /// Holds the actual data of the string table. |
| | 187 | string_data: std.ArrayListUnmanaged(u8) = .{}, |
| | 188 | |
| | 189 | /// Accepts a string and searches for a corresponding string. |
| | 190 | /// When found, de-duplicates the string and returns the existing offset instead. |
| | 191 | /// When the string is not found in the `string_table`, a new entry will be inserted |
| | 192 | /// and the new offset to its data will be returned. |
| | 193 | pub fn put(self: *StringTable, allocator: Allocator, string: []const u8) !u32 { |
| | 194 | const gop = try self.string_table.getOrPutContextAdapted( |
| | 195 | allocator, |
| | 196 | string, |
| | 197 | std.hash_map.StringIndexAdapter{ .bytes = &self.string_data }, |
| | 198 | .{ .bytes = &self.string_data }, |
| | 199 | ); |
| | 200 | if (gop.found_existing) { |
| | 201 | const off = gop.key_ptr.*; |
| | 202 | log.debug("reusing string '{s}' at offset 0x{x}", .{ string, off }); |
| | 203 | return off; |
| | 204 | } |
| | 205 | |
| | 206 | try self.string_data.ensureUnusedCapacity(allocator, string.len + 1); |
| | 207 | const offset = @intCast(u32, self.string_data.items.len); |
| | 208 | |
| | 209 | log.debug("writing new string '{s}' at offset 0x{x}", .{ string, offset }); |
| | 210 | |
| | 211 | self.string_data.appendSliceAssumeCapacity(string); |
| | 212 | self.string_data.appendAssumeCapacity(0); |
| | 213 | |
| | 214 | gop.key_ptr.* = offset; |
| | 215 | |
| | 216 | return offset; |
| | 217 | } |
| | 218 | |
| | 219 | /// From a given offset, returns its corresponding string value. |
| | 220 | /// Asserts offset does not exceed bounds. |
| | 221 | pub fn get(self: StringTable, off: u32) []const u8 { |
| | 222 | assert(off < self.string_data.items.len); |
| | 223 | return mem.sliceTo(@ptrCast([*:0]const u8, self.string_data.items.ptr + off), 0); |
| | 224 | } |
| | 225 | |
| | 226 | /// Frees all resources of the string table. Any references pointing |
| | 227 | /// to the strings will be invalid. |
| | 228 | pub fn deinit(self: *StringTable, allocator: Allocator) void { |
| | 229 | self.string_data.deinit(allocator); |
| | 230 | self.string_table.deinit(allocator); |
| | 231 | self.* = undefined; |
| | 232 | } |
| 158 | }; | 233 | }; |
| 159 | | 234 | |
| 160 | pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Options) !*Wasm { | 235 | pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Options) !*Wasm { |
| ... | @@ -177,7 +252,7 @@ pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Option | ... | @@ -177,7 +252,7 @@ pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Option |
| 177 | // As sym_index '0' is reserved, we use it for our stack pointer symbol | 252 | // As sym_index '0' is reserved, we use it for our stack pointer symbol |
| 178 | const symbol = try wasm_bin.symbols.addOne(allocator); | 253 | const symbol = try wasm_bin.symbols.addOne(allocator); |
| 179 | symbol.* = .{ | 254 | symbol.* = .{ |
| 180 | .name = "__stack_pointer", | 255 | .name = try wasm_bin.string_table.put(allocator, "__stack_pointer"), |
| 181 | .tag = .global, | 256 | .tag = .global, |
| 182 | .flags = 0, | 257 | .flags = 0, |
| 183 | .index = 0, | 258 | .index = 0, |
| ... | @@ -268,12 +343,12 @@ fn resolveSymbolsInObject(self: *Wasm, object_index: u16) !void { | ... | @@ -268,12 +343,12 @@ fn resolveSymbolsInObject(self: *Wasm, object_index: u16) !void { |
| 268 | .file = object_index, | 343 | .file = object_index, |
| 269 | .index = sym_index, | 344 | .index = sym_index, |
| 270 | }; | 345 | }; |
| 271 | const sym_name = std.mem.sliceTo(symbol.name, 0); | 346 | const sym_name = object.string_table.get(symbol.name); |
| 272 | | 347 | |
| 273 | if (symbol.isLocal()) { | 348 | if (symbol.isLocal()) { |
| 274 | if (symbol.isUndefined()) { | 349 | if (symbol.isUndefined()) { |
| 275 | log.err("Local symbols are not allowed to reference imports", .{}); | 350 | log.err("Local symbols are not allowed to reference imports", .{}); |
| 276 | log.err(" symbol '{s}' defined in '{s}'", .{ symbol.name, object.name }); | 351 | log.err(" symbol '{s}' defined in '{s}'", .{ sym_name, object.name }); |
| 277 | return error.undefinedLocal; | 352 | return error.undefinedLocal; |
| 278 | } | 353 | } |
| 279 | try self.resolved_symbols.putNoClobber(self.base.allocator, location, {}); | 354 | try self.resolved_symbols.putNoClobber(self.base.allocator, location, {}); |
| ... | @@ -299,7 +374,7 @@ fn resolveSymbolsInObject(self: *Wasm, object_index: u16) !void { | ... | @@ -299,7 +374,7 @@ fn resolveSymbolsInObject(self: *Wasm, object_index: u16) !void { |
| 299 | | 374 | |
| 300 | if (!existing_sym.isUndefined()) { | 375 | if (!existing_sym.isUndefined()) { |
| 301 | if (!symbol.isUndefined()) { | 376 | if (!symbol.isUndefined()) { |
| 302 | log.err("symbol '{s}' defined multiple times", .{existing_sym.name}); | 377 | log.err("symbol '{s}' defined multiple times", .{sym_name}); |
| 303 | log.err(" first definition in '{s}'", .{existing_file_path}); | 378 | log.err(" first definition in '{s}'", .{existing_file_path}); |
| 304 | log.err(" next definition in '{s}'", .{object.name}); | 379 | log.err(" next definition in '{s}'", .{object.name}); |
| 305 | return error.SymbolCollision; | 380 | return error.SymbolCollision; |
| ... | @@ -309,7 +384,7 @@ fn resolveSymbolsInObject(self: *Wasm, object_index: u16) !void { | ... | @@ -309,7 +384,7 @@ fn resolveSymbolsInObject(self: *Wasm, object_index: u16) !void { |
| 309 | } | 384 | } |
| 310 | | 385 | |
| 311 | // simply overwrite with the new symbol | 386 | // simply overwrite with the new symbol |
| 312 | log.debug("Overwriting symbol '{s}'", .{symbol.name}); | 387 | log.debug("Overwriting symbol '{s}'", .{sym_name}); |
| 313 | log.debug(" old definition in '{s}'", .{existing_file_path}); | 388 | log.debug(" old definition in '{s}'", .{existing_file_path}); |
| 314 | log.debug(" new definition in '{s}'", .{object.name}); | 389 | log.debug(" new definition in '{s}'", .{object.name}); |
| 315 | try self.discarded.putNoClobber(self.base.allocator, maybe_existing.value_ptr.*, location); | 390 | try self.discarded.putNoClobber(self.base.allocator, maybe_existing.value_ptr.*, location); |
| ... | @@ -328,12 +403,7 @@ pub fn deinit(self: *Wasm) void { | ... | @@ -328,12 +403,7 @@ pub fn deinit(self: *Wasm) void { |
| 328 | | 403 | |
| 329 | var decl_it = self.decls.keyIterator(); | 404 | var decl_it = self.decls.keyIterator(); |
| 330 | while (decl_it.next()) |decl_ptr| { | 405 | while (decl_it.next()) |decl_ptr| { |
| 331 | const decl = decl_ptr.*; | 406 | decl_ptr.*.link.wasm.deinit(gpa); |
| 332 | const atom: *Atom = &decl.link.wasm; | | |
| 333 | for (atom.locals.items) |local| { | | |
| 334 | gpa.free(mem.sliceTo(self.symbols.items[local.sym_index].name, 0)); | | |
| 335 | } | | |
| 336 | decl.link.wasm.deinit(gpa); | | |
| 337 | } | 407 | } |
| 338 | | 408 | |
| 339 | for (self.func_types.items) |*func_type| { | 409 | for (self.func_types.items) |*func_type| { |
| ... | @@ -374,6 +444,8 @@ pub fn deinit(self: *Wasm) void { | ... | @@ -374,6 +444,8 @@ pub fn deinit(self: *Wasm) void { |
| 374 | self.function_table.deinit(gpa); | 444 | self.function_table.deinit(gpa); |
| 375 | self.tables.deinit(gpa); | 445 | self.tables.deinit(gpa); |
| 376 | self.exports.deinit(gpa); | 446 | self.exports.deinit(gpa); |
| | 447 | |
| | 448 | self.string_table.deinit(gpa); |
| 377 | } | 449 | } |
| 378 | | 450 | |
| 379 | pub fn allocateDeclIndexes(self: *Wasm, decl: *Module.Decl) !void { | 451 | pub fn allocateDeclIndexes(self: *Wasm, decl: *Module.Decl) !void { |
| ... | @@ -498,7 +570,10 @@ fn finishUpdateDecl(self: *Wasm, decl: *Module.Decl, code: []const u8) !void { | ... | @@ -498,7 +570,10 @@ fn finishUpdateDecl(self: *Wasm, decl: *Module.Decl, code: []const u8) !void { |
| 498 | atom.size = @intCast(u32, code.len); | 570 | atom.size = @intCast(u32, code.len); |
| 499 | atom.alignment = decl.ty.abiAlignment(self.base.options.target); | 571 | atom.alignment = decl.ty.abiAlignment(self.base.options.target); |
| 500 | const symbol = &self.symbols.items[atom.sym_index]; | 572 | const symbol = &self.symbols.items[atom.sym_index]; |
| 501 | symbol.name = decl.name; | 573 | |
| | 574 | const full_name = try decl.getFullyQualifiedName(self.base.allocator); |
| | 575 | defer self.base.allocator.free(full_name); |
| | 576 | symbol.name = try self.string_table.put(self.base.allocator, full_name); |
| 502 | try atom.code.appendSlice(self.base.allocator, code); | 577 | try atom.code.appendSlice(self.base.allocator, code); |
| 503 | } | 578 | } |
| 504 | | 579 | |
| ... | @@ -511,8 +586,9 @@ pub fn lowerUnnamedConst(self: *Wasm, decl: *Module.Decl, tv: TypedValue) !u32 { | ... | @@ -511,8 +586,9 @@ pub fn lowerUnnamedConst(self: *Wasm, decl: *Module.Decl, tv: TypedValue) !u32 { |
| 511 | // Create and initialize a new local symbol and atom | 586 | // Create and initialize a new local symbol and atom |
| 512 | const local_index = decl.link.wasm.locals.items.len; | 587 | const local_index = decl.link.wasm.locals.items.len; |
| 513 | const name = try std.fmt.allocPrintZ(self.base.allocator, "__unnamed_{s}_{d}", .{ decl.name, local_index }); | 588 | const name = try std.fmt.allocPrintZ(self.base.allocator, "__unnamed_{s}_{d}", .{ decl.name, local_index }); |
| | 589 | defer self.base.allocator.free(name); |
| 514 | var symbol: Symbol = .{ | 590 | var symbol: Symbol = .{ |
| 515 | .name = name, | 591 | .name = try self.string_table.put(self.base.allocator, name), |
| 516 | .flags = 0, | 592 | .flags = 0, |
| 517 | .tag = .data, | 593 | .tag = .data, |
| 518 | .index = undefined, | 594 | .index = undefined, |
| ... | @@ -615,7 +691,7 @@ pub fn deleteExport(self: *Wasm, exp: Export) void { | ... | @@ -615,7 +691,7 @@ pub fn deleteExport(self: *Wasm, exp: Export) void { |
| 615 | const sym_index = exp.sym_index orelse return; | 691 | const sym_index = exp.sym_index orelse return; |
| 616 | const loc: SymbolLoc = .{ .file = null, .index = sym_index }; | 692 | const loc: SymbolLoc = .{ .file = null, .index = sym_index }; |
| 617 | const symbol = loc.getSymbol(self); | 693 | const symbol = loc.getSymbol(self); |
| 618 | const symbol_name = mem.sliceTo(symbol.name, 0); | 694 | const symbol_name = self.string_table.get(symbol.name); |
| 619 | log.debug("Deleting export for decl '{s}'", .{symbol_name}); | 695 | log.debug("Deleting export for decl '{s}'", .{symbol_name}); |
| 620 | if (self.export_names.fetchRemove(loc)) |kv| { | 696 | if (self.export_names.fetchRemove(loc)) |kv| { |
| 621 | assert(self.globals.remove(kv.value)); | 697 | assert(self.globals.remove(kv.value)); |
| ... | @@ -656,7 +732,7 @@ pub fn updateDeclExports( | ... | @@ -656,7 +732,7 @@ pub fn updateDeclExports( |
| 656 | // are strong symbols, we have a linker error. | 732 | // are strong symbols, we have a linker error. |
| 657 | // In the other case we replace one with the other. | 733 | // In the other case we replace one with the other. |
| 658 | if (!exp_is_weak and !existing_sym.isWeak()) { | 734 | if (!exp_is_weak and !existing_sym.isWeak()) { |
| 659 | try module.failed_exports.putNoClobber(module.gpa, exp, try Module.ErrorMsg.create( | 735 | try module.failed_exports.put(module.gpa, exp, try Module.ErrorMsg.create( |
| 660 | module.gpa, | 736 | module.gpa, |
| 661 | decl.srcLoc(), | 737 | decl.srcLoc(), |
| 662 | \\LinkError: symbol '{s}' defined multiple times | 738 | \\LinkError: symbol '{s}' defined multiple times |
| ... | @@ -665,6 +741,7 @@ pub fn updateDeclExports( | ... | @@ -665,6 +741,7 @@ pub fn updateDeclExports( |
| 665 | , | 741 | , |
| 666 | .{ exp.options.name, self.name, self.name }, | 742 | .{ exp.options.name, self.name, self.name }, |
| 667 | )); | 743 | )); |
| | 744 | continue; |
| 668 | } else if (exp_is_weak) { | 745 | } else if (exp_is_weak) { |
| 669 | continue; // to-be-exported symbol is weak, so we keep the existing symbol | 746 | continue; // to-be-exported symbol is weak, so we keep the existing symbol |
| 670 | } else { | 747 | } else { |
| ... | @@ -697,7 +774,7 @@ pub fn updateDeclExports( | ... | @@ -697,7 +774,7 @@ pub fn updateDeclExports( |
| 697 | }, | 774 | }, |
| 698 | } | 775 | } |
| 699 | // Ensure the symbol will be exported using the given name | 776 | // Ensure the symbol will be exported using the given name |
| 700 | if (!mem.eql(u8, exp.options.name, mem.sliceTo(exp.exported_decl.name, 0))) { | 777 | if (!mem.eql(u8, exp.options.name, sym_loc.getName(self))) { |
| 701 | try self.export_names.put(self.base.allocator, sym_loc, exp.options.name); | 778 | try self.export_names.put(self.base.allocator, sym_loc, exp.options.name); |
| 702 | } | 779 | } |
| 703 | | 780 | |
| ... | @@ -725,7 +802,6 @@ pub fn freeDecl(self: *Wasm, decl: *Module.Decl) void { | ... | @@ -725,7 +802,6 @@ pub fn freeDecl(self: *Wasm, decl: *Module.Decl) void { |
| 725 | for (atom.locals.items) |local_atom| { | 802 | for (atom.locals.items) |local_atom| { |
| 726 | const local_symbol = &self.symbols.items[local_atom.sym_index]; | 803 | const local_symbol = &self.symbols.items[local_atom.sym_index]; |
| 727 | local_symbol.tag = .dead; // also for any local symbol | 804 | local_symbol.tag = .dead; // also for any local symbol |
| 728 | self.base.allocator.free(mem.sliceTo(local_symbol.name, 0)); | | |
| 729 | self.symbols_free_list.append(self.base.allocator, local_atom.sym_index) catch {}; | 805 | self.symbols_free_list.append(self.base.allocator, local_atom.sym_index) catch {}; |
| 730 | assert(self.resolved_symbols.swapRemove(local_atom.symbolLoc())); | 806 | assert(self.resolved_symbols.swapRemove(local_atom.symbolLoc())); |
| 731 | } | 807 | } |
| ... | @@ -755,14 +831,15 @@ fn mapFunctionTable(self: *Wasm) void { | ... | @@ -755,14 +831,15 @@ fn mapFunctionTable(self: *Wasm) void { |
| 755 | } | 831 | } |
| 756 | | 832 | |
| 757 | fn addOrUpdateImport(self: *Wasm, decl: *Module.Decl) !void { | 833 | fn addOrUpdateImport(self: *Wasm, decl: *Module.Decl) !void { |
| | 834 | // For the import name itself, we use the decl's name, rather than the fully qualified name |
| | 835 | const decl_name = mem.sliceTo(decl.name, 0); |
| 758 | const symbol_index = decl.link.wasm.sym_index; | 836 | const symbol_index = decl.link.wasm.sym_index; |
| 759 | const symbol: *Symbol = &self.symbols.items[symbol_index]; | 837 | const symbol: *Symbol = &self.symbols.items[symbol_index]; |
| 760 | symbol.name = decl.name; | | |
| 761 | symbol.setUndefined(true); | 838 | symbol.setUndefined(true); |
| 762 | symbol.setGlobal(true); | 839 | symbol.setGlobal(true); |
| 763 | try self.globals.putNoClobber( | 840 | try self.globals.putNoClobber( |
| 764 | self.base.allocator, | 841 | self.base.allocator, |
| 765 | mem.sliceTo(symbol.name, 0), | 842 | decl_name, |
| 766 | .{ .file = null, .index = symbol_index }, | 843 | .{ .file = null, .index = symbol_index }, |
| 767 | ); | 844 | ); |
| 768 | try self.resolved_symbols.put(self.base.allocator, .{ .file = null, .index = symbol_index }, {}); | 845 | try self.resolved_symbols.put(self.base.allocator, .{ .file = null, .index = symbol_index }, {}); |
| ... | @@ -776,7 +853,7 @@ fn addOrUpdateImport(self: *Wasm, decl: *Module.Decl) !void { | ... | @@ -776,7 +853,7 @@ fn addOrUpdateImport(self: *Wasm, decl: *Module.Decl) !void { |
| 776 | if (!gop.found_existing) { | 853 | if (!gop.found_existing) { |
| 777 | gop.value_ptr.* = .{ | 854 | gop.value_ptr.* = .{ |
| 778 | .module_name = module_name, | 855 | .module_name = module_name, |
| 779 | .name = mem.sliceTo(symbol.name, 0), | 856 | .name = decl_name, |
| 780 | .kind = .{ .function = decl.fn_link.wasm.type_index }, | 857 | .kind = .{ .function = decl.fn_link.wasm.type_index }, |
| 781 | }; | 858 | }; |
| 782 | } | 859 | } |
| ... | @@ -815,7 +892,7 @@ fn parseAtom(self: *Wasm, atom: *Atom, kind: Kind) !void { | ... | @@ -815,7 +892,7 @@ fn parseAtom(self: *Wasm, atom: *Atom, kind: Kind) !void { |
| 815 | // TODO: Add mutables global decls to .bss section instead | 892 | // TODO: Add mutables global decls to .bss section instead |
| 816 | const segment_name = try std.mem.concat(self.base.allocator, u8, &.{ | 893 | const segment_name = try std.mem.concat(self.base.allocator, u8, &.{ |
| 817 | ".rodata.", | 894 | ".rodata.", |
| 818 | std.mem.span(symbol.name), | 895 | self.string_table.get(symbol.name), |
| 819 | }); | 896 | }); |
| 820 | errdefer self.base.allocator.free(segment_name); | 897 | errdefer self.base.allocator.free(segment_name); |
| 821 | const segment_info: types.Segment = .{ | 898 | const segment_info: types.Segment = .{ |
| ... | @@ -886,7 +963,7 @@ fn allocateAtoms(self: *Wasm) !void { | ... | @@ -886,7 +963,7 @@ fn allocateAtoms(self: *Wasm) !void { |
| 886 | atom.offset = offset; | 963 | atom.offset = offset; |
| 887 | const symbol_loc = atom.symbolLoc(); | 964 | const symbol_loc = atom.symbolLoc(); |
| 888 | log.debug("Atom '{s}' allocated from 0x{x:0>8} to 0x{x:0>8} size={d}", .{ | 965 | log.debug("Atom '{s}' allocated from 0x{x:0>8} to 0x{x:0>8} size={d}", .{ |
| 889 | symbol_loc.getSymbol(self).name, | 966 | symbol_loc.getName(self), |
| 890 | offset, | 967 | offset, |
| 891 | offset + atom.size, | 968 | offset + atom.size, |
| 892 | atom.size, | 969 | atom.size, |
| ... | @@ -906,7 +983,7 @@ fn setupImports(self: *Wasm) !void { | ... | @@ -906,7 +983,7 @@ fn setupImports(self: *Wasm) !void { |
| 906 | // remove an import if it was resolved | 983 | // remove an import if it was resolved |
| 907 | if (self.imports.remove(discarded.*)) { | 984 | if (self.imports.remove(discarded.*)) { |
| 908 | log.debug("Removed symbol '{s}' as an import", .{ | 985 | log.debug("Removed symbol '{s}' as an import", .{ |
| 909 | discarded.getSymbol(self).name, | 986 | discarded.getName(self), |
| 910 | }); | 987 | }); |
| 911 | } | 988 | } |
| 912 | } | 989 | } |
| ... | @@ -923,7 +1000,7 @@ fn setupImports(self: *Wasm) !void { | ... | @@ -923,7 +1000,7 @@ fn setupImports(self: *Wasm) !void { |
| 923 | continue; | 1000 | continue; |
| 924 | } | 1001 | } |
| 925 | | 1002 | |
| 926 | log.debug("Symbol '{s}' will be imported from the host", .{symbol.name}); | 1003 | log.debug("Symbol '{s}' will be imported from the host", .{symbol_loc.getName(self)}); |
| 927 | const import = self.objects.items[symbol_loc.file.?].findImport(symbol.tag.externalType(), symbol.index); | 1004 | const import = self.objects.items[symbol_loc.file.?].findImport(symbol.tag.externalType(), symbol.index); |
| 928 | // TODO: De-duplicate imports | 1005 | // TODO: De-duplicate imports |
| 929 | try self.imports.putNoClobber(self.base.allocator, symbol_loc, import); | 1006 | try self.imports.putNoClobber(self.base.allocator, symbol_loc, import); |
| ... | @@ -1036,12 +1113,12 @@ fn mergeTypes(self: *Wasm) !void { | ... | @@ -1036,12 +1113,12 @@ fn mergeTypes(self: *Wasm) !void { |
| 1036 | } | 1113 | } |
| 1037 | | 1114 | |
| 1038 | if (symbol.isUndefined()) { | 1115 | if (symbol.isUndefined()) { |
| 1039 | log.debug("Adding type from extern function '{s}'", .{symbol.name}); | 1116 | log.debug("Adding type from extern function '{s}'", .{sym_loc.getName(self)}); |
| 1040 | const import: *wasm.Import = self.imports.getPtr(sym_loc).?; | 1117 | const import: *wasm.Import = self.imports.getPtr(sym_loc).?; |
| 1041 | const original_type = object.func_types[import.kind.function]; | 1118 | const original_type = object.func_types[import.kind.function]; |
| 1042 | import.kind.function = try self.putOrGetFuncType(original_type); | 1119 | import.kind.function = try self.putOrGetFuncType(original_type); |
| 1043 | } else { | 1120 | } else { |
| 1044 | log.debug("Adding type from function '{s}'", .{symbol.name}); | 1121 | log.debug("Adding type from function '{s}'", .{sym_loc.getName(self)}); |
| 1045 | const func = &self.functions.items[symbol.index - self.imported_functions_count]; | 1122 | const func = &self.functions.items[symbol.index - self.imported_functions_count]; |
| 1046 | func.type_index = try self.putOrGetFuncType(object.func_types[func.type_index]); | 1123 | func.type_index = try self.putOrGetFuncType(object.func_types[func.type_index]); |
| 1047 | } | 1124 | } |
| ... | @@ -1057,13 +1134,14 @@ fn setupExports(self: *Wasm) !void { | ... | @@ -1057,13 +1134,14 @@ fn setupExports(self: *Wasm) !void { |
| 1057 | const symbol = sym_loc.getSymbol(self); | 1134 | const symbol = sym_loc.getSymbol(self); |
| 1058 | if (!symbol.isExported()) continue; | 1135 | if (!symbol.isExported()) continue; |
| 1059 | | 1136 | |
| 1060 | const export_name = if (self.export_names.get(sym_loc)) |name| name else mem.sliceTo(symbol.name, 0); | 1137 | const sym_name = sym_loc.getName(self); |
| | 1138 | const export_name = if (self.export_names.get(sym_loc)) |name| name else sym_name; |
| 1061 | const exp: wasm.Export = .{ | 1139 | const exp: wasm.Export = .{ |
| 1062 | .name = export_name, | 1140 | .name = export_name, |
| 1063 | .kind = symbol.tag.externalType(), | 1141 | .kind = symbol.tag.externalType(), |
| 1064 | .index = symbol.index, | 1142 | .index = symbol.index, |
| 1065 | }; | 1143 | }; |
| 1066 | log.debug("Exporting symbol '{s}' as '{s}' at index: ({d})", .{ symbol.name, exp.name, exp.index }); | 1144 | log.debug("Exporting symbol '{s}' as '{s}' at index: ({d})", .{ sym_name, exp.name, exp.index }); |
| 1067 | try self.exports.append(self.base.allocator, exp); | 1145 | try self.exports.append(self.base.allocator, exp); |
| 1068 | } | 1146 | } |
| 1069 | | 1147 | |
| ... | @@ -1670,8 +1748,8 @@ fn emitNameSection(self: *Wasm, file: fs.File, arena: Allocator) !void { | ... | @@ -1670,8 +1748,8 @@ fn emitNameSection(self: *Wasm, file: fs.File, arena: Allocator) !void { |
| 1670 | for (self.resolved_symbols.keys()) |sym_loc| { | 1748 | for (self.resolved_symbols.keys()) |sym_loc| { |
| 1671 | const symbol = sym_loc.getSymbol(self).*; | 1749 | const symbol = sym_loc.getSymbol(self).*; |
| 1672 | switch (symbol.tag) { | 1750 | switch (symbol.tag) { |
| 1673 | .function => funcs.appendAssumeCapacity(.{ .index = symbol.index, .name = mem.sliceTo(symbol.name, 0) }), | 1751 | .function => funcs.appendAssumeCapacity(.{ .index = symbol.index, .name = sym_loc.getName(self) }), |
| 1674 | .global => globals.appendAssumeCapacity(.{ .index = symbol.index, .name = mem.sliceTo(symbol.name, 0) }), | 1752 | .global => globals.appendAssumeCapacity(.{ .index = symbol.index, .name = sym_loc.getName(self) }), |
| 1675 | else => {}, | 1753 | else => {}, |
| 1676 | } | 1754 | } |
| 1677 | } | 1755 | } |
| ... | @@ -2275,11 +2353,11 @@ fn emitSymbolTable(self: *Wasm, file: fs.File, arena: Allocator, symbol_table: * | ... | @@ -2275,11 +2353,11 @@ fn emitSymbolTable(self: *Wasm, file: fs.File, arena: Allocator, symbol_table: * |
| 2275 | try leb.writeULEB128(writer, @enumToInt(symbol.tag)); | 2353 | try leb.writeULEB128(writer, @enumToInt(symbol.tag)); |
| 2276 | try leb.writeULEB128(writer, symbol.flags); | 2354 | try leb.writeULEB128(writer, symbol.flags); |
| 2277 | | 2355 | |
| | 2356 | const sym_name = if (self.export_names.get(sym_loc)) |exp_name| exp_name else sym_loc.getName(self); |
| 2278 | switch (symbol.tag) { | 2357 | switch (symbol.tag) { |
| 2279 | .data => { | 2358 | .data => { |
| 2280 | const name = mem.sliceTo(symbol.name, 0); | 2359 | try leb.writeULEB128(writer, @intCast(u32, sym_name.len)); |
| 2281 | try leb.writeULEB128(writer, @intCast(u32, name.len)); | 2360 | try writer.writeAll(sym_name); |
| 2282 | try writer.writeAll(name); | | |
| 2283 | | 2361 | |
| 2284 | if (symbol.isDefined()) { | 2362 | if (symbol.isDefined()) { |
| 2285 | try leb.writeULEB128(writer, symbol.index); | 2363 | try leb.writeULEB128(writer, symbol.index); |
| ... | @@ -2294,9 +2372,8 @@ fn emitSymbolTable(self: *Wasm, file: fs.File, arena: Allocator, symbol_table: * | ... | @@ -2294,9 +2372,8 @@ fn emitSymbolTable(self: *Wasm, file: fs.File, arena: Allocator, symbol_table: * |
| 2294 | else => { | 2372 | else => { |
| 2295 | try leb.writeULEB128(writer, symbol.index); | 2373 | try leb.writeULEB128(writer, symbol.index); |
| 2296 | if (symbol.isDefined()) { | 2374 | if (symbol.isDefined()) { |
| 2297 | const name = mem.sliceTo(symbol.name, 0); | 2375 | try leb.writeULEB128(writer, @intCast(u32, sym_name.len)); |
| 2298 | try leb.writeULEB128(writer, @intCast(u32, name.len)); | 2376 | try writer.writeAll(sym_name); |
| 2299 | try writer.writeAll(name); | | |
| 2300 | } | 2377 | } |
| 2301 | }, | 2378 | }, |
| 2302 | } | 2379 | } |