authorgravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2022-09-11 17:41:56+02:00
committergravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2022-09-12 21:19:16+02:00
log61f317e3862101a22411ac1f6005ef4ef5b8ab56
treea74b473409a2859c0d0dc41755af9ab2efcd98ae
parent6dbf5f1d8686c1f5b31f3dfce9b1ac0944f8e3a5
signaturelock-open Commit is signed but in an unrecognized format.

wasm-linker: rename self to descriptive name


6 files changed, 957 insertions(+), 959 deletions(-)

src/link/Wasm.zig+758-759
......@@ -8,7 +8,6 @@ const assert = std.debug.assert;
88const fs = std.fs;
99const leb = std.leb;
1010const log = std.log.scoped(.link);
11const wasm = std.wasm;
1211
1312const Atom = @import("Wasm/Atom.zig");
1413const Dwarf = @import("Dwarf.zig");
......@@ -106,17 +105,17 @@ dwarf: ?Dwarf = null,
106105
107106// Output sections
108107/// Output type section
109func_types: std.ArrayListUnmanaged(wasm.Type) = .{},
108func_types: std.ArrayListUnmanaged(std.wasm.Type) = .{},
110109/// Output function section where the key is the original
111110/// function index and the value is function.
112111/// This allows us to map multiple symbols to the same function.
113functions: std.AutoArrayHashMapUnmanaged(struct { file: ?u16, index: u32 }, wasm.Func) = .{},
112functions: std.AutoArrayHashMapUnmanaged(struct { file: ?u16, index: u32 }, std.wasm.Func) = .{},
114113/// Output global section
115wasm_globals: std.ArrayListUnmanaged(wasm.Global) = .{},
114wasm_globals: std.ArrayListUnmanaged(std.wasm.Global) = .{},
116115/// Memory section
117memories: wasm.Memory = .{ .limits = .{ .min = 0, .max = null } },
116memories: std.wasm.Memory = .{ .limits = .{ .min = 0, .max = null } },
118117/// Output table section
119tables: std.ArrayListUnmanaged(wasm.Table) = .{},
118tables: std.ArrayListUnmanaged(std.wasm.Table) = .{},
120119/// Output export section
121120exports: std.ArrayListUnmanaged(types.Export) = .{},
122121
......@@ -203,39 +202,39 @@ pub const SymbolLoc = struct {
203202 file: ?u16,
204203
205204 /// From a given location, returns the corresponding symbol in the wasm binary
206 pub fn getSymbol(self: SymbolLoc, wasm_bin: *const Wasm) *Symbol {
207 if (wasm_bin.discarded.get(self)) |new_loc| {
205 pub fn getSymbol(loc: SymbolLoc, wasm_bin: *const Wasm) *Symbol {
206 if (wasm_bin.discarded.get(loc)) |new_loc| {
208207 return new_loc.getSymbol(wasm_bin);
209208 }
210 if (self.file) |object_index| {
209 if (loc.file) |object_index| {
211210 const object = wasm_bin.objects.items[object_index];
212 return &object.symtable[self.index];
211 return &object.symtable[loc.index];
213212 }
214 return &wasm_bin.symbols.items[self.index];
213 return &wasm_bin.symbols.items[loc.index];
215214 }
216215
217216 /// From a given location, returns the name of the symbol.
218 pub fn getName(self: SymbolLoc, wasm_bin: *const Wasm) []const u8 {
219 if (wasm_bin.discarded.get(self)) |new_loc| {
217 pub fn getName(loc: SymbolLoc, wasm_bin: *const Wasm) []const u8 {
218 if (wasm_bin.discarded.get(loc)) |new_loc| {
220219 return new_loc.getName(wasm_bin);
221220 }
222 if (self.file) |object_index| {
221 if (loc.file) |object_index| {
223222 const object = wasm_bin.objects.items[object_index];
224 return object.string_table.get(object.symtable[self.index].name);
223 return object.string_table.get(object.symtable[loc.index].name);
225224 }
226 return wasm_bin.string_table.get(wasm_bin.symbols.items[self.index].name);
225 return wasm_bin.string_table.get(wasm_bin.symbols.items[loc.index].name);
227226 }
228227
229228 /// From a given symbol location, returns the final location.
230229 /// e.g. when a symbol was resolved and replaced by the symbol
231230 /// in a different file, this will return said location.
232231 /// If the symbol wasn't replaced by another, this will return
233 /// the given location itself.
234 pub fn finalLoc(self: SymbolLoc, wasm_bin: *const Wasm) SymbolLoc {
235 if (wasm_bin.discarded.get(self)) |new_loc| {
232 /// the given location itwasm.
233 pub fn finalLoc(loc: SymbolLoc, wasm_bin: *const Wasm) SymbolLoc {
234 if (wasm_bin.discarded.get(loc)) |new_loc| {
236235 return new_loc.finalLoc(wasm_bin);
237236 }
238 return self;
237 return loc;
239238 }
240239};
241240
......@@ -258,12 +257,12 @@ pub const StringTable = struct {
258257 /// When found, de-duplicates the string and returns the existing offset instead.
259258 /// When the string is not found in the `string_table`, a new entry will be inserted
260259 /// and the new offset to its data will be returned.
261 pub fn put(self: *StringTable, allocator: Allocator, string: []const u8) !u32 {
262 const gop = try self.string_table.getOrPutContextAdapted(
260 pub fn put(table: *StringTable, allocator: Allocator, string: []const u8) !u32 {
261 const gop = try table.string_table.getOrPutContextAdapted(
263262 allocator,
264263 string,
265 std.hash_map.StringIndexAdapter{ .bytes = &self.string_data },
266 .{ .bytes = &self.string_data },
264 std.hash_map.StringIndexAdapter{ .bytes = &table.string_data },
265 .{ .bytes = &table.string_data },
267266 );
268267 if (gop.found_existing) {
269268 const off = gop.key_ptr.*;
......@@ -271,13 +270,13 @@ pub const StringTable = struct {
271270 return off;
272271 }
273272
274 try self.string_data.ensureUnusedCapacity(allocator, string.len + 1);
275 const offset = @intCast(u32, self.string_data.items.len);
273 try table.string_data.ensureUnusedCapacity(allocator, string.len + 1);
274 const offset = @intCast(u32, table.string_data.items.len);
276275
277276 log.debug("writing new string '{s}' at offset 0x{x}", .{ string, offset });
278277
279 self.string_data.appendSliceAssumeCapacity(string);
280 self.string_data.appendAssumeCapacity(0);
278 table.string_data.appendSliceAssumeCapacity(string);
279 table.string_data.appendAssumeCapacity(0);
281280
282281 gop.key_ptr.* = offset;
283282
......@@ -286,26 +285,26 @@ pub const StringTable = struct {
286285
287286 /// From a given offset, returns its corresponding string value.
288287 /// Asserts offset does not exceed bounds.
289 pub fn get(self: StringTable, off: u32) []const u8 {
290 assert(off < self.string_data.items.len);
291 return mem.sliceTo(@ptrCast([*:0]const u8, self.string_data.items.ptr + off), 0);
288 pub fn get(table: StringTable, off: u32) []const u8 {
289 assert(off < table.string_data.items.len);
290 return mem.sliceTo(@ptrCast([*:0]const u8, table.string_data.items.ptr + off), 0);
292291 }
293292
294293 /// Returns the offset of a given string when it exists.
295294 /// Will return null if the given string does not yet exist within the string table.
296 pub fn getOffset(self: *StringTable, string: []const u8) ?u32 {
297 return self.string_table.getKeyAdapted(
295 pub fn getOffset(table: *StringTable, string: []const u8) ?u32 {
296 return table.string_table.getKeyAdapted(
298297 string,
299 std.hash_map.StringIndexAdapter{ .bytes = &self.string_data },
298 std.hash_map.StringIndexAdapter{ .bytes = &table.string_data },
300299 );
301300 }
302301
303302 /// Frees all resources of the string table. Any references pointing
304303 /// to the strings will be invalid.
305 pub fn deinit(self: *StringTable, allocator: Allocator) void {
306 self.string_data.deinit(allocator);
307 self.string_table.deinit(allocator);
308 self.* = undefined;
304 pub fn deinit(table: *StringTable, allocator: Allocator) void {
305 table.string_data.deinit(allocator);
306 table.string_table.deinit(allocator);
307 table.* = undefined;
309308 }
310309};
311310
......@@ -370,9 +369,9 @@ pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Option
370369}
371370
372371pub fn createEmpty(gpa: Allocator, options: link.Options) !*Wasm {
373 const self = try gpa.create(Wasm);
374 errdefer gpa.destroy(self);
375 self.* = .{
372 const wasm = try gpa.create(Wasm);
373 errdefer gpa.destroy(wasm);
374 wasm.* = .{
376375 .base = .{
377376 .tag = .wasm,
378377 .options = options,
......@@ -385,33 +384,33 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*Wasm {
385384 const use_llvm = build_options.have_llvm and options.use_llvm;
386385 const use_stage1 = build_options.have_stage1 and options.use_stage1;
387386 if (use_llvm and !use_stage1) {
388 self.llvm_object = try LlvmObject.create(gpa, options);
387 wasm.llvm_object = try LlvmObject.create(gpa, options);
389388 }
390 return self;
389 return wasm;
391390}
392391
393392/// Initializes symbols and atoms for the debug sections
394393/// Initialization is only done when compiling Zig code.
395394/// When Zig is invoked as a linker instead, the atoms
396395/// and symbols come from the object files instead.
397pub fn initDebugSections(self: *Wasm) !void {
398 if (self.dwarf == null) return; // not compiling Zig code, so no need to pre-initialize debug sections
399 assert(self.debug_info_index == null);
396pub fn initDebugSections(wasm: *Wasm) !void {
397 if (wasm.dwarf == null) return; // not compiling Zig code, so no need to pre-initialize debug sections
398 assert(wasm.debug_info_index == null);
400399 // this will create an Atom and set the index for us.
401 self.debug_info_atom = try self.createDebugSectionForIndex(&self.debug_info_index, ".debug_info");
402 self.debug_line_atom = try self.createDebugSectionForIndex(&self.debug_line_index, ".debug_line");
403 self.debug_loc_atom = try self.createDebugSectionForIndex(&self.debug_loc_index, ".debug_loc");
404 self.debug_abbrev_atom = try self.createDebugSectionForIndex(&self.debug_abbrev_index, ".debug_abbrev");
405 self.debug_ranges_atom = try self.createDebugSectionForIndex(&self.debug_ranges_index, ".debug_ranges");
406 self.debug_str_atom = try self.createDebugSectionForIndex(&self.debug_str_index, ".debug_str");
407 self.debug_pubnames_atom = try self.createDebugSectionForIndex(&self.debug_pubnames_index, ".debug_pubnames");
408 self.debug_pubtypes_atom = try self.createDebugSectionForIndex(&self.debug_pubtypes_index, ".debug_pubtypes");
400 wasm.debug_info_atom = try wasm.createDebugSectionForIndex(&wasm.debug_info_index, ".debug_info");
401 wasm.debug_line_atom = try wasm.createDebugSectionForIndex(&wasm.debug_line_index, ".debug_line");
402 wasm.debug_loc_atom = try wasm.createDebugSectionForIndex(&wasm.debug_loc_index, ".debug_loc");
403 wasm.debug_abbrev_atom = try wasm.createDebugSectionForIndex(&wasm.debug_abbrev_index, ".debug_abbrev");
404 wasm.debug_ranges_atom = try wasm.createDebugSectionForIndex(&wasm.debug_ranges_index, ".debug_ranges");
405 wasm.debug_str_atom = try wasm.createDebugSectionForIndex(&wasm.debug_str_index, ".debug_str");
406 wasm.debug_pubnames_atom = try wasm.createDebugSectionForIndex(&wasm.debug_pubnames_index, ".debug_pubnames");
407 wasm.debug_pubtypes_atom = try wasm.createDebugSectionForIndex(&wasm.debug_pubtypes_index, ".debug_pubtypes");
409408}
410409
411fn parseInputFiles(self: *Wasm, files: []const []const u8) !void {
410fn parseInputFiles(wasm: *Wasm, files: []const []const u8) !void {
412411 for (files) |path| {
413 if (try self.parseObjectFile(path)) continue;
414 if (try self.parseArchive(path, false)) continue; // load archives lazily
412 if (try wasm.parseObjectFile(path)) continue;
413 if (try wasm.parseArchive(path, false)) continue; // load archives lazily
415414 log.warn("Unexpected file format at path: '{s}'", .{path});
416415 }
417416}
......@@ -419,16 +418,16 @@ fn parseInputFiles(self: *Wasm, files: []const []const u8) !void {
419418/// Parses the object file from given path. Returns true when the given file was an object
420419/// file and parsed successfully. Returns false when file is not an object file.
421420/// May return an error instead when parsing failed.
422fn parseObjectFile(self: *Wasm, path: []const u8) !bool {
421fn parseObjectFile(wasm: *Wasm, path: []const u8) !bool {
423422 const file = try fs.cwd().openFile(path, .{});
424423 errdefer file.close();
425424
426 var object = Object.create(self.base.allocator, file, path, null) catch |err| switch (err) {
425 var object = Object.create(wasm.base.allocator, file, path, null) catch |err| switch (err) {
427426 error.InvalidMagicByte, error.NotObjectFile => return false,
428427 else => |e| return e,
429428 };
430 errdefer object.deinit(self.base.allocator);
431 try self.objects.append(self.base.allocator, object);
429 errdefer object.deinit(wasm.base.allocator);
430 try wasm.objects.append(wasm.base.allocator, object);
432431 return true;
433432}
434433
......@@ -440,7 +439,7 @@ fn parseObjectFile(self: *Wasm, path: []const u8) !bool {
440439/// When `force_load` is `true`, it will for link all object files in the archive.
441440/// When false, it will only link with object files that contain symbols that
442441/// are referenced by other object files or Zig code.
443fn parseArchive(self: *Wasm, path: []const u8, force_load: bool) !bool {
442fn parseArchive(wasm: *Wasm, path: []const u8, force_load: bool) !bool {
444443 const file = try fs.cwd().openFile(path, .{});
445444 errdefer file.close();
446445
......@@ -448,25 +447,25 @@ fn parseArchive(self: *Wasm, path: []const u8, force_load: bool) !bool {
448447 .file = file,
449448 .name = path,
450449 };
451 archive.parse(self.base.allocator) catch |err| switch (err) {
450 archive.parse(wasm.base.allocator) catch |err| switch (err) {
452451 error.EndOfStream, error.NotArchive => {
453 archive.deinit(self.base.allocator);
452 archive.deinit(wasm.base.allocator);
454453 return false;
455454 },
456455 else => |e| return e,
457456 };
458457
459458 if (!force_load) {
460 errdefer archive.deinit(self.base.allocator);
461 try self.archives.append(self.base.allocator, archive);
459 errdefer archive.deinit(wasm.base.allocator);
460 try wasm.archives.append(wasm.base.allocator, archive);
462461 return true;
463462 }
464 defer archive.deinit(self.base.allocator);
463 defer archive.deinit(wasm.base.allocator);
465464
466465 // In this case we must force link all embedded object files within the archive
467466 // We loop over all symbols, and then group them by offset as the offset
468467 // notates where the object file starts.
469 var offsets = std.AutoArrayHashMap(u32, void).init(self.base.allocator);
468 var offsets = std.AutoArrayHashMap(u32, void).init(wasm.base.allocator);
470469 defer offsets.deinit();
471470 for (archive.toc.values()) |symbol_offsets| {
472471 for (symbol_offsets.items) |sym_offset| {
......@@ -475,15 +474,15 @@ fn parseArchive(self: *Wasm, path: []const u8, force_load: bool) !bool {
475474 }
476475
477476 for (offsets.keys()) |file_offset| {
478 const object = try self.objects.addOne(self.base.allocator);
479 object.* = try archive.parseObject(self.base.allocator, file_offset);
477 const object = try wasm.objects.addOne(wasm.base.allocator);
478 object.* = try archive.parseObject(wasm.base.allocator, file_offset);
480479 }
481480
482481 return true;
483482}
484483
485fn resolveSymbolsInObject(self: *Wasm, object_index: u16) !void {
486 const object: Object = self.objects.items[object_index];
484fn resolveSymbolsInObject(wasm: *Wasm, object_index: u16) !void {
485 const object: Object = wasm.objects.items[object_index];
487486 log.debug("Resolving symbols in object: '{s}'", .{object.name});
488487
489488 for (object.symtable) |symbol, i| {
......@@ -496,7 +495,7 @@ fn resolveSymbolsInObject(self: *Wasm, object_index: u16) !void {
496495 if (mem.eql(u8, sym_name, "__indirect_function_table")) {
497496 continue;
498497 }
499 const sym_name_index = try self.string_table.put(self.base.allocator, sym_name);
498 const sym_name_index = try wasm.string_table.put(wasm.base.allocator, sym_name);
500499
501500 if (symbol.isLocal()) {
502501 if (symbol.isUndefined()) {
......@@ -504,27 +503,27 @@ fn resolveSymbolsInObject(self: *Wasm, object_index: u16) !void {
504503 log.err(" symbol '{s}' defined in '{s}'", .{ sym_name, object.name });
505504 return error.undefinedLocal;
506505 }
507 try self.resolved_symbols.putNoClobber(self.base.allocator, location, {});
506 try wasm.resolved_symbols.putNoClobber(wasm.base.allocator, location, {});
508507 continue;
509508 }
510509
511 const maybe_existing = try self.globals.getOrPut(self.base.allocator, sym_name_index);
510 const maybe_existing = try wasm.globals.getOrPut(wasm.base.allocator, sym_name_index);
512511 if (!maybe_existing.found_existing) {
513512 maybe_existing.value_ptr.* = location;
514 try self.resolved_symbols.putNoClobber(self.base.allocator, location, {});
513 try wasm.resolved_symbols.putNoClobber(wasm.base.allocator, location, {});
515514
516515 if (symbol.isUndefined()) {
517 try self.undefs.putNoClobber(self.base.allocator, sym_name, location);
516 try wasm.undefs.putNoClobber(wasm.base.allocator, sym_name, location);
518517 }
519518 continue;
520519 }
521520
522521 const existing_loc = maybe_existing.value_ptr.*;
523 const existing_sym: *Symbol = existing_loc.getSymbol(self);
522 const existing_sym: *Symbol = existing_loc.getSymbol(wasm);
524523
525524 const existing_file_path = if (existing_loc.file) |file| blk: {
526 break :blk self.objects.items[file].name;
527 } else self.name;
525 break :blk wasm.objects.items[file].name;
526 } else wasm.name;
528527
529528 if (!existing_sym.isUndefined()) outer: {
530529 if (!symbol.isUndefined()) inner: {
......@@ -541,7 +540,7 @@ fn resolveSymbolsInObject(self: *Wasm, object_index: u16) !void {
541540 return error.SymbolCollision;
542541 }
543542
544 try self.discarded.put(self.base.allocator, location, existing_loc);
543 try wasm.discarded.put(wasm.base.allocator, location, existing_loc);
545544 continue; // Do not overwrite defined symbols with undefined symbols
546545 }
547546
......@@ -554,12 +553,12 @@ fn resolveSymbolsInObject(self: *Wasm, object_index: u16) !void {
554553
555554 if (existing_sym.isUndefined() and symbol.isUndefined()) {
556555 const existing_name = if (existing_loc.file) |file_index| blk: {
557 const obj = self.objects.items[file_index];
556 const obj = wasm.objects.items[file_index];
558557 const name_index = obj.findImport(symbol.tag.externalType(), existing_sym.index).module_name;
559558 break :blk obj.string_table.get(name_index);
560559 } else blk: {
561 const name_index = self.imports.get(existing_loc).?.module_name;
562 break :blk self.string_table.get(name_index);
560 const name_index = wasm.imports.get(existing_loc).?.module_name;
561 break :blk wasm.string_table.get(name_index);
563562 };
564563
565564 const module_index = object.findImport(symbol.tag.externalType(), symbol.index).module_name;
......@@ -577,8 +576,8 @@ fn resolveSymbolsInObject(self: *Wasm, object_index: u16) !void {
577576 }
578577
579578 if (existing_sym.tag == .global) {
580 const existing_ty = self.getGlobalType(existing_loc);
581 const new_ty = self.getGlobalType(location);
579 const existing_ty = wasm.getGlobalType(existing_loc);
580 const new_ty = wasm.getGlobalType(location);
582581 if (existing_ty.mutable != new_ty.mutable or existing_ty.valtype != new_ty.valtype) {
583582 log.err("symbol '{s}' mismatching global types", .{sym_name});
584583 log.err(" first definition in '{s}'", .{existing_file_path});
......@@ -588,8 +587,8 @@ fn resolveSymbolsInObject(self: *Wasm, object_index: u16) !void {
588587 }
589588
590589 if (existing_sym.tag == .function) {
591 const existing_ty = self.getFunctionSignature(existing_loc);
592 const new_ty = self.getFunctionSignature(location);
590 const existing_ty = wasm.getFunctionSignature(existing_loc);
591 const new_ty = wasm.getFunctionSignature(location);
593592 if (!existing_ty.eql(new_ty)) {
594593 log.err("symbol '{s}' mismatching function signatures.", .{sym_name});
595594 log.err(" expected signature {}, but found signature {}", .{ existing_ty, new_ty });
......@@ -601,7 +600,7 @@ fn resolveSymbolsInObject(self: *Wasm, object_index: u16) !void {
601600
602601 // when both symbols are weak, we skip overwriting
603602 if (existing_sym.isWeak() and symbol.isWeak()) {
604 try self.discarded.put(self.base.allocator, location, existing_loc);
603 try wasm.discarded.put(wasm.base.allocator, location, existing_loc);
605604 continue;
606605 }
607606
......@@ -609,27 +608,27 @@ fn resolveSymbolsInObject(self: *Wasm, object_index: u16) !void {
609608 log.debug("Overwriting symbol '{s}'", .{sym_name});
610609 log.debug(" old definition in '{s}'", .{existing_file_path});
611610 log.debug(" new definition in '{s}'", .{object.name});
612 try self.discarded.putNoClobber(self.base.allocator, existing_loc, location);
611 try wasm.discarded.putNoClobber(wasm.base.allocator, existing_loc, location);
613612 maybe_existing.value_ptr.* = location;
614 try self.globals.put(self.base.allocator, sym_name_index, location);
615 try self.resolved_symbols.put(self.base.allocator, location, {});
616 assert(self.resolved_symbols.swapRemove(existing_loc));
613 try wasm.globals.put(wasm.base.allocator, sym_name_index, location);
614 try wasm.resolved_symbols.put(wasm.base.allocator, location, {});
615 assert(wasm.resolved_symbols.swapRemove(existing_loc));
617616 if (existing_sym.isUndefined()) {
618 assert(self.undefs.swapRemove(sym_name));
617 assert(wasm.undefs.swapRemove(sym_name));
619618 }
620619 }
621620}
622621
623fn resolveSymbolsInArchives(self: *Wasm) !void {
624 if (self.archives.items.len == 0) return;
622fn resolveSymbolsInArchives(wasm: *Wasm) !void {
623 if (wasm.archives.items.len == 0) return;
625624
626625 log.debug("Resolving symbols in archives", .{});
627626 var index: u32 = 0;
628 undef_loop: while (index < self.undefs.count()) {
629 const undef_sym_loc = self.undefs.values()[index];
630 const sym_name = undef_sym_loc.getName(self);
627 undef_loop: while (index < wasm.undefs.count()) {
628 const undef_sym_loc = wasm.undefs.values()[index];
629 const sym_name = undef_sym_loc.getName(wasm);
631630
632 for (self.archives.items) |archive| {
631 for (wasm.archives.items) |archive| {
633632 const offset = archive.toc.get(sym_name) orelse {
634633 // symbol does not exist in this archive
635634 continue;
......@@ -639,10 +638,10 @@ fn resolveSymbolsInArchives(self: *Wasm) !void {
639638 // Symbol is found in unparsed object file within current archive.
640639 // Parse object and and resolve symbols again before we check remaining
641640 // undefined symbols.
642 const object_file_index = @intCast(u16, self.objects.items.len);
643 var object = try archive.parseObject(self.base.allocator, offset.items[0]);
644 try self.objects.append(self.base.allocator, object);
645 try self.resolveSymbolsInObject(object_file_index);
641 const object_file_index = @intCast(u16, wasm.objects.items.len);
642 var object = try archive.parseObject(wasm.base.allocator, offset.items[0]);
643 try wasm.objects.append(wasm.base.allocator, object);
644 try wasm.resolveSymbolsInObject(object_file_index);
646645
647646 // continue loop for any remaining undefined symbols that still exist
648647 // after resolving last object file
......@@ -652,18 +651,18 @@ fn resolveSymbolsInArchives(self: *Wasm) !void {
652651 }
653652}
654653
655fn checkUndefinedSymbols(self: *const Wasm) !void {
656 if (self.base.options.output_mode == .Obj) return;
654fn checkUndefinedSymbols(wasm: *const Wasm) !void {
655 if (wasm.base.options.output_mode == .Obj) return;
657656
658657 var found_undefined_symbols = false;
659 for (self.undefs.values()) |undef| {
660 const symbol = undef.getSymbol(self);
658 for (wasm.undefs.values()) |undef| {
659 const symbol = undef.getSymbol(wasm);
661660 if (symbol.tag == .data) {
662661 found_undefined_symbols = true;
663662 const file_name = if (undef.file) |file_index| name: {
664 break :name self.objects.items[file_index].name;
665 } else self.name;
666 log.err("could not resolve undefined symbol '{s}'", .{undef.getName(self)});
663 break :name wasm.objects.items[file_index].name;
664 } else wasm.name;
665 log.err("could not resolve undefined symbol '{s}'", .{undef.getName(wasm)});
667666 log.err(" defined in '{s}'", .{file_name});
668667 }
669668 }
......@@ -672,80 +671,80 @@ fn checkUndefinedSymbols(self: *const Wasm) !void {
672671 }
673672}
674673
675pub fn deinit(self: *Wasm) void {
676 const gpa = self.base.allocator;
674pub fn deinit(wasm: *Wasm) void {
675 const gpa = wasm.base.allocator;
677676 if (build_options.have_llvm) {
678 if (self.llvm_object) |llvm_object| llvm_object.destroy(gpa);
677 if (wasm.llvm_object) |llvm_object| llvm_object.destroy(gpa);
679678 }
680679
681 if (self.base.options.module) |mod| {
682 var decl_it = self.decls.keyIterator();
680 if (wasm.base.options.module) |mod| {
681 var decl_it = wasm.decls.keyIterator();
683682 while (decl_it.next()) |decl_index_ptr| {
684683 const decl = mod.declPtr(decl_index_ptr.*);
685684 decl.link.wasm.deinit(gpa);
686685 }
687686 } else {
688 assert(self.decls.count() == 0);
687 assert(wasm.decls.count() == 0);
689688 }
690689
691 for (self.func_types.items) |*func_type| {
690 for (wasm.func_types.items) |*func_type| {
692691 func_type.deinit(gpa);
693692 }
694 for (self.segment_info.values()) |segment_info| {
693 for (wasm.segment_info.values()) |segment_info| {
695694 gpa.free(segment_info.name);
696695 }
697 for (self.objects.items) |*object| {
696 for (wasm.objects.items) |*object| {
698697 object.deinit(gpa);
699698 }
700699
701 for (self.archives.items) |*archive| {
700 for (wasm.archives.items) |*archive| {
702701 archive.deinit(gpa);
703702 }
704703
705 self.decls.deinit(gpa);
706 self.symbols.deinit(gpa);
707 self.symbols_free_list.deinit(gpa);
708 self.globals.deinit(gpa);
709 self.resolved_symbols.deinit(gpa);
710 self.undefs.deinit(gpa);
711 self.discarded.deinit(gpa);
712 self.symbol_atom.deinit(gpa);
713 self.export_names.deinit(gpa);
714 self.atoms.deinit(gpa);
715 for (self.managed_atoms.items) |managed_atom| {
704 wasm.decls.deinit(gpa);
705 wasm.symbols.deinit(gpa);
706 wasm.symbols_free_list.deinit(gpa);
707 wasm.globals.deinit(gpa);
708 wasm.resolved_symbols.deinit(gpa);
709 wasm.undefs.deinit(gpa);
710 wasm.discarded.deinit(gpa);
711 wasm.symbol_atom.deinit(gpa);
712 wasm.export_names.deinit(gpa);
713 wasm.atoms.deinit(gpa);
714 for (wasm.managed_atoms.items) |managed_atom| {
716715 managed_atom.deinit(gpa);
717716 gpa.destroy(managed_atom);
718717 }
719 self.managed_atoms.deinit(gpa);
720 self.segments.deinit(gpa);
721 self.data_segments.deinit(gpa);
722 self.segment_info.deinit(gpa);
723 self.objects.deinit(gpa);
724 self.archives.deinit(gpa);
718 wasm.managed_atoms.deinit(gpa);
719 wasm.segments.deinit(gpa);
720 wasm.data_segments.deinit(gpa);
721 wasm.segment_info.deinit(gpa);
722 wasm.objects.deinit(gpa);
723 wasm.archives.deinit(gpa);
725724
726725 // free output sections
727 self.imports.deinit(gpa);
728 self.func_types.deinit(gpa);
729 self.functions.deinit(gpa);
730 self.wasm_globals.deinit(gpa);
731 self.function_table.deinit(gpa);
732 self.tables.deinit(gpa);
733 self.exports.deinit(gpa);
726 wasm.imports.deinit(gpa);
727 wasm.func_types.deinit(gpa);
728 wasm.functions.deinit(gpa);
729 wasm.wasm_globals.deinit(gpa);
730 wasm.function_table.deinit(gpa);
731 wasm.tables.deinit(gpa);
732 wasm.exports.deinit(gpa);
734733
735 self.string_table.deinit(gpa);
734 wasm.string_table.deinit(gpa);
736735
737 if (self.dwarf) |*dwarf| {
736 if (wasm.dwarf) |*dwarf| {
738737 dwarf.deinit();
739738 }
740739}
741740
742pub fn allocateDeclIndexes(self: *Wasm, decl_index: Module.Decl.Index) !void {
743 if (self.llvm_object) |_| return;
744 const decl = self.base.options.module.?.declPtr(decl_index);
741pub fn allocateDeclIndexes(wasm: *Wasm, decl_index: Module.Decl.Index) !void {
742 if (wasm.llvm_object) |_| return;
743 const decl = wasm.base.options.module.?.declPtr(decl_index);
745744 if (decl.link.wasm.sym_index != 0) return;
746745
747 try self.symbols.ensureUnusedCapacity(self.base.allocator, 1);
748 try self.decls.putNoClobber(self.base.allocator, decl_index, {});
746 try wasm.symbols.ensureUnusedCapacity(wasm.base.allocator, 1);
747 try wasm.decls.putNoClobber(wasm.base.allocator, decl_index, {});
749748
750749 const atom = &decl.link.wasm;
751750
......@@ -756,22 +755,22 @@ pub fn allocateDeclIndexes(self: *Wasm, decl_index: Module.Decl.Index) !void {
756755 .index = undefined, // will be set after updateDecl
757756 };
758757
759 if (self.symbols_free_list.popOrNull()) |index| {
758 if (wasm.symbols_free_list.popOrNull()) |index| {
760759 atom.sym_index = index;
761 self.symbols.items[index] = symbol;
760 wasm.symbols.items[index] = symbol;
762761 } else {
763 atom.sym_index = @intCast(u32, self.symbols.items.len);
764 self.symbols.appendAssumeCapacity(symbol);
762 atom.sym_index = @intCast(u32, wasm.symbols.items.len);
763 wasm.symbols.appendAssumeCapacity(symbol);
765764 }
766 try self.symbol_atom.putNoClobber(self.base.allocator, atom.symbolLoc(), atom);
765 try wasm.symbol_atom.putNoClobber(wasm.base.allocator, atom.symbolLoc(), atom);
767766}
768767
769pub fn updateFunc(self: *Wasm, mod: *Module, func: *Module.Fn, air: Air, liveness: Liveness) !void {
768pub fn updateFunc(wasm: *Wasm, mod: *Module, func: *Module.Fn, air: Air, liveness: Liveness) !void {
770769 if (build_options.skip_non_native and builtin.object_format != .wasm) {
771770 @panic("Attempted to compile for object format that was disabled by build configuration");
772771 }
773772 if (build_options.have_llvm) {
774 if (self.llvm_object) |llvm_object| return llvm_object.updateFunc(mod, func, air, liveness);
773 if (wasm.llvm_object) |llvm_object| return llvm_object.updateFunc(mod, func, air, liveness);
775774 }
776775
777776 const tracy = trace(@src());
......@@ -783,13 +782,13 @@ pub fn updateFunc(self: *Wasm, mod: *Module, func: *Module.Fn, air: Air, livenes
783782
784783 decl.link.wasm.clear();
785784
786 var decl_state: ?Dwarf.DeclState = if (self.dwarf) |*dwarf| try dwarf.initDeclState(mod, decl) else null;
785 var decl_state: ?Dwarf.DeclState = if (wasm.dwarf) |*dwarf| try dwarf.initDeclState(mod, decl) else null;
787786 defer if (decl_state) |*ds| ds.deinit();
788787
789 var code_writer = std.ArrayList(u8).init(self.base.allocator);
788 var code_writer = std.ArrayList(u8).init(wasm.base.allocator);
790789 defer code_writer.deinit();
791790 const result = try codegen.generateFunction(
792 &self.base,
791 &wasm.base,
793792 decl.srcLoc(),
794793 func,
795794 air,
......@@ -807,9 +806,9 @@ pub fn updateFunc(self: *Wasm, mod: *Module, func: *Module.Fn, air: Air, livenes
807806 },
808807 };
809808
810 if (self.dwarf) |*dwarf| {
809 if (wasm.dwarf) |*dwarf| {
811810 try dwarf.commitDeclState(
812 &self.base,
811 &wasm.base,
813812 mod,
814813 decl,
815814 // Actual value will be written after relocation.
......@@ -820,17 +819,17 @@ pub fn updateFunc(self: *Wasm, mod: *Module, func: *Module.Fn, air: Air, livenes
820819 &decl_state.?,
821820 );
822821 }
823 return self.finishUpdateDecl(decl, code);
822 return wasm.finishUpdateDecl(decl, code);
824823}
825824
826825// Generate code for the Decl, storing it in memory to be later written to
827826// the file on flush().
828pub fn updateDecl(self: *Wasm, mod: *Module, decl_index: Module.Decl.Index) !void {
827pub fn updateDecl(wasm: *Wasm, mod: *Module, decl_index: Module.Decl.Index) !void {
829828 if (build_options.skip_non_native and builtin.object_format != .wasm) {
830829 @panic("Attempted to compile for object format that was disabled by build configuration");
831830 }
832831 if (build_options.have_llvm) {
833 if (self.llvm_object) |llvm_object| return llvm_object.updateDecl(mod, decl_index);
832 if (wasm.llvm_object) |llvm_object| return llvm_object.updateDecl(mod, decl_index);
834833 }
835834
836835 const tracy = trace(@src());
......@@ -850,15 +849,15 @@ pub fn updateDecl(self: *Wasm, mod: *Module, decl_index: Module.Decl.Index) !voi
850849 if (decl.isExtern()) {
851850 const variable = decl.getVariable().?;
852851 const name = mem.sliceTo(decl.name, 0);
853 return self.addOrUpdateImport(name, decl.link.wasm.sym_index, variable.lib_name, null);
852 return wasm.addOrUpdateImport(name, decl.link.wasm.sym_index, variable.lib_name, null);
854853 }
855854 const val = if (decl.val.castTag(.variable)) |payload| payload.data.init else decl.val;
856855
857 var code_writer = std.ArrayList(u8).init(self.base.allocator);
856 var code_writer = std.ArrayList(u8).init(wasm.base.allocator);
858857 defer code_writer.deinit();
859858
860859 const res = try codegen.generateSymbol(
861 &self.base,
860 &wasm.base,
862861 decl.srcLoc(),
863862 .{ .ty = decl.ty, .val = val },
864863 &code_writer,
......@@ -876,46 +875,46 @@ pub fn updateDecl(self: *Wasm, mod: *Module, decl_index: Module.Decl.Index) !voi
876875 },
877876 };
878877
879 return self.finishUpdateDecl(decl, code);
878 return wasm.finishUpdateDecl(decl, code);
880879}
881880
882pub fn updateDeclLineNumber(self: *Wasm, mod: *Module, decl: *const Module.Decl) !void {
883 if (self.llvm_object) |_| return;
884 if (self.dwarf) |*dw| {
881pub fn updateDeclLineNumber(wasm: *Wasm, mod: *Module, decl: *const Module.Decl) !void {
882 if (wasm.llvm_object) |_| return;
883 if (wasm.dwarf) |*dw| {
885884 const tracy = trace(@src());
886885 defer tracy.end();
887886
888887 const decl_name = try decl.getFullyQualifiedName(mod);
889 defer self.base.allocator.free(decl_name);
888 defer wasm.base.allocator.free(decl_name);
890889
891890 log.debug("updateDeclLineNumber {s}{*}", .{ decl_name, decl });
892 try dw.updateDeclLineNumber(&self.base, decl);
891 try dw.updateDeclLineNumber(&wasm.base, decl);
893892 }
894893}
895894
896fn finishUpdateDecl(self: *Wasm, decl: *Module.Decl, code: []const u8) !void {
897 const mod = self.base.options.module.?;
895fn finishUpdateDecl(wasm: *Wasm, decl: *Module.Decl, code: []const u8) !void {
896 const mod = wasm.base.options.module.?;
898897 const atom: *Atom = &decl.link.wasm;
899 const symbol = &self.symbols.items[atom.sym_index];
898 const symbol = &wasm.symbols.items[atom.sym_index];
900899 const full_name = try decl.getFullyQualifiedName(mod);
901 defer self.base.allocator.free(full_name);
902 symbol.name = try self.string_table.put(self.base.allocator, full_name);
903 try atom.code.appendSlice(self.base.allocator, code);
904 try self.resolved_symbols.put(self.base.allocator, atom.symbolLoc(), {});
900 defer wasm.base.allocator.free(full_name);
901 symbol.name = try wasm.string_table.put(wasm.base.allocator, full_name);
902 try atom.code.appendSlice(wasm.base.allocator, code);
903 try wasm.resolved_symbols.put(wasm.base.allocator, atom.symbolLoc(), {});
905904
906905 if (code.len == 0) return;
907906 atom.size = @intCast(u32, code.len);
908 atom.alignment = decl.ty.abiAlignment(self.base.options.target);
907 atom.alignment = decl.ty.abiAlignment(wasm.base.options.target);
909908}
910909
911910/// From a given symbol location, returns its `wasm.GlobalType`.
912911/// Asserts the Symbol represents a global.
913fn getGlobalType(self: *const Wasm, loc: SymbolLoc) wasm.GlobalType {
914 const symbol = loc.getSymbol(self);
912fn getGlobalType(wasm: *const Wasm, loc: SymbolLoc) std.wasm.GlobalType {
913 const symbol = loc.getSymbol(wasm);
915914 assert(symbol.tag == .global);
916915 const is_undefined = symbol.isUndefined();
917916 if (loc.file) |file_index| {
918 const obj: Object = self.objects.items[file_index];
917 const obj: Object = wasm.objects.items[file_index];
919918 if (is_undefined) {
920919 return obj.findImport(.global, symbol.index).kind.global;
921920 }
......@@ -923,19 +922,19 @@ fn getGlobalType(self: *const Wasm, loc: SymbolLoc) wasm.GlobalType {
923922 return obj.globals[symbol.index - import_global_count].global_type;
924923 }
925924 if (is_undefined) {
926 return self.imports.get(loc).?.kind.global;
925 return wasm.imports.get(loc).?.kind.global;
927926 }
928 return self.wasm_globals.items[symbol.index].global_type;
927 return wasm.wasm_globals.items[symbol.index].global_type;
929928}
930929
931930/// From a given symbol location, returns its `wasm.Type`.
932931/// Asserts the Symbol represents a function.
933fn getFunctionSignature(self: *const Wasm, loc: SymbolLoc) wasm.Type {
934 const symbol = loc.getSymbol(self);
932fn getFunctionSignature(wasm: *const Wasm, loc: SymbolLoc) std.wasm.Type {
933 const symbol = loc.getSymbol(wasm);
935934 assert(symbol.tag == .function);
936935 const is_undefined = symbol.isUndefined();
937936 if (loc.file) |file_index| {
938 const obj: Object = self.objects.items[file_index];
937 const obj: Object = wasm.objects.items[file_index];
939938 if (is_undefined) {
940939 const ty_index = obj.findImport(.function, symbol.index).kind.function;
941940 return obj.func_types[ty_index];
......@@ -945,55 +944,55 @@ fn getFunctionSignature(self: *const Wasm, loc: SymbolLoc) wasm.Type {
945944 return obj.func_types[type_index];
946945 }
947946 if (is_undefined) {
948 const ty_index = self.imports.get(loc).?.kind.function;
949 return self.func_types.items[ty_index];
947 const ty_index = wasm.imports.get(loc).?.kind.function;
948 return wasm.func_types.items[ty_index];
950949 }
951 return self.func_types.items[self.functions.get(.{ .file = loc.file, .index = loc.index }).?.type_index];
950 return wasm.func_types.items[wasm.functions.get(.{ .file = loc.file, .index = loc.index }).?.type_index];
952951}
953952
954953/// Lowers a constant typed value to a local symbol and atom.
955954/// Returns the symbol index of the local
956955/// The given `decl` is the parent decl whom owns the constant.
957pub fn lowerUnnamedConst(self: *Wasm, tv: TypedValue, decl_index: Module.Decl.Index) !u32 {
956pub fn lowerUnnamedConst(wasm: *Wasm, tv: TypedValue, decl_index: Module.Decl.Index) !u32 {
958957 assert(tv.ty.zigTypeTag() != .Fn); // cannot create local symbols for functions
959958
960 const mod = self.base.options.module.?;
959 const mod = wasm.base.options.module.?;
961960 const decl = mod.declPtr(decl_index);
962961
963962 // Create and initialize a new local symbol and atom
964963 const local_index = decl.link.wasm.locals.items.len;
965964 const fqdn = try decl.getFullyQualifiedName(mod);
966 defer self.base.allocator.free(fqdn);
967 const name = try std.fmt.allocPrintZ(self.base.allocator, "__unnamed_{s}_{d}", .{ fqdn, local_index });
968 defer self.base.allocator.free(name);
965 defer wasm.base.allocator.free(fqdn);
966 const name = try std.fmt.allocPrintZ(wasm.base.allocator, "__unnamed_{s}_{d}", .{ fqdn, local_index });
967 defer wasm.base.allocator.free(name);
969968 var symbol: Symbol = .{
970 .name = try self.string_table.put(self.base.allocator, name),
969 .name = try wasm.string_table.put(wasm.base.allocator, name),
971970 .flags = 0,
972971 .tag = .data,
973972 .index = undefined,
974973 };
975974 symbol.setFlag(.WASM_SYM_BINDING_LOCAL);
976975
977 const atom = try decl.link.wasm.locals.addOne(self.base.allocator);
976 const atom = try decl.link.wasm.locals.addOne(wasm.base.allocator);
978977 atom.* = Atom.empty;
979 atom.alignment = tv.ty.abiAlignment(self.base.options.target);
980 try self.symbols.ensureUnusedCapacity(self.base.allocator, 1);
978 atom.alignment = tv.ty.abiAlignment(wasm.base.options.target);
979 try wasm.symbols.ensureUnusedCapacity(wasm.base.allocator, 1);
981980
982 if (self.symbols_free_list.popOrNull()) |index| {
981 if (wasm.symbols_free_list.popOrNull()) |index| {
983982 atom.sym_index = index;
984 self.symbols.items[index] = symbol;
983 wasm.symbols.items[index] = symbol;
985984 } else {
986 atom.sym_index = @intCast(u32, self.symbols.items.len);
987 self.symbols.appendAssumeCapacity(symbol);
985 atom.sym_index = @intCast(u32, wasm.symbols.items.len);
986 wasm.symbols.appendAssumeCapacity(symbol);
988987 }
989 try self.resolved_symbols.putNoClobber(self.base.allocator, atom.symbolLoc(), {});
990 try self.symbol_atom.putNoClobber(self.base.allocator, atom.symbolLoc(), atom);
988 try wasm.resolved_symbols.putNoClobber(wasm.base.allocator, atom.symbolLoc(), {});
989 try wasm.symbol_atom.putNoClobber(wasm.base.allocator, atom.symbolLoc(), atom);
991990
992 var value_bytes = std.ArrayList(u8).init(self.base.allocator);
991 var value_bytes = std.ArrayList(u8).init(wasm.base.allocator);
993992 defer value_bytes.deinit();
994993
995994 const result = try codegen.generateSymbol(
996 &self.base,
995 &wasm.base,
997996 decl.srcLoc(),
998997 tv,
999998 &value_bytes,
......@@ -1014,7 +1013,7 @@ pub fn lowerUnnamedConst(self: *Wasm, tv: TypedValue, decl_index: Module.Decl.In
10141013 };
10151014
10161015 atom.size = @intCast(u32, code.len);
1017 try atom.code.appendSlice(self.base.allocator, code);
1016 try atom.code.appendSlice(wasm.base.allocator, code);
10181017 return atom.sym_index;
10191018}
10201019
......@@ -1022,9 +1021,9 @@ pub fn lowerUnnamedConst(self: *Wasm, tv: TypedValue, decl_index: Module.Decl.In
10221021/// such as an exported or imported symbol.
10231022/// If the symbol does not yet exist, creates a new one symbol instead
10241023/// and then returns the index to it.
1025pub fn getGlobalSymbol(self: *Wasm, name: []const u8) !u32 {
1026 const name_index = try self.string_table.put(self.base.allocator, name);
1027 const gop = try self.globals.getOrPut(self.base.allocator, name_index);
1024pub fn getGlobalSymbol(wasm: *Wasm, name: []const u8) !u32 {
1025 const name_index = try wasm.string_table.put(wasm.base.allocator, name);
1026 const gop = try wasm.globals.getOrPut(wasm.base.allocator, name_index);
10281027 if (gop.found_existing) {
10291028 return gop.value_ptr.*.index;
10301029 }
......@@ -1038,46 +1037,46 @@ pub fn getGlobalSymbol(self: *Wasm, name: []const u8) !u32 {
10381037 symbol.setGlobal(true);
10391038 symbol.setUndefined(true);
10401039
1041 const sym_index = if (self.symbols_free_list.popOrNull()) |index| index else blk: {
1042 var index = @intCast(u32, self.symbols.items.len);
1043 try self.symbols.ensureUnusedCapacity(self.base.allocator, 1);
1044 self.symbols.items.len += 1;
1040 const sym_index = if (wasm.symbols_free_list.popOrNull()) |index| index else blk: {
1041 var index = @intCast(u32, wasm.symbols.items.len);
1042 try wasm.symbols.ensureUnusedCapacity(wasm.base.allocator, 1);
1043 wasm.symbols.items.len += 1;
10451044 break :blk index;
10461045 };
1047 self.symbols.items[sym_index] = symbol;
1046 wasm.symbols.items[sym_index] = symbol;
10481047 gop.value_ptr.* = .{ .index = sym_index, .file = null };
1049 try self.resolved_symbols.put(self.base.allocator, gop.value_ptr.*, {});
1050 try self.undefs.putNoClobber(self.base.allocator, name, gop.value_ptr.*);
1048 try wasm.resolved_symbols.put(wasm.base.allocator, gop.value_ptr.*, {});
1049 try wasm.undefs.putNoClobber(wasm.base.allocator, name, gop.value_ptr.*);
10511050 return sym_index;
10521051}
10531052
10541053/// For a given decl, find the given symbol index's atom, and create a relocation for the type.
10551054/// Returns the given pointer address
10561055pub fn getDeclVAddr(
1057 self: *Wasm,
1056 wasm: *Wasm,
10581057 decl_index: Module.Decl.Index,
10591058 reloc_info: link.File.RelocInfo,
10601059) !u64 {
1061 const mod = self.base.options.module.?;
1060 const mod = wasm.base.options.module.?;
10621061 const decl = mod.declPtr(decl_index);
10631062 const target_symbol_index = decl.link.wasm.sym_index;
10641063 assert(target_symbol_index != 0);
10651064 assert(reloc_info.parent_atom_index != 0);
1066 const atom = self.symbol_atom.get(.{ .file = null, .index = reloc_info.parent_atom_index }).?;
1067 const is_wasm32 = self.base.options.target.cpu.arch == .wasm32;
1065 const atom = wasm.symbol_atom.get(.{ .file = null, .index = reloc_info.parent_atom_index }).?;
1066 const is_wasm32 = wasm.base.options.target.cpu.arch == .wasm32;
10681067 if (decl.ty.zigTypeTag() == .Fn) {
10691068 assert(reloc_info.addend == 0); // addend not allowed for function relocations
10701069 // We found a function pointer, so add it to our table,
10711070 // as function pointers are not allowed to be stored inside the data section.
10721071 // They are instead stored in a function table which are called by index.
1073 try self.addTableFunction(target_symbol_index);
1074 try atom.relocs.append(self.base.allocator, .{
1072 try wasm.addTableFunction(target_symbol_index);
1073 try atom.relocs.append(wasm.base.allocator, .{
10751074 .index = target_symbol_index,
10761075 .offset = @intCast(u32, reloc_info.offset),
10771076 .relocation_type = if (is_wasm32) .R_WASM_TABLE_INDEX_I32 else .R_WASM_TABLE_INDEX_I64,
10781077 });
10791078 } else {
1080 try atom.relocs.append(self.base.allocator, .{
1079 try atom.relocs.append(wasm.base.allocator, .{
10811080 .index = target_symbol_index,
10821081 .offset = @intCast(u32, reloc_info.offset),
10831082 .relocation_type = if (is_wasm32) .R_WASM_MEMORY_ADDR_I32 else .R_WASM_MEMORY_ADDR_I64,
......@@ -1091,22 +1090,22 @@ pub fn getDeclVAddr(
10911090 return target_symbol_index;
10921091}
10931092
1094pub fn deleteExport(self: *Wasm, exp: Export) void {
1095 if (self.llvm_object) |_| return;
1093pub fn deleteExport(wasm: *Wasm, exp: Export) void {
1094 if (wasm.llvm_object) |_| return;
10961095 const sym_index = exp.sym_index orelse return;
10971096 const loc: SymbolLoc = .{ .file = null, .index = sym_index };
1098 const symbol = loc.getSymbol(self);
1099 const symbol_name = self.string_table.get(symbol.name);
1097 const symbol = loc.getSymbol(wasm);
1098 const symbol_name = wasm.string_table.get(symbol.name);
11001099 log.debug("Deleting export for decl '{s}'", .{symbol_name});
1101 if (self.export_names.fetchRemove(loc)) |kv| {
1102 assert(self.globals.remove(kv.value));
1100 if (wasm.export_names.fetchRemove(loc)) |kv| {
1101 assert(wasm.globals.remove(kv.value));
11031102 } else {
1104 assert(self.globals.remove(symbol.name));
1103 assert(wasm.globals.remove(symbol.name));
11051104 }
11061105}
11071106
11081107pub fn updateDeclExports(
1109 self: *Wasm,
1108 wasm: *Wasm,
11101109 mod: *Module,
11111110 decl_index: Module.Decl.Index,
11121111 exports: []const *Module.Export,
......@@ -1115,7 +1114,7 @@ pub fn updateDeclExports(
11151114 @panic("Attempted to compile for object format that was disabled by build configuration");
11161115 }
11171116 if (build_options.have_llvm) {
1118 if (self.llvm_object) |llvm_object| return llvm_object.updateDeclExports(mod, decl_index, exports);
1117 if (wasm.llvm_object) |llvm_object| return llvm_object.updateDeclExports(mod, decl_index, exports);
11191118 }
11201119
11211120 const decl = mod.declPtr(decl_index);
......@@ -1131,10 +1130,10 @@ pub fn updateDeclExports(
11311130 continue;
11321131 }
11331132
1134 const export_name = try self.string_table.put(self.base.allocator, exp.options.name);
1135 if (self.globals.getPtr(export_name)) |existing_loc| {
1133 const export_name = try wasm.string_table.put(wasm.base.allocator, exp.options.name);
1134 if (wasm.globals.getPtr(export_name)) |existing_loc| {
11361135 if (existing_loc.index == decl.link.wasm.sym_index) continue;
1137 const existing_sym: Symbol = existing_loc.getSymbol(self).*;
1136 const existing_sym: Symbol = existing_loc.getSymbol(wasm).*;
11381137
11391138 const exp_is_weak = exp.options.linkage == .Internal or exp.options.linkage == .Weak;
11401139 // When both the to-bo-exported symbol and the already existing symbol
......@@ -1148,7 +1147,7 @@ pub fn updateDeclExports(
11481147 \\ first definition in '{s}'
11491148 \\ next definition in '{s}'
11501149 ,
1151 .{ exp.options.name, self.name, self.name },
1150 .{ exp.options.name, wasm.name, wasm.name },
11521151 ));
11531152 continue;
11541153 } else if (exp_is_weak) {
......@@ -1163,7 +1162,7 @@ pub fn updateDeclExports(
11631162 const exported_decl = mod.declPtr(exp.exported_decl);
11641163 const sym_index = exported_decl.link.wasm.sym_index;
11651164 const sym_loc = exported_decl.link.wasm.symbolLoc();
1166 const symbol = sym_loc.getSymbol(self);
1165 const symbol = sym_loc.getSymbol(wasm);
11671166 switch (exp.options.linkage) {
11681167 .Internal => {
11691168 symbol.setFlag(.WASM_SYM_VISIBILITY_HIDDEN);
......@@ -1183,68 +1182,68 @@ pub fn updateDeclExports(
11831182 },
11841183 }
11851184 // Ensure the symbol will be exported using the given name
1186 if (!mem.eql(u8, exp.options.name, sym_loc.getName(self))) {
1187 try self.export_names.put(self.base.allocator, sym_loc, export_name);
1185 if (!mem.eql(u8, exp.options.name, sym_loc.getName(wasm))) {
1186 try wasm.export_names.put(wasm.base.allocator, sym_loc, export_name);
11881187 }
11891188
11901189 symbol.setGlobal(true);
11911190 symbol.setUndefined(false);
1192 try self.globals.put(
1193 self.base.allocator,
1191 try wasm.globals.put(
1192 wasm.base.allocator,
11941193 export_name,
11951194 sym_loc,
11961195 );
11971196
11981197 // if the symbol was previously undefined, remove it as an import
1199 _ = self.imports.remove(sym_loc);
1200 _ = self.undefs.swapRemove(exp.options.name);
1198 _ = wasm.imports.remove(sym_loc);
1199 _ = wasm.undefs.swapRemove(exp.options.name);
12011200 exp.link.wasm.sym_index = sym_index;
12021201 }
12031202}
12041203
1205pub fn freeDecl(self: *Wasm, decl_index: Module.Decl.Index) void {
1204pub fn freeDecl(wasm: *Wasm, decl_index: Module.Decl.Index) void {
12061205 if (build_options.have_llvm) {
1207 if (self.llvm_object) |llvm_object| return llvm_object.freeDecl(decl_index);
1206 if (wasm.llvm_object) |llvm_object| return llvm_object.freeDecl(decl_index);
12081207 }
1209 const mod = self.base.options.module.?;
1208 const mod = wasm.base.options.module.?;
12101209 const decl = mod.declPtr(decl_index);
12111210 const atom = &decl.link.wasm;
1212 self.symbols_free_list.append(self.base.allocator, atom.sym_index) catch {};
1213 _ = self.decls.remove(decl_index);
1214 self.symbols.items[atom.sym_index].tag = .dead;
1211 wasm.symbols_free_list.append(wasm.base.allocator, atom.sym_index) catch {};
1212 _ = wasm.decls.remove(decl_index);
1213 wasm.symbols.items[atom.sym_index].tag = .dead;
12151214 for (atom.locals.items) |local_atom| {
1216 const local_symbol = &self.symbols.items[local_atom.sym_index];
1215 const local_symbol = &wasm.symbols.items[local_atom.sym_index];
12171216 local_symbol.tag = .dead; // also for any local symbol
1218 self.symbols_free_list.append(self.base.allocator, local_atom.sym_index) catch {};
1219 assert(self.resolved_symbols.swapRemove(local_atom.symbolLoc()));
1220 assert(self.symbol_atom.remove(local_atom.symbolLoc()));
1217 wasm.symbols_free_list.append(wasm.base.allocator, local_atom.sym_index) catch {};
1218 assert(wasm.resolved_symbols.swapRemove(local_atom.symbolLoc()));
1219 assert(wasm.symbol_atom.remove(local_atom.symbolLoc()));
12211220 }
12221221
12231222 if (decl.isExtern()) {
1224 _ = self.imports.remove(atom.symbolLoc());
1223 _ = wasm.imports.remove(atom.symbolLoc());
12251224 }
1226 _ = self.resolved_symbols.swapRemove(atom.symbolLoc());
1227 _ = self.symbol_atom.remove(atom.symbolLoc());
1225 _ = wasm.resolved_symbols.swapRemove(atom.symbolLoc());
1226 _ = wasm.symbol_atom.remove(atom.symbolLoc());
12281227
1229 if (self.dwarf) |*dwarf| {
1228 if (wasm.dwarf) |*dwarf| {
12301229 dwarf.freeDecl(decl);
12311230 dwarf.freeAtom(&atom.dbg_info_atom);
12321231 }
12331232
1234 atom.deinit(self.base.allocator);
1233 atom.deinit(wasm.base.allocator);
12351234}
12361235
12371236/// Appends a new entry to the indirect function table
1238pub fn addTableFunction(self: *Wasm, symbol_index: u32) !void {
1239 const index = @intCast(u32, self.function_table.count());
1240 try self.function_table.put(self.base.allocator, .{ .file = null, .index = symbol_index }, index);
1237pub fn addTableFunction(wasm: *Wasm, symbol_index: u32) !void {
1238 const index = @intCast(u32, wasm.function_table.count());
1239 try wasm.function_table.put(wasm.base.allocator, .{ .file = null, .index = symbol_index }, index);
12411240}
12421241
12431242/// Assigns indexes to all indirect functions.
12441243/// Starts at offset 1, where the value `0` represents an unresolved function pointer
12451244/// or null-pointer
1246fn mapFunctionTable(self: *Wasm) void {
1247 var it = self.function_table.valueIterator();
1245fn mapFunctionTable(wasm: *Wasm) void {
1246 var it = wasm.function_table.valueIterator();
12481247 var index: u32 = 1;
12491248 while (it.next()) |value_ptr| : (index += 1) {
12501249 value_ptr.* = index;
......@@ -1255,7 +1254,7 @@ fn mapFunctionTable(self: *Wasm) void {
12551254/// When `type_index` is non-null, we assume an external function.
12561255/// In all other cases, a data-symbol will be created instead.
12571256pub fn addOrUpdateImport(
1258 self: *Wasm,
1257 wasm: *Wasm,
12591258 /// Name of the import
12601259 name: []const u8,
12611260 /// Symbol index that is external
......@@ -1268,28 +1267,28 @@ pub fn addOrUpdateImport(
12681267 type_index: ?u32,
12691268) !void {
12701269 assert(symbol_index != 0);
1271 // For the import name itself, we use the decl's name, rather than the fully qualified name
1272 const decl_name_index = try self.string_table.put(self.base.allocator, name);
1273 const symbol: *Symbol = &self.symbols.items[symbol_index];
1270 // For the import name itwasm, we use the decl's name, rather than the fully qualified name
1271 const decl_name_index = try wasm.string_table.put(wasm.base.allocator, name);
1272 const symbol: *Symbol = &wasm.symbols.items[symbol_index];
12741273 symbol.setUndefined(true);
12751274 symbol.setGlobal(true);
12761275 symbol.name = decl_name_index;
1277 const global_gop = try self.globals.getOrPut(self.base.allocator, decl_name_index);
1276 const global_gop = try wasm.globals.getOrPut(wasm.base.allocator, decl_name_index);
12781277 if (!global_gop.found_existing) {
12791278 const loc: SymbolLoc = .{ .file = null, .index = symbol_index };
12801279 global_gop.value_ptr.* = loc;
1281 try self.resolved_symbols.put(self.base.allocator, loc, {});
1282 try self.undefs.putNoClobber(self.base.allocator, name, loc);
1280 try wasm.resolved_symbols.put(wasm.base.allocator, loc, {});
1281 try wasm.undefs.putNoClobber(wasm.base.allocator, name, loc);
12831282 }
12841283
12851284 if (type_index) |ty_index| {
1286 const gop = try self.imports.getOrPut(self.base.allocator, .{ .index = symbol_index, .file = null });
1285 const gop = try wasm.imports.getOrPut(wasm.base.allocator, .{ .index = symbol_index, .file = null });
12871286 const module_name = if (lib_name) |l_name| blk: {
12881287 break :blk mem.sliceTo(l_name, 0);
1289 } else self.host_name;
1288 } else wasm.host_name;
12901289 if (!gop.found_existing) {
12911290 gop.value_ptr.* = .{
1292 .module_name = try self.string_table.put(self.base.allocator, module_name),
1291 .module_name = try wasm.string_table.put(wasm.base.allocator, module_name),
12931292 .name = decl_name_index,
12941293 .kind = .{ .function = ty_index },
12951294 };
......@@ -1326,36 +1325,36 @@ const Kind = union(enum) {
13261325};
13271326
13281327/// Parses an Atom and inserts its metadata into the corresponding sections.
1329fn parseAtom(self: *Wasm, atom: *Atom, kind: Kind) !void {
1330 const symbol = (SymbolLoc{ .file = null, .index = atom.sym_index }).getSymbol(self);
1328fn parseAtom(wasm: *Wasm, atom: *Atom, kind: Kind) !void {
1329 const symbol = (SymbolLoc{ .file = null, .index = atom.sym_index }).getSymbol(wasm);
13311330 const final_index: u32 = switch (kind) {
13321331 .function => |fn_data| result: {
1333 const index = @intCast(u32, self.functions.count() + self.imported_functions_count);
1334 try self.functions.putNoClobber(
1335 self.base.allocator,
1332 const index = @intCast(u32, wasm.functions.count() + wasm.imported_functions_count);
1333 try wasm.functions.putNoClobber(
1334 wasm.base.allocator,
13361335 .{ .file = null, .index = index },
13371336 .{ .type_index = fn_data.type_index },
13381337 );
13391338 symbol.tag = .function;
13401339 symbol.index = index;
13411340
1342 if (self.code_section_index == null) {
1343 self.code_section_index = @intCast(u32, self.segments.items.len);
1344 try self.segments.append(self.base.allocator, .{
1341 if (wasm.code_section_index == null) {
1342 wasm.code_section_index = @intCast(u32, wasm.segments.items.len);
1343 try wasm.segments.append(wasm.base.allocator, .{
13451344 .alignment = atom.alignment,
13461345 .size = atom.size,
13471346 .offset = 0,
13481347 });
13491348 }
13501349
1351 break :result self.code_section_index.?;
1350 break :result wasm.code_section_index.?;
13521351 },
13531352 .data => result: {
1354 const segment_name = try std.mem.concat(self.base.allocator, u8, &.{
1353 const segment_name = try std.mem.concat(wasm.base.allocator, u8, &.{
13551354 kind.segmentName(),
1356 self.string_table.get(symbol.name),
1355 wasm.string_table.get(symbol.name),
13571356 });
1358 errdefer self.base.allocator.free(segment_name);
1357 errdefer wasm.base.allocator.free(segment_name);
13591358 const segment_info: types.Segment = .{
13601359 .name = segment_name,
13611360 .alignment = atom.alignment,
......@@ -1367,59 +1366,59 @@ fn parseAtom(self: *Wasm, atom: *Atom, kind: Kind) !void {
13671366 // we set the entire region of it to zeroes.
13681367 // We do not have to do this when exporting the memory (the default) because the runtime
13691368 // will do it for us, and we do not emit the bss segment at all.
1370 if ((self.base.options.output_mode == .Obj or self.base.options.import_memory) and kind.data == .uninitialized) {
1369 if ((wasm.base.options.output_mode == .Obj or wasm.base.options.import_memory) and kind.data == .uninitialized) {
13711370 std.mem.set(u8, atom.code.items, 0);
13721371 }
13731372
1374 const should_merge = self.base.options.output_mode != .Obj;
1375 const gop = try self.data_segments.getOrPut(self.base.allocator, segment_info.outputName(should_merge));
1373 const should_merge = wasm.base.options.output_mode != .Obj;
1374 const gop = try wasm.data_segments.getOrPut(wasm.base.allocator, segment_info.outputName(should_merge));
13761375 if (gop.found_existing) {
13771376 const index = gop.value_ptr.*;
1378 self.segments.items[index].size += atom.size;
1377 wasm.segments.items[index].size += atom.size;
13791378
1380 symbol.index = @intCast(u32, self.segment_info.getIndex(index).?);
1379 symbol.index = @intCast(u32, wasm.segment_info.getIndex(index).?);
13811380 // segment info already exists, so free its memory
1382 self.base.allocator.free(segment_name);
1381 wasm.base.allocator.free(segment_name);
13831382 break :result index;
13841383 } else {
1385 const index = @intCast(u32, self.segments.items.len);
1386 try self.segments.append(self.base.allocator, .{
1384 const index = @intCast(u32, wasm.segments.items.len);
1385 try wasm.segments.append(wasm.base.allocator, .{
13871386 .alignment = atom.alignment,
13881387 .size = 0,
13891388 .offset = 0,
13901389 });
13911390 gop.value_ptr.* = index;
13921391
1393 const info_index = @intCast(u32, self.segment_info.count());
1394 try self.segment_info.put(self.base.allocator, index, segment_info);
1392 const info_index = @intCast(u32, wasm.segment_info.count());
1393 try wasm.segment_info.put(wasm.base.allocator, index, segment_info);
13951394 symbol.index = info_index;
13961395 break :result index;
13971396 }
13981397 },
13991398 };
14001399
1401 const segment: *Segment = &self.segments.items[final_index];
1400 const segment: *Segment = &wasm.segments.items[final_index];
14021401 segment.alignment = std.math.max(segment.alignment, atom.alignment);
14031402
1404 try self.appendAtomAtIndex(final_index, atom);
1403 try wasm.appendAtomAtIndex(final_index, atom);
14051404}
14061405
14071406/// From a given index, append the given `Atom` at the back of the linked list.
14081407/// Simply inserts it into the map of atoms when it doesn't exist yet.
1409pub fn appendAtomAtIndex(self: *Wasm, index: u32, atom: *Atom) !void {
1410 if (self.atoms.getPtr(index)) |last| {
1408pub fn appendAtomAtIndex(wasm: *Wasm, index: u32, atom: *Atom) !void {
1409 if (wasm.atoms.getPtr(index)) |last| {
14111410 last.*.next = atom;
14121411 atom.prev = last.*;
14131412 last.* = atom;
14141413 } else {
1415 try self.atoms.putNoClobber(self.base.allocator, index, atom);
1414 try wasm.atoms.putNoClobber(wasm.base.allocator, index, atom);
14161415 }
14171416}
14181417
14191418/// Allocates debug atoms into their respective debug sections
14201419/// to merge them with maybe-existing debug atoms from object files.
1421fn allocateDebugAtoms(self: *Wasm) !void {
1422 if (self.dwarf == null) return;
1420fn allocateDebugAtoms(wasm: *Wasm) !void {
1421 if (wasm.dwarf == null) return;
14231422
14241423 const allocAtom = struct {
14251424 fn f(bin: *Wasm, maybe_index: *?u32, atom: *Atom) !void {
......@@ -1435,24 +1434,24 @@ fn allocateDebugAtoms(self: *Wasm) !void {
14351434 }
14361435 }.f;
14371436
1438 try allocAtom(self, &self.debug_info_index, self.debug_info_atom.?);
1439 try allocAtom(self, &self.debug_line_index, self.debug_line_atom.?);
1440 try allocAtom(self, &self.debug_loc_index, self.debug_loc_atom.?);
1441 try allocAtom(self, &self.debug_str_index, self.debug_str_atom.?);
1442 try allocAtom(self, &self.debug_ranges_index, self.debug_ranges_atom.?);
1443 try allocAtom(self, &self.debug_abbrev_index, self.debug_abbrev_atom.?);
1444 try allocAtom(self, &self.debug_pubnames_index, self.debug_pubnames_atom.?);
1445 try allocAtom(self, &self.debug_pubtypes_index, self.debug_pubtypes_atom.?);
1437 try allocAtom(wasm, &wasm.debug_info_index, wasm.debug_info_atom.?);
1438 try allocAtom(wasm, &wasm.debug_line_index, wasm.debug_line_atom.?);
1439 try allocAtom(wasm, &wasm.debug_loc_index, wasm.debug_loc_atom.?);
1440 try allocAtom(wasm, &wasm.debug_str_index, wasm.debug_str_atom.?);
1441 try allocAtom(wasm, &wasm.debug_ranges_index, wasm.debug_ranges_atom.?);
1442 try allocAtom(wasm, &wasm.debug_abbrev_index, wasm.debug_abbrev_atom.?);
1443 try allocAtom(wasm, &wasm.debug_pubnames_index, wasm.debug_pubnames_atom.?);
1444 try allocAtom(wasm, &wasm.debug_pubtypes_index, wasm.debug_pubtypes_atom.?);
14461445}
14471446
1448fn allocateAtoms(self: *Wasm) !void {
1447fn allocateAtoms(wasm: *Wasm) !void {
14491448 // first sort the data segments
1450 try sortDataSegments(self);
1451 try allocateDebugAtoms(self);
1449 try sortDataSegments(wasm);
1450 try allocateDebugAtoms(wasm);
14521451
1453 var it = self.atoms.iterator();
1452 var it = wasm.atoms.iterator();
14541453 while (it.next()) |entry| {
1455 const segment = &self.segments.items[entry.key_ptr.*];
1454 const segment = &wasm.segments.items[entry.key_ptr.*];
14561455 var atom: *Atom = entry.value_ptr.*.getFirst();
14571456 var offset: u32 = 0;
14581457 while (true) {
......@@ -1460,26 +1459,26 @@ fn allocateAtoms(self: *Wasm) !void {
14601459 atom.offset = offset;
14611460 const symbol_loc = atom.symbolLoc();
14621461 log.debug("Atom '{s}' allocated from 0x{x:0>8} to 0x{x:0>8} size={d}", .{
1463 symbol_loc.getName(self),
1462 symbol_loc.getName(wasm),
14641463 offset,
14651464 offset + atom.size,
14661465 atom.size,
14671466 });
14681467 offset += atom.size;
1469 try self.symbol_atom.put(self.base.allocator, atom.symbolLoc(), atom); // Update atom pointers
1468 try wasm.symbol_atom.put(wasm.base.allocator, atom.symbolLoc(), atom); // Update atom pointers
14701469 atom = atom.next orelse break;
14711470 }
14721471 segment.size = std.mem.alignForwardGeneric(u32, offset, segment.alignment);
14731472 }
14741473}
14751474
1476fn sortDataSegments(self: *Wasm) !void {
1475fn sortDataSegments(wasm: *Wasm) !void {
14771476 var new_mapping: std.StringArrayHashMapUnmanaged(u32) = .{};
1478 try new_mapping.ensureUnusedCapacity(self.base.allocator, self.data_segments.count());
1479 errdefer new_mapping.deinit(self.base.allocator);
1477 try new_mapping.ensureUnusedCapacity(wasm.base.allocator, wasm.data_segments.count());
1478 errdefer new_mapping.deinit(wasm.base.allocator);
14801479
1481 const keys = try self.base.allocator.dupe([]const u8, self.data_segments.keys());
1482 defer self.base.allocator.free(keys);
1480 const keys = try wasm.base.allocator.dupe([]const u8, wasm.data_segments.keys());
1481 defer wasm.base.allocator.free(keys);
14831482
14841483 const SortContext = struct {
14851484 fn sort(_: void, lhs: []const u8, rhs: []const u8) bool {
......@@ -1496,63 +1495,63 @@ fn sortDataSegments(self: *Wasm) !void {
14961495
14971496 std.sort.sort([]const u8, keys, {}, SortContext.sort);
14981497 for (keys) |key| {
1499 const segment_index = self.data_segments.get(key).?;
1498 const segment_index = wasm.data_segments.get(key).?;
15001499 new_mapping.putAssumeCapacity(key, segment_index);
15011500 }
1502 self.data_segments.deinit(self.base.allocator);
1503 self.data_segments = new_mapping;
1501 wasm.data_segments.deinit(wasm.base.allocator);
1502 wasm.data_segments = new_mapping;
15041503}
15051504
1506fn setupImports(self: *Wasm) !void {
1505fn setupImports(wasm: *Wasm) !void {
15071506 log.debug("Merging imports", .{});
1508 var discarded_it = self.discarded.keyIterator();
1507 var discarded_it = wasm.discarded.keyIterator();
15091508 while (discarded_it.next()) |discarded| {
15101509 if (discarded.file == null) {
15111510 // remove an import if it was resolved
1512 if (self.imports.remove(discarded.*)) {
1511 if (wasm.imports.remove(discarded.*)) {
15131512 log.debug("Removed symbol '{s}' as an import", .{
1514 discarded.getName(self),
1513 discarded.getName(wasm),
15151514 });
15161515 }
15171516 }
15181517 }
15191518
1520 for (self.resolved_symbols.keys()) |symbol_loc| {
1519 for (wasm.resolved_symbols.keys()) |symbol_loc| {
15211520 if (symbol_loc.file == null) {
15221521 // imports generated by Zig code are already in the `import` section
15231522 continue;
15241523 }
15251524
1526 const symbol = symbol_loc.getSymbol(self);
1527 if (std.mem.eql(u8, symbol_loc.getName(self), "__indirect_function_table")) {
1525 const symbol = symbol_loc.getSymbol(wasm);
1526 if (std.mem.eql(u8, symbol_loc.getName(wasm), "__indirect_function_table")) {
15281527 continue;
15291528 }
15301529 if (!symbol.requiresImport()) {
15311530 continue;
15321531 }
15331532
1534 log.debug("Symbol '{s}' will be imported from the host", .{symbol_loc.getName(self)});
1535 const object = self.objects.items[symbol_loc.file.?];
1533 log.debug("Symbol '{s}' will be imported from the host", .{symbol_loc.getName(wasm)});
1534 const object = wasm.objects.items[symbol_loc.file.?];
15361535 const import = object.findImport(symbol.tag.externalType(), symbol.index);
15371536
15381537 // We copy the import to a new import to ensure the names contain references
15391538 // to the internal string table, rather than of the object file.
15401539 var new_imp: types.Import = .{
1541 .module_name = try self.string_table.put(self.base.allocator, object.string_table.get(import.module_name)),
1542 .name = try self.string_table.put(self.base.allocator, object.string_table.get(import.name)),
1540 .module_name = try wasm.string_table.put(wasm.base.allocator, object.string_table.get(import.module_name)),
1541 .name = try wasm.string_table.put(wasm.base.allocator, object.string_table.get(import.name)),
15431542 .kind = import.kind,
15441543 };
15451544 // TODO: De-duplicate imports when they contain the same names and type
1546 try self.imports.putNoClobber(self.base.allocator, symbol_loc, new_imp);
1545 try wasm.imports.putNoClobber(wasm.base.allocator, symbol_loc, new_imp);
15471546 }
15481547
15491548 // Assign all indexes of the imports to their representing symbols
15501549 var function_index: u32 = 0;
15511550 var global_index: u32 = 0;
15521551 var table_index: u32 = 0;
1553 var it = self.imports.iterator();
1552 var it = wasm.imports.iterator();
15541553 while (it.next()) |entry| {
1555 const symbol = entry.key_ptr.*.getSymbol(self);
1554 const symbol = entry.key_ptr.*.getSymbol(wasm);
15561555 const import: types.Import = entry.value_ptr.*;
15571556 switch (import.kind) {
15581557 .function => {
......@@ -1570,9 +1569,9 @@ fn setupImports(self: *Wasm) !void {
15701569 else => unreachable,
15711570 }
15721571 }
1573 self.imported_functions_count = function_index;
1574 self.imported_globals_count = global_index;
1575 self.imported_tables_count = table_index;
1572 wasm.imported_functions_count = function_index;
1573 wasm.imported_globals_count = global_index;
1574 wasm.imported_tables_count = table_index;
15761575
15771576 log.debug("Merged ({d}) functions, ({d}) globals, and ({d}) tables into import section", .{
15781577 function_index,
......@@ -1583,26 +1582,26 @@ fn setupImports(self: *Wasm) !void {
15831582
15841583/// Takes the global, function and table section from each linked object file
15851584/// and merges it into a single section for each.
1586fn mergeSections(self: *Wasm) !void {
1585fn mergeSections(wasm: *Wasm) !void {
15871586 // append the indirect function table if initialized
1588 if (self.string_table.getOffset("__indirect_function_table")) |offset| {
1589 const sym_loc = self.globals.get(offset).?;
1590 const table: wasm.Table = .{
1591 .limits = .{ .min = @intCast(u32, self.function_table.count()), .max = null },
1587 if (wasm.string_table.getOffset("__indirect_function_table")) |offset| {
1588 const sym_loc = wasm.globals.get(offset).?;
1589 const table: std.wasm.Table = .{
1590 .limits = .{ .min = @intCast(u32, wasm.function_table.count()), .max = null },
15921591 .reftype = .funcref,
15931592 };
1594 sym_loc.getSymbol(self).index = @intCast(u32, self.tables.items.len) + self.imported_tables_count;
1595 try self.tables.append(self.base.allocator, table);
1593 sym_loc.getSymbol(wasm).index = @intCast(u32, wasm.tables.items.len) + wasm.imported_tables_count;
1594 try wasm.tables.append(wasm.base.allocator, table);
15961595 }
15971596
1598 for (self.resolved_symbols.keys()) |sym_loc| {
1597 for (wasm.resolved_symbols.keys()) |sym_loc| {
15991598 if (sym_loc.file == null) {
16001599 // Zig code-generated symbols are already within the sections and do not
16011600 // require to be merged
16021601 continue;
16031602 }
16041603
1605 const object = self.objects.items[sym_loc.file.?];
1604 const object = wasm.objects.items[sym_loc.file.?];
16061605 const symbol = &object.symtable[sym_loc.index];
16071606 if (symbol.isUndefined() or (symbol.tag != .function and symbol.tag != .global and symbol.tag != .table)) {
16081607 // Skip undefined symbols as they go in the `import` section
......@@ -1615,51 +1614,51 @@ fn mergeSections(self: *Wasm) !void {
16151614 switch (symbol.tag) {
16161615 .function => {
16171616 const original_func = object.functions[index];
1618 const gop = try self.functions.getOrPut(
1619 self.base.allocator,
1617 const gop = try wasm.functions.getOrPut(
1618 wasm.base.allocator,
16201619 .{ .file = sym_loc.file, .index = symbol.index },
16211620 );
16221621 if (!gop.found_existing) {
16231622 gop.value_ptr.* = original_func;
16241623 }
1625 symbol.index = @intCast(u32, gop.index) + self.imported_functions_count;
1624 symbol.index = @intCast(u32, gop.index) + wasm.imported_functions_count;
16261625 },
16271626 .global => {
16281627 const original_global = object.globals[index];
1629 symbol.index = @intCast(u32, self.wasm_globals.items.len) + self.imported_globals_count;
1630 try self.wasm_globals.append(self.base.allocator, original_global);
1628 symbol.index = @intCast(u32, wasm.wasm_globals.items.len) + wasm.imported_globals_count;
1629 try wasm.wasm_globals.append(wasm.base.allocator, original_global);
16311630 },
16321631 .table => {
16331632 const original_table = object.tables[index];
1634 symbol.index = @intCast(u32, self.tables.items.len) + self.imported_tables_count;
1635 try self.tables.append(self.base.allocator, original_table);
1633 symbol.index = @intCast(u32, wasm.tables.items.len) + wasm.imported_tables_count;
1634 try wasm.tables.append(wasm.base.allocator, original_table);
16361635 },
16371636 else => unreachable,
16381637 }
16391638 }
16401639
1641 log.debug("Merged ({d}) functions", .{self.functions.count()});
1642 log.debug("Merged ({d}) globals", .{self.wasm_globals.items.len});
1643 log.debug("Merged ({d}) tables", .{self.tables.items.len});
1640 log.debug("Merged ({d}) functions", .{wasm.functions.count()});
1641 log.debug("Merged ({d}) globals", .{wasm.wasm_globals.items.len});
1642 log.debug("Merged ({d}) tables", .{wasm.tables.items.len});
16441643}
16451644
16461645/// Merges function types of all object files into the final
16471646/// 'types' section, while assigning the type index to the representing
16481647/// section (import, export, function).
1649fn mergeTypes(self: *Wasm) !void {
1648fn mergeTypes(wasm: *Wasm) !void {
16501649 // A map to track which functions have already had their
16511650 // type inserted. If we do this for the same function multiple times,
16521651 // it will be overwritten with the incorrect type.
1653 var dirty = std.AutoHashMap(u32, void).init(self.base.allocator);
1654 try dirty.ensureUnusedCapacity(@intCast(u32, self.functions.count()));
1652 var dirty = std.AutoHashMap(u32, void).init(wasm.base.allocator);
1653 try dirty.ensureUnusedCapacity(@intCast(u32, wasm.functions.count()));
16551654 defer dirty.deinit();
16561655
1657 for (self.resolved_symbols.keys()) |sym_loc| {
1656 for (wasm.resolved_symbols.keys()) |sym_loc| {
16581657 if (sym_loc.file == null) {
16591658 // zig code-generated symbols are already present in final type section
16601659 continue;
16611660 }
1662 const object = self.objects.items[sym_loc.file.?];
1661 const object = wasm.objects.items[sym_loc.file.?];
16631662 const symbol = object.symtable[sym_loc.index];
16641663 if (symbol.tag != .function) {
16651664 // Only functions have types
......@@ -1667,32 +1666,32 @@ fn mergeTypes(self: *Wasm) !void {
16671666 }
16681667
16691668 if (symbol.isUndefined()) {
1670 log.debug("Adding type from extern function '{s}'", .{sym_loc.getName(self)});
1671 const import: *types.Import = self.imports.getPtr(sym_loc).?;
1669 log.debug("Adding type from extern function '{s}'", .{sym_loc.getName(wasm)});
1670 const import: *types.Import = wasm.imports.getPtr(sym_loc).?;
16721671 const original_type = object.func_types[import.kind.function];
1673 import.kind.function = try self.putOrGetFuncType(original_type);
1672 import.kind.function = try wasm.putOrGetFuncType(original_type);
16741673 } else if (!dirty.contains(symbol.index)) {
1675 log.debug("Adding type from function '{s}'", .{sym_loc.getName(self)});
1676 const func = &self.functions.values()[symbol.index - self.imported_functions_count];
1677 func.type_index = try self.putOrGetFuncType(object.func_types[func.type_index]);
1674 log.debug("Adding type from function '{s}'", .{sym_loc.getName(wasm)});
1675 const func = &wasm.functions.values()[symbol.index - wasm.imported_functions_count];
1676 func.type_index = try wasm.putOrGetFuncType(object.func_types[func.type_index]);
16781677 dirty.putAssumeCapacityNoClobber(symbol.index, {});
16791678 }
16801679 }
1681 log.debug("Completed merging and deduplicating types. Total count: ({d})", .{self.func_types.items.len});
1680 log.debug("Completed merging and deduplicating types. Total count: ({d})", .{wasm.func_types.items.len});
16821681}
16831682
1684fn setupExports(self: *Wasm) !void {
1685 if (self.base.options.output_mode == .Obj) return;
1683fn setupExports(wasm: *Wasm) !void {
1684 if (wasm.base.options.output_mode == .Obj) return;
16861685 log.debug("Building exports from symbols", .{});
16871686
1688 for (self.resolved_symbols.keys()) |sym_loc| {
1689 const symbol = sym_loc.getSymbol(self);
1687 for (wasm.resolved_symbols.keys()) |sym_loc| {
1688 const symbol = sym_loc.getSymbol(wasm);
16901689 if (!symbol.isExported()) continue;
16911690
1692 const sym_name = sym_loc.getName(self);
1693 const export_name = if (self.export_names.get(sym_loc)) |name| name else blk: {
1691 const sym_name = sym_loc.getName(wasm);
1692 const export_name = if (wasm.export_names.get(sym_loc)) |name| name else blk: {
16941693 if (sym_loc.file == null) break :blk symbol.name;
1695 break :blk try self.string_table.put(self.base.allocator, sym_name);
1694 break :blk try wasm.string_table.put(wasm.base.allocator, sym_name);
16961695 };
16971696 const exp: types.Export = .{
16981697 .name = export_name,
......@@ -1701,21 +1700,21 @@ fn setupExports(self: *Wasm) !void {
17011700 };
17021701 log.debug("Exporting symbol '{s}' as '{s}' at index: ({d})", .{
17031702 sym_name,
1704 self.string_table.get(exp.name),
1703 wasm.string_table.get(exp.name),
17051704 exp.index,
17061705 });
1707 try self.exports.append(self.base.allocator, exp);
1706 try wasm.exports.append(wasm.base.allocator, exp);
17081707 }
17091708
1710 log.debug("Completed building exports. Total count: ({d})", .{self.exports.items.len});
1709 log.debug("Completed building exports. Total count: ({d})", .{wasm.exports.items.len});
17111710}
17121711
1713fn setupStart(self: *Wasm) !void {
1714 const entry_name = self.base.options.entry orelse "_start";
1712fn setupStart(wasm: *Wasm) !void {
1713 const entry_name = wasm.base.options.entry orelse "_start";
17151714
1716 const symbol_name_offset = self.string_table.getOffset(entry_name) orelse {
1717 if (self.base.options.output_mode == .Exe) {
1718 if (self.base.options.wasi_exec_model == .reactor) return; // Not required for reactors
1715 const symbol_name_offset = wasm.string_table.getOffset(entry_name) orelse {
1716 if (wasm.base.options.output_mode == .Exe) {
1717 if (wasm.base.options.wasi_exec_model == .reactor) return; // Not required for reactors
17191718 } else {
17201719 return; // No entry point needed for non-executable wasm files
17211720 }
......@@ -1723,45 +1722,45 @@ fn setupStart(self: *Wasm) !void {
17231722 return error.MissingSymbol;
17241723 };
17251724
1726 const symbol_loc = self.globals.get(symbol_name_offset).?;
1727 const symbol = symbol_loc.getSymbol(self);
1725 const symbol_loc = wasm.globals.get(symbol_name_offset).?;
1726 const symbol = symbol_loc.getSymbol(wasm);
17281727 if (symbol.tag != .function) {
17291728 log.err("Entry symbol '{s}' is not a function", .{entry_name});
17301729 return error.InvalidEntryKind;
17311730 }
17321731
17331732 // Ensure the symbol is exported so host environment can access it
1734 if (self.base.options.output_mode != .Obj) {
1733 if (wasm.base.options.output_mode != .Obj) {
17351734 symbol.setFlag(.WASM_SYM_EXPORTED);
17361735 }
17371736}
17381737
17391738/// Sets up the memory section of the wasm module, as well as the stack.
1740fn setupMemory(self: *Wasm) !void {
1739fn setupMemory(wasm: *Wasm) !void {
17411740 log.debug("Setting up memory layout", .{});
17421741 const page_size = 64 * 1024;
1743 const stack_size = self.base.options.stack_size_override orelse page_size * 1;
1742 const stack_size = wasm.base.options.stack_size_override orelse page_size * 1;
17441743 const stack_alignment = 16; // wasm's stack alignment as specified by tool-convention
17451744 // Always place the stack at the start by default
17461745 // unless the user specified the global-base flag
17471746 var place_stack_first = true;
1748 var memory_ptr: u64 = if (self.base.options.global_base) |base| blk: {
1747 var memory_ptr: u64 = if (wasm.base.options.global_base) |base| blk: {
17491748 place_stack_first = false;
17501749 break :blk base;
17511750 } else 0;
17521751
1753 const is_obj = self.base.options.output_mode == .Obj;
1752 const is_obj = wasm.base.options.output_mode == .Obj;
17541753
17551754 if (place_stack_first and !is_obj) {
17561755 memory_ptr = std.mem.alignForwardGeneric(u64, memory_ptr, stack_alignment);
17571756 memory_ptr += stack_size;
17581757 // We always put the stack pointer global at index 0
1759 self.wasm_globals.items[0].init.i32_const = @bitCast(i32, @intCast(u32, memory_ptr));
1758 wasm.wasm_globals.items[0].init.i32_const = @bitCast(i32, @intCast(u32, memory_ptr));
17601759 }
17611760
17621761 var offset: u32 = @intCast(u32, memory_ptr);
1763 for (self.data_segments.values()) |segment_index| {
1764 const segment = &self.segments.items[segment_index];
1762 for (wasm.data_segments.values()) |segment_index| {
1763 const segment = &wasm.segments.items[segment_index];
17651764 memory_ptr = std.mem.alignForwardGeneric(u64, memory_ptr, segment.alignment);
17661765 memory_ptr += segment.size;
17671766 segment.offset = offset;
......@@ -1771,14 +1770,14 @@ fn setupMemory(self: *Wasm) !void {
17711770 if (!place_stack_first and !is_obj) {
17721771 memory_ptr = std.mem.alignForwardGeneric(u64, memory_ptr, stack_alignment);
17731772 memory_ptr += stack_size;
1774 self.wasm_globals.items[0].init.i32_const = @bitCast(i32, @intCast(u32, memory_ptr));
1773 wasm.wasm_globals.items[0].init.i32_const = @bitCast(i32, @intCast(u32, memory_ptr));
17751774 }
17761775
17771776 // Setup the max amount of pages
17781777 // For now we only support wasm32 by setting the maximum allowed memory size 2^32-1
17791778 const max_memory_allowed: u64 = (1 << 32) - 1;
17801779
1781 if (self.base.options.initial_memory) |initial_memory| {
1780 if (wasm.base.options.initial_memory) |initial_memory| {
17821781 if (!std.mem.isAlignedGeneric(u64, initial_memory, page_size)) {
17831782 log.err("Initial memory must be {d}-byte aligned", .{page_size});
17841783 return error.MissAlignment;
......@@ -1796,10 +1795,10 @@ fn setupMemory(self: *Wasm) !void {
17961795
17971796 // In case we do not import memory, but define it ourselves,
17981797 // set the minimum amount of pages on the memory section.
1799 self.memories.limits.min = @intCast(u32, std.mem.alignForwardGeneric(u64, memory_ptr, page_size) / page_size);
1800 log.debug("Total memory pages: {d}", .{self.memories.limits.min});
1798 wasm.memories.limits.min = @intCast(u32, std.mem.alignForwardGeneric(u64, memory_ptr, page_size) / page_size);
1799 log.debug("Total memory pages: {d}", .{wasm.memories.limits.min});
18011800
1802 if (self.base.options.max_memory) |max_memory| {
1801 if (wasm.base.options.max_memory) |max_memory| {
18031802 if (!std.mem.isAlignedGeneric(u64, max_memory, page_size)) {
18041803 log.err("Maximum memory must be {d}-byte aligned", .{page_size});
18051804 return error.MissAlignment;
......@@ -1812,83 +1811,83 @@ fn setupMemory(self: *Wasm) !void {
18121811 log.err("Maximum memory exceeds maxmium amount {d}", .{max_memory_allowed});
18131812 return error.MemoryTooBig;
18141813 }
1815 self.memories.limits.max = @intCast(u32, max_memory / page_size);
1816 log.debug("Maximum memory pages: {?d}", .{self.memories.limits.max});
1814 wasm.memories.limits.max = @intCast(u32, max_memory / page_size);
1815 log.debug("Maximum memory pages: {?d}", .{wasm.memories.limits.max});
18171816 }
18181817}
18191818
18201819/// From a given object's index and the index of the segment, returns the corresponding
18211820/// index of the segment within the final data section. When the segment does not yet
18221821/// exist, a new one will be initialized and appended. The new index will be returned in that case.
1823pub fn getMatchingSegment(self: *Wasm, object_index: u16, relocatable_index: u32) !?u32 {
1824 const object: Object = self.objects.items[object_index];
1822pub fn getMatchingSegment(wasm: *Wasm, object_index: u16, relocatable_index: u32) !?u32 {
1823 const object: Object = wasm.objects.items[object_index];
18251824 const relocatable_data = object.relocatable_data[relocatable_index];
1826 const index = @intCast(u32, self.segments.items.len);
1825 const index = @intCast(u32, wasm.segments.items.len);
18271826
18281827 switch (relocatable_data.type) {
18291828 .data => {
18301829 const segment_info = object.segment_info[relocatable_data.index];
1831 const merge_segment = self.base.options.output_mode != .Obj;
1832 const result = try self.data_segments.getOrPut(self.base.allocator, segment_info.outputName(merge_segment));
1830 const merge_segment = wasm.base.options.output_mode != .Obj;
1831 const result = try wasm.data_segments.getOrPut(wasm.base.allocator, segment_info.outputName(merge_segment));
18331832 if (!result.found_existing) {
18341833 result.value_ptr.* = index;
1835 try self.appendDummySegment();
1834 try wasm.appendDummySegment();
18361835 return index;
18371836 } else return result.value_ptr.*;
18381837 },
1839 .code => return self.code_section_index orelse blk: {
1840 self.code_section_index = index;
1841 try self.appendDummySegment();
1838 .code => return wasm.code_section_index orelse blk: {
1839 wasm.code_section_index = index;
1840 try wasm.appendDummySegment();
18421841 break :blk index;
18431842 },
18441843 .debug => {
18451844 const debug_name = object.getDebugName(relocatable_data);
18461845 if (mem.eql(u8, debug_name, ".debug_info")) {
1847 return self.debug_info_index orelse blk: {
1848 self.debug_info_index = index;
1849 try self.appendDummySegment();
1846 return wasm.debug_info_index orelse blk: {
1847 wasm.debug_info_index = index;
1848 try wasm.appendDummySegment();
18501849 break :blk index;
18511850 };
18521851 } else if (mem.eql(u8, debug_name, ".debug_line")) {
1853 return self.debug_line_index orelse blk: {
1854 self.debug_line_index = index;
1855 try self.appendDummySegment();
1852 return wasm.debug_line_index orelse blk: {
1853 wasm.debug_line_index = index;
1854 try wasm.appendDummySegment();
18561855 break :blk index;
18571856 };
18581857 } else if (mem.eql(u8, debug_name, ".debug_loc")) {
1859 return self.debug_loc_index orelse blk: {
1860 self.debug_loc_index = index;
1861 try self.appendDummySegment();
1858 return wasm.debug_loc_index orelse blk: {
1859 wasm.debug_loc_index = index;
1860 try wasm.appendDummySegment();
18621861 break :blk index;
18631862 };
18641863 } else if (mem.eql(u8, debug_name, ".debug_ranges")) {
1865 return self.debug_line_index orelse blk: {
1866 self.debug_ranges_index = index;
1867 try self.appendDummySegment();
1864 return wasm.debug_line_index orelse blk: {
1865 wasm.debug_ranges_index = index;
1866 try wasm.appendDummySegment();
18681867 break :blk index;
18691868 };
18701869 } else if (mem.eql(u8, debug_name, ".debug_pubnames")) {
1871 return self.debug_pubnames_index orelse blk: {
1872 self.debug_pubnames_index = index;
1873 try self.appendDummySegment();
1870 return wasm.debug_pubnames_index orelse blk: {
1871 wasm.debug_pubnames_index = index;
1872 try wasm.appendDummySegment();
18741873 break :blk index;
18751874 };
18761875 } else if (mem.eql(u8, debug_name, ".debug_pubtypes")) {
1877 return self.debug_pubtypes_index orelse blk: {
1878 self.debug_pubtypes_index = index;
1879 try self.appendDummySegment();
1876 return wasm.debug_pubtypes_index orelse blk: {
1877 wasm.debug_pubtypes_index = index;
1878 try wasm.appendDummySegment();
18801879 break :blk index;
18811880 };
18821881 } else if (mem.eql(u8, debug_name, ".debug_abbrev")) {
1883 return self.debug_abbrev_index orelse blk: {
1884 self.debug_abbrev_index = index;
1885 try self.appendDummySegment();
1882 return wasm.debug_abbrev_index orelse blk: {
1883 wasm.debug_abbrev_index = index;
1884 try wasm.appendDummySegment();
18861885 break :blk index;
18871886 };
18881887 } else if (mem.eql(u8, debug_name, ".debug_str")) {
1889 return self.debug_str_index orelse blk: {
1890 self.debug_str_index = index;
1891 try self.appendDummySegment();
1888 return wasm.debug_str_index orelse blk: {
1889 wasm.debug_str_index = index;
1890 try wasm.appendDummySegment();
18921891 break :blk index;
18931892 };
18941893 } else {
......@@ -1901,8 +1900,8 @@ pub fn getMatchingSegment(self: *Wasm, object_index: u16, relocatable_index: u32
19011900}
19021901
19031902/// Appends a new segment with default field values
1904fn appendDummySegment(self: *Wasm) !void {
1905 try self.segments.append(self.base.allocator, .{
1903fn appendDummySegment(wasm: *Wasm) !void {
1904 try wasm.segments.append(wasm.base.allocator, .{
19061905 .alignment = 1,
19071906 .size = 0,
19081907 .offset = 0,
......@@ -1912,8 +1911,8 @@ fn appendDummySegment(self: *Wasm) !void {
19121911/// Returns the symbol index of the error name table.
19131912///
19141913/// When the symbol does not yet exist, it will create a new one instead.
1915pub fn getErrorTableSymbol(self: *Wasm) !u32 {
1916 if (self.error_table_symbol) |symbol| {
1914pub fn getErrorTableSymbol(wasm: *Wasm) !u32 {
1915 if (wasm.error_table_symbol) |symbol| {
19171916 return symbol;
19181917 }
19191918
......@@ -1922,14 +1921,14 @@ pub fn getErrorTableSymbol(self: *Wasm) !u32 {
19221921 // during `flush` when we know all possible error names.
19231922
19241923 // As sym_index '0' is reserved, we use it for our stack pointer symbol
1925 const symbol_index = self.symbols_free_list.popOrNull() orelse blk: {
1926 const index = @intCast(u32, self.symbols.items.len);
1927 _ = try self.symbols.addOne(self.base.allocator);
1924 const symbol_index = wasm.symbols_free_list.popOrNull() orelse blk: {
1925 const index = @intCast(u32, wasm.symbols.items.len);
1926 _ = try wasm.symbols.addOne(wasm.base.allocator);
19281927 break :blk index;
19291928 };
19301929
1931 const sym_name = try self.string_table.put(self.base.allocator, "__zig_err_name_table");
1932 const symbol = &self.symbols.items[symbol_index];
1930 const sym_name = try wasm.string_table.put(wasm.base.allocator, "__zig_err_name_table");
1931 const symbol = &wasm.symbols.items[symbol_index];
19331932 symbol.* = .{
19341933 .name = sym_name,
19351934 .tag = .data,
......@@ -1940,17 +1939,17 @@ pub fn getErrorTableSymbol(self: *Wasm) !u32 {
19401939
19411940 const slice_ty = Type.initTag(.const_slice_u8_sentinel_0);
19421941
1943 const atom = try self.base.allocator.create(Atom);
1942 const atom = try wasm.base.allocator.create(Atom);
19441943 atom.* = Atom.empty;
19451944 atom.sym_index = symbol_index;
1946 atom.alignment = slice_ty.abiAlignment(self.base.options.target);
1947 try self.managed_atoms.append(self.base.allocator, atom);
1945 atom.alignment = slice_ty.abiAlignment(wasm.base.options.target);
1946 try wasm.managed_atoms.append(wasm.base.allocator, atom);
19481947 const loc = atom.symbolLoc();
1949 try self.resolved_symbols.put(self.base.allocator, loc, {});
1950 try self.symbol_atom.put(self.base.allocator, loc, atom);
1948 try wasm.resolved_symbols.put(wasm.base.allocator, loc, {});
1949 try wasm.symbol_atom.put(wasm.base.allocator, loc, atom);
19511950
19521951 log.debug("Error name table was created with symbol index: ({d})", .{symbol_index});
1953 self.error_table_symbol = symbol_index;
1952 wasm.error_table_symbol = symbol_index;
19541953 return symbol_index;
19551954}
19561955
......@@ -1958,24 +1957,24 @@ pub fn getErrorTableSymbol(self: *Wasm) !u32 {
19581957///
19591958/// This creates a table that consists of pointers and length to each error name.
19601959/// The table is what is being pointed to within the runtime bodies that are generated.
1961fn populateErrorNameTable(self: *Wasm) !void {
1962 const symbol_index = self.error_table_symbol orelse return;
1963 const atom: *Atom = self.symbol_atom.get(.{ .file = null, .index = symbol_index }).?;
1960fn populateErrorNameTable(wasm: *Wasm) !void {
1961 const symbol_index = wasm.error_table_symbol orelse return;
1962 const atom: *Atom = wasm.symbol_atom.get(.{ .file = null, .index = symbol_index }).?;
19641963 // Rather than creating a symbol for each individual error name,
19651964 // we create a symbol for the entire region of error names. We then calculate
19661965 // the pointers into the list using addends which are appended to the relocation.
1967 const names_atom = try self.base.allocator.create(Atom);
1966 const names_atom = try wasm.base.allocator.create(Atom);
19681967 names_atom.* = Atom.empty;
1969 try self.managed_atoms.append(self.base.allocator, names_atom);
1970 const names_symbol_index = self.symbols_free_list.popOrNull() orelse blk: {
1971 const index = @intCast(u32, self.symbols.items.len);
1972 _ = try self.symbols.addOne(self.base.allocator);
1968 try wasm.managed_atoms.append(wasm.base.allocator, names_atom);
1969 const names_symbol_index = wasm.symbols_free_list.popOrNull() orelse blk: {
1970 const index = @intCast(u32, wasm.symbols.items.len);
1971 _ = try wasm.symbols.addOne(wasm.base.allocator);
19731972 break :blk index;
19741973 };
19751974 names_atom.sym_index = names_symbol_index;
19761975 names_atom.alignment = 1;
1977 const sym_name = try self.string_table.put(self.base.allocator, "__zig_err_names");
1978 const names_symbol = &self.symbols.items[names_symbol_index];
1976 const sym_name = try wasm.string_table.put(wasm.base.allocator, "__zig_err_names");
1977 const names_symbol = &wasm.symbols.items[names_symbol_index];
19791978 names_symbol.* = .{
19801979 .name = sym_name,
19811980 .tag = .data,
......@@ -1988,27 +1987,27 @@ fn populateErrorNameTable(self: *Wasm) !void {
19881987
19891988 // Addend for each relocation to the table
19901989 var addend: u32 = 0;
1991 const mod = self.base.options.module.?;
1990 const mod = wasm.base.options.module.?;
19921991 for (mod.error_name_list.items) |error_name| {
19931992 const len = @intCast(u32, error_name.len + 1); // names are 0-termianted
19941993
19951994 const slice_ty = Type.initTag(.const_slice_u8_sentinel_0);
19961995 const offset = @intCast(u32, atom.code.items.len);
19971996 // first we create the data for the slice of the name
1998 try atom.code.appendNTimes(self.base.allocator, 0, 4); // ptr to name, will be relocated
1999 try atom.code.writer(self.base.allocator).writeIntLittle(u32, len - 1);
1997 try atom.code.appendNTimes(wasm.base.allocator, 0, 4); // ptr to name, will be relocated
1998 try atom.code.writer(wasm.base.allocator).writeIntLittle(u32, len - 1);
20001999 // create relocation to the error name
2001 try atom.relocs.append(self.base.allocator, .{
2000 try atom.relocs.append(wasm.base.allocator, .{
20022001 .index = names_symbol_index,
20032002 .relocation_type = .R_WASM_MEMORY_ADDR_I32,
20042003 .offset = offset,
20052004 .addend = addend,
20062005 });
2007 atom.size += @intCast(u32, slice_ty.abiSize(self.base.options.target));
2006 atom.size += @intCast(u32, slice_ty.abiSize(wasm.base.options.target));
20082007 addend += len;
20092008
20102009 // as we updated the error name table, we now store the actual name within the names atom
2011 try names_atom.code.ensureUnusedCapacity(self.base.allocator, len);
2010 try names_atom.code.ensureUnusedCapacity(wasm.base.allocator, len);
20122011 names_atom.code.appendSliceAssumeCapacity(error_name);
20132012 names_atom.code.appendAssumeCapacity(0);
20142013
......@@ -2017,51 +2016,51 @@ fn populateErrorNameTable(self: *Wasm) !void {
20172016 names_atom.size = addend;
20182017
20192018 const name_loc = names_atom.symbolLoc();
2020 try self.resolved_symbols.put(self.base.allocator, name_loc, {});
2021 try self.symbol_atom.put(self.base.allocator, name_loc, names_atom);
2019 try wasm.resolved_symbols.put(wasm.base.allocator, name_loc, {});
2020 try wasm.symbol_atom.put(wasm.base.allocator, name_loc, names_atom);
20222021
20232022 // link the atoms with the rest of the binary so they can be allocated
20242023 // and relocations will be performed.
2025 try self.parseAtom(atom, .{ .data = .read_only });
2026 try self.parseAtom(names_atom, .{ .data = .read_only });
2024 try wasm.parseAtom(atom, .{ .data = .read_only });
2025 try wasm.parseAtom(names_atom, .{ .data = .read_only });
20272026}
20282027
20292028/// From a given index variable, creates a new debug section.
20302029/// This initializes the index, appends a new segment,
20312030/// and finally, creates a managed `Atom`.
2032pub fn createDebugSectionForIndex(self: *Wasm, index: *?u32, name: []const u8) !*Atom {
2033 const new_index = @intCast(u32, self.segments.items.len);
2031pub fn createDebugSectionForIndex(wasm: *Wasm, index: *?u32, name: []const u8) !*Atom {
2032 const new_index = @intCast(u32, wasm.segments.items.len);
20342033 index.* = new_index;
2035 try self.appendDummySegment();
2034 try wasm.appendDummySegment();
20362035 // _ = index;
20372036
2038 const sym_index = self.symbols_free_list.popOrNull() orelse idx: {
2039 const tmp_index = @intCast(u32, self.symbols.items.len);
2040 _ = try self.symbols.addOne(self.base.allocator);
2037 const sym_index = wasm.symbols_free_list.popOrNull() orelse idx: {
2038 const tmp_index = @intCast(u32, wasm.symbols.items.len);
2039 _ = try wasm.symbols.addOne(wasm.base.allocator);
20412040 break :idx tmp_index;
20422041 };
2043 self.symbols.items[sym_index] = .{
2042 wasm.symbols.items[sym_index] = .{
20442043 .tag = .section,
2045 .name = try self.string_table.put(self.base.allocator, name),
2044 .name = try wasm.string_table.put(wasm.base.allocator, name),
20462045 .index = 0,
20472046 .flags = @enumToInt(Symbol.Flag.WASM_SYM_BINDING_LOCAL),
20482047 };
20492048
2050 const atom = try self.base.allocator.create(Atom);
2049 const atom = try wasm.base.allocator.create(Atom);
20512050 atom.* = Atom.empty;
20522051 atom.alignment = 1; // debug sections are always 1-byte-aligned
20532052 atom.sym_index = sym_index;
2054 try self.managed_atoms.append(self.base.allocator, atom);
2055 try self.symbol_atom.put(self.base.allocator, atom.symbolLoc(), atom);
2053 try wasm.managed_atoms.append(wasm.base.allocator, atom);
2054 try wasm.symbol_atom.put(wasm.base.allocator, atom.symbolLoc(), atom);
20562055 return atom;
20572056}
20582057
2059fn resetState(self: *Wasm) void {
2060 for (self.segment_info.values()) |segment_info| {
2061 self.base.allocator.free(segment_info.name);
2058fn resetState(wasm: *Wasm) void {
2059 for (wasm.segment_info.values()) |segment_info| {
2060 wasm.base.allocator.free(segment_info.name);
20622061 }
2063 if (self.base.options.module) |mod| {
2064 var decl_it = self.decls.keyIterator();
2062 if (wasm.base.options.module) |mod| {
2063 var decl_it = wasm.decls.keyIterator();
20652064 while (decl_it.next()) |decl_index_ptr| {
20662065 const decl = mod.declPtr(decl_index_ptr.*);
20672066 const atom = &decl.link.wasm;
......@@ -2074,46 +2073,46 @@ fn resetState(self: *Wasm) void {
20742073 }
20752074 }
20762075 }
2077 self.functions.clearRetainingCapacity();
2078 self.exports.clearRetainingCapacity();
2079 self.segments.clearRetainingCapacity();
2080 self.segment_info.clearRetainingCapacity();
2081 self.data_segments.clearRetainingCapacity();
2082 self.atoms.clearRetainingCapacity();
2083 self.symbol_atom.clearRetainingCapacity();
2084 self.code_section_index = null;
2085 self.debug_info_index = null;
2086 self.debug_line_index = null;
2087 self.debug_loc_index = null;
2088 self.debug_str_index = null;
2089 self.debug_ranges_index = null;
2090 self.debug_abbrev_index = null;
2091 self.debug_pubnames_index = null;
2092 self.debug_pubtypes_index = null;
2076 wasm.functions.clearRetainingCapacity();
2077 wasm.exports.clearRetainingCapacity();
2078 wasm.segments.clearRetainingCapacity();
2079 wasm.segment_info.clearRetainingCapacity();
2080 wasm.data_segments.clearRetainingCapacity();
2081 wasm.atoms.clearRetainingCapacity();
2082 wasm.symbol_atom.clearRetainingCapacity();
2083 wasm.code_section_index = null;
2084 wasm.debug_info_index = null;
2085 wasm.debug_line_index = null;
2086 wasm.debug_loc_index = null;
2087 wasm.debug_str_index = null;
2088 wasm.debug_ranges_index = null;
2089 wasm.debug_abbrev_index = null;
2090 wasm.debug_pubnames_index = null;
2091 wasm.debug_pubtypes_index = null;
20932092}
20942093
2095pub fn flush(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !void {
2096 if (self.base.options.emit == null) {
2094pub fn flush(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !void {
2095 if (wasm.base.options.emit == null) {
20972096 if (build_options.have_llvm) {
2098 if (self.llvm_object) |llvm_object| {
2097 if (wasm.llvm_object) |llvm_object| {
20992098 return try llvm_object.flushModule(comp, prog_node);
21002099 }
21012100 }
21022101 return;
21032102 }
2104 if (build_options.have_llvm and self.base.options.use_lld) {
2105 return self.linkWithLLD(comp, prog_node);
2103 if (build_options.have_llvm and wasm.base.options.use_lld) {
2104 return wasm.linkWithLLD(comp, prog_node);
21062105 } else {
2107 return self.flushModule(comp, prog_node);
2106 return wasm.flushModule(comp, prog_node);
21082107 }
21092108}
21102109
2111pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !void {
2110pub fn flushModule(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !void {
21122111 const tracy = trace(@src());
21132112 defer tracy.end();
21142113
21152114 if (build_options.have_llvm) {
2116 if (self.llvm_object) |llvm_object| {
2115 if (wasm.llvm_object) |llvm_object| {
21172116 return try llvm_object.flushModule(comp, prog_node);
21182117 }
21192118 }
......@@ -2123,7 +2122,7 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod
21232122 defer sub_prog_node.end();
21242123
21252124 // ensure the error names table is populated when an error name is referenced
2126 try self.populateErrorNameTable();
2125 try wasm.populateErrorNameTable();
21272126
21282127 // The amount of sections that will be written
21292128 var section_count: u32 = 0;
......@@ -2133,15 +2132,15 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod
21332132 var data_section_index: ?u32 = null;
21342133
21352134 // Used for all temporary memory allocated during flushin
2136 var arena_instance = std.heap.ArenaAllocator.init(self.base.allocator);
2135 var arena_instance = std.heap.ArenaAllocator.init(wasm.base.allocator);
21372136 defer arena_instance.deinit();
21382137 const arena = arena_instance.allocator();
21392138
21402139 // Positional arguments to the linker such as object files and static archives.
21412140 var positionals = std.ArrayList([]const u8).init(arena);
2142 try positionals.ensureUnusedCapacity(self.base.options.objects.len);
2141 try positionals.ensureUnusedCapacity(wasm.base.options.objects.len);
21432142
2144 for (self.base.options.objects) |object| {
2143 for (wasm.base.options.objects) |object| {
21452144 positionals.appendAssumeCapacity(object.path);
21462145 }
21472146
......@@ -2153,66 +2152,66 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod
21532152 try positionals.append(lib.full_object_path);
21542153 }
21552154
2156 try self.parseInputFiles(positionals.items);
2155 try wasm.parseInputFiles(positionals.items);
21572156
2158 for (self.objects.items) |_, object_index| {
2159 try self.resolveSymbolsInObject(@intCast(u16, object_index));
2157 for (wasm.objects.items) |_, object_index| {
2158 try wasm.resolveSymbolsInObject(@intCast(u16, object_index));
21602159 }
21612160
2162 try self.resolveSymbolsInArchives();
2163 try self.checkUndefinedSymbols();
2161 try wasm.resolveSymbolsInArchives();
2162 try wasm.checkUndefinedSymbols();
21642163
21652164 // When we finish/error we reset the state of the linker
21662165 // So we can rebuild the binary file on each incremental update
2167 defer self.resetState();
2168 try self.setupStart();
2169 try self.setupImports();
2170 if (self.base.options.module) |mod| {
2171 var decl_it = self.decls.keyIterator();
2166 defer wasm.resetState();
2167 try wasm.setupStart();
2168 try wasm.setupImports();
2169 if (wasm.base.options.module) |mod| {
2170 var decl_it = wasm.decls.keyIterator();
21722171 while (decl_it.next()) |decl_index_ptr| {
21732172 const decl = mod.declPtr(decl_index_ptr.*);
21742173 if (decl.isExtern()) continue;
21752174 const atom = &decl.*.link.wasm;
21762175 if (decl.ty.zigTypeTag() == .Fn) {
2177 try self.parseAtom(atom, .{ .function = decl.fn_link.wasm });
2176 try wasm.parseAtom(atom, .{ .function = decl.fn_link.wasm });
21782177 } else if (decl.getVariable()) |variable| {
21792178 if (!variable.is_mutable) {
2180 try self.parseAtom(atom, .{ .data = .read_only });
2179 try wasm.parseAtom(atom, .{ .data = .read_only });
21812180 } else if (variable.init.isUndefDeep()) {
2182 try self.parseAtom(atom, .{ .data = .uninitialized });
2181 try wasm.parseAtom(atom, .{ .data = .uninitialized });
21832182 } else {
2184 try self.parseAtom(atom, .{ .data = .initialized });
2183 try wasm.parseAtom(atom, .{ .data = .initialized });
21852184 }
21862185 } else {
2187 try self.parseAtom(atom, .{ .data = .read_only });
2186 try wasm.parseAtom(atom, .{ .data = .read_only });
21882187 }
21892188
21902189 // also parse atoms for a decl's locals
21912190 for (atom.locals.items) |*local_atom| {
2192 try self.parseAtom(local_atom, .{ .data = .read_only });
2191 try wasm.parseAtom(local_atom, .{ .data = .read_only });
21932192 }
21942193 }
21952194
2196 if (self.dwarf) |*dwarf| {
2197 try dwarf.flushModule(&self.base, self.base.options.module.?);
2195 if (wasm.dwarf) |*dwarf| {
2196 try dwarf.flushModule(&wasm.base, wasm.base.options.module.?);
21982197 }
21992198 }
22002199
2201 for (self.objects.items) |*object, object_index| {
2202 try object.parseIntoAtoms(self.base.allocator, @intCast(u16, object_index), self);
2200 for (wasm.objects.items) |*object, object_index| {
2201 try object.parseIntoAtoms(wasm.base.allocator, @intCast(u16, object_index), wasm);
22032202 }
22042203
2205 try self.allocateAtoms();
2206 try self.setupMemory();
2207 self.mapFunctionTable();
2208 try self.mergeSections();
2209 try self.mergeTypes();
2210 try self.setupExports();
2204 try wasm.allocateAtoms();
2205 try wasm.setupMemory();
2206 wasm.mapFunctionTable();
2207 try wasm.mergeSections();
2208 try wasm.mergeTypes();
2209 try wasm.setupExports();
22112210
22122211 const header_size = 5 + 1;
2213 const is_obj = self.base.options.output_mode == .Obj;
2212 const is_obj = wasm.base.options.output_mode == .Obj;
22142213
2215 var binary_bytes = std.ArrayList(u8).init(self.base.allocator);
2214 var binary_bytes = std.ArrayList(u8).init(wasm.base.allocator);
22162215 defer binary_bytes.deinit();
22172216 const binary_writer = binary_bytes.writer();
22182217
......@@ -2221,18 +2220,18 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod
22212220 try binary_writer.writeAll(&[_]u8{0} ** 8);
22222221
22232222 // Type section
2224 if (self.func_types.items.len != 0) {
2223 if (wasm.func_types.items.len != 0) {
22252224 const header_offset = try reserveVecSectionHeader(&binary_bytes);
2226 log.debug("Writing type section. Count: ({d})", .{self.func_types.items.len});
2227 for (self.func_types.items) |func_type| {
2228 try leb.writeULEB128(binary_writer, wasm.function_type);
2225 log.debug("Writing type section. Count: ({d})", .{wasm.func_types.items.len});
2226 for (wasm.func_types.items) |func_type| {
2227 try leb.writeULEB128(binary_writer, std.wasm.function_type);
22292228 try leb.writeULEB128(binary_writer, @intCast(u32, func_type.params.len));
22302229 for (func_type.params) |param_ty| {
2231 try leb.writeULEB128(binary_writer, wasm.valtype(param_ty));
2230 try leb.writeULEB128(binary_writer, std.wasm.valtype(param_ty));
22322231 }
22332232 try leb.writeULEB128(binary_writer, @intCast(u32, func_type.returns.len));
22342233 for (func_type.returns) |ret_ty| {
2235 try leb.writeULEB128(binary_writer, wasm.valtype(ret_ty));
2234 try leb.writeULEB128(binary_writer, std.wasm.valtype(ret_ty));
22362235 }
22372236 }
22382237
......@@ -2241,50 +2240,50 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod
22412240 header_offset,
22422241 .type,
22432242 @intCast(u32, binary_bytes.items.len - header_offset - header_size),
2244 @intCast(u32, self.func_types.items.len),
2243 @intCast(u32, wasm.func_types.items.len),
22452244 );
22462245 section_count += 1;
22472246 }
22482247
22492248 // Import section
2250 const import_memory = self.base.options.import_memory or is_obj;
2251 const import_table = self.base.options.import_table or is_obj;
2252 if (self.imports.count() != 0 or import_memory or import_table) {
2249 const import_memory = wasm.base.options.import_memory or is_obj;
2250 const import_table = wasm.base.options.import_table or is_obj;
2251 if (wasm.imports.count() != 0 or import_memory or import_table) {
22532252 const header_offset = try reserveVecSectionHeader(&binary_bytes);
22542253
22552254 // import table is always first table so emit that first
22562255 if (import_table) {
22572256 const table_imp: types.Import = .{
2258 .module_name = try self.string_table.put(self.base.allocator, self.host_name),
2259 .name = try self.string_table.put(self.base.allocator, "__indirect_function_table"),
2257 .module_name = try wasm.string_table.put(wasm.base.allocator, wasm.host_name),
2258 .name = try wasm.string_table.put(wasm.base.allocator, "__indirect_function_table"),
22602259 .kind = .{
22612260 .table = .{
22622261 .limits = .{
2263 .min = @intCast(u32, self.function_table.count()),
2262 .min = @intCast(u32, wasm.function_table.count()),
22642263 .max = null,
22652264 },
22662265 .reftype = .funcref,
22672266 },
22682267 },
22692268 };
2270 try self.emitImport(binary_writer, table_imp);
2269 try wasm.emitImport(binary_writer, table_imp);
22712270 }
22722271
2273 var it = self.imports.iterator();
2272 var it = wasm.imports.iterator();
22742273 while (it.next()) |entry| {
2275 assert(entry.key_ptr.*.getSymbol(self).isUndefined());
2274 assert(entry.key_ptr.*.getSymbol(wasm).isUndefined());
22762275 const import = entry.value_ptr.*;
2277 try self.emitImport(binary_writer, import);
2276 try wasm.emitImport(binary_writer, import);
22782277 }
22792278
22802279 if (import_memory) {
22812280 const mem_name = if (is_obj) "__linear_memory" else "memory";
22822281 const mem_imp: types.Import = .{
2283 .module_name = try self.string_table.put(self.base.allocator, self.host_name),
2284 .name = try self.string_table.put(self.base.allocator, mem_name),
2285 .kind = .{ .memory = self.memories.limits },
2282 .module_name = try wasm.string_table.put(wasm.base.allocator, wasm.host_name),
2283 .name = try wasm.string_table.put(wasm.base.allocator, mem_name),
2284 .kind = .{ .memory = wasm.memories.limits },
22862285 };
2287 try self.emitImport(binary_writer, mem_imp);
2286 try wasm.emitImport(binary_writer, mem_imp);
22882287 }
22892288
22902289 try writeVecSectionHeader(
......@@ -2292,15 +2291,15 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod
22922291 header_offset,
22932292 .import,
22942293 @intCast(u32, binary_bytes.items.len - header_offset - header_size),
2295 @intCast(u32, self.imports.count() + @boolToInt(import_memory) + @boolToInt(import_table)),
2294 @intCast(u32, wasm.imports.count() + @boolToInt(import_memory) + @boolToInt(import_table)),
22962295 );
22972296 section_count += 1;
22982297 }
22992298
23002299 // Function section
2301 if (self.functions.count() != 0) {
2300 if (wasm.functions.count() != 0) {
23022301 const header_offset = try reserveVecSectionHeader(&binary_bytes);
2303 for (self.functions.values()) |function| {
2302 for (wasm.functions.values()) |function| {
23042303 try leb.writeULEB128(binary_writer, function.type_index);
23052304 }
23062305
......@@ -2309,19 +2308,19 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod
23092308 header_offset,
23102309 .function,
23112310 @intCast(u32, binary_bytes.items.len - header_offset - header_size),
2312 @intCast(u32, self.functions.count()),
2311 @intCast(u32, wasm.functions.count()),
23132312 );
23142313 section_count += 1;
23152314 }
23162315
23172316 // Table section
2318 const export_table = self.base.options.export_table;
2319 if (!import_table and self.function_table.count() != 0) {
2317 const export_table = wasm.base.options.export_table;
2318 if (!import_table and wasm.function_table.count() != 0) {
23202319 const header_offset = try reserveVecSectionHeader(&binary_bytes);
23212320
2322 try leb.writeULEB128(binary_writer, wasm.reftype(.funcref));
2321 try leb.writeULEB128(binary_writer, std.wasm.reftype(.funcref));
23232322 try emitLimits(binary_writer, .{
2324 .min = @intCast(u32, self.function_table.count()) + 1,
2323 .min = @intCast(u32, wasm.function_table.count()) + 1,
23252324 .max = null,
23262325 });
23272326
......@@ -2339,7 +2338,7 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod
23392338 if (!import_memory) {
23402339 const header_offset = try reserveVecSectionHeader(&binary_bytes);
23412340
2342 try emitLimits(binary_writer, self.memories.limits);
2341 try emitLimits(binary_writer, wasm.memories.limits);
23432342 try writeVecSectionHeader(
23442343 binary_bytes.items,
23452344 header_offset,
......@@ -2351,11 +2350,11 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod
23512350 }
23522351
23532352 // Global section (used to emit stack pointer)
2354 if (self.wasm_globals.items.len > 0) {
2353 if (wasm.wasm_globals.items.len > 0) {
23552354 const header_offset = try reserveVecSectionHeader(&binary_bytes);
23562355
2357 for (self.wasm_globals.items) |global| {
2358 try binary_writer.writeByte(wasm.valtype(global.global_type.valtype));
2356 for (wasm.wasm_globals.items) |global| {
2357 try binary_writer.writeByte(std.wasm.valtype(global.global_type.valtype));
23592358 try binary_writer.writeByte(@boolToInt(global.global_type.mutable));
23602359 try emitInit(binary_writer, global.init);
23612360 }
......@@ -2365,17 +2364,17 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod
23652364 header_offset,
23662365 .global,
23672366 @intCast(u32, binary_bytes.items.len - header_offset - header_size),
2368 @intCast(u32, self.wasm_globals.items.len),
2367 @intCast(u32, wasm.wasm_globals.items.len),
23692368 );
23702369 section_count += 1;
23712370 }
23722371
23732372 // Export section
2374 if (self.exports.items.len != 0 or export_table or !import_memory) {
2373 if (wasm.exports.items.len != 0 or export_table or !import_memory) {
23752374 const header_offset = try reserveVecSectionHeader(&binary_bytes);
23762375
2377 for (self.exports.items) |exp| {
2378 const name = self.string_table.get(exp.name);
2376 for (wasm.exports.items) |exp| {
2377 const name = wasm.string_table.get(exp.name);
23792378 try leb.writeULEB128(binary_writer, @intCast(u32, name.len));
23802379 try binary_writer.writeAll(name);
23812380 try leb.writeULEB128(binary_writer, @enumToInt(exp.kind));
......@@ -2385,14 +2384,14 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod
23852384 if (export_table) {
23862385 try leb.writeULEB128(binary_writer, @intCast(u32, "__indirect_function_table".len));
23872386 try binary_writer.writeAll("__indirect_function_table");
2388 try binary_writer.writeByte(wasm.externalKind(.table));
2387 try binary_writer.writeByte(std.wasm.externalKind(.table));
23892388 try leb.writeULEB128(binary_writer, @as(u32, 0)); // function table is always the first table
23902389 }
23912390
23922391 if (!import_memory) {
23932392 try leb.writeULEB128(binary_writer, @intCast(u32, "memory".len));
23942393 try binary_writer.writeAll("memory");
2395 try binary_writer.writeByte(wasm.externalKind(.memory));
2394 try binary_writer.writeByte(std.wasm.externalKind(.memory));
23962395 try leb.writeULEB128(binary_writer, @as(u32, 0));
23972396 }
23982397
......@@ -2401,13 +2400,13 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod
24012400 header_offset,
24022401 .@"export",
24032402 @intCast(u32, binary_bytes.items.len - header_offset - header_size),
2404 @intCast(u32, self.exports.items.len) + @boolToInt(export_table) + @boolToInt(!import_memory),
2403 @intCast(u32, wasm.exports.items.len) + @boolToInt(export_table) + @boolToInt(!import_memory),
24052404 );
24062405 section_count += 1;
24072406 }
24082407
24092408 // element section (function table)
2410 if (self.function_table.count() > 0) {
2409 if (wasm.function_table.count() > 0) {
24112410 const header_offset = try reserveVecSectionHeader(&binary_bytes);
24122411
24132412 var flags: u32 = 0x2; // Yes we have a table
......@@ -2415,10 +2414,10 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod
24152414 try leb.writeULEB128(binary_writer, @as(u32, 0)); // index of that table. TODO: Store synthetic symbols
24162415 try emitInit(binary_writer, .{ .i32_const = 1 }); // We start at index 1, so unresolved function pointers are invalid
24172416 try leb.writeULEB128(binary_writer, @as(u8, 0));
2418 try leb.writeULEB128(binary_writer, @intCast(u32, self.function_table.count()));
2419 var symbol_it = self.function_table.keyIterator();
2417 try leb.writeULEB128(binary_writer, @intCast(u32, wasm.function_table.count()));
2418 var symbol_it = wasm.function_table.keyIterator();
24202419 while (symbol_it.next()) |symbol_loc_ptr| {
2421 try leb.writeULEB128(binary_writer, symbol_loc_ptr.*.getSymbol(self).index);
2420 try leb.writeULEB128(binary_writer, symbol_loc_ptr.*.getSymbol(wasm).index);
24222421 }
24232422
24242423 try writeVecSectionHeader(
......@@ -2433,17 +2432,17 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod
24332432
24342433 // Code section
24352434 var code_section_size: u32 = 0;
2436 if (self.code_section_index) |code_index| {
2435 if (wasm.code_section_index) |code_index| {
24372436 const header_offset = try reserveVecSectionHeader(&binary_bytes);
2438 var atom: *Atom = self.atoms.get(code_index).?.getFirst();
2437 var atom: *Atom = wasm.atoms.get(code_index).?.getFirst();
24392438
24402439 // The code section must be sorted in line with the function order.
2441 var sorted_atoms = try std.ArrayList(*Atom).initCapacity(self.base.allocator, self.functions.count());
2440 var sorted_atoms = try std.ArrayList(*Atom).initCapacity(wasm.base.allocator, wasm.functions.count());
24422441 defer sorted_atoms.deinit();
24432442
24442443 while (true) {
24452444 if (!is_obj) {
2446 atom.resolveRelocs(self);
2445 atom.resolveRelocs(wasm);
24472446 }
24482447 sorted_atoms.appendAssumeCapacity(atom);
24492448 atom = atom.next orelse break;
......@@ -2457,7 +2456,7 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod
24572456 }
24582457 }.sort;
24592458
2460 std.sort.sort(*Atom, sorted_atoms.items, self, atom_sort_fn);
2459 std.sort.sort(*Atom, sorted_atoms.items, wasm, atom_sort_fn);
24612460
24622461 for (sorted_atoms.items) |sorted_atom| {
24632462 try leb.writeULEB128(binary_writer, sorted_atom.size);
......@@ -2470,17 +2469,17 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod
24702469 header_offset,
24712470 .code,
24722471 code_section_size,
2473 @intCast(u32, self.functions.count()),
2472 @intCast(u32, wasm.functions.count()),
24742473 );
24752474 code_section_index = section_count;
24762475 section_count += 1;
24772476 }
24782477
24792478 // Data section
2480 if (self.data_segments.count() != 0) {
2479 if (wasm.data_segments.count() != 0) {
24812480 const header_offset = try reserveVecSectionHeader(&binary_bytes);
24822481
2483 var it = self.data_segments.iterator();
2482 var it = wasm.data_segments.iterator();
24842483 var segment_count: u32 = 0;
24852484 while (it.next()) |entry| {
24862485 // do not output 'bss' section unless we import memory and therefore
......@@ -2488,8 +2487,8 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod
24882487 if (!import_memory and std.mem.eql(u8, entry.key_ptr.*, ".bss")) continue;
24892488 segment_count += 1;
24902489 const atom_index = entry.value_ptr.*;
2491 var atom: *Atom = self.atoms.getPtr(atom_index).?.*.getFirst();
2492 const segment = self.segments.items[atom_index];
2490 var atom: *Atom = wasm.atoms.getPtr(atom_index).?.*.getFirst();
2491 const segment = wasm.segments.items[atom_index];
24932492
24942493 // flag and index to memory section (currently, there can only be 1 memory section in wasm)
24952494 try leb.writeULEB128(binary_writer, @as(u32, 0));
......@@ -2501,7 +2500,7 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod
25012500 var current_offset: u32 = 0;
25022501 while (true) {
25032502 if (!is_obj) {
2504 atom.resolveRelocs(self);
2503 atom.resolveRelocs(wasm);
25052504 }
25062505
25072506 // Pad with zeroes to ensure all segments are aligned
......@@ -2546,25 +2545,25 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod
25462545 // we never store all symbols in a single table, but store a location reference instead.
25472546 // This means that for a relocatable object file, we need to generate one and provide it to the relocation sections.
25482547 var symbol_table = std.AutoArrayHashMap(SymbolLoc, u32).init(arena);
2549 try self.emitLinkSection(&binary_bytes, &symbol_table);
2548 try wasm.emitLinkSection(&binary_bytes, &symbol_table);
25502549 if (code_section_index) |code_index| {
2551 try self.emitCodeRelocations(&binary_bytes, code_index, symbol_table);
2550 try wasm.emitCodeRelocations(&binary_bytes, code_index, symbol_table);
25522551 }
25532552 if (data_section_index) |data_index| {
2554 try self.emitDataRelocations(&binary_bytes, data_index, symbol_table);
2553 try wasm.emitDataRelocations(&binary_bytes, data_index, symbol_table);
25552554 }
2556 } else if (!self.base.options.strip) {
2557 if (self.dwarf) |*dwarf| {
2558 const mod = self.base.options.module.?;
2559 try dwarf.writeDbgAbbrev(&self.base);
2555 } else if (!wasm.base.options.strip) {
2556 if (wasm.dwarf) |*dwarf| {
2557 const mod = wasm.base.options.module.?;
2558 try dwarf.writeDbgAbbrev(&wasm.base);
25602559 // for debug info and ranges, the address is always 0,
25612560 // as locations are always offsets relative to 'code' section.
2562 try dwarf.writeDbgInfoHeader(&self.base, mod, 0, code_section_size);
2563 try dwarf.writeDbgAranges(&self.base, 0, code_section_size);
2564 try dwarf.writeDbgLineHeader(&self.base, mod);
2561 try dwarf.writeDbgInfoHeader(&wasm.base, mod, 0, code_section_size);
2562 try dwarf.writeDbgAranges(&wasm.base, 0, code_section_size);
2563 try dwarf.writeDbgLineHeader(&wasm.base, mod);
25652564 }
25662565
2567 var debug_bytes = std.ArrayList(u8).init(self.base.allocator);
2566 var debug_bytes = std.ArrayList(u8).init(wasm.base.allocator);
25682567 defer debug_bytes.deinit();
25692568
25702569 const DebugSection = struct {
......@@ -2573,21 +2572,21 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod
25732572 };
25742573
25752574 const debug_sections: []const DebugSection = &.{
2576 .{ .name = ".debug_info", .index = self.debug_info_index },
2577 .{ .name = ".debug_pubtypes", .index = self.debug_pubtypes_index },
2578 .{ .name = ".debug_abbrev", .index = self.debug_abbrev_index },
2579 .{ .name = ".debug_line", .index = self.debug_line_index },
2580 .{ .name = ".debug_str", .index = self.debug_str_index },
2581 .{ .name = ".debug_pubnames", .index = self.debug_pubnames_index },
2582 .{ .name = ".debug_loc", .index = self.debug_loc_index },
2583 .{ .name = ".debug_ranges", .index = self.debug_ranges_index },
2575 .{ .name = ".debug_info", .index = wasm.debug_info_index },
2576 .{ .name = ".debug_pubtypes", .index = wasm.debug_pubtypes_index },
2577 .{ .name = ".debug_abbrev", .index = wasm.debug_abbrev_index },
2578 .{ .name = ".debug_line", .index = wasm.debug_line_index },
2579 .{ .name = ".debug_str", .index = wasm.debug_str_index },
2580 .{ .name = ".debug_pubnames", .index = wasm.debug_pubnames_index },
2581 .{ .name = ".debug_loc", .index = wasm.debug_loc_index },
2582 .{ .name = ".debug_ranges", .index = wasm.debug_ranges_index },
25842583 };
25852584
25862585 for (debug_sections) |item| {
25872586 if (item.index) |index| {
2588 var atom = self.atoms.get(index).?.getFirst();
2587 var atom = wasm.atoms.get(index).?.getFirst();
25892588 while (true) {
2590 atom.resolveRelocs(self);
2589 atom.resolveRelocs(wasm);
25912590 try debug_bytes.appendSlice(atom.code.items);
25922591 atom = atom.next orelse break;
25932592 }
......@@ -2595,20 +2594,20 @@ pub fn flushModule(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod
25952594 debug_bytes.clearRetainingCapacity();
25962595 }
25972596 }
2598 try self.emitNameSection(&binary_bytes, arena);
2597 try wasm.emitNameSection(&binary_bytes, arena);
25992598 }
26002599
26012600 // Only when writing all sections executed properly we write the magic
26022601 // bytes. This allows us to easily detect what went wrong while generating
26032602 // the final binary.
2604 mem.copy(u8, binary_bytes.items, &(wasm.magic ++ wasm.version));
2603 mem.copy(u8, binary_bytes.items, &(std.wasm.magic ++ std.wasm.version));
26052604
26062605 // finally, write the entire binary into the file.
26072606 var iovec = [_]std.os.iovec_const{.{
26082607 .iov_base = binary_bytes.items.ptr,
26092608 .iov_len = binary_bytes.items.len,
26102609 }};
2611 try self.base.file.?.writevAll(&iovec);
2610 try wasm.base.file.?.writevAll(&iovec);
26122611}
26132612
26142613fn emitDebugSection(binary_bytes: *std.ArrayList(u8), data: []const u8, name: []const u8) !void {
......@@ -2629,7 +2628,7 @@ fn emitDebugSection(binary_bytes: *std.ArrayList(u8), data: []const u8, name: []
26292628 );
26302629}
26312630
2632fn emitNameSection(self: *Wasm, binary_bytes: *std.ArrayList(u8), arena: std.mem.Allocator) !void {
2631fn emitNameSection(wasm: *Wasm, binary_bytes: *std.ArrayList(u8), arena: std.mem.Allocator) !void {
26332632 const Name = struct {
26342633 index: u32,
26352634 name: []const u8,
......@@ -2642,15 +2641,15 @@ fn emitNameSection(self: *Wasm, binary_bytes: *std.ArrayList(u8), arena: std.mem
26422641
26432642 // we must de-duplicate symbols that point to the same function
26442643 var funcs = std.AutoArrayHashMap(u32, Name).init(arena);
2645 try funcs.ensureUnusedCapacity(self.functions.count() + self.imported_functions_count);
2646 var globals = try std.ArrayList(Name).initCapacity(arena, self.wasm_globals.items.len + self.imported_globals_count);
2647 var segments = try std.ArrayList(Name).initCapacity(arena, self.data_segments.count());
2644 try funcs.ensureUnusedCapacity(wasm.functions.count() + wasm.imported_functions_count);
2645 var globals = try std.ArrayList(Name).initCapacity(arena, wasm.wasm_globals.items.len + wasm.imported_globals_count);
2646 var segments = try std.ArrayList(Name).initCapacity(arena, wasm.data_segments.count());
26482647
2649 for (self.resolved_symbols.keys()) |sym_loc| {
2650 const symbol = sym_loc.getSymbol(self).*;
2648 for (wasm.resolved_symbols.keys()) |sym_loc| {
2649 const symbol = sym_loc.getSymbol(wasm).*;
26512650 const name = if (symbol.isUndefined()) blk: {
2652 break :blk self.string_table.get(self.imports.get(sym_loc).?.name);
2653 } else sym_loc.getName(self);
2651 break :blk wasm.string_table.get(wasm.imports.get(sym_loc).?.name);
2652 } else sym_loc.getName(wasm);
26542653 switch (symbol.tag) {
26552654 .function => {
26562655 const gop = funcs.getOrPutAssumeCapacity(symbol.index);
......@@ -2664,10 +2663,10 @@ fn emitNameSection(self: *Wasm, binary_bytes: *std.ArrayList(u8), arena: std.mem
26642663 }
26652664 // data segments are already 'ordered'
26662665 var data_segment_index: u32 = 0;
2667 for (self.data_segments.keys()) |key| {
2666 for (wasm.data_segments.keys()) |key| {
26682667 // bss section is not emitted when this condition holds true, so we also
26692668 // do not output a name for it.
2670 if (!self.base.options.import_memory and std.mem.eql(u8, key, ".bss")) continue;
2669 if (!wasm.base.options.import_memory and std.mem.eql(u8, key, ".bss")) continue;
26712670 segments.appendAssumeCapacity(.{ .index = data_segment_index, .name = key });
26722671 data_segment_index += 1;
26732672 }
......@@ -2680,9 +2679,9 @@ fn emitNameSection(self: *Wasm, binary_bytes: *std.ArrayList(u8), arena: std.mem
26802679 try leb.writeULEB128(writer, @intCast(u32, "name".len));
26812680 try writer.writeAll("name");
26822681
2683 try self.emitNameSubsection(.function, funcs.values(), writer);
2684 try self.emitNameSubsection(.global, globals.items, writer);
2685 try self.emitNameSubsection(.data_segment, segments.items, writer);
2682 try wasm.emitNameSubsection(.function, funcs.values(), writer);
2683 try wasm.emitNameSubsection(.global, globals.items, writer);
2684 try wasm.emitNameSubsection(.data_segment, segments.items, writer);
26862685
26872686 try writeCustomSectionHeader(
26882687 binary_bytes.items,
......@@ -2691,9 +2690,9 @@ fn emitNameSection(self: *Wasm, binary_bytes: *std.ArrayList(u8), arena: std.mem
26912690 );
26922691}
26932692
2694fn emitNameSubsection(self: *Wasm, section_id: std.wasm.NameSubsection, names: anytype, writer: anytype) !void {
2693fn emitNameSubsection(wasm: *Wasm, section_id: std.wasm.NameSubsection, names: anytype, writer: anytype) !void {
26952694 // We must emit subsection size, so first write to a temporary list
2696 var section_list = std.ArrayList(u8).init(self.base.allocator);
2695 var section_list = std.ArrayList(u8).init(wasm.base.allocator);
26972696 defer section_list.deinit();
26982697 const sub_writer = section_list.writer();
26992698
......@@ -2711,7 +2710,7 @@ fn emitNameSubsection(self: *Wasm, section_id: std.wasm.NameSubsection, names: a
27112710 try writer.writeAll(section_list.items);
27122711}
27132712
2714fn emitLimits(writer: anytype, limits: wasm.Limits) !void {
2713fn emitLimits(writer: anytype, limits: std.wasm.Limits) !void {
27152714 try leb.writeULEB128(writer, @boolToInt(limits.max != null));
27162715 try leb.writeULEB128(writer, limits.min);
27172716 if (limits.max) |max| {
......@@ -2719,38 +2718,38 @@ fn emitLimits(writer: anytype, limits: wasm.Limits) !void {
27192718 }
27202719}
27212720
2722fn emitInit(writer: anytype, init_expr: wasm.InitExpression) !void {
2721fn emitInit(writer: anytype, init_expr: std.wasm.InitExpression) !void {
27232722 switch (init_expr) {
27242723 .i32_const => |val| {
2725 try writer.writeByte(wasm.opcode(.i32_const));
2724 try writer.writeByte(std.wasm.opcode(.i32_const));
27262725 try leb.writeILEB128(writer, val);
27272726 },
27282727 .i64_const => |val| {
2729 try writer.writeByte(wasm.opcode(.i64_const));
2728 try writer.writeByte(std.wasm.opcode(.i64_const));
27302729 try leb.writeILEB128(writer, val);
27312730 },
27322731 .f32_const => |val| {
2733 try writer.writeByte(wasm.opcode(.f32_const));
2732 try writer.writeByte(std.wasm.opcode(.f32_const));
27342733 try writer.writeIntLittle(u32, @bitCast(u32, val));
27352734 },
27362735 .f64_const => |val| {
2737 try writer.writeByte(wasm.opcode(.f64_const));
2736 try writer.writeByte(std.wasm.opcode(.f64_const));
27382737 try writer.writeIntLittle(u64, @bitCast(u64, val));
27392738 },
27402739 .global_get => |val| {
2741 try writer.writeByte(wasm.opcode(.global_get));
2740 try writer.writeByte(std.wasm.opcode(.global_get));
27422741 try leb.writeULEB128(writer, val);
27432742 },
27442743 }
2745 try writer.writeByte(wasm.opcode(.end));
2744 try writer.writeByte(std.wasm.opcode(.end));
27462745}
27472746
2748fn emitImport(self: *Wasm, writer: anytype, import: types.Import) !void {
2749 const module_name = self.string_table.get(import.module_name);
2747fn emitImport(wasm: *Wasm, writer: anytype, import: types.Import) !void {
2748 const module_name = wasm.string_table.get(import.module_name);
27502749 try leb.writeULEB128(writer, @intCast(u32, module_name.len));
27512750 try writer.writeAll(module_name);
27522751
2753 const name = self.string_table.get(import.name);
2752 const name = wasm.string_table.get(import.name);
27542753 try leb.writeULEB128(writer, @intCast(u32, name.len));
27552754 try writer.writeAll(name);
27562755
......@@ -2758,11 +2757,11 @@ fn emitImport(self: *Wasm, writer: anytype, import: types.Import) !void {
27582757 switch (import.kind) {
27592758 .function => |type_index| try leb.writeULEB128(writer, type_index),
27602759 .global => |global_type| {
2761 try leb.writeULEB128(writer, wasm.valtype(global_type.valtype));
2760 try leb.writeULEB128(writer, std.wasm.valtype(global_type.valtype));
27622761 try writer.writeByte(@boolToInt(global_type.mutable));
27632762 },
27642763 .table => |table| {
2765 try leb.writeULEB128(writer, wasm.reftype(table.reftype));
2764 try leb.writeULEB128(writer, std.wasm.reftype(table.reftype));
27662765 try emitLimits(writer, table.limits);
27672766 },
27682767 .memory => |limits| {
......@@ -2771,28 +2770,28 @@ fn emitImport(self: *Wasm, writer: anytype, import: types.Import) !void {
27712770 }
27722771}
27732772
2774fn linkWithLLD(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !void {
2773fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !void {
27752774 const tracy = trace(@src());
27762775 defer tracy.end();
27772776
2778 var arena_allocator = std.heap.ArenaAllocator.init(self.base.allocator);
2777 var arena_allocator = std.heap.ArenaAllocator.init(wasm.base.allocator);
27792778 defer arena_allocator.deinit();
27802779 const arena = arena_allocator.allocator();
27812780
2782 const directory = self.base.options.emit.?.directory; // Just an alias to make it shorter to type.
2783 const full_out_path = try directory.join(arena, &[_][]const u8{self.base.options.emit.?.sub_path});
2781 const directory = wasm.base.options.emit.?.directory; // Just an alias to make it shorter to type.
2782 const full_out_path = try directory.join(arena, &[_][]const u8{wasm.base.options.emit.?.sub_path});
27842783
27852784 // If there is no Zig code to compile, then we should skip flushing the output file because it
27862785 // will not be part of the linker line anyway.
2787 const module_obj_path: ?[]const u8 = if (self.base.options.module) |mod| blk: {
2788 const use_stage1 = build_options.have_stage1 and self.base.options.use_stage1;
2786 const module_obj_path: ?[]const u8 = if (wasm.base.options.module) |mod| blk: {
2787 const use_stage1 = build_options.have_stage1 and wasm.base.options.use_stage1;
27892788 if (use_stage1) {
27902789 const obj_basename = try std.zig.binNameAlloc(arena, .{
2791 .root_name = self.base.options.root_name,
2792 .target = self.base.options.target,
2790 .root_name = wasm.base.options.root_name,
2791 .target = wasm.base.options.target,
27932792 .output_mode = .Obj,
27942793 });
2795 switch (self.base.options.cache_mode) {
2794 switch (wasm.base.options.cache_mode) {
27962795 .incremental => break :blk try mod.zig_cache_artifact_directory.join(
27972796 arena,
27982797 &[_][]const u8{obj_basename},
......@@ -2803,12 +2802,12 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !
28032802 }
28042803 }
28052804
2806 try self.flushModule(comp, prog_node);
2805 try wasm.flushModule(comp, prog_node);
28072806
28082807 if (fs.path.dirname(full_out_path)) |dirname| {
2809 break :blk try fs.path.join(arena, &.{ dirname, self.base.intermediary_basename.? });
2808 break :blk try fs.path.join(arena, &.{ dirname, wasm.base.intermediary_basename.? });
28102809 } else {
2811 break :blk self.base.intermediary_basename.?;
2810 break :blk wasm.base.intermediary_basename.?;
28122811 }
28132812 } else null;
28142813
......@@ -2817,31 +2816,31 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !
28172816 sub_prog_node.context.refresh();
28182817 defer sub_prog_node.end();
28192818
2820 const is_obj = self.base.options.output_mode == .Obj;
2819 const is_obj = wasm.base.options.output_mode == .Obj;
28212820
2822 const compiler_rt_path: ?[]const u8 = if (self.base.options.include_compiler_rt and !is_obj)
2821 const compiler_rt_path: ?[]const u8 = if (wasm.base.options.include_compiler_rt and !is_obj)
28232822 comp.compiler_rt_lib.?.full_object_path
28242823 else
28252824 null;
28262825
2827 const target = self.base.options.target;
2826 const target = wasm.base.options.target;
28282827
28292828 const id_symlink_basename = "lld.id";
28302829
28312830 var man: Cache.Manifest = undefined;
2832 defer if (!self.base.options.disable_lld_caching) man.deinit();
2831 defer if (!wasm.base.options.disable_lld_caching) man.deinit();
28332832
28342833 var digest: [Cache.hex_digest_len]u8 = undefined;
28352834
2836 if (!self.base.options.disable_lld_caching) {
2835 if (!wasm.base.options.disable_lld_caching) {
28372836 man = comp.cache_parent.obtain();
28382837
28392838 // We are about to obtain this lock, so here we give other processes a chance first.
2840 self.base.releaseLock();
2839 wasm.base.releaseLock();
28412840
28422841 comptime assert(Compilation.link_hash_implementation_version == 7);
28432842
2844 for (self.base.options.objects) |obj| {
2843 for (wasm.base.options.objects) |obj| {
28452844 _ = try man.addFile(obj.path, null);
28462845 man.hash.add(obj.must_link);
28472846 }
......@@ -2850,18 +2849,18 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !
28502849 }
28512850 try man.addOptionalFile(module_obj_path);
28522851 try man.addOptionalFile(compiler_rt_path);
2853 man.hash.addOptionalBytes(self.base.options.entry);
2854 man.hash.addOptional(self.base.options.stack_size_override);
2855 man.hash.add(self.base.options.import_memory);
2856 man.hash.add(self.base.options.import_table);
2857 man.hash.add(self.base.options.export_table);
2858 man.hash.addOptional(self.base.options.initial_memory);
2859 man.hash.addOptional(self.base.options.max_memory);
2860 man.hash.add(self.base.options.shared_memory);
2861 man.hash.addOptional(self.base.options.global_base);
2862 man.hash.add(self.base.options.export_symbol_names.len);
2852 man.hash.addOptionalBytes(wasm.base.options.entry);
2853 man.hash.addOptional(wasm.base.options.stack_size_override);
2854 man.hash.add(wasm.base.options.import_memory);
2855 man.hash.add(wasm.base.options.import_table);
2856 man.hash.add(wasm.base.options.export_table);
2857 man.hash.addOptional(wasm.base.options.initial_memory);
2858 man.hash.addOptional(wasm.base.options.max_memory);
2859 man.hash.add(wasm.base.options.shared_memory);
2860 man.hash.addOptional(wasm.base.options.global_base);
2861 man.hash.add(wasm.base.options.export_symbol_names.len);
28632862 // strip does not need to go into the linker hash because it is part of the hash namespace
2864 for (self.base.options.export_symbol_names) |symbol_name| {
2863 for (wasm.base.options.export_symbol_names) |symbol_name| {
28652864 man.hash.addBytes(symbol_name);
28662865 }
28672866
......@@ -2882,7 +2881,7 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !
28822881 if (mem.eql(u8, prev_digest, &digest)) {
28832882 log.debug("WASM LLD digest={s} match - skipping invocation", .{std.fmt.fmtSliceHexLower(&digest)});
28842883 // Hot diggity dog! The output binary is already there.
2885 self.base.lock = man.toOwnedLock();
2884 wasm.base.lock = man.toOwnedLock();
28862885 return;
28872886 }
28882887 log.debug("WASM LLD prev_digest={s} new_digest={s}", .{ std.fmt.fmtSliceHexLower(prev_digest), std.fmt.fmtSliceHexLower(&digest) });
......@@ -2899,8 +2898,8 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !
28992898 // here. TODO: think carefully about how we can avoid this redundant operation when doing
29002899 // build-obj. See also the corresponding TODO in linkAsArchive.
29012900 const the_object_path = blk: {
2902 if (self.base.options.objects.len != 0)
2903 break :blk self.base.options.objects[0].path;
2901 if (wasm.base.options.objects.len != 0)
2902 break :blk wasm.base.options.objects[0].path;
29042903
29052904 if (comp.c_object_table.count() != 0)
29062905 break :blk comp.c_object_table.keys()[0].status.success.object_path;
......@@ -2919,7 +2918,7 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !
29192918 }
29202919 } else {
29212920 // Create an LLD command line and invoke it.
2922 var argv = std.ArrayList([]const u8).init(self.base.allocator);
2921 var argv = std.ArrayList([]const u8).init(wasm.base.allocator);
29232922 defer argv.deinit();
29242923 // We will invoke ourselves as a child process to gain access to LLD.
29252924 // This is necessary because LLD does not behave properly as a library -
......@@ -2927,47 +2926,47 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !
29272926 try argv.appendSlice(&[_][]const u8{ comp.self_exe_path.?, "wasm-ld" });
29282927 try argv.append("-error-limit=0");
29292928
2930 if (self.base.options.lto) {
2931 switch (self.base.options.optimize_mode) {
2929 if (wasm.base.options.lto) {
2930 switch (wasm.base.options.optimize_mode) {
29322931 .Debug => {},
29332932 .ReleaseSmall => try argv.append("-O2"),
29342933 .ReleaseFast, .ReleaseSafe => try argv.append("-O3"),
29352934 }
29362935 }
29372936
2938 if (self.base.options.import_memory) {
2937 if (wasm.base.options.import_memory) {
29392938 try argv.append("--import-memory");
29402939 }
29412940
2942 if (self.base.options.import_table) {
2943 assert(!self.base.options.export_table);
2941 if (wasm.base.options.import_table) {
2942 assert(!wasm.base.options.export_table);
29442943 try argv.append("--import-table");
29452944 }
29462945
2947 if (self.base.options.export_table) {
2948 assert(!self.base.options.import_table);
2946 if (wasm.base.options.export_table) {
2947 assert(!wasm.base.options.import_table);
29492948 try argv.append("--export-table");
29502949 }
29512950
2952 if (self.base.options.strip) {
2951 if (wasm.base.options.strip) {
29532952 try argv.append("-s");
29542953 }
29552954
2956 if (self.base.options.initial_memory) |initial_memory| {
2955 if (wasm.base.options.initial_memory) |initial_memory| {
29572956 const arg = try std.fmt.allocPrint(arena, "--initial-memory={d}", .{initial_memory});
29582957 try argv.append(arg);
29592958 }
29602959
2961 if (self.base.options.max_memory) |max_memory| {
2960 if (wasm.base.options.max_memory) |max_memory| {
29622961 const arg = try std.fmt.allocPrint(arena, "--max-memory={d}", .{max_memory});
29632962 try argv.append(arg);
29642963 }
29652964
2966 if (self.base.options.shared_memory) {
2965 if (wasm.base.options.shared_memory) {
29672966 try argv.append("--shared-memory");
29682967 }
29692968
2970 if (self.base.options.global_base) |global_base| {
2969 if (wasm.base.options.global_base) |global_base| {
29712970 const arg = try std.fmt.allocPrint(arena, "--global-base={d}", .{global_base});
29722971 try argv.append(arg);
29732972 } else {
......@@ -2980,29 +2979,29 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !
29802979
29812980 var auto_export_symbols = true;
29822981 // Users are allowed to specify which symbols they want to export to the wasm host.
2983 for (self.base.options.export_symbol_names) |symbol_name| {
2982 for (wasm.base.options.export_symbol_names) |symbol_name| {
29842983 const arg = try std.fmt.allocPrint(arena, "--export={s}", .{symbol_name});
29852984 try argv.append(arg);
29862985 auto_export_symbols = false;
29872986 }
29882987
2989 if (self.base.options.rdynamic) {
2988 if (wasm.base.options.rdynamic) {
29902989 try argv.append("--export-dynamic");
29912990 auto_export_symbols = false;
29922991 }
29932992
29942993 if (auto_export_symbols) {
2995 if (self.base.options.module) |mod| {
2994 if (wasm.base.options.module) |mod| {
29962995 // when we use stage1, we use the exports that stage1 provided us.
29972996 // For stage2, we can directly retrieve them from the module.
2998 const use_stage1 = build_options.have_stage1 and self.base.options.use_stage1;
2997 const use_stage1 = build_options.have_stage1 and wasm.base.options.use_stage1;
29992998 if (use_stage1) {
30002999 for (comp.export_symbol_names.items) |symbol_name| {
30013000 try argv.append(try std.fmt.allocPrint(arena, "--export={s}", .{symbol_name}));
30023001 }
30033002 } else {
30043003 const skip_export_non_fn = target.os.tag == .wasi and
3005 self.base.options.wasi_exec_model == .command;
3004 wasm.base.options.wasi_exec_model == .command;
30063005 for (mod.decl_exports.values()) |exports| {
30073006 for (exports) |exprt| {
30083007 const exported_decl = mod.declPtr(exprt.exported_decl);
......@@ -3020,7 +3019,7 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !
30203019 }
30213020 }
30223021
3023 if (self.base.options.entry) |entry| {
3022 if (wasm.base.options.entry) |entry| {
30243023 try argv.append("--entry");
30253024 try argv.append(entry);
30263025 }
......@@ -3028,16 +3027,16 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !
30283027 // Increase the default stack size to a more reasonable value of 1MB instead of
30293028 // the default of 1 Wasm page being 64KB, unless overridden by the user.
30303029 try argv.append("-z");
3031 const stack_size = self.base.options.stack_size_override orelse wasm.page_size * 16;
3030 const stack_size = wasm.base.options.stack_size_override orelse std.wasm.page_size * 16;
30323031 const arg = try std.fmt.allocPrint(arena, "stack-size={d}", .{stack_size});
30333032 try argv.append(arg);
30343033
3035 if (self.base.options.output_mode == .Exe) {
3036 if (self.base.options.wasi_exec_model == .reactor) {
3034 if (wasm.base.options.output_mode == .Exe) {
3035 if (wasm.base.options.wasi_exec_model == .reactor) {
30373036 // Reactor execution model does not have _start so lld doesn't look for it.
30383037 try argv.append("--no-entry");
30393038 }
3040 } else if (self.base.options.entry == null) {
3039 } else if (wasm.base.options.entry == null) {
30413040 try argv.append("--no-entry"); // So lld doesn't look for _start.
30423041 }
30433042 try argv.appendSlice(&[_][]const u8{
......@@ -3051,10 +3050,10 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !
30513050 }
30523051
30533052 if (target.os.tag == .wasi) {
3054 const is_exe_or_dyn_lib = self.base.options.output_mode == .Exe or
3055 (self.base.options.output_mode == .Lib and self.base.options.link_mode == .Dynamic);
3053 const is_exe_or_dyn_lib = wasm.base.options.output_mode == .Exe or
3054 (wasm.base.options.output_mode == .Lib and wasm.base.options.link_mode == .Dynamic);
30563055 if (is_exe_or_dyn_lib) {
3057 const wasi_emulated_libs = self.base.options.wasi_emulated_libs;
3056 const wasi_emulated_libs = wasm.base.options.wasi_emulated_libs;
30583057 for (wasi_emulated_libs) |crt_file| {
30593058 try argv.append(try comp.get_libc_crt_file(
30603059 arena,
......@@ -3062,15 +3061,15 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !
30623061 ));
30633062 }
30643063
3065 if (self.base.options.link_libc) {
3064 if (wasm.base.options.link_libc) {
30663065 try argv.append(try comp.get_libc_crt_file(
30673066 arena,
3068 wasi_libc.execModelCrtFileFullName(self.base.options.wasi_exec_model),
3067 wasi_libc.execModelCrtFileFullName(wasm.base.options.wasi_exec_model),
30693068 ));
30703069 try argv.append(try comp.get_libc_crt_file(arena, "libc.a"));
30713070 }
30723071
3073 if (self.base.options.link_libcpp) {
3072 if (wasm.base.options.link_libcpp) {
30743073 try argv.append(comp.libcxx_static_lib.?.full_object_path);
30753074 try argv.append(comp.libcxxabi_static_lib.?.full_object_path);
30763075 }
......@@ -3079,7 +3078,7 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !
30793078
30803079 // Positional arguments to the linker such as object files.
30813080 var whole_archive = false;
3082 for (self.base.options.objects) |obj| {
3081 for (wasm.base.options.objects) |obj| {
30833082 if (obj.must_link and !whole_archive) {
30843083 try argv.append("-whole-archive");
30853084 whole_archive = true;
......@@ -3101,9 +3100,9 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !
31013100 try argv.append(p);
31023101 }
31033102
3104 if (self.base.options.output_mode != .Obj and
3105 !self.base.options.skip_linker_dependencies and
3106 !self.base.options.link_libc)
3103 if (wasm.base.options.output_mode != .Obj and
3104 !wasm.base.options.skip_linker_dependencies and
3105 !wasm.base.options.link_libc)
31073106 {
31083107 try argv.append(comp.libc_static_lib.?.full_object_path);
31093108 }
......@@ -3112,7 +3111,7 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !
31123111 try argv.append(p);
31133112 }
31143113
3115 if (self.base.options.verbose_link) {
3114 if (wasm.base.options.verbose_link) {
31163115 // Skip over our own name so that the LLD linker name is the first argv item.
31173116 Compilation.dump_argv(argv.items[1..]);
31183117 }
......@@ -3129,7 +3128,7 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !
31293128
31303129 const term = child.spawnAndWait() catch |err| {
31313130 log.err("unable to spawn {s}: {s}", .{ argv.items[0], @errorName(err) });
3132 return error.UnableToSpawnSelf;
3131 return error.UnableToSpawnwasm;
31333132 };
31343133 switch (term) {
31353134 .Exited => |code| {
......@@ -3150,7 +3149,7 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !
31503149
31513150 const term = child.wait() catch |err| {
31523151 log.err("unable to spawn {s}: {s}", .{ argv.items[0], @errorName(err) });
3153 return error.UnableToSpawnSelf;
3152 return error.UnableToSpawnwasm;
31543153 };
31553154
31563155 switch (term) {
......@@ -3184,7 +3183,7 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !
31843183 }
31853184 }
31863185
3187 if (!self.base.options.disable_lld_caching) {
3186 if (!wasm.base.options.disable_lld_caching) {
31883187 // Update the file with the digest. If it fails we can continue; it only
31893188 // means that the next invocation will have an unnecessary cache miss.
31903189 Cache.writeSmallFile(directory.handle, id_symlink_basename, &digest) catch |err| {
......@@ -3196,7 +3195,7 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !
31963195 };
31973196 // We hang on to this lock so that the output file path can be used without
31983197 // other processes clobbering it.
3199 self.base.lock = man.toOwnedLock();
3198 wasm.base.lock = man.toOwnedLock();
32003199 }
32013200}
32023201
......@@ -3208,7 +3207,7 @@ fn reserveVecSectionHeader(bytes: *std.ArrayList(u8)) !u32 {
32083207 return offset;
32093208}
32103209
3211fn reserveCustomSectionHeader(bytes: *std.ArrayList(u8)) !u64 {
3210fn reserveCustomSectionHeader(bytes: *std.ArrayList(u8)) !u32 {
32123211 // unlike regular section, we don't emit the count
32133212 const header_size = 1 + 5;
32143213 const offset = @intCast(u32, bytes.items.len);
......@@ -3216,7 +3215,7 @@ fn reserveCustomSectionHeader(bytes: *std.ArrayList(u8)) !u64 {
32163215 return offset;
32173216}
32183217
3219fn writeVecSectionHeader(buffer: []u8, offset: u32, section: wasm.Section, size: u32, items: u32) !void {
3218fn writeVecSectionHeader(buffer: []u8, offset: u32, section: std.wasm.Section, size: u32, items: u32) !void {
32203219 var buf: [1 + 5 + 5]u8 = undefined;
32213220 buf[0] = @enumToInt(section);
32223221 leb.writeUnsignedFixed(5, buf[1..6], size);
......@@ -3224,14 +3223,14 @@ fn writeVecSectionHeader(buffer: []u8, offset: u32, section: wasm.Section, size:
32243223 mem.copy(u8, buffer[offset..], &buf);
32253224}
32263225
3227fn writeCustomSectionHeader(buffer: []u8, offset: u64, size: u32) !void {
3226fn writeCustomSectionHeader(buffer: []u8, offset: u32, size: u32) !void {
32283227 var buf: [1 + 5]u8 = undefined;
32293228 buf[0] = 0; // 0 = 'custom' section
32303229 leb.writeUnsignedFixed(5, buf[1..6], size);
32313230 mem.copy(u8, buffer[offset..], &buf);
32323231}
32333232
3234fn emitLinkSection(self: *Wasm, binary_bytes: *std.ArrayList(u8), symbol_table: *std.AutoArrayHashMap(SymbolLoc, u32)) !void {
3233fn emitLinkSection(wasm: *Wasm, binary_bytes: *std.ArrayList(u8), symbol_table: *std.AutoArrayHashMap(SymbolLoc, u32)) !void {
32353234 const offset = try reserveCustomSectionHeader(binary_bytes);
32363235 const writer = binary_bytes.writer();
32373236 // emit "linking" custom section name
......@@ -3244,22 +3243,22 @@ fn emitLinkSection(self: *Wasm, binary_bytes: *std.ArrayList(u8), symbol_table:
32443243
32453244 // For each subsection type (found in types.Subsection) we can emit a section.
32463245 // Currently, we only support emitting segment info and the symbol table.
3247 try self.emitSymbolTable(binary_bytes, symbol_table);
3248 try self.emitSegmentInfo(binary_bytes);
3246 try wasm.emitSymbolTable(binary_bytes, symbol_table);
3247 try wasm.emitSegmentInfo(binary_bytes);
32493248
32503249 const size = @intCast(u32, binary_bytes.items.len - offset - 6);
32513250 try writeCustomSectionHeader(binary_bytes.items, offset, size);
32523251}
32533252
3254fn emitSymbolTable(self: *Wasm, binary_bytes: *std.ArrayList(u8), symbol_table: *std.AutoArrayHashMap(SymbolLoc, u32)) !void {
3253fn emitSymbolTable(wasm: *Wasm, binary_bytes: *std.ArrayList(u8), symbol_table: *std.AutoArrayHashMap(SymbolLoc, u32)) !void {
32553254 const writer = binary_bytes.writer();
32563255
32573256 try leb.writeULEB128(writer, @enumToInt(types.SubsectionType.WASM_SYMBOL_TABLE));
32583257 const table_offset = binary_bytes.items.len;
32593258
32603259 var symbol_count: u32 = 0;
3261 for (self.resolved_symbols.keys()) |sym_loc| {
3262 const symbol = sym_loc.getSymbol(self).*;
3260 for (wasm.resolved_symbols.keys()) |sym_loc| {
3261 const symbol = sym_loc.getSymbol(wasm).*;
32633262 if (symbol.tag == .dead) continue; // Do not emit dead symbols
32643263 try symbol_table.putNoClobber(sym_loc, symbol_count);
32653264 symbol_count += 1;
......@@ -3267,7 +3266,7 @@ fn emitSymbolTable(self: *Wasm, binary_bytes: *std.ArrayList(u8), symbol_table:
32673266 try leb.writeULEB128(writer, @enumToInt(symbol.tag));
32683267 try leb.writeULEB128(writer, symbol.flags);
32693268
3270 const sym_name = if (self.export_names.get(sym_loc)) |exp_name| self.string_table.get(exp_name) else sym_loc.getName(self);
3269 const sym_name = if (wasm.export_names.get(sym_loc)) |exp_name| wasm.string_table.get(exp_name) else sym_loc.getName(wasm);
32713270 switch (symbol.tag) {
32723271 .data => {
32733272 try leb.writeULEB128(writer, @intCast(u32, sym_name.len));
......@@ -3275,7 +3274,7 @@ fn emitSymbolTable(self: *Wasm, binary_bytes: *std.ArrayList(u8), symbol_table:
32753274
32763275 if (symbol.isDefined()) {
32773276 try leb.writeULEB128(writer, symbol.index);
3278 const atom = self.symbol_atom.get(sym_loc).?;
3277 const atom = wasm.symbol_atom.get(sym_loc).?;
32793278 try leb.writeULEB128(writer, @as(u32, atom.offset));
32803279 try leb.writeULEB128(writer, @as(u32, atom.size));
32813280 }
......@@ -3299,13 +3298,13 @@ fn emitSymbolTable(self: *Wasm, binary_bytes: *std.ArrayList(u8), symbol_table:
32993298 try binary_bytes.insertSlice(table_offset, &buf);
33003299}
33013300
3302fn emitSegmentInfo(self: *Wasm, binary_bytes: *std.ArrayList(u8)) !void {
3301fn emitSegmentInfo(wasm: *Wasm, binary_bytes: *std.ArrayList(u8)) !void {
33033302 const writer = binary_bytes.writer();
33043303 try leb.writeULEB128(writer, @enumToInt(types.SubsectionType.WASM_SEGMENT_INFO));
33053304 const segment_offset = binary_bytes.items.len;
33063305
3307 try leb.writeULEB128(writer, @intCast(u32, self.segment_info.count()));
3308 for (self.segment_info.values()) |segment_info| {
3306 try leb.writeULEB128(writer, @intCast(u32, wasm.segment_info.count()));
3307 for (wasm.segment_info.values()) |segment_info| {
33093308 log.debug("Emit segment: {s} align({d}) flags({b})", .{
33103309 segment_info.name,
33113310 @ctz(segment_info.alignment),
......@@ -3336,12 +3335,12 @@ pub fn getULEB128Size(uint_value: anytype) u32 {
33363335
33373336/// For each relocatable section, emits a custom "relocation.<section_name>" section
33383337fn emitCodeRelocations(
3339 self: *Wasm,
3338 wasm: *Wasm,
33403339 binary_bytes: *std.ArrayList(u8),
33413340 section_index: u32,
33423341 symbol_table: std.AutoArrayHashMap(SymbolLoc, u32),
33433342) !void {
3344 const code_index = self.code_section_index orelse return;
3343 const code_index = wasm.code_section_index orelse return;
33453344 const writer = binary_bytes.writer();
33463345 const header_offset = try reserveCustomSectionHeader(binary_bytes);
33473346
......@@ -3353,7 +3352,7 @@ fn emitCodeRelocations(
33533352 const reloc_start = binary_bytes.items.len;
33543353
33553354 var count: u32 = 0;
3356 var atom: *Atom = self.atoms.get(code_index).?.getFirst();
3355 var atom: *Atom = wasm.atoms.get(code_index).?.getFirst();
33573356 // for each atom, we calculate the uleb size and append that
33583357 var size_offset: u32 = 5; // account for code section size leb128
33593358 while (true) {
......@@ -3382,12 +3381,12 @@ fn emitCodeRelocations(
33823381}
33833382
33843383fn emitDataRelocations(
3385 self: *Wasm,
3384 wasm: *Wasm,
33863385 binary_bytes: *std.ArrayList(u8),
33873386 section_index: u32,
33883387 symbol_table: std.AutoArrayHashMap(SymbolLoc, u32),
33893388) !void {
3390 if (self.data_segments.count() == 0) return;
3389 if (wasm.data_segments.count() == 0) return;
33913390 const writer = binary_bytes.writer();
33923391 const header_offset = try reserveCustomSectionHeader(binary_bytes);
33933392
......@@ -3401,8 +3400,8 @@ fn emitDataRelocations(
34013400 var count: u32 = 0;
34023401 // for each atom, we calculate the uleb size and append that
34033402 var size_offset: u32 = 5; // account for code section size leb128
3404 for (self.data_segments.values()) |segment_index| {
3405 var atom: *Atom = self.atoms.get(segment_index).?.getFirst();
3403 for (wasm.data_segments.values()) |segment_index| {
3404 var atom: *Atom = wasm.atoms.get(segment_index).?.getFirst();
34063405 while (true) {
34073406 size_offset += getULEB128Size(atom.size);
34083407 for (atom.relocs.items) |relocation| {
......@@ -3435,18 +3434,18 @@ fn emitDataRelocations(
34353434
34363435/// Searches for an a matching function signature, when not found
34373436/// a new entry will be made. The index of the existing/new signature will be returned.
3438pub fn putOrGetFuncType(self: *Wasm, func_type: wasm.Type) !u32 {
3437pub fn putOrGetFuncType(wasm: *Wasm, func_type: std.wasm.Type) !u32 {
34393438 var index: u32 = 0;
3440 while (index < self.func_types.items.len) : (index += 1) {
3441 if (self.func_types.items[index].eql(func_type)) return index;
3439 while (index < wasm.func_types.items.len) : (index += 1) {
3440 if (wasm.func_types.items[index].eql(func_type)) return index;
34423441 }
34433442
34443443 // functype does not exist.
3445 const params = try self.base.allocator.dupe(wasm.Valtype, func_type.params);
3446 errdefer self.base.allocator.free(params);
3447 const returns = try self.base.allocator.dupe(wasm.Valtype, func_type.returns);
3448 errdefer self.base.allocator.free(returns);
3449 try self.func_types.append(self.base.allocator, .{
3444 const params = try wasm.base.allocator.dupe(std.wasm.Valtype, func_type.params);
3445 errdefer wasm.base.allocator.free(params);
3446 const returns = try wasm.base.allocator.dupe(std.wasm.Valtype, func_type.returns);
3447 errdefer wasm.base.allocator.free(returns);
3448 try wasm.func_types.append(wasm.base.allocator, .{
34503449 .params = params,
34513450 .returns = returns,
34523451 });
src/link/Wasm/Archive.zig-1
......@@ -4,7 +4,6 @@ const std = @import("std");
44const assert = std.debug.assert;
55const fs = std.fs;
66const log = std.log.scoped(.archive);
7const macho = std.macho;
87const mem = std.mem;
98
109const Allocator = mem.Allocator;
src/link/Wasm/Atom.zig+36-36
......@@ -55,37 +55,37 @@ pub const empty: Atom = .{
5555};
5656
5757/// Frees all resources owned by this `Atom`.
58pub fn deinit(self: *Atom, gpa: Allocator) void {
59 self.relocs.deinit(gpa);
60 self.code.deinit(gpa);
58pub fn deinit(atom: *Atom, gpa: Allocator) void {
59 atom.relocs.deinit(gpa);
60 atom.code.deinit(gpa);
6161
62 for (self.locals.items) |*local| {
62 for (atom.locals.items) |*local| {
6363 local.deinit(gpa);
6464 }
65 self.locals.deinit(gpa);
65 atom.locals.deinit(gpa);
6666}
6767
6868/// Sets the length of relocations and code to '0',
6969/// effectively resetting them and allowing them to be re-populated.
70pub fn clear(self: *Atom) void {
71 self.relocs.clearRetainingCapacity();
72 self.code.clearRetainingCapacity();
70pub fn clear(atom: *Atom) void {
71 atom.relocs.clearRetainingCapacity();
72 atom.code.clearRetainingCapacity();
7373}
7474
75pub fn format(self: Atom, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {
75pub fn format(atom: Atom, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {
7676 _ = fmt;
7777 _ = options;
7878 try writer.print("Atom{{ .sym_index = {d}, .alignment = {d}, .size = {d}, .offset = 0x{x:0>8} }}", .{
79 self.sym_index,
80 self.alignment,
81 self.size,
82 self.offset,
79 atom.sym_index,
80 atom.alignment,
81 atom.size,
82 atom.offset,
8383 });
8484}
8585
8686/// Returns the first `Atom` from a given atom
87pub fn getFirst(self: *Atom) *Atom {
88 var tmp = self;
87pub fn getFirst(atom: *Atom) *Atom {
88 var tmp = atom;
8989 while (tmp.prev) |prev| tmp = prev;
9090 return tmp;
9191}
......@@ -94,9 +94,9 @@ pub fn getFirst(self: *Atom) *Atom {
9494/// produced from Zig code, rather than an object file.
9595/// This is useful for debug sections where we want to extend
9696/// the bytes, and don't want to overwrite existing Atoms.
97pub fn getFirstZigAtom(self: *Atom) *Atom {
98 if (self.file == null) return self;
99 var tmp = self;
97pub fn getFirstZigAtom(atom: *Atom) *Atom {
98 if (atom.file == null) return atom;
99 var tmp = atom;
100100 return while (tmp.prev) |prev| {
101101 if (prev.file == null) break prev;
102102 tmp = prev;
......@@ -104,24 +104,24 @@ pub fn getFirstZigAtom(self: *Atom) *Atom {
104104}
105105
106106/// Returns the location of the symbol that represents this `Atom`
107pub fn symbolLoc(self: Atom) Wasm.SymbolLoc {
108 return .{ .file = self.file, .index = self.sym_index };
107pub fn symbolLoc(atom: Atom) Wasm.SymbolLoc {
108 return .{ .file = atom.file, .index = atom.sym_index };
109109}
110110
111111/// Resolves the relocations within the atom, writing the new value
112112/// at the calculated offset.
113pub fn resolveRelocs(self: *Atom, wasm_bin: *const Wasm) void {
114 if (self.relocs.items.len == 0) return;
115 const symbol_name = self.symbolLoc().getName(wasm_bin);
113pub fn resolveRelocs(atom: *Atom, wasm_bin: *const Wasm) void {
114 if (atom.relocs.items.len == 0) return;
115 const symbol_name = atom.symbolLoc().getName(wasm_bin);
116116 log.debug("Resolving relocs in atom '{s}' count({d})", .{
117117 symbol_name,
118 self.relocs.items.len,
118 atom.relocs.items.len,
119119 });
120120
121 for (self.relocs.items) |reloc| {
122 const value = self.relocationValue(reloc, wasm_bin);
121 for (atom.relocs.items) |reloc| {
122 const value = atom.relocationValue(reloc, wasm_bin);
123123 log.debug("Relocating '{s}' referenced in '{s}' offset=0x{x:0>8} value={d}", .{
124 (Wasm.SymbolLoc{ .file = self.file, .index = reloc.index }).getName(wasm_bin),
124 (Wasm.SymbolLoc{ .file = atom.file, .index = reloc.index }).getName(wasm_bin),
125125 symbol_name,
126126 reloc.offset,
127127 value,
......@@ -133,10 +133,10 @@ pub fn resolveRelocs(self: *Atom, wasm_bin: *const Wasm) void {
133133 .R_WASM_GLOBAL_INDEX_I32,
134134 .R_WASM_MEMORY_ADDR_I32,
135135 .R_WASM_SECTION_OFFSET_I32,
136 => std.mem.writeIntLittle(u32, self.code.items[reloc.offset..][0..4], @intCast(u32, value)),
136 => std.mem.writeIntLittle(u32, atom.code.items[reloc.offset..][0..4], @intCast(u32, value)),
137137 .R_WASM_TABLE_INDEX_I64,
138138 .R_WASM_MEMORY_ADDR_I64,
139 => std.mem.writeIntLittle(u64, self.code.items[reloc.offset..][0..8], value),
139 => std.mem.writeIntLittle(u64, atom.code.items[reloc.offset..][0..8], value),
140140 .R_WASM_GLOBAL_INDEX_LEB,
141141 .R_WASM_EVENT_INDEX_LEB,
142142 .R_WASM_FUNCTION_INDEX_LEB,
......@@ -145,11 +145,11 @@ pub fn resolveRelocs(self: *Atom, wasm_bin: *const Wasm) void {
145145 .R_WASM_TABLE_INDEX_SLEB,
146146 .R_WASM_TABLE_NUMBER_LEB,
147147 .R_WASM_TYPE_INDEX_LEB,
148 => leb.writeUnsignedFixed(5, self.code.items[reloc.offset..][0..5], @intCast(u32, value)),
148 => leb.writeUnsignedFixed(5, atom.code.items[reloc.offset..][0..5], @intCast(u32, value)),
149149 .R_WASM_MEMORY_ADDR_LEB64,
150150 .R_WASM_MEMORY_ADDR_SLEB64,
151151 .R_WASM_TABLE_INDEX_SLEB64,
152 => leb.writeUnsignedFixed(10, self.code.items[reloc.offset..][0..10], value),
152 => leb.writeUnsignedFixed(10, atom.code.items[reloc.offset..][0..10], value),
153153 }
154154 }
155155}
......@@ -157,8 +157,8 @@ pub fn resolveRelocs(self: *Atom, wasm_bin: *const Wasm) void {
157157/// From a given `relocation` will return the new value to be written.
158158/// All values will be represented as a `u64` as all values can fit within it.
159159/// The final value must be casted to the correct size.
160fn relocationValue(self: Atom, relocation: types.Relocation, wasm_bin: *const Wasm) u64 {
161 const target_loc = (Wasm.SymbolLoc{ .file = self.file, .index = relocation.index }).finalLoc(wasm_bin);
160fn relocationValue(atom: Atom, relocation: types.Relocation, wasm_bin: *const Wasm) u64 {
161 const target_loc = (Wasm.SymbolLoc{ .file = atom.file, .index = relocation.index }).finalLoc(wasm_bin);
162162 const symbol = target_loc.getSymbol(wasm_bin).*;
163163 switch (relocation.relocation_type) {
164164 .R_WASM_FUNCTION_INDEX_LEB => return symbol.index,
......@@ -203,7 +203,7 @@ fn relocationValue(self: Atom, relocation: types.Relocation, wasm_bin: *const Wa
203203 },
204204 .R_WASM_FUNCTION_OFFSET_I32 => {
205205 const target_atom = wasm_bin.symbol_atom.get(target_loc).?;
206 var atom = target_atom.getFirst();
206 var current_atom = target_atom.getFirst();
207207 var offset: u32 = 0;
208208 // TODO: Calculate this during atom allocation, rather than
209209 // this linear calculation. For now it's done here as atoms
......@@ -211,8 +211,8 @@ fn relocationValue(self: Atom, relocation: types.Relocation, wasm_bin: *const Wa
211211 // merged until later.
212212 while (true) {
213213 offset += 5; // each atom uses 5 bytes to store its body's size
214 if (atom == target_atom) break;
215 atom = atom.next.?;
214 if (current_atom == target_atom) break;
215 current_atom = current_atom.next.?;
216216 }
217217 return target_atom.offset + offset + (relocation.addend orelse 0);
218218 },
src/link/Wasm/Object.zig+114-114
......@@ -88,28 +88,28 @@ const RelocatableData = struct {
8888 /// meta data of the given object file.
8989 /// NOTE: Alignment is encoded as a power of 2, so we shift the symbol's
9090 /// alignment to retrieve the natural alignment.
91 pub fn getAlignment(self: RelocatableData, object: *const Object) u32 {
92 if (self.type != .data) return 1;
93 const data_alignment = object.segment_info[self.index].alignment;
91 pub fn getAlignment(relocatable_data: RelocatableData, object: *const Object) u32 {
92 if (relocatable_data.type != .data) return 1;
93 const data_alignment = object.segment_info[relocatable_data.index].alignment;
9494 if (data_alignment == 0) return 1;
9595 // Decode from power of 2 to natural alignment
9696 return @as(u32, 1) << @intCast(u5, data_alignment);
9797 }
9898
9999 /// Returns the symbol kind that corresponds to the relocatable section
100 pub fn getSymbolKind(self: RelocatableData) Symbol.Tag {
101 return switch (self.type) {
100 pub fn getSymbolKind(relocatable_data: RelocatableData) Symbol.Tag {
101 return switch (relocatable_data.type) {
102102 .data => .data,
103103 .code => .function,
104104 .debug => .section,
105105 };
106106 }
107107
108 /// Returns the index within a section itself, or in case of a debug section,
108 /// Returns the index within a section itrelocatable_data, or in case of a debug section,
109109 /// returns the section index within the object file.
110 pub fn getIndex(self: RelocatableData) u32 {
111 if (self.type == .debug) return self.section_index;
112 return self.index;
110 pub fn getIndex(relocatable_data: RelocatableData) u32 {
111 if (relocatable_data.type == .debug) return relocatable_data.section_index;
112 return relocatable_data.index;
113113 }
114114};
115115
......@@ -153,51 +153,51 @@ pub fn create(gpa: Allocator, file: std.fs.File, name: []const u8, maybe_max_siz
153153
154154/// Frees all memory of `Object` at once. The given `Allocator` must be
155155/// the same allocator that was used when `init` was called.
156pub fn deinit(self: *Object, gpa: Allocator) void {
157 if (self.file) |file| {
156pub fn deinit(object: *Object, gpa: Allocator) void {
157 if (object.file) |file| {
158158 file.close();
159159 }
160 for (self.func_types) |func_ty| {
160 for (object.func_types) |func_ty| {
161161 gpa.free(func_ty.params);
162162 gpa.free(func_ty.returns);
163163 }
164 gpa.free(self.func_types);
165 gpa.free(self.functions);
166 gpa.free(self.imports);
167 gpa.free(self.tables);
168 gpa.free(self.memories);
169 gpa.free(self.globals);
170 gpa.free(self.exports);
171 for (self.elements) |el| {
164 gpa.free(object.func_types);
165 gpa.free(object.functions);
166 gpa.free(object.imports);
167 gpa.free(object.tables);
168 gpa.free(object.memories);
169 gpa.free(object.globals);
170 gpa.free(object.exports);
171 for (object.elements) |el| {
172172 gpa.free(el.func_indexes);
173173 }
174 gpa.free(self.elements);
175 gpa.free(self.features);
176 for (self.relocations.values()) |val| {
174 gpa.free(object.elements);
175 gpa.free(object.features);
176 for (object.relocations.values()) |val| {
177177 gpa.free(val);
178178 }
179 self.relocations.deinit(gpa);
180 gpa.free(self.symtable);
181 gpa.free(self.comdat_info);
182 gpa.free(self.init_funcs);
183 for (self.segment_info) |info| {
179 object.relocations.deinit(gpa);
180 gpa.free(object.symtable);
181 gpa.free(object.comdat_info);
182 gpa.free(object.init_funcs);
183 for (object.segment_info) |info| {
184184 gpa.free(info.name);
185185 }
186 gpa.free(self.segment_info);
187 for (self.relocatable_data) |rel_data| {
186 gpa.free(object.segment_info);
187 for (object.relocatable_data) |rel_data| {
188188 gpa.free(rel_data.data[0..rel_data.size]);
189189 }
190 gpa.free(self.relocatable_data);
191 self.string_table.deinit(gpa);
192 gpa.free(self.name);
193 self.* = undefined;
190 gpa.free(object.relocatable_data);
191 object.string_table.deinit(gpa);
192 gpa.free(object.name);
193 object.* = undefined;
194194}
195195
196196/// Finds the import within the list of imports from a given kind and index of that kind.
197197/// Asserts the import exists
198pub fn findImport(self: *const Object, import_kind: std.wasm.ExternalKind, index: u32) types.Import {
198pub fn findImport(object: *const Object, import_kind: std.wasm.ExternalKind, index: u32) types.Import {
199199 var i: u32 = 0;
200 return for (self.imports) |import| {
200 return for (object.imports) |import| {
201201 if (std.meta.activeTag(import.kind) == import_kind) {
202202 if (i == index) return import;
203203 i += 1;
......@@ -206,16 +206,16 @@ pub fn findImport(self: *const Object, import_kind: std.wasm.ExternalKind, index
206206}
207207
208208/// Counts the entries of imported `kind` and returns the result
209pub fn importedCountByKind(self: *const Object, kind: std.wasm.ExternalKind) u32 {
209pub fn importedCountByKind(object: *const Object, kind: std.wasm.ExternalKind) u32 {
210210 var i: u32 = 0;
211 return for (self.imports) |imp| {
211 return for (object.imports) |imp| {
212212 if (@as(std.wasm.ExternalKind, imp.kind) == kind) i += 1;
213213 } else i;
214214}
215215
216216/// From a given `RelocatableDate`, find the corresponding debug section name
217pub fn getDebugName(self: *const Object, relocatable_data: RelocatableData) []const u8 {
218 return self.string_table.get(relocatable_data.index);
217pub fn getDebugName(object: *const Object, relocatable_data: RelocatableData) []const u8 {
218 return object.string_table.get(relocatable_data.index);
219219}
220220
221221/// Checks if the object file is an MVP version.
......@@ -224,13 +224,13 @@ pub fn getDebugName(self: *const Object, relocatable_data: RelocatableData) []co
224224/// we initialize a new table symbol that corresponds to that import and return that symbol.
225225///
226226/// When the object file is *NOT* MVP, we return `null`.
227fn checkLegacyIndirectFunctionTable(self: *Object) !?Symbol {
227fn checkLegacyIndirectFunctionTable(object: *Object) !?Symbol {
228228 var table_count: usize = 0;
229 for (self.symtable) |sym| {
229 for (object.symtable) |sym| {
230230 if (sym.tag == .table) table_count += 1;
231231 }
232232
233 const import_table_count = self.importedCountByKind(.table);
233 const import_table_count = object.importedCountByKind(.table);
234234
235235 // For each import table, we also have a symbol so this is not a legacy object file
236236 if (import_table_count == table_count) return null;
......@@ -244,7 +244,7 @@ fn checkLegacyIndirectFunctionTable(self: *Object) !?Symbol {
244244 }
245245
246246 // MVP object files cannot have any table definitions, only imports (for the indirect function table).
247 if (self.tables.len > 0) {
247 if (object.tables.len > 0) {
248248 log.err("Unexpected table definition without representing table symbols.", .{});
249249 return error.UnexpectedTable;
250250 }
......@@ -254,14 +254,14 @@ fn checkLegacyIndirectFunctionTable(self: *Object) !?Symbol {
254254 return error.MissingTableSymbols;
255255 }
256256
257 var table_import: types.Import = for (self.imports) |imp| {
257 var table_import: types.Import = for (object.imports) |imp| {
258258 if (imp.kind == .table) {
259259 break imp;
260260 }
261261 } else unreachable;
262262
263 if (!std.mem.eql(u8, self.string_table.get(table_import.name), "__indirect_function_table")) {
264 log.err("Non-indirect function table import '{s}' is missing a corresponding symbol", .{self.string_table.get(table_import.name)});
263 if (!std.mem.eql(u8, object.string_table.get(table_import.name), "__indirect_function_table")) {
264 log.err("Non-indirect function table import '{s}' is missing a corresponding symbol", .{object.string_table.get(table_import.name)});
265265 return error.MissingTableSymbols;
266266 }
267267
......@@ -313,41 +313,41 @@ pub const ParseError = error{
313313 UnknownFeature,
314314};
315315
316fn parse(self: *Object, gpa: Allocator, reader: anytype, is_object_file: *bool) Parser(@TypeOf(reader)).Error!void {
317 var parser = Parser(@TypeOf(reader)).init(self, reader);
316fn parse(object: *Object, gpa: Allocator, reader: anytype, is_object_file: *bool) Parser(@TypeOf(reader)).Error!void {
317 var parser = Parser(@TypeOf(reader)).init(object, reader);
318318 return parser.parseObject(gpa, is_object_file);
319319}
320320
321321fn Parser(comptime ReaderType: type) type {
322322 return struct {
323 const Self = @This();
323 const ObjectParser = @This();
324324 const Error = ReaderType.Error || ParseError;
325325
326326 reader: std.io.CountingReader(ReaderType),
327327 /// Object file we're building
328328 object: *Object,
329329
330 fn init(object: *Object, reader: ReaderType) Self {
330 fn init(object: *Object, reader: ReaderType) ObjectParser {
331331 return .{ .object = object, .reader = std.io.countingReader(reader) };
332332 }
333333
334334 /// Verifies that the first 4 bytes contains \0Asm
335 fn verifyMagicBytes(self: *Self) Error!void {
335 fn verifyMagicBytes(parser: *ObjectParser) Error!void {
336336 var magic_bytes: [4]u8 = undefined;
337337
338 try self.reader.reader().readNoEof(&magic_bytes);
338 try parser.reader.reader().readNoEof(&magic_bytes);
339339 if (!std.mem.eql(u8, &magic_bytes, &std.wasm.magic)) {
340340 log.debug("Invalid magic bytes '{s}'", .{&magic_bytes});
341341 return error.InvalidMagicByte;
342342 }
343343 }
344344
345 fn parseObject(self: *Self, gpa: Allocator, is_object_file: *bool) Error!void {
346 errdefer self.object.deinit(gpa);
347 try self.verifyMagicBytes();
348 const version = try self.reader.reader().readIntLittle(u32);
345 fn parseObject(parser: *ObjectParser, gpa: Allocator, is_object_file: *bool) Error!void {
346 errdefer parser.object.deinit(gpa);
347 try parser.verifyMagicBytes();
348 const version = try parser.reader.reader().readIntLittle(u32);
349349
350 self.object.version = version;
350 parser.object.version = version;
351351 var relocatable_data = std.ArrayList(RelocatableData).init(gpa);
352352 var debug_names = std.ArrayList(u8).init(gpa);
353353
......@@ -360,9 +360,9 @@ fn Parser(comptime ReaderType: type) type {
360360 }
361361
362362 var section_index: u32 = 0;
363 while (self.reader.reader().readByte()) |byte| : (section_index += 1) {
364 const len = try readLeb(u32, self.reader.reader());
365 var limited_reader = std.io.limitedReader(self.reader.reader(), len);
363 while (parser.reader.reader().readByte()) |byte| : (section_index += 1) {
364 const len = try readLeb(u32, parser.reader.reader());
365 var limited_reader = std.io.limitedReader(parser.reader.reader(), len);
366366 const reader = limited_reader.reader();
367367 switch (@intToEnum(std.wasm.Section, byte)) {
368368 .custom => {
......@@ -373,12 +373,12 @@ fn Parser(comptime ReaderType: type) type {
373373
374374 if (std.mem.eql(u8, name, "linking")) {
375375 is_object_file.* = true;
376 self.object.relocatable_data = relocatable_data.items; // at this point no new relocatable sections will appear so we're free to store them.
377 try self.parseMetadata(gpa, @intCast(usize, reader.context.bytes_left));
376 parser.object.relocatable_data = relocatable_data.items; // at this point no new relocatable sections will appear so we're free to store them.
377 try parser.parseMetadata(gpa, @intCast(usize, reader.context.bytes_left));
378378 } else if (std.mem.startsWith(u8, name, "reloc")) {
379 try self.parseRelocations(gpa);
379 try parser.parseRelocations(gpa);
380380 } else if (std.mem.eql(u8, name, "target_features")) {
381 try self.parseFeatures(gpa);
381 try parser.parseFeatures(gpa);
382382 } else if (std.mem.startsWith(u8, name, ".debug")) {
383383 const debug_size = @intCast(u32, reader.context.bytes_left);
384384 const debug_content = try gpa.alloc(u8, debug_size);
......@@ -389,7 +389,7 @@ fn Parser(comptime ReaderType: type) type {
389389 .type = .debug,
390390 .data = debug_content.ptr,
391391 .size = debug_size,
392 .index = try self.object.string_table.put(gpa, name),
392 .index = try parser.object.string_table.put(gpa, name),
393393 .offset = 0, // debug sections only contain 1 entry, so no need to calculate offset
394394 .section_index = section_index,
395395 });
......@@ -398,7 +398,7 @@ fn Parser(comptime ReaderType: type) type {
398398 }
399399 },
400400 .type => {
401 for (try readVec(&self.object.func_types, reader, gpa)) |*type_val| {
401 for (try readVec(&parser.object.func_types, reader, gpa)) |*type_val| {
402402 if ((try reader.readByte()) != std.wasm.function_type) return error.ExpectedFuncType;
403403
404404 for (try readVec(&type_val.params, reader, gpa)) |*param| {
......@@ -412,7 +412,7 @@ fn Parser(comptime ReaderType: type) type {
412412 try assertEnd(reader);
413413 },
414414 .import => {
415 for (try readVec(&self.object.imports, reader, gpa)) |*import| {
415 for (try readVec(&parser.object.imports, reader, gpa)) |*import| {
416416 const module_len = try readLeb(u32, reader);
417417 const module_name = try gpa.alloc(u8, module_len);
418418 defer gpa.free(module_name);
......@@ -438,21 +438,21 @@ fn Parser(comptime ReaderType: type) type {
438438 };
439439
440440 import.* = .{
441 .module_name = try self.object.string_table.put(gpa, module_name),
442 .name = try self.object.string_table.put(gpa, name),
441 .module_name = try parser.object.string_table.put(gpa, module_name),
442 .name = try parser.object.string_table.put(gpa, name),
443443 .kind = kind_value,
444444 };
445445 }
446446 try assertEnd(reader);
447447 },
448448 .function => {
449 for (try readVec(&self.object.functions, reader, gpa)) |*func| {
449 for (try readVec(&parser.object.functions, reader, gpa)) |*func| {
450450 func.* = .{ .type_index = try readLeb(u32, reader) };
451451 }
452452 try assertEnd(reader);
453453 },
454454 .table => {
455 for (try readVec(&self.object.tables, reader, gpa)) |*table| {
455 for (try readVec(&parser.object.tables, reader, gpa)) |*table| {
456456 table.* = .{
457457 .reftype = try readEnum(std.wasm.RefType, reader),
458458 .limits = try readLimits(reader),
......@@ -461,13 +461,13 @@ fn Parser(comptime ReaderType: type) type {
461461 try assertEnd(reader);
462462 },
463463 .memory => {
464 for (try readVec(&self.object.memories, reader, gpa)) |*memory| {
464 for (try readVec(&parser.object.memories, reader, gpa)) |*memory| {
465465 memory.* = .{ .limits = try readLimits(reader) };
466466 }
467467 try assertEnd(reader);
468468 },
469469 .global => {
470 for (try readVec(&self.object.globals, reader, gpa)) |*global| {
470 for (try readVec(&parser.object.globals, reader, gpa)) |*global| {
471471 global.* = .{
472472 .global_type = .{
473473 .valtype = try readEnum(std.wasm.Valtype, reader),
......@@ -479,13 +479,13 @@ fn Parser(comptime ReaderType: type) type {
479479 try assertEnd(reader);
480480 },
481481 .@"export" => {
482 for (try readVec(&self.object.exports, reader, gpa)) |*exp| {
482 for (try readVec(&parser.object.exports, reader, gpa)) |*exp| {
483483 const name_len = try readLeb(u32, reader);
484484 const name = try gpa.alloc(u8, name_len);
485485 defer gpa.free(name);
486486 try reader.readNoEof(name);
487487 exp.* = .{
488 .name = try self.object.string_table.put(gpa, name),
488 .name = try parser.object.string_table.put(gpa, name),
489489 .kind = try readEnum(std.wasm.ExternalKind, reader),
490490 .index = try readLeb(u32, reader),
491491 };
......@@ -493,11 +493,11 @@ fn Parser(comptime ReaderType: type) type {
493493 try assertEnd(reader);
494494 },
495495 .start => {
496 self.object.start = try readLeb(u32, reader);
496 parser.object.start = try readLeb(u32, reader);
497497 try assertEnd(reader);
498498 },
499499 .element => {
500 for (try readVec(&self.object.elements, reader, gpa)) |*elem| {
500 for (try readVec(&parser.object.elements, reader, gpa)) |*elem| {
501501 elem.table_index = try readLeb(u32, reader);
502502 elem.offset = try readInit(reader);
503503
......@@ -521,7 +521,7 @@ fn Parser(comptime ReaderType: type) type {
521521 .type = .code,
522522 .data = data.ptr,
523523 .size = code_len,
524 .index = self.object.importedCountByKind(.function) + index,
524 .index = parser.object.importedCountByKind(.function) + index,
525525 .offset = offset,
526526 .section_index = section_index,
527527 });
......@@ -551,22 +551,22 @@ fn Parser(comptime ReaderType: type) type {
551551 });
552552 }
553553 },
554 else => try self.reader.reader().skipBytes(len, .{}),
554 else => try parser.reader.reader().skipBytes(len, .{}),
555555 }
556556 } else |err| switch (err) {
557557 error.EndOfStream => {}, // finished parsing the file
558558 else => |e| return e,
559559 }
560 self.object.relocatable_data = relocatable_data.toOwnedSlice();
560 parser.object.relocatable_data = relocatable_data.toOwnedSlice();
561561 }
562562
563563 /// Based on the "features" custom section, parses it into a list of
564564 /// features that tell the linker what features were enabled and may be mandatory
565565 /// to be able to link.
566566 /// Logs an info message when an undefined feature is detected.
567 fn parseFeatures(self: *Self, gpa: Allocator) !void {
568 const reader = self.reader.reader();
569 for (try readVec(&self.object.features, reader, gpa)) |*feature| {
567 fn parseFeatures(parser: *ObjectParser, gpa: Allocator) !void {
568 const reader = parser.reader.reader();
569 for (try readVec(&parser.object.features, reader, gpa)) |*feature| {
570570 const prefix = try readEnum(types.Feature.Prefix, reader);
571571 const name_len = try leb.readULEB128(u32, reader);
572572 const name = try gpa.alloc(u8, name_len);
......@@ -587,8 +587,8 @@ fn Parser(comptime ReaderType: type) type {
587587 /// Parses a "reloc" custom section into a list of relocations.
588588 /// The relocations are mapped into `Object` where the key is the section
589589 /// they apply to.
590 fn parseRelocations(self: *Self, gpa: Allocator) !void {
591 const reader = self.reader.reader();
590 fn parseRelocations(parser: *ObjectParser, gpa: Allocator) !void {
591 const reader = parser.reader.reader();
592592 const section = try leb.readULEB128(u32, reader);
593593 const count = try leb.readULEB128(u32, reader);
594594 const relocations = try gpa.alloc(types.Relocation, count);
......@@ -616,15 +616,15 @@ fn Parser(comptime ReaderType: type) type {
616616 });
617617 }
618618
619 try self.object.relocations.putNoClobber(gpa, section, relocations);
619 try parser.object.relocations.putNoClobber(gpa, section, relocations);
620620 }
621621
622622 /// Parses the "linking" custom section. Versions that are not
623623 /// supported will be an error. `payload_size` is required to be able
624624 /// to calculate the subsections we need to parse, as that data is not
625 /// available within the section itself.
626 fn parseMetadata(self: *Self, gpa: Allocator, payload_size: usize) !void {
627 var limited = std.io.limitedReader(self.reader.reader(), payload_size);
625 /// available within the section itparser.
626 fn parseMetadata(parser: *ObjectParser, gpa: Allocator, payload_size: usize) !void {
627 var limited = std.io.limitedReader(parser.reader.reader(), payload_size);
628628 const limited_reader = limited.reader();
629629
630630 const version = try leb.readULEB128(u32, limited_reader);
......@@ -632,7 +632,7 @@ fn Parser(comptime ReaderType: type) type {
632632 if (version != 2) return error.UnsupportedVersion;
633633
634634 while (limited.bytes_left > 0) {
635 try self.parseSubsection(gpa, limited_reader);
635 try parser.parseSubsection(gpa, limited_reader);
636636 }
637637 }
638638
......@@ -640,9 +640,9 @@ fn Parser(comptime ReaderType: type) type {
640640 /// The `reader` param for this is to provide a `LimitedReader`, which allows
641641 /// us to only read until a max length.
642642 ///
643 /// `self` is used to provide access to other sections that may be needed,
643 /// `parser` is used to provide access to other sections that may be needed,
644644 /// such as access to the `import` section to find the name of a symbol.
645 fn parseSubsection(self: *Self, gpa: Allocator, reader: anytype) !void {
645 fn parseSubsection(parser: *ObjectParser, gpa: Allocator, reader: anytype) !void {
646646 const sub_type = try leb.readULEB128(u8, reader);
647647 log.debug("Found subsection: {s}", .{@tagName(@intToEnum(types.SubsectionType, sub_type))});
648648 const payload_len = try leb.readULEB128(u32, reader);
......@@ -674,7 +674,7 @@ fn Parser(comptime ReaderType: type) type {
674674 segment.flags,
675675 });
676676 }
677 self.object.segment_info = segments;
677 parser.object.segment_info = segments;
678678 },
679679 .WASM_INIT_FUNCS => {
680680 const funcs = try gpa.alloc(types.InitFunc, count);
......@@ -686,7 +686,7 @@ fn Parser(comptime ReaderType: type) type {
686686 };
687687 log.debug("Found function - prio: {d}, index: {d}", .{ func.priority, func.symbol_index });
688688 }
689 self.object.init_funcs = funcs;
689 parser.object.init_funcs = funcs;
690690 },
691691 .WASM_COMDAT_INFO => {
692692 const comdats = try gpa.alloc(types.Comdat, count);
......@@ -719,7 +719,7 @@ fn Parser(comptime ReaderType: type) type {
719719 };
720720 }
721721
722 self.object.comdat_info = comdats;
722 parser.object.comdat_info = comdats;
723723 },
724724 .WASM_SYMBOL_TABLE => {
725725 var symbols = try std.ArrayList(Symbol).initCapacity(gpa, count);
......@@ -727,22 +727,22 @@ fn Parser(comptime ReaderType: type) type {
727727 var i: usize = 0;
728728 while (i < count) : (i += 1) {
729729 const symbol = symbols.addOneAssumeCapacity();
730 symbol.* = try self.parseSymbol(gpa, reader);
730 symbol.* = try parser.parseSymbol(gpa, reader);
731731 log.debug("Found symbol: type({s}) name({s}) flags(0b{b:0>8})", .{
732732 @tagName(symbol.tag),
733 self.object.string_table.get(symbol.name),
733 parser.object.string_table.get(symbol.name),
734734 symbol.flags,
735735 });
736736 }
737737
738738 // we found all symbols, check for indirect function table
739739 // in case of an MVP object file
740 if (try self.object.checkLegacyIndirectFunctionTable()) |symbol| {
740 if (try parser.object.checkLegacyIndirectFunctionTable()) |symbol| {
741741 try symbols.append(symbol);
742742 log.debug("Found legacy indirect function table. Created symbol", .{});
743743 }
744744
745 self.object.symtable = symbols.toOwnedSlice();
745 parser.object.symtable = symbols.toOwnedSlice();
746746 },
747747 }
748748 }
......@@ -750,7 +750,7 @@ fn Parser(comptime ReaderType: type) type {
750750 /// Parses the symbol information based on its kind,
751751 /// requires access to `Object` to find the name of a symbol when it's
752752 /// an import and flag `WASM_SYM_EXPLICIT_NAME` is not set.
753 fn parseSymbol(self: *Self, gpa: Allocator, reader: anytype) !Symbol {
753 fn parseSymbol(parser: *ObjectParser, gpa: Allocator, reader: anytype) !Symbol {
754754 const tag = @intToEnum(Symbol.Tag, try leb.readULEB128(u8, reader));
755755 const flags = try leb.readULEB128(u32, reader);
756756 var symbol: Symbol = .{
......@@ -766,7 +766,7 @@ fn Parser(comptime ReaderType: type) type {
766766 const name = try gpa.alloc(u8, name_len);
767767 defer gpa.free(name);
768768 try reader.readNoEof(name);
769 symbol.name = try self.object.string_table.put(gpa, name);
769 symbol.name = try parser.object.string_table.put(gpa, name);
770770
771771 // Data symbols only have the following fields if the symbol is defined
772772 if (symbol.isDefined()) {
......@@ -778,7 +778,7 @@ fn Parser(comptime ReaderType: type) type {
778778 },
779779 .section => {
780780 symbol.index = try leb.readULEB128(u32, reader);
781 for (self.object.relocatable_data) |data| {
781 for (parser.object.relocatable_data) |data| {
782782 if (data.section_index == symbol.index) {
783783 symbol.name = data.index;
784784 break;
......@@ -791,7 +791,7 @@ fn Parser(comptime ReaderType: type) type {
791791
792792 const is_undefined = symbol.isUndefined();
793793 if (is_undefined) {
794 maybe_import = self.object.findImport(symbol.tag.externalType(), symbol.index);
794 maybe_import = parser.object.findImport(symbol.tag.externalType(), symbol.index);
795795 }
796796 const explicit_name = symbol.hasFlag(.WASM_SYM_EXPLICIT_NAME);
797797 if (!(is_undefined and !explicit_name)) {
......@@ -799,7 +799,7 @@ fn Parser(comptime ReaderType: type) type {
799799 const name = try gpa.alloc(u8, name_len);
800800 defer gpa.free(name);
801801 try reader.readNoEof(name);
802 symbol.name = try self.object.string_table.put(gpa, name);
802 symbol.name = try parser.object.string_table.put(gpa, name);
803803 } else {
804804 symbol.name = maybe_import.?.name;
805805 }
......@@ -872,7 +872,7 @@ fn assertEnd(reader: anytype) !void {
872872}
873873
874874/// Parses an object file into atoms, for code and data sections
875pub fn parseIntoAtoms(self: *Object, gpa: Allocator, object_index: u16, wasm_bin: *Wasm) !void {
875pub fn parseIntoAtoms(object: *Object, gpa: Allocator, object_index: u16, wasm_bin: *Wasm) !void {
876876 const Key = struct {
877877 kind: Symbol.Tag,
878878 index: u32,
......@@ -882,7 +882,7 @@ pub fn parseIntoAtoms(self: *Object, gpa: Allocator, object_index: u16, wasm_bin
882882 list.deinit();
883883 } else symbol_for_segment.deinit();
884884
885 for (self.symtable) |symbol, symbol_index| {
885 for (object.symtable) |symbol, symbol_index| {
886886 switch (symbol.tag) {
887887 .function, .data, .section => if (!symbol.isUndefined()) {
888888 const gop = try symbol_for_segment.getOrPut(.{ .kind = symbol.tag, .index = symbol.index });
......@@ -896,7 +896,7 @@ pub fn parseIntoAtoms(self: *Object, gpa: Allocator, object_index: u16, wasm_bin
896896 }
897897 }
898898
899 for (self.relocatable_data) |relocatable_data, index| {
899 for (object.relocatable_data) |relocatable_data, index| {
900900 const final_index = (try wasm_bin.getMatchingSegment(object_index, @intCast(u32, index))) orelse {
901901 continue; // found unknown section, so skip parsing into atom as we do not know how to handle it.
902902 };
......@@ -911,12 +911,12 @@ pub fn parseIntoAtoms(self: *Object, gpa: Allocator, object_index: u16, wasm_bin
911911 try wasm_bin.managed_atoms.append(gpa, atom);
912912 atom.file = object_index;
913913 atom.size = relocatable_data.size;
914 atom.alignment = relocatable_data.getAlignment(self);
914 atom.alignment = relocatable_data.getAlignment(object);
915915
916 const relocations: []types.Relocation = self.relocations.get(relocatable_data.section_index) orelse &.{};
916 const relocations: []types.Relocation = object.relocations.get(relocatable_data.section_index) orelse &.{};
917917 for (relocations) |relocation| {
918918 if (isInbetween(relocatable_data.offset, atom.size, relocation.offset)) {
919 // set the offset relative to the offset of the segment itself,
919 // set the offset relative to the offset of the segment itobject,
920920 // rather than within the entire section.
921921 var reloc = relocation;
922922 reloc.offset -= relocatable_data.offset;
......@@ -942,8 +942,8 @@ pub fn parseIntoAtoms(self: *Object, gpa: Allocator, object_index: u16, wasm_bin
942942 // symbols referencing the same atom will be added as alias
943943 // or as 'parent' when they are global.
944944 while (symbols.popOrNull()) |idx| {
945 const alias_symbol = self.symtable[idx];
946 const symbol = self.symtable[atom.sym_index];
945 const alias_symbol = object.symtable[idx];
946 const symbol = object.symtable[atom.sym_index];
947947 if (alias_symbol.isGlobal() and symbol.isLocal()) {
948948 atom.sym_index = idx;
949949 }
......@@ -957,7 +957,7 @@ pub fn parseIntoAtoms(self: *Object, gpa: Allocator, object_index: u16, wasm_bin
957957 }
958958
959959 try wasm_bin.appendAtomAtIndex(final_index, atom);
960 log.debug("Parsed into atom: '{s}' at segment index {d}", .{ self.string_table.get(self.symtable[atom.sym_index].name), final_index });
960 log.debug("Parsed into atom: '{s}' at segment index {d}", .{ object.string_table.get(object.symtable[atom.sym_index].name), final_index });
961961 }
962962}
963963
src/link/Wasm/Symbol.zig+44-44
......@@ -34,8 +34,8 @@ pub const Tag = enum {
3434
3535 /// From a given symbol tag, returns the `ExternalType`
3636 /// Asserts the given tag can be represented as an external type.
37 pub fn externalType(self: Tag) std.wasm.ExternalKind {
38 return switch (self) {
37 pub fn externalType(tag: Tag) std.wasm.ExternalKind {
38 return switch (tag) {
3939 .function => .function,
4040 .global => .global,
4141 .data => .memory,
......@@ -78,85 +78,85 @@ pub const Flag = enum(u32) {
7878
7979/// Verifies if the given symbol should be imported from the
8080/// host environment or not
81pub fn requiresImport(self: Symbol) bool {
82 if (self.tag == .data) return false;
83 if (!self.isUndefined()) return false;
84 if (self.isWeak()) return false;
85 // if (self.isDefined() and self.isWeak()) return true; //TODO: Only when building shared lib
81pub fn requiresImport(symbol: Symbol) bool {
82 if (symbol.tag == .data) return false;
83 if (!symbol.isUndefined()) return false;
84 if (symbol.isWeak()) return false;
85 // if (symbol.isDefined() and symbol.isWeak()) return true; //TODO: Only when building shared lib
8686
8787 return true;
8888}
8989
90pub fn hasFlag(self: Symbol, flag: Flag) bool {
91 return self.flags & @enumToInt(flag) != 0;
90pub fn hasFlag(symbol: Symbol, flag: Flag) bool {
91 return symbol.flags & @enumToInt(flag) != 0;
9292}
9393
94pub fn setFlag(self: *Symbol, flag: Flag) void {
95 self.flags |= @enumToInt(flag);
94pub fn setFlag(symbol: *Symbol, flag: Flag) void {
95 symbol.flags |= @enumToInt(flag);
9696}
9797
98pub fn isUndefined(self: Symbol) bool {
99 return self.flags & @enumToInt(Flag.WASM_SYM_UNDEFINED) != 0;
98pub fn isUndefined(symbol: Symbol) bool {
99 return symbol.flags & @enumToInt(Flag.WASM_SYM_UNDEFINED) != 0;
100100}
101101
102pub fn setUndefined(self: *Symbol, is_undefined: bool) void {
102pub fn setUndefined(symbol: *Symbol, is_undefined: bool) void {
103103 if (is_undefined) {
104 self.setFlag(.WASM_SYM_UNDEFINED);
104 symbol.setFlag(.WASM_SYM_UNDEFINED);
105105 } else {
106 self.flags &= ~@enumToInt(Flag.WASM_SYM_UNDEFINED);
106 symbol.flags &= ~@enumToInt(Flag.WASM_SYM_UNDEFINED);
107107 }
108108}
109109
110pub fn setGlobal(self: *Symbol, is_global: bool) void {
110pub fn setGlobal(symbol: *Symbol, is_global: bool) void {
111111 if (is_global) {
112 self.flags &= ~@enumToInt(Flag.WASM_SYM_BINDING_LOCAL);
112 symbol.flags &= ~@enumToInt(Flag.WASM_SYM_BINDING_LOCAL);
113113 } else {
114 self.setFlag(.WASM_SYM_BINDING_LOCAL);
114 symbol.setFlag(.WASM_SYM_BINDING_LOCAL);
115115 }
116116}
117117
118pub fn isDefined(self: Symbol) bool {
119 return !self.isUndefined();
118pub fn isDefined(symbol: Symbol) bool {
119 return !symbol.isUndefined();
120120}
121121
122pub fn isVisible(self: Symbol) bool {
123 return self.flags & @enumToInt(Flag.WASM_SYM_VISIBILITY_HIDDEN) == 0;
122pub fn isVisible(symbol: Symbol) bool {
123 return symbol.flags & @enumToInt(Flag.WASM_SYM_VISIBILITY_HIDDEN) == 0;
124124}
125125
126pub fn isLocal(self: Symbol) bool {
127 return self.flags & @enumToInt(Flag.WASM_SYM_BINDING_LOCAL) != 0;
126pub fn isLocal(symbol: Symbol) bool {
127 return symbol.flags & @enumToInt(Flag.WASM_SYM_BINDING_LOCAL) != 0;
128128}
129129
130pub fn isGlobal(self: Symbol) bool {
131 return self.flags & @enumToInt(Flag.WASM_SYM_BINDING_LOCAL) == 0;
130pub fn isGlobal(symbol: Symbol) bool {
131 return symbol.flags & @enumToInt(Flag.WASM_SYM_BINDING_LOCAL) == 0;
132132}
133133
134pub fn isHidden(self: Symbol) bool {
135 return self.flags & @enumToInt(Flag.WASM_SYM_VISIBILITY_HIDDEN) != 0;
134pub fn isHidden(symbol: Symbol) bool {
135 return symbol.flags & @enumToInt(Flag.WASM_SYM_VISIBILITY_HIDDEN) != 0;
136136}
137137
138pub fn isNoStrip(self: Symbol) bool {
139 return self.flags & @enumToInt(Flag.WASM_SYM_NO_STRIP) != 0;
138pub fn isNoStrip(symbol: Symbol) bool {
139 return symbol.flags & @enumToInt(Flag.WASM_SYM_NO_STRIP) != 0;
140140}
141141
142pub fn isExported(self: Symbol) bool {
143 if (self.isUndefined() or self.isLocal()) return false;
144 if (self.isHidden()) return false;
145 if (self.hasFlag(.WASM_SYM_EXPORTED)) return true;
146 if (self.hasFlag(.WASM_SYM_BINDING_WEAK)) return false;
142pub fn isExported(symbol: Symbol) bool {
143 if (symbol.isUndefined() or symbol.isLocal()) return false;
144 if (symbol.isHidden()) return false;
145 if (symbol.hasFlag(.WASM_SYM_EXPORTED)) return true;
146 if (symbol.hasFlag(.WASM_SYM_BINDING_WEAK)) return false;
147147 return true;
148148}
149149
150pub fn isWeak(self: Symbol) bool {
151 return self.flags & @enumToInt(Flag.WASM_SYM_BINDING_WEAK) != 0;
150pub fn isWeak(symbol: Symbol) bool {
151 return symbol.flags & @enumToInt(Flag.WASM_SYM_BINDING_WEAK) != 0;
152152}
153153
154154/// Formats the symbol into human-readable text
155pub fn format(self: Symbol, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {
155pub fn format(symbol: Symbol, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {
156156 _ = fmt;
157157 _ = options;
158158
159 const kind_fmt: u8 = switch (self.tag) {
159 const kind_fmt: u8 = switch (symbol.tag) {
160160 .function => 'F',
161161 .data => 'D',
162162 .global => 'G',
......@@ -165,12 +165,12 @@ pub fn format(self: Symbol, comptime fmt: []const u8, options: std.fmt.FormatOpt
165165 .table => 'T',
166166 .dead => '-',
167167 };
168 const visible: []const u8 = if (self.isVisible()) "yes" else "no";
169 const binding: []const u8 = if (self.isLocal()) "local" else "global";
170 const undef: []const u8 = if (self.isUndefined()) "undefined" else "";
168 const visible: []const u8 = if (symbol.isVisible()) "yes" else "no";
169 const binding: []const u8 = if (symbol.isLocal()) "local" else "global";
170 const undef: []const u8 = if (symbol.isUndefined()) "undefined" else "";
171171
172172 try writer.print(
173173 "{c} binding={s} visible={s} id={d} name_offset={d} {s}",
174 .{ kind_fmt, binding, visible, self.index, self.name, undef },
174 .{ kind_fmt, binding, visible, symbol.index, symbol.name, undef },
175175 );
176176}
src/link/Wasm/types.zig+5-5
......@@ -202,22 +202,22 @@ pub const Feature = struct {
202202 required = '=',
203203 };
204204
205 pub fn toString(self: Feature) []const u8 {
206 return switch (self.tag) {
205 pub fn toString(feature: Feature) []const u8 {
206 return switch (feature.tag) {
207207 .bulk_memory => "bulk-memory",
208208 .exception_handling => "exception-handling",
209209 .mutable_globals => "mutable-globals",
210210 .nontrapping_fptoint => "nontrapping-fptoint",
211211 .sign_ext => "sign-ext",
212212 .tail_call => "tail-call",
213 else => @tagName(self),
213 else => @tagName(feature),
214214 };
215215 }
216216
217 pub fn format(self: Feature, comptime fmt: []const u8, opt: std.fmt.FormatOptions, writer: anytype) !void {
217 pub fn format(feature: Feature, comptime fmt: []const u8, opt: std.fmt.FormatOptions, writer: anytype) !void {
218218 _ = opt;
219219 _ = fmt;
220 try writer.print("{c} {s}", .{ self.prefix, self.toString() });
220 try writer.print("{c} {s}", .{ feature.prefix, feature.toString() });
221221 }
222222};
223223